Thread: Scheduling Policy

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    146

    Scheduling Policy

    Hi,

    I am trying to learn pthreads and pthreads attributes... I wrote a simple program which creates 2 threads... 1 prints world and another prints hello... I have set priority of the thread which prints hello higher than the other so it should print hello world.. but some how it isn't doing so...

    Here's the code...

    Code:
    #include <stdio.h>
    #include <pthread.h>
    #include <sched.h>
    
    pthread_mutex_t mutex1;
    
    char *message1 = "Hello";
    char *message2 = "World";
    
    void print_Hello( void );
    void print_World( void );
    
    int main()
    {
    	pthread_t thread1, thread2;
    	pthread_attr_t atri1,atri2;
    	
    	int priority_high=500, priority_low=10;
    	int status=0;
    	int t = 25;
    	struct sched_param para1;
    	struct sched_param para2;
    	para1.sched_priority = priority_high;
    	para2.sched_priority = priority_low;
    	status = pthread_mutex_init(&mutex1,NULL);
            if(status!=0)
            {
                    printf("\nMUTEX init failed !\n");
                    return 0;
            }
    
    	status = pthread_attr_init(&atri1);
    	if(status!=0)
    	{
    		printf("\nAttribute init failed !\n");
    		return 0;
    	}
    	status = pthread_attr_init(&atri2);
    	if(status!=0)
    	{
                    printf("\nAttribute init failed !\n");
                    return 0;
            }
    	status = pthread_attr_setschedpolicy(&atri1, SCHED_RR);
    	if(status!=0)
            {
                    printf("\nSched policy init failed 1!\n");
                    return 0;
            }
    	status = pthread_attr_setschedpolicy(&atri2, SCHED_RR);
            if(status!=0)
            {
                    printf("\nSched policy init failed 2!\n");
                    return 0;
            }
    
    	status = pthread_attr_setschedparam(&atri1, &para1);
    	if(status!=0)
            {
                    printf("\nCould not set Priority : 1 !\n");
                    return 0;
            }
    	status = pthread_attr_setschedparam(&atri2, &para2);
            if(status!=0)
            {
                    printf("\nCould not set priority : 2!\n");
                    return 0;
            } 
    	while(--t>0)
    	{       status=pthread_create( &thread1, &atri2,(void*)&print_World, NULL);
    		if(status!=0)
    			printf("\nThread 1 Could not be created");
    		status=	pthread_create(&thread2, &atri1,(void*)&print_Hello, NULL);
    		if(status!=0)
    			printf("\nThread 2 Could not be created");
    	}
    	return 0;
    }
    void print_Hello( void )
    {
    
    //	while(1)
    //	{
    		pthread_mutex_lock(&mutex1);
    		printf("%s ", message1); 
    		pthread_mutex_unlock(&mutex1);
    
    //	}
    }
    void print_World( void )
    {
    
    //	while(1)
    //	{ 
           		 pthread_mutex_lock(&mutex1);
    		 printf("%s ", message2);
    		 pthread_mutex_unlock(&mutex1);
    
    //	}
    }
    I tried changing scheduling policies, adding / removing mutex but still it keep on printing World Hello World Hello...

    So, can anybody suggest what am I doing wrong?

    Thanks,
    Edesign
    Last edited by edesign; 05-12-2009 at 01:32 AM.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Yes, you would have to add more locking to ensure that the threads begin to execute in the right order. You could for example have a mutex that is locked by main, then unlocked by thread hello, which the thread world is waiting for.

    When you create thread World, it is ready to run, and will get the lock before thread Hello is started.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Feb 2008
    Posts
    146
    But can't we schedule normal execution order of threads by some means? ( I mean not who'll get the lock first but who'll be executed first kind of schedule..) Once both the threads are in run state shouldn't the one with higher priority execute first?

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    No, there is no guarantee whatsoever of which runs first, second or third between threads when it comes to starting the threads. To ensure ordering, YOU as a programmer will have to use some form of synchronization. This is one part of what makes multithreaded programming hard.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Feb 2008
    Posts
    146
    I've locked the mutex prior to creating any thread and unlocked it after both of them are created...so now the thread with higher priority should be able to lock the mutex first but still no change in output..

    Code:
    #include <stdio.h>
    #include <semaphore.h>
    #include <pthread.h>
    #include <sched.h>
    
    pthread_mutex_t mutex1;
    
    char *message1 = "Hello";
    char *message2 = "World";
    
    void print_Hello( void );
    void print_World( void );
    
    int main()
    {
    	pthread_t thread1, thread2;
    	pthread_attr_t atri1,atri2;
    	
    	int priority_high=500, priority_low=10;
    	int status=0;
    	int t = 10;
    	struct sched_param para1;
    	struct sched_param para2;
    	para1.sched_priority = priority_high;
    	para2.sched_priority = priority_low;
    	status = pthread_mutex_init(&mutex1,NULL);
            if(status!=0)
            {
                    printf("\nMUTEX init failed !\n");
                    return 0;
            }
    
    	status = pthread_attr_init(&atri1);
    	if(status!=0)
    	{
    		printf("\nAttribute init failed !\n");
    		return 0;
    	}
    	status = pthread_attr_init(&atri2);
    	if(status!=0)
    	{
                    printf("\nAttribute init failed !\n");
                    return 0;
            }	
    	status = pthread_attr_setschedpolicy(&atri1, SCHED_FIFO);
    	if(status!=0)
            {
                    printf("\nSched policy init failed 1!\n");
                    return 0;
            }
    	status = pthread_attr_setschedpolicy(&atri2, SCHED_FIFO);
            if(status!=0)
            {
                    printf("\nSched policy init failed 2!\n");
                    return 0;
            }
    
    	status = pthread_attr_setschedparam(&atri1, &para1);
    	if(status!=0)
            {
                    printf("\nCould not set Priority : 1 !\n");
                    return 0;
            }
    	status = pthread_attr_setschedparam(&atri2, &para2);
            if(status!=0)
            {
                    printf("\nCould not set priority : 2!\n");
                    return 0;
            } 
    	pthread_mutex_lock(&mutex1);
    	while(--t>0)
    	{       
    		status = pthread_create( &thread1, &atri2,(void*)&print_World, NULL);
    		if(status != 0)
    			printf("\nThread 1 Could not be created");
    		status = pthread_create(&thread2, &atri1,(void*)&print_Hello, NULL);
    		if(status != 0)
    			printf("\nThread 2 Could not be created");
    		pthread_mutex_unlock(&mutex1);
    	}
    	return 0;
    }
    void print_Hello( void )
    {
    
    //	while(1)
    //	{
    		pthread_mutex_lock(&mutex1);
    		printf("%s\n ", message1); 
    		pthread_mutex_unlock(&mutex1);
    
    //	}
    }
    void print_World( void )
    {
    
    //	while(1)
    //	{ 
           		 pthread_mutex_lock(&mutex1);
    		 printf("%s\n ", message2);
    		 pthread_mutex_unlock(&mutex1);
    
    //	}
    }

  6. #6
    Registered User
    Join Date
    Feb 2008
    Posts
    146
    ok.... I finally got the solution I wanted... first of all I was not setting PTHREAD_EXPLICIT_SCHED ...

    Also I needed to move the mutex_lock statement inside while loop...

    Now it's working... just for reference I added this piece of code...

    Code:
    status = pthread_attr_setinheritsched(&atri1, PTHREAD_EXPLICIT_SCHED);
            if(status!=0)
            {
                    printf("\nExplicit Sched init failed 1!\n");
                    return 0;
            }
    	status = pthread_attr_setinheritsched(&atri2, PTHREAD_EXPLICIT_SCHED);
            if(status!=0)
            {
                    printf("\nExplicit Sched init failed 2!\n");
                    return 0;
            }
    And ya, to set scheduling you need to run the code as root....

    @matsp : Thanks a lot...

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I'm pretty sure that's NOT the right solution - particularly if you have to be root to run the code indicates that you are doing something unusual/not right.

    Linux, Windows and many other non-RTOS will not have STRICT priorities [1], so the only way to chain different threads is to use locks. Your previous full code post shows that you are using the SAME lock to lock the threads and the ordering thread1 vs thread2 - that still leaves you with a race for which runs when.

    I think you need to have a second semaphore/lock to control the order of thread 1 and thread 2, besides the lock to prevent printf from running in parallel [which there likely is one already inside printf, or really weird stuff would happen when printing from multiple threads].

    [1] And more importantly, in a modern system with multiple cores, it's quite possible to have more than one thread running at any given time. Which of those threads "get" the lock when you unlock it at main will be completely arbitrary (and undefined) [it may well be predictable in your test app on a particular OS, etc, but generally, but that is the nature of undefined behaviour - it is not a good source of random numbers, it's a good source of "not quite knowing what will happen if something changes!"].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Feb 2008
    Posts
    146
    Actually I already ordered the threads using semaphores...but I was asked explicitly to make use of scheduling attributes...

    I am not sure that I understand you completely, here is what I think the program does..

    Before the threads are created main is locking the mutex, than both the threads are created and in run state...but none of them can lock the mutex as it is still not unlocked..

    Now it is unlocked by main...so both threads can lock it and execute themselves, but as we've set priority of a particular thead higher than the other the one with higher priority will lock the mutex.. the other thread will have to wait till this thread unlocks the mutex...

    Please correct me if my understanding is wrong...

    About being root : otherwise thread creation will fail with error no 22 that refers to EINVAL ..
    running it as root solves that problem...I read it on some forum, and the reason mentioned was that "To change the default priority, you need to be root", I am not sure what may be the reason otherwise..

    Thanks,
    Edesign

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Ok, so if someone told you to use scheduling rather than using explicit locks, then my advice isn't going to be very good.

    Yes, you are right, the higher priority thread will take priority. However, if the two threads are both waiting for the lock, and they are BOTH scheduled on two cores in the machine, it still becomes a race-condition, and you can not KNOW that the higher priority thread ACTUALLY gets the lock - they are still racing ahead. Depending on lots of factors (such as which processor gets to run which thread), one will probably win most of the time.

    I'm pretty sure that the "unlock/lock" code doesn't look at which thread is higher priority and "gives" the lock to that thread - it allows both threads to run in unlock, and then both will attempt to lock at the same time. One will be first, the other thread will be second - classical race-condition.

    I have no experience with scheduling parameters for pthreads, so I can not advice on this. I consider that type of method to be a pretty unreliable source of thread coordination (and it's much harder to look at the thread code itself and understand what is going on, if nothing else), so I have never used such mechanisms.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Priority doesn't work that way. Think of the consequences if it did. The highest priority task on the system would get 100% of all resources, and nothing else could ever do anything. Sort of defeats the purpose of multitasking.

    Higher priority threads have a tendency to be scheduled more often, and a tendency to cause preemption of a lower priority task when they become runnable, but that's just the average behavior.

    Also, trying to guarantee that a specific thread gets the lock first, seems to defeat the purpose of locking. If only thread A is supposed to acquire the lock, why bother having a lock at all? Just let thread A do its thing, and forbid all other threads from doing anything.

    Suppose you want the behavior where any thread can acquire the lock, but A always takes priority. This requires either A) lock stealing, where a thread which had a lock suddenly finds itself without it, which would force you to continually check whether you still have the lock before doing anything, which is inherently full of race condition, or B) prediction of the future, and if you figure that one out, please let me know how
    Last edited by brewbuck; 05-12-2009 at 08:50 PM.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. scheduling in linux
    By anjana in forum Linux Programming
    Replies: 2
    Last Post: 05-24-2007, 03:48 PM
  2. POSIX threads policy and priority
    By arunj in forum Linux Programming
    Replies: 2
    Last Post: 06-13-2006, 03:48 AM
  3. Round Robin Scheduling using c.
    By eclipt in forum C Programming
    Replies: 8
    Last Post: 12-28-2005, 04:58 PM
  4. curses problem
    By rajesh23 in forum Linux Programming
    Replies: 2
    Last Post: 10-07-2003, 07:27 AM
  5. US antitrust policy
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 11-03-2002, 07:36 PM