Search code examples
clinuxmultithreadingscheduling

Creating threads with different scheduling priorities


First-time C user here. I've been learning to create basic C programs, and my professor gave us our first big assignment and I'm hopelessly lost.

for part of it, I'm supposed to create three different threads with SCHED_OTHER, SCHED_RR, and SCHED_FIFO as their respective scheduling priorities. Each of these 3 threads will wait for the "main" thread to signal that they should start running a "task".

This task is a function call with non-yielding and non-blocking instructions that should take 5 to 10 seconds to complete.

So basically, two questions:

  • How to I create a thread in C with a defined priority(SCHED_OTHER, SCHED_RR, or SCHED_FIFO) (how do I use pthread_create()?)

  • How would I go about writing these tasks? (pseudocode is fine)


Solution

  • How to I create a thread in C with a defined priority(SCHED_OTHER, SCHED_RR, or SCHED_FIFO) (how do I use pthread_create()?) (pseudocode is fine)

    That last bit, "pseudocode is fine" is the important bit. You should consider moving it earlier in the question, because even I thought this was a fishing expedition for getting somebody do your homework for you, before I saw that.

    When you create a new POSIX thread, you tell the pthread_create() function which function the new thread should run. When the thread returns from that function, or exits using pthread_exit(), it stops executing. Normally, another thread reaps it via pthread_join(), which can also provide the return value (a pointer) from the thread function.

    The thread function takes a void pointer (void *) as a parameter, and returns one. It is common to not need either. If you want to pass an integer value, you can use (void *)(intptr_t)value or (void *)(uintptr_t)value to cast a signed or unsigned value to a pointer; and (intptr_t)ptr or (uintptr_t)ptr to cast a pointer ptr to signed or unsigned integer type. These types are specified in <stdint.h> in POSIX.

    You can also supply a set of attributes as a specification for the C library as to what kind of properties the created thread should have. These attributes are not consumed during the creation, and you can use the same set of attributes to create any number of threads. A normal variable can hold the attributes; you do not need to dynamically allocate memory for it. The most common thing to do with thread attributes is to set the stack size to a sane value, as the default stack size tends to be huge (something like 8 megabytes), which is usually the first limit encountered when a process tries to create a large number of threads.

    So, to create the three threads, each with a specific scheduler policy, you do:

    Initialize a set of pthread attributes,
        using pthread_attr_init()
    
    Set the scheduler policy attribute,
        using pthread_attr_setschedpolicy()
    Create the thread using pthread_create(),
        but do remember to check for errors
    
    Set the scheduler policy attribute,
        using pthread_attr_setschedpolicy()
    Create the thread using pthread_create(),
        but do remember to check for errors
    
    Set the scheduler policy attribute,
        using pthread_attr_setschedpolicy()
    Create the thread using pthread_create(),
        but do remember to check for errors
    
    Discard the thread attributes,
        using pthread_attr_destroy()
    
    The main/initial thread is free to twiddle
    its proverbial thumbs here.
    
    Wait for each of the three threads to exit
        using three calls to pthread_join()
    
    Done.
    

    You may also wish to check for errors when setting the scheduler policy attribute (and also if you set the scheduler priority), because not all policies and priorities are allowed for unprivileged users. I hope you'll have lots of

    retcode = ... pthreads-related function call ...;
    if (retcode) {
        fprintf(stderr, "pthread_suchandsuch() failed: %s.\n", strerror(retcode));
        exit(EXIT_FAILURE);
    }
    

    in your code. It might look verbose, but it is extremely helpful when you are looking for reasons why something did not work. (Also, use gcc -Wall -O2 -pthread sources.. -o binary to compile your program.)

    I warmly recommend you keep a browser window open to Linux man pages online, the most up to date and well-maintained source of core man pages for Linux and POSIXy systems.