none
SetThreadPriorityBoost does not work. RRS feed

  • Question

  • Hi Guys,

    I created 8 threads, 2 of them are set to THREAD_PRIORITY_ABOVE_NORMAL priority, rest of them use the default priority.

    Then I run SetThreadPriorityBoost to disable the PriorityBoost for the 6 normal default threads. Then I kick of these 8 threads.

    However, after the 2 high priority threads start to run, I still see the 6 default priority threads got CPU time..

    According to the following article, 'Threads are scheduled in a round-robin fashion at each priority level, and only when there are no executable threads at a higher level does scheduling of threads at a lower level take place.'

    https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-setthreadpriority 

    I have use SetProcessAffinityMask to limit all threads to 2 CPUs.

    Why the 6 default priority threads are still running???  

    Any suggestions would be appreciated.

    Here is my code.

    I'm running the program in windows 10 system with 8 processors .

    #include <windows.h>
    #include <stdio.h>
    #define THREADCOUNT 8
    
    DWORD AccessSharedResource(LPVOID par);
    
    int main()
    {
    
     printf("Run SetProcessAffinityMask to bind all threads to CPU0 and CPU2\n");
    	if(!SetProcessAffinityMask(GetCurrentProcess(),0x05))				
    		{
    			DWORD dError=GetLastError();
    			printf("SetProcessAffinityMask failed with error:%d\n",dError);
    		}
    	HANDLE hThread[THREADCOUNT];
    	DWORD lpThreadId;
    	for(int i=0;i<THREADCOUNT;i++)
    	{
    		hThread[i]=CreateThread(
    			NULL,//secuirty flag
    			0,//default stack size
    			(LPTHREAD_START_ROUTINE)AccessSharedResource, the function associated to this threa
    			(LPVOID)i,//the parameter passed to function AccessSharedResource
    			CREATE_SUSPENDED,
    			&lpThreadId // thread Identifier
    			);
    		
    		
    		if(hThread[i]==NULL)
    		{
    			printf("Failed to create Thread, errorcode=%d",GetLastError());
    			return 0;
    		}
    			
    	}
    	
    
    	for(int i=0;i<THREADCOUNT;i++)
    	{
    	
    	
    		if(i>=THREADCOUNT-2)
    			{
    			if(SetThreadPriority(hThread[i],THREAD_PRIORITY_ABOVE_NORMAL))
    				{
    					printf("SetThreadPriority THREAD_PRIORITY_ABOVE_NORMAL to thread %d\n",i);
    				}
    				else
    					{
    						int dError=GetLastError();
    						printf("SetThreadPriority failed with error %d\n",dError);
    					}
    			}
    			else
    				{
    						if(SetThreadPriorityBoost(hThread[i],TRUE))//Disable Priority boost for thread 0~thread5
    							{
    								printf("SetThreadPriorityBoost disable for thread %d\n",i);
    							}
    				}
    
    	}
    	
    	
    	for(int i=0;i<THREADCOUNT;i++)
    	{
    	  printf("priority of thread %d is %d\n",i,GetThreadPriority(hThread[i]));
    		ResumeThread(hThread[i]);
    	}
    		
    	WaitForMultipleObjects(THREADCOUNT,	hThread,true,INFINITE);
    	
    		for(int i=0;i<THREADCOUNT;i++)
    	{
    		
    		CloseHandle(hThread[i]);
    	}
    	
    
    	return 1;	
    }
    
    DWORD AccessSharedResource(LPVOID par)
    {
    	
    
    	for(int i=0;i<10000000;i++)
    	{
    		for(int j=0;j<10000000;j++)
    		{
    			if((int)par>=6)
      	{
      			printf("Thread id=%d is running on CPU %d\n",(int)par,GetCurrentProcessorNumber());
      	}
      	else
      		{
      			printf("..............You should not see this until Thread 6&7 complete....................\n");
      		}
    		}
    	}
      if((int)par>=6)
      	{
      		printf("Thread %d has compelted\n",(int)par);
      	}
    
    	return 0;
    }
    
    
    



    Sunday, June 16, 2019 10:14 PM

