Click here to Skip to main content
15,881,803 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi.

I have a C# project, where I have to both access the current workload of my processor, and ensure, that I run some specific code on every kernel of the processor. My problem is, that accessing the workload of my processor seems to prevent me from correctly assigning a thread affinity mask. I have some code here, that illustrates the problem:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace KernelAffinitySpike
{
    class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern UIntPtr SetThreadAffinityMask(IntPtr hThread, UIntPtr dwThreadAffinityMask);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr GetCurrentThread();

        private static PerformanceCounter cpuUsage;
        private static UIntPtr oldMask, newMask, testMask; // thread-level processor affinity masks.

        static void Main(string[] args)
        {
            InitPerformanceCounter();

            Console.WriteLine("Pre: thread affinity: " + CurrentThreadAffinityMask());
            if (AllKernelsAccessible())
                Console.WriteLine("Pre: all kernels accessible");
            else
            {
                Console.Write("Pre: some kernels not accessible: ");
                foreach (UInt32 kernel in InaccessibleKernels())
                    Console.Write(kernel + " ");
                Console.WriteLine();
            }

            float load = cpuUsage.NextValue();

            Console.WriteLine("Post: thread affinity: " + CurrentThreadAffinityMask());
            if (AllKernelsAccessible())
                Console.WriteLine("Post: all kernels accessible");
            else
            {
                Console.Write("Post: some kernels not accessible: ");
                foreach (UInt32 kernel in InaccessibleKernels())
                    Console.Write(kernel + " ");
                Console.WriteLine();
            }

            Console.ReadLine();
        }

        static void InitPerformanceCounter()
        {
            cpuUsage = new PerformanceCounter();
            cpuUsage.CategoryName = "Processor";
            cpuUsage.CounterName = "% Processor Time"; 
            cpuUsage.InstanceName = "_Total";
        }

        static UInt32 CurrentThreadAffinityMask()
        {
            oldMask = SetThreadAffinityMask(GetCurrentThread(), (UIntPtr) 3); // 3 just enables all processors on a dual core. I'm only interested in the return value.
            SetThreadAffinityMask(GetCurrentThread(), oldMask);
            return (UInt32) oldMask;
        }

        static List<uint32> InaccessibleKernels()
        {
            List<uint32> inaccessible = new List<uint32>();
            for (int i = 0; i < Environment.ProcessorCount; i++)
            {
                newMask = (UIntPtr)(1 << i);
                oldMask = SetThreadAffinityMask(GetCurrentThread(), newMask);
                testMask = SetThreadAffinityMask(GetCurrentThread(), oldMask);
                if (newMask != testMask)
                    inaccessible.Add((UInt32) newMask);
            }
            return inaccessible;
        }

        static bool AllKernelsAccessible()
        {
            return InaccessibleKernels().Count == 0;
        }
    }
}</uint32></uint32></uint32>


Running this code yields the following output:

Pre: thread affinity: 3
Pre: all kernels accessible
Post: thread affinity: 2
Post: some kernels not accessible: 1

So, it seems that the cpuUsage.NextValue call somehow changes the thread affinity mask, and also makes it impossible to change the mask to 1. It does make sense, that the Nextvalue call would have to interact with the thread affinity mask in some way, if it is aggregating a performance count from each kernel, but I cannot understand, why it should affect future changes to the thread affinity mask. Does anybody have an explanation, or a workaround to this problem?
Posted
Comments
ely_bob 22-Dec-10 16:05pm    
What is the OS version your running? because on vista and W7 it can be murkey...?
el_vez 22-Dec-10 21:48pm    
My OS is XP, SP3.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900