POSIX threads and fairness (semaphores) - c

I have created a program in C that creates 2 buffers. The buffer indices hold single characters, 'A' or 'b' etc... In order to learn more about multithreading, I created a set of semaphores based on the producer/consumer problem to produce characters and consume characters from the buffers. I have 3 producer threads for each buffer and 10 consumer threads. The consumers take one item from each buffer, then report it (freeing the memory of the consumed item also). Now, from what I've read, sem_wait() is supposed to signal the "longest waiting thread" when it comes out of a blocking state (I read this in a book and in an online POSIX library).
Now, is this actually true?
The application I have made should have both consumers and producers waiting at the same sem_wait() gate, but the producers get into the critical section more than double the time of any consumer. The consumers do have an extra semaphore to wait for, but that shouldn't make that huge of a difference. I can't seem to figure out why it's happening, so I'm hoping someone else does. If I sleep(1) on the producer threads, the consumers get in just fine and the buffers hover around 0 items...like I would think would happen otherwise.
Also, should thread creation order play any role in how I structure the program for fairness?
IE, produce one of each type in a round robin fashion until everyone is created and running.
Are there any methods anyone can describe to me to institute a more fair system of thread access? I've read that creating a FIFO queue system might be one solution, where the longest waiting thread has the highest priority (which is what I thought sem_wait() would do anyways).
Just wondering what methods are out there for both rudimentary and higher level threading.

The POSIX standard actually says that "the highest priority thread that has been waiting the longest shall be unblocked" only when the SCHED_FIFO or SCHED_RR scheduling policy applies to the blocked thread.
If you're not using one of those two realtime scheduling policies, then the semaphore does not have to be "fair".

Related

Adding Prioritization To a Thread Without Busy Waiting in C (Linux)

I have a prioritization problem in my homework. Some threads have higher priorities than the others and the other threads have to wait to access a file until all those threads have finished their job. We are not allowed to use busy waiting. Is there another solution to solve this. Thanks.
Yeah, OK, like my comment.
The low-priority threads must wait on the, (initialized to zero), semaphore before accessing the file. The high-priority threads, when they have finished with tbe file, must acquire the mutex, count down the high count check for zero and release the mutex. The last high-thread that finds zero should then issue [low count] units to the semaphore, so releasing all the low threads.
Actually, a mutex-protected struct with state data can handle just about any weird locking/sequencing/prioritizing scheme that your prof can come up with, no matter how much tequila it consumes first:)

does semaphore preserve wait order [duplicate]

I have created a program in C that creates 2 buffers. The buffer indices hold single characters, 'A' or 'b' etc... In order to learn more about multithreading, I created a set of semaphores based on the producer/consumer problem to produce characters and consume characters from the buffers. I have 3 producer threads for each buffer and 10 consumer threads. The consumers take one item from each buffer, then report it (freeing the memory of the consumed item also). Now, from what I've read, sem_wait() is supposed to signal the "longest waiting thread" when it comes out of a blocking state (I read this in a book and in an online POSIX library).
Now, is this actually true?
The application I have made should have both consumers and producers waiting at the same sem_wait() gate, but the producers get into the critical section more than double the time of any consumer. The consumers do have an extra semaphore to wait for, but that shouldn't make that huge of a difference. I can't seem to figure out why it's happening, so I'm hoping someone else does. If I sleep(1) on the producer threads, the consumers get in just fine and the buffers hover around 0 items...like I would think would happen otherwise.
Also, should thread creation order play any role in how I structure the program for fairness?
IE, produce one of each type in a round robin fashion until everyone is created and running.
Are there any methods anyone can describe to me to institute a more fair system of thread access? I've read that creating a FIFO queue system might be one solution, where the longest waiting thread has the highest priority (which is what I thought sem_wait() would do anyways).
Just wondering what methods are out there for both rudimentary and higher level threading.
The POSIX standard actually says that "the highest priority thread that has been waiting the longest shall be unblocked" only when the SCHED_FIFO or SCHED_RR scheduling policy applies to the blocked thread.
If you're not using one of those two realtime scheduling policies, then the semaphore does not have to be "fair".

Managing a variable number of worker threads with graceful exit

