Link to home
Start Free TrialLog in
Avatar of plq
plqFlag for United Kingdom of Great Britain and Northern Ireland

asked on

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

Avatar of jkr
jkr
Flag of Germany image

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")
Avatar of plq

ASKER

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)

ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of plq

ASKER

Yep, the code was not well written and it was indeed setting all 32 bits and therefore appearing negative.. thanks for helping once again..