Answers

  • One thing I will point out is that you shouldn't be casting the thread function pointer in the call to CreateThread. In your code, you have:

    (LPTHREAD_START_ROUTINE)AccessSharedResource

    there is never any need to do this, and if it fails to compile if you don't do this then you have defined the function incorrectly.

    For example:

    #include <Windows.h>
    #include <cstdio>
    
    DWORD CALLBACK threadproc(LPVOID)
    {
    	wprintf(L"Hello from the thread\n");
    
    	return 0;
    }
    
    int wmain()
    {
    	HANDLE thread = CreateThread(nullptr, 0, threadproc, nullptr, 0, nullptr);
    
    	WaitForSingleObject(thread, INFINITE);
    
    	CloseHandle(thread);
    
    	return 0;
    }

    Notice how there is no cast in this little program before threadproc in CreateThread?

    For your actual question, there is one thing that I will suggest. Add a time stamp to the output and then get each thread to write to separate files.

    There is one thing that can override scheduling priorities very easily, and that is locks. Output to the console is synchronised between threads so it could be possible that one thread is outputting to the console and other threads are waiting on it. Then when one of the high priority threads finish, one of the low priority threads wakes up faster than the other high priority thread and grabs the lock. Or the second high priority thread was waiting for the console and was scheduled to run, but one of the low priority threads ready to run at the head of one of the lower priority queues did get to run, and in this time it managed to grab the console lock.

    Scheduling priorities only apply to threads which are ready to run after all, so if a thread is waiting on a lock then it is not ready to run.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Monday, June 17, 2019 2:36 AM

All replies

  • For one thing, at the point you resume the first normal-priority thread, the two high-priority ones are still suspended. So the first thread has time to run and do some work.

    Igor Tandetnik

    Sunday, June 16, 2019 11:20 PM
  • thanks Lgor,

    however, i still see the 6 low priority threads got run after my 2 high priority threads start to run.

    Monday, June 17, 2019 12:07 AM
  • One thing I will point out is that you shouldn't be casting the thread function pointer in the call to CreateThread. In your code, you have:

    (LPTHREAD_START_ROUTINE)AccessSharedResource

    there is never any need to do this, and if it fails to compile if you don't do this then you have defined the function incorrectly.

    For example:

    #include <Windows.h>
    #include <cstdio>
    
    DWORD CALLBACK threadproc(LPVOID)
    {
    	wprintf(L"Hello from the thread\n");
    
    	return 0;
    }
    
    int wmain()
    {
    	HANDLE thread = CreateThread(nullptr, 0, threadproc, nullptr, 0, nullptr);
    
    	WaitForSingleObject(thread, INFINITE);
    
    	CloseHandle(thread);
    
    	return 0;
    }

    Notice how there is no cast in this little program before threadproc in CreateThread?

    For your actual question, there is one thing that I will suggest. Add a time stamp to the output and then get each thread to write to separate files.

    There is one thing that can override scheduling priorities very easily, and that is locks. Output to the console is synchronised between threads so it could be possible that one thread is outputting to the console and other threads are waiting on it. Then when one of the high priority threads finish, one of the low priority threads wakes up faster than the other high priority thread and grabs the lock. Or the second high priority thread was waiting for the console and was scheduled to run, but one of the low priority threads ready to run at the head of one of the lower priority queues did get to run, and in this time it managed to grab the console lock.

    Scheduling priorities only apply to threads which are ready to run after all, so if a thread is waiting on a lock then it is not ready to run.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Monday, June 17, 2019 2:36 AM
  • Your higher-priority threads are doing I/O.  That always involves blocking at some point, and when they block, the other threads will get a chance to run.

    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Monday, June 17, 2019 5:32 AM
  • Hello,

    Thanks for posting here.

    Thread priorities can also result in different behavior on single-core versus multi-core platforms. For example, consider an application that has two threads of differing priorities. In an attempt to improve performance, the developer assumes that the higher priority thread will always run without interference from the lower priority thread. On a single-core platform, this may be valid, as the operating system’s scheduler will not yield the CPU to the lower priority thread. However, on multi-core platforms, the scheduler may schedule both threads on separate cores. Therefore, both threads may run simultaneously. If the developer had optimized the code to assume that the higher priority thread would always run without interference from the lower priority thread, the code would be unstable on multi-core and multi-processor systems. 

    Best Wishes,

    Jack Zhang


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, June 17, 2019 8:20 AM
    Moderator