I have a boss thread that spawns up to M worker threads. Over the lifetime of the program, workers may be added and removed. When the program-wide shutdown flag is signalled, I want to await the completion of these workers.
Currently, any of the threads can add/remove threads, but it's strictly not a requirement as long as any thread can initiate a spawn/removal.
What's stopping me from using a counting semaphore or pthread_barrier_wait() is that it expects a fixed number of threads.
I can't loop pthread_join() over all workers either because I'd risk leaking zombie threads that have exited and possibly since then been replaced.
The boss thread itself has no other purpose than spawning the threads initially and making sure that the process exits gracefully.
I've spent days on and off on this problem and cannot come up with something robust and simple; are there any fairly well-established ways to accomplish this with POSIX threads?
1) "Currently, any of the threads can add/remove threads"
and
2) "are there any fairly well-established ways to accomplish this with POSIX threads"
Yes. Don't do (1). Have the boss thread do it.
Or, you can protect the code which spawns threads with a critical section or mutex (I assume you are already doing this). They should check a flag to see if shutdown is in progress, and if it is, don't spawn any more threads.
You can also have a counter of "ideal number of threads" and "actual number of threads" and have threads suicide if they find "ideal > actual". (I.e. they should decrement actual, exit the critical section/mutex, then quit).
When you need to initiate shutdown, use the SAME mutex/section to set the flag. Once done, you know the number of threads cannot increase, so you can use the most recent value.
Indeed, to exit you can just have the boss thread set "ideal" to zero, exit the mutex, and repeatedly sleep 10ms and repeat until all threads have exited. Worst case is you wait an extra 10ms to quit. If that's too much cut it to 1ms.
These are just ideas. The central concept is that all thread creation/removal, and messages about thread creation/removal should be protected by a mutex to ensure that only one thread is adding/removing/querying status at a time. Once you have that in place, there is more than one way to do it...
Threads that want to initiate spawns/removals should ask the boss thread to actually do it for them. Then the boss thread doesn't have to worry about threads it doesn't know about, and you can use one of the simple methods you described in your question.
I'll take the opposite tac as some of the other answers since I have to do this now and again.
(1) Give every spawned thread access to a single pipe file descriptor either through the data passed through pthread_create or globally. Only the boss thread reads the pipe. Each thread announces its creation and termination to the boss via the pipe by passing its tid and boss adds or removes it from its list and pthread_joins it as appropriate. Boss can block on the pipe w/o having to do anything special.
(2) Do more or less the above with some other mechanism. Global ctr and list with accompanying condition variable to wake up boss; a message queue, etc.

How to resuse threads - pthreads c

I am programming using pthreads in C.
I have a parent thread which needs to create 4 child threads with id 0, 1, 2, 3.
When the parent thread gets data, it will set split the data and assign it to 4 seperate context variables - one for each sub-thread.
The sub-threads have to process this data and in the mean time the parent thread should wait on these threads.
Once these sub-threads have done executing, they will set the output in their corresponding context variables and wait(for reuse).
Once the parent thread knows that all these sub-threads have completed this round, it computes the global output and prints it out.
Now it waits for new data(the sub-threads are not killed yet, they are just waiting).
If the parent thread gets more data the above process is repeated - albeit with the already created 4 threads.
If the parent thread receives a kill command (assume a specific kind of data), it indicates to all the sub-threads and they terminate themselves. Now the parent thread can terminate.
I am a Masters research student and I am encountering the need for the above scenario. I know that this can be done using pthread_cond_wait, pthread_Cond_signal. I have written the code but it is just running indefinitely and I cannot figure out why.
My guess is that, the way I have coded it, I have over-complicated the scenario. It will be very helpful to know how this can be implemented. If there is a need, I can post a simplified version of my code to show what I am trying to do(even though I think that my approach is flawed!)...
Can you please give me any insights into how this scenario can be implemented using pthreads?
As far what can be seen from your description, there seems to be nothing wrong with the principle.
What you are trying to implement is a worker pool, I guess, there should be a lot of implementations out there. If the work that your threads are doing is a substantial computation (say at least a CPU second or so) such a scheme is a complete overkill. Mondern implementations of POSIX threads are efficient enough that they support the creation of a lot of threads, really a lot, and the overhead is not prohibitive.
The only thing that would be important if you have your workers communicate through shared variables, mutexes etc (and not via the return value of the thread) is that you start your threads detached, by using the attribute parameter to pthread_create.
Once you have such an implementation for your task, measure. Only then, if your profiler tells you that you spend a substantial amount of time in the pthread routines, start thinking of implementing (or using) a worker pool to recycle your threads.
One producer-consumer thread with 4 threads hanging off it. The thread that wants to queue the four tasks assembles the four context structs containing, as well as all the other data stuff, a function pointer to an 'OnComplete' func. Then it submits all four contexts to the queue, atomically incrementing a a taskCount up to 4 as it does so, and waits on an event/condvar/semaphore.
The four threads get a context from the P-C queue and work away.
When done, the threads call the 'OnComplete' function pointer.
In OnComplete, the threads atomically count down taskCount. If a thread decrements it to zero, is signals the the event/condvar/semaphore and the originating thread runs on, knowing that all the tasks are done.
It's not that difficult to arrange it so that the assembly of the contexts and the synchro waiting is done in a task as well, so allowing the pool to process multiple 'ForkAndWait' operations at once for multiple requesting threads.
I have to add that operations like this are a huge pile easier in an OO language. The latest Java, for example, has a 'ForkAndWait' threadpool class that should do exactly this kind of stuff, but C++, (or even C#, if you're into serfdom), is better than plain C.

Semaphore queues

I'm extending the functionality of a semaphore. I ran into a roadblock when I realized I don't know the implementation of an actual semaphore and to make sure my code ran correctly, I needed to know this.
I know a semaphore works by blocking threads that are waiting on it when they call sem_wait() and another thread currently has it locked. The thread is then blocked and then put into a wait list for that semaphore.
My question relates to what happens on a sem_post(). Is the next thread pulled off the waiting list, set as the locking thread, and allowed to be unblocked? Or is the scheme for posting completely different?
Thanks!
The next thread to unblock on it's sem_wait() will be whatever thread the OS decides is the next one to context switch into. Nobody makes any guarantee of ordering; it depends on your OS's scheduling strategy. It might be the thread that has been off the CPU for the longest, or the one that has been assigned the highest "priority", or the one that has historically had certain resource-usage statistics, or whatever.
Most likely, your current thread (the one that called sem_post()) will continue running for a while, until it either starts waiting for user input, blocks on another semaphore, or runs out of its os-allotted time slice. Then, the OS will switch in some totally unrelated process to run for a fraction of a second (probably Firefox or something), then go off and handle some network traffic, get itself a cup of tea, and, finally, when it gets around to it, pick whichever of your other threads it feels like, based on something like whether it feels based on past history that the particular thread is more CPU or I/O-bound.
In many OSes, priority is given to I/O-bound processes that haven't been around for very long. The theory is that new processes might be short-lived (if it's been around for five hours already, odds are it won't be finishing up in the next 1ms) so we might as well get them over with. I/O-bound processes are likely to continue to be I/O-bound, which means that chances are they are going to switch off the CPU shortly while waiting for other resources. Basically, the OS wants to find the process that it's going to be able to be done with ASAP, so it can get back to sipping its tea and running your malware.
Semaphores have two operations:
P() To acquire the semaphore (you seem to call this sem_wait)
V() To release the semaphore (you seem to call this sem_post)
Semaphores also have an integer associated to them, which is the number of concurrent threads allowed to pass P() without blocking. Other calls to P() will block until V() is called to free up spots.
That is the classic definition of a semaphore.
Edit: Semaphores do not make any guarantee of order. They don't have to actually use a queue or other FIFO structure. When only one thread is allowed at a time, when it calls V(), another (possibly random) thread will then return from its P() call and continue.
According to the IEEE standards, the behavior of POSIX semaphores:
If the semaphore value resulting from this operation is positive, then no threads were blocked waiting for the semaphore to become unlocked; the semaphore value is simply incremented.
If the value of the semaphore resulting from this operation is zero, then one of the threads blocked waiting for the semaphore shall be allowed to return successfully from its call to sem_wait(). If the Process Scheduling option is supported, the thread to be unblocked shall be chosen in a manner appropriate to the scheduling policies and parameters in effect for the blocked threads. In the case of the schedulers SCHED_FIFO and SCHED_RR, the highest priority waiting thread shall be unblocked, and if there is more than one highest priority thread blocked waiting for the semaphore, then the highest priority thread that has been waiting the longest shall be unblocked. If the Process Scheduling option is not defined, the choice of a thread to unblock is unspecified.
If the Process Sporadic Server option is supported, and the scheduling policy is SCHED_SPORADIC, the semantics are as per SCHED_FIFO above."

Resources