Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1232
  • Last Modified:

GetProcessAffinityMask Returns 2^32-1 in SystemAffinity- breaks my program.

Hi FOlks,

See attached code. On a very large Dell R910 server dwSystemAffinity gets set to 4294967296, whereas on my machine its set to 15.

This is causing what seems to be an infinite loop in the code. I'm sure its the bit shift at the end of the while loop ?

Any ideas ??

thanks
Paul

//
//
//
unsigned char CPUCount(unsigned int *TotAvailLogical,
					   unsigned int *TotAvailCore,
					   unsigned int *PhysicalNum)
{
	unsigned char StatusFlag = 0;
	unsigned int numLPEnabled = 0;
	DWORD dwAffinityMask;
	int j = 0, MaxLPPerCore;
	unsigned char apicID, PackageIDMask;
	unsigned char tblPkgID[1024], tblCoreID[1024], tblSMTID[1024];
	//char	tmp[1024];
	//g_s3Levels[0] = 0;
	*TotAvailCore = 1;
	*PhysicalNum  = 1;

			/* *** */ debugprintf(TEXT("CPUC 001\n"));

#ifdef LINUX
	//we need to make sure that this process is allowed to run on 
	//all of the logical processors that the OS itself can run on.
	//A process could acquire/inherit affinity settings that restricts the 
	// current process to run on a subset of all logical processor visible to OS.

	// Linux doesn't easily allow us to look at the Affinity Bitmask directly,
	// but it does provide an API to test affinity maskbits of the current process 
	// against each logical processor visible under OS.
	int sysNumProcs = sysconf(_SC_NPROCESSORS_CONF); //This will tell us how many 
													//CPUs are currently enabled.
	
	//this will tell us which processors this process can run on. 
	 cpu_set_t allowedCPUs;	 
	 sched_getaffinity(0, sizeof(allowedCPUs), &allowedCPUs);
	 
	for (int i = 0; i < sysNumProcs; i++ )
	{
		if ( CPU_ISSET(i, &allowedCPUs) == 0 )
		{
			StatusFlag = USER_CONFIG_ISSUE;		
			return StatusFlag;
		}
	}
#else
	DWORD dwProcessAffinity, dwSystemAffinity;
			/* *** */ debugprintf(TEXT("CPUC 002\n"));
	GetProcessAffinityMask(GetCurrentProcess(), 
						   &dwProcessAffinity,
						   &dwSystemAffinity);
			/* *** */ debugprintf(TEXT("CPUC 003\n"));
	if (dwProcessAffinity != dwSystemAffinity)  // not all CPUs are enabled
	{
		StatusFlag = USER_CONFIG_ISSUE;		
		return StatusFlag;
	}
			/* *** */ debugprintf(TEXT("CPUC 004\n"));
#endif
	
	// Assumwe that cores within a package have the SAME number of 
	// logical processors.  Also, values returned by
	// MaxLogicalProcPerPhysicalProc and MaxCorePerPhysicalProc do not have
	// to be power of 2.

			/* *** */ debugprintf(TEXT("CPUC 005\n"));
	MaxLPPerCore = MaxLogicalProcPerPhysicalProc() / MaxCorePerPhysicalProc();
	dwAffinityMask = 1;
			/* *** */ debugprintf(TEXT("CPUC 006\n"));

	printf("System Affinity %u", dwSystemAffinity);

	if (dwSystemAffinity > 0)
	{

#ifdef LINUX
		cpu_set_t currentCPU;
		while ( j < sysNumProcs )
		{
			CPU_ZERO(&currentCPU);
			CPU_SET(j, &currentCPU);
			if ( sched_setaffinity (0, sizeof(currentCPU), &currentCPU) == 0 )
			{
				sleep(0);  // Ensure system to switch to the right CPU
#else
				/* *** */ debugprintf(TEXT("CPUC 007\n"));
				
		while (dwAffinityMask && dwAffinityMask <= dwSystemAffinity)
		{
			if (SetThreadAffinityMask(GetCurrentThread(), dwAffinityMask))
			{
				Sleep(0);  // Ensure system to switch to the right CPU
#endif
				apicID = GetAPIC_ID();


				// Store SMT ID and core ID of each logical processor
				// Shift vlaue for SMT ID is 0
				// Shift value for core ID is the mask width for maximum logical
				// processors per core

				tblSMTID[j]  = GetNzbSubID(apicID, MaxLPPerCore, 0);
				/* *** */ debugprintf(TEXT("CPUC 011\n"));
				tblCoreID[j] = GetNzbSubID(apicID, 
							   MaxCorePerPhysicalProc(),
							   (unsigned char) find_maskwidth(MaxLPPerCore));

				// Extract package ID, assume single cluster.
				// Shift value is the mask width for max Logical per package

				PackageIDMask = (unsigned char) (0xff << 
								find_maskwidth(MaxLogicalProcPerPhysicalProc()));

				tblPkgID[j] = apicID & PackageIDMask;
				//sprintf(tmp,"  AffinityMask = %d; Initial APIC = %d; Physical ID = %d, Core ID = %d,  SMT ID = %d\n",
				//	    dwAffinityMask, apicID, tblPkgID[j], tblCoreID[j], tblSMTID[j]);
				//strcat(g_s3Levels, tmp);

				numLPEnabled ++;   // Number of available logical processors in the system.

				printf ("CPUCStatus %u %u %u\n", j, dwAffinityMask, dwSystemAffinity);

			} // if

			j++;
			dwAffinityMask = 1 << j;

			printf ("CPUCLoopOut %u %d %d\n", j, dwAffinityMask, dwSystemAffinity);
			// if (j > 100) break;

		} // while


	}
	else
	{
		numLPEnabled = MaxLPPerCore;
	}

    // restore the affinity setting to its original state
#ifdef LINUX
	sched_setaffinity (0, sizeof(allowedCPUs), &allowedCPUs);
	sleep(0);
#else
			/* *** */ debugprintf(TEXT("CPUC 017\n"));
    SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinity);
			/* *** */ debugprintf(TEXT("CPUC 018\n"));
	Sleep(0);
			/* *** */ debugprintf(TEXT("CPUC 019\n"));
#endif
	*TotAvailLogical = numLPEnabled;
	
	//
	// Count available cores (TotAvailCore) in the system
	//
	unsigned char CoreIDBucket[1024];
	DWORD ProcessorMask, pCoreMask[1024];
	unsigned int i, ProcessorNum;

			/* *** */ debugprintf(TEXT("CPUC 020\n"));

	CoreIDBucket[0] = tblPkgID[0] | tblCoreID[0];
	ProcessorMask = 1;
	pCoreMask[0] = ProcessorMask;

			/* *** */ debugprintf(TEXT("CPUC 021\n"));

	for (ProcessorNum = 1; ProcessorNum < numLPEnabled; ProcessorNum++)
	{
		ProcessorMask <<= 1;
		for (i = 0; i < *TotAvailCore; i++)
		{
			// Comparing bit-fields of logical processors residing in different packages
			// Assuming the bit-masks are the same on all processors in the system.
			if ((tblPkgID[ProcessorNum] | tblCoreID[ProcessorNum]) == CoreIDBucket[i])
			{
				pCoreMask[i] |= ProcessorMask;
				break;
			}

		}  // for i

		if (i == *TotAvailCore)   // did not match any bucket.  Start a new one.
		{
			CoreIDBucket[i] = tblPkgID[ProcessorNum] | tblCoreID[ProcessorNum];
			pCoreMask[i] = ProcessorMask;

			(*TotAvailCore)++;	// Number of available cores in the system

		}

	}  // for ProcessorNum

			/* *** */ debugprintf(TEXT("CPUC 022\n"));

	//
	// Count physical processor (PhysicalNum) in the system
	//
	unsigned char PackageIDBucket[1024];
	DWORD pPackageMask[1024];

			/* *** */ debugprintf(TEXT("CPUC 023\n"));

	PackageIDBucket[0] = tblPkgID[0];
	ProcessorMask = 1;
	pPackageMask[0] = ProcessorMask;

			/* *** */ debugprintf(TEXT("CPUC 024\n"));

	for (ProcessorNum = 1; ProcessorNum < numLPEnabled; ProcessorNum++)
	{
		ProcessorMask <<= 1;
		for (i = 0; i < *PhysicalNum; i++)
		{
			// Comparing bit-fields of logical processors residing in different packages
			// Assuming the bit-masks are the same on all processors in the system.
			if (tblPkgID[ProcessorNum]== PackageIDBucket[i])
			{
				pPackageMask[i] |= ProcessorMask;
				break;
			}

			/* *** */ debugprintf(TEXT("CPUC 025\n"));
		}  // for i

		if (i == *PhysicalNum)   // did not match any bucket.  Start a new one.
		{
			PackageIDBucket[i] = tblPkgID[ProcessorNum];
			pPackageMask[i] = ProcessorMask;

			(*PhysicalNum)++;	// Total number of physical processors in the system

		}

	}  // for ProcessorNum

//
// Check to see if the system is multi-core 
// Check if the system is hyper-threading
//
			/* *** */ debugprintf(TEXT("CPUC 026\n"));
if (*TotAvailCore > *PhysicalNum) 
{
	// Multi-core
	if (MaxLPPerCore == 1)
		StatusFlag = MULTI_CORE_AND_HT_NOT_CAPABLE;
	else if (numLPEnabled > *TotAvailCore)
		StatusFlag = MULTI_CORE_AND_HT_ENABLED;
		else StatusFlag = MULTI_CORE_AND_HT_DISABLED;

}
else
{
	// Single-core
	if (MaxLPPerCore == 1)
		StatusFlag = SINGLE_CORE_AND_HT_NOT_CAPABLE;
	else if (numLPEnabled > *TotAvailCore)
		StatusFlag = SINGLE_CORE_AND_HT_ENABLED;
		else StatusFlag = SINGLE_CORE_AND_HT_DISABLED;


}

			/* *** */ debugprintf(TEXT("CPUC 027\n"));


return StatusFlag;
}

Open in new window

0
plq
Asked:
plq
  • 2
  • 2
1 Solution
 
jkrCommented:
Actually, the value you get is -1, yet since DWORD is unsigned, the interpretation of the value is somewhat off. And since a DWORD also just has 32 bits, it indicates that the Dell server has at least 32 cores ;o)

Since I then assume (with 32bit Windows only supporting 32 CPUs) that you're running a 32bit application on WOW64, see http://msdn.microsoft.com/en-us/library/aa384228%28v=VS.85%29.aspx ("Processor Affinity Under WOW64")
0
 
plqAuthor Commented:
Hello jkr - hope you're doing ok.

Yes it definitely has 32 cores and it is a 32 bit program running under WOW on a x64 machine.

I suspect its right then in setting all 32 bits, but where's the problem in my program ?  Is it that number 1 << j ??

Should it be instead

dwAffinityMask = ( (unsigned int) 1 ) << (unsigned int) j

(or just declare j as unsigned of course)

0
 
jkrCommented:
Well, your 'while condition 'dwAffinityMask <= dwSystemAffinity' in that case pretty much always evaluates to 'true'. Furthermore, you could just add a '&& j <= 32' to the condition (which will fix that problem), since you cannot detect any more than 32 CPUs from 32bit code anyway.
0
 
plqAuthor Commented:
Yep, the code was not well written and it was indeed setting all 32 bits and therefore appearing negative.. thanks for helping once again..
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now