C Semaphores synchronization - c

I have 2 programs that need to communicate with each other, the first one must output what the second one puts into the shared memory, but I've removed everything but the semaphores, because there is a problem with synchronization.
This is a school assignment, so I must use semaphores in exactly the way shown below, don't propse anything else because I can't use it.
#include <sys/shm.h>
#include <errno.h>
#include <sys/sem.h>
int main()
{
int semid;
struct sembuf sobs;
semid=semget(9999,1,IPC_CREAT|0600);
semctl(semid, 0, SETVAL,1);
sobs.sem_num=0;
sobs.sem_op= 0;
sobs.sem_flg=0;
semop(semid,&sobs,1);
/* DO SOMETHING */
sobs.sem_op=1;
semop(semid,&sobs,1);
shmctl(shmid1,IPC_RMID,0);
return 0;
}
And the second program:
#include <sys/shm.h>
#include <errno.h>
#include <sys/sem.h>
int main()
{
int semid;
struct sembuf sobs;
semid=semget(9999,1,0600);
sobs.sem_num=0;
sobs.sem_op=-1;
sobs.sem_flg=0;
semop(semid,&sobs,1);
/* DO SOMETHING */
sobs.sem_op=1;
semop(semid,&sobs,1);
shmctl(shmid1,IPC_RMID,0);
return 0;
}
So the problem is that if I put a sleep() above the DO SOMETHING in the second program, the first one will still go into the critical section, and it will finish before the second one, but the first one mustn't go into the critical section before the second one exits it, what can I do to prevent the first one from entering?

Typically program A should set the semaphore to 0 initially using semctl. Then program A calls semop with sobs.sem_op=-1, to wait on the semaphore.
Program B doesn't need to do anything with the semaphore before "do something". (Note that A has to be run first, so that the semaphore is created and setup before B starts.) After B is done it should signal A by calling semop with sobs.sem_op=1.
In short A sets up the semaphore and waits for it before "doing something". B "does something" and then signals the semaphore to wake A.

You're using so-called SysV (System V) semaphores, as opposed to POSIX semaphores. You might want to look up tutorials for that. Your first mistake is the first argument to semget: you aren't supposed to pass it a value that you've defined, you should use ftok(3) instead (if you chose the key yourself collisions are pretty likely: too many people will simply use 1 or 42 as key value).
Next, some explanations on how semaphores work:
A semaphore has a value.
You can increase its value (foo.sem_op > 0). This is a non-blocking operation.
You can decrease its value (foo.sem_op < 0). This may block (which is what it's used for). Explanation below.
You can wait for it to become 0 (foo.sem_op == 0). If the semaphore is already 0 it doesn't block, otherwise it blocks.
When you decrease the semaphore, the following scenarios can happen (simplified):
If decreasing the semaphore would not make it become negative the call does not block.
If decreasing the semaphore by the value in foo.sem_op would make the semaphore negative it will block until the semaphore's value has become large enough so that the decreasing won't make the semaphore negative any more.
You'd like to use the semaphore as a mutex. In this case you only want values of "1". The pattern now usually looks like this:
Initialize the semaphore, set it to 1.
The first worker decreases the semaphore by -1. This immediately succeeds.
The second worker tries to decrease the semaphore by -1. This blocks as it would make the semaphore negative.
The first worker finishes and increases the semaphore.
This wakes up the second worker which now decreases the semaphore.
When the second worker is done it also increases the semaphore.
So we have:
Lock mutex: decrease the semaphore by -1.
Unlock mutex: increase the semaphore by 1.

Related

Only one thread ever acquiring semaphore

I have a program in which multiple threads are in a loop where they acquire a binary semaphore and then increase a global counter. However, by printing out the thread IDs, I notice that only one thread ever acquires the semaphore. Here's my MRE:
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_THREADS 10
#define MAX_COUNTER 100
struct threadCtx {
sem_t sem;
unsigned int counter;
};
static void *
threadFunc(void *args)
{
struct threadCtx *ctx = args;
pthread_t self;
bool done = false;
self = pthread_self();
while (!done) {
sem_wait(&ctx->sem);
if ( ctx->counter == MAX_COUNTER ) {
done = true;
}
else {
sleep(1);
printf("Thread %u increasing the counter to %u\n", (unsigned int)self, ++ctx->counter);
}
sem_post(&ctx->sem);
}
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
struct threadCtx ctx = {.counter = 0};
sem_init(&sem.ctx, 0, 1);
for (int k=0; k<NUM_THREADS; k++) {
pthread_create(threads+k, NULL, threadFunc, &ctx);
}
for (int k=0; k<NUM_THREADS; k++) {
pthread_join(threads[k], NULL);
}
sem_destroy(&ctx.sem);
return 0;
}
The output is
Thread 1004766976 increasing the counter to 1
Thread 1004766976 increasing the counter to 2
Thread 1004766976 increasing the counter to 3
...
If I remove the call to sleep, the behavior is closer to what I would expect (i.e., the threads being woken up in a seemingly indeterminate manner). Why would this be?
David Schwartz's answer explains what is happening at a low level. That is to say, he's looking at it from the perspective of an OS developer or a hardware designer. Nothing wrong with that, but let's look at your program from the perspective of a Software Architect:
You've got multiple threads all executing the same loop. The loop locks the mutex,* it does some "work," and then it releases the mutex. OK, but what does it do next? Almost the very next thing that your loop does after releasing the mutex is it locks the mutex again. Your loop spends practically 100% of its time doing "work" with the mutex locked.
So, what's the point of running that same loop in multiple threads when there's never any opportunity for two or more threads to work at the same time?
If you want to use threads to do a parallel computation, you need to find/invent safe ways for the threads to do most of their work with the mutex unlocked. They should only lock a mutex for just long enough to post a result or, to take another assignment.
Sometimes that means writing code that is less efficient than single threaded code would be. But suppose that program (A) has a single thread that makes almost 100% use of a CPU, while program (B) uses eight CPUs but only uses them with 50% efficiency. Which program is going to win?
* I know, your example uses a sem_t (semaphore) object. But "semaphore" is what you are using. "Mutex" is the role in which you are using it.
Why would this be?
Context switches are expensive and your implementation is, wisely, minimizing them. Your threads are all fighting over the same resource, trying to schedule them closely will make performance much worse, probably for the entire system.
Since the thread that keeps getting the semaphore never uses up its timeslice, it will keep getting the resource. It is your responsibility to write code to do the work that you want done. It's the implementation's responsibility to execute your code as efficiently as it can, and that's what it's doing.
Most likely, what's going under the hood is this:
The thread that keeps getting the sempahore can always make forward progress except when it is sleeping. But when it is sleeping, no other thread that needs the sempahore can make forward progress.
The thread that keeps getting the semaphore never exhausts its timeslice because it sleeps before that happens.
So there is no reason for the implementation to ever block this thread other than when it is sleeping, meaning that no other thread can get the semaphore. If you don't want this thread to keep sleeping with the semaphore and blocking other threads, then write different code.

How to block on a semaphore until its value is positive

I want to use semaphores to make threads block until the semaphores become positive; but when my threads block on a semaphore, they unblock immediately on the first sem_post called on it, regardless of the value of that semaphore afterwards.
The situation is as follows:
Semaphore is set to -1.
A thread is started to wait 5 seconds before posting to the semaphore.
Once 5 seconds pass, the thread posts to the semaphore.
The semaphore's value is 0, but the main process unblocks anyway.
Here is the code demonstrating the situation:
/**
* testing whether sem_post on semaphore unblocks threads
* despite still being negative.
**/
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
sem_t sem;
void *proc(void *arg)
{
sleep(5);
puts("posting");
sem_post(&sem);
}
void setup()
{
pthread_t pt;
pthread_create(&pt, 0, proc, 0);
}
int main(int argc, char **argv)
{
sem_init(&sem, 0, -1);
setup();
sem_wait(&sem);
return 0;
}
I have found a crude way to overcome this issue by wrapping sem_wait in a busy loop that checks if the semaphore's value is 0, but this seems like a wrong way to approach this.
Is there a more elegant way to block on a semaphore until its value is positive (not 0, nor negative)?
You can't initialize the semaphore to -1 because the API to initialize it only takes unsigned values.
int sem_init(sem_t *sem, int pshared, unsigned int value);
The Open Group
Probably, using -1 caused a value larger than SEM_VALUE_MAX to be passed to sem_init(), and the initialization actually failed. You should check the return code, and if errno got set to EINVAL.
The sem_init() function will fail if:
[EINVAL]
The value argument exceeds SEM_VALUE_MAX.
...
The Open Group
If you want threads to block on a semaphore on first call to sem_wait, initialize the semaphore to 0 instead.
If your system supports it, you can use sem_getvalue to find the number of waiters on the semaphore if the count is 0.
If sem is locked, then the value returned by sem_getvalue() is either zero or a negative number whose absolute value represents the number of processes waiting for the semaphore at some unspecified time during the call.
The Open Group
An implementation is allowed to choose which behavior they want, so this only works if your system supports it. Linux, for example, does not support it, since it chooses to return 0 if the semaphore count is 0.
If one or more processes or threads are blocked waiting to lock the
semaphore with sem_wait(3), POSIX.1 permits two possibilities for the
value returned in sval: either 0 is returned; or a negative number
whose absolute value is the count of the number of processes and
threads currently blocked in sem_wait(3). Linux adopts the former
behavior.
man7.org
Probably the most reliable way for you to implement what you want is to use a mutual exclusion variable, a condition variable, and a counter.
extern pthread_mutex_t lock;
extern pthread_cond_t queue;
extern atomic_uint waiters;
/* assume waiters is initially 0 */
pthread_mutex_lock(&lock);
++waiters;
while (my_status() == WAITING) {
pthread_cond_wait(&queue, &lock);
}
--waiters;
pthread_mutex_unlock(&lock);
Try initializing the semaphore with zero or a positive integer value. If you initialize with zero sem_init(&sem, 0, 0); you will see the desired behavior.

Polling a semaphore multiple times simultaneously using posix C

This question requires that two semaphores be used, one as a mutex, and one as a counting semaphore, and that the pair be used to simulate the interaction between students and a teacher's assistant.
I have been able to utilize the binary semaphore easily enough, however I cannot seem to find many examples that show the use of a counting semaphore, so I am quite sure I have it wrong, which is causing my code to not execute properly.
My code is below
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>
#include <time.h>
#include <sys/types.h>
void *taThread();
void *student();
sem_t taMutex;
sem_t semaphore;
int main()
{
pthread_t tid1;
srand(time(NULL));
sem_init(&taMutex,0,1);
sem_init(&semaphore,1,3);
pthread_create(&tid1, NULL, &taThread, NULL);
pthread_join(tid1, NULL);
return 0;
}
void *taThread()
{
pthread_t tid2[10];
int it = 0;
printf("Teacher's Assistant taking a nap.\n");
for (it = 0; it < 10; it ++)
{
pthread_create(&tid2[it], NULL, &student, NULL);
}
for (it = 0; it < 10; it ++)
{
pthread_join(tid2[it], NULL);
}
}
void *student()
{
int xTime;
xTime = rand() % 10 + 1;
if (sem_wait(&taMutex) == 0)
{
printf("Student has awakened TA and is getting help. This will take %d minutes.\n", xTime);
sleep(xTime);
sem_post(&taMutex);
}
else if (sem_wait(&semaphore) > 2 )
{
printf("Student will return at another time.\n");
}
else
{
sem_wait(&semaphore);
printf("Student is working on their assignment until TA becomes available.\n");
sem_wait(&taMutex);
sem_post(&semaphore);
printf("Student is entering the TA's office. This will take %d minutes", xTime);
sleep(xTime);
sem_post(&taMutex);
}
}
My main question is: how can I get the threads to poll the counting semaphore concurrently?
I am trying to get a backup, with some students being forced to leave (or exit the thread) unhelped, with others waiting in the semaphore. Any assistance is appreciated, and any clarifications will be offered.
I'm not sure if your class / teacher wants to make special distinctions here, but fundamentally, a binary semaphore is mostly equivalent to a copunting semaphore initialized to 1,1 so that when you count it down ("P") to zero it becomes "busy" (locked like a mutex) and when you release it ("V") it counts up to its maximum of 1 and it's now "un-busy" (unlocked). A counting semaphore typically starts with a higher initial value, typically for counting some resource (like 3 available chairs in a room), so that when you count it down there may still be some left. When you're done using the counted resource (e.g., when the "student" leaves the "TA's office") you count it back up ("V").
With POSIX semaphores, the call:
sem_init(&semaphore,1,3);
says that this is a process-shared semaphore (2nd argument nonzero), rather than a thread-shared semaphore; you don't seem to need that, and I'm not sure if some systems might give you an error—a failing sem_init call, that is—if &semaphore is not in a process-shared region. You should be able to just use 0, 3. Otherwise, this is fine: it's saying, in effect, that there are three "unoccupied chairs" in the "office".
Other than that, you'll need to either use sem_trywait (as #pilcrow suggested), sem_timedwait, or a signal to interrupt the sem_wait call (e.g., SIGALRM), in order to have some student who tries to get a "seat" in the "office" to discover that he can't get one within some time-period. Just calling sem_wait means "wait until there's an unoccupied chair, even if that takes arbitrarily long". Only two things stop this potentially-infinite wait: either a chair becomes available, or a signal interrupts the call.
(The return value from the various sem_* functions tells you whether you "got" the "chair" you were waiting for. sem_wait waits "forever", sem_trywait waits not-at-all, and sem_timedwait waits until you "get the chair" or the clock runs out, whichever occurs first.)
1The real difference between a true binary semaphore and a counting semaphore is that a binary semaphore doesn't offer you the ability to count. It's either acquired (and an acquire will block), or not-acquired (and an acquire will succeed and block other acquires). Various implementations may consider releasing an already-released binary semaphore a no-op or an error (e.g., runtime panic). POSIX just doesn't offer binary semaphores at all: sem_init initializes a counting semaphore and it's your responsibility to set it to 1, and not over-increment it by releasing when it's already released. See also comments below.

Linux futex syscall spurious wakes with return value 0?

I've run into an issue with the Linux futex syscall (FUTEX_WAIT operation) sometimes returning early seemingly without cause. The documentation specifies certain conditions that may cause it to return early (without a FUTEX_WAKE) but these all involve non-zero return values: EAGAIN if the value at the futex address does not match, ETIMEDOUT for timed waits that timeout, EINTR when interrupted by a (non-restarting) signal, etc. But I'm seeing a return value of 0. What, other than FUTEX_WAKE or the termination of a thread whose set_tid_address pointer points to the futex, could cause FUTEX_WAIT to return with a return value of 0?
In case it's useful, the particular futex I was waiting on is the thread tid address (set by the clone syscall with CLONE_CHILD_CLEARTID), and the thread had not terminated. My (apparently incorrect) assumption that the FUTEX_WAIT operation returning 0 could only happen when the thread terminated lead to serious errors in program logic, which I've since fixed by looping and retrying even if it returns 0, but now I'm curious as to why it happened.
Here is a minimal test case:
#define _GNU_SOURCE
#include <sched.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <linux/futex.h>
#include <signal.h>
static char stack[32768];
static int tid;
static int foo(void *p)
{
syscall(SYS_getpid);
syscall(SYS_getpid);
syscall(SYS_exit, 0);
}
int main()
{
int pid = getpid();
for (;;) {
int x = clone(foo, stack+sizeof stack,
CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND
|CLONE_THREAD|CLONE_SYSVSEM //|CLONE_SETTLS
|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID
|CLONE_DETACHED,
0, &tid, 0, &tid);
syscall(SYS_futex, &tid, FUTEX_WAIT, x, 0);
/* Should fail... */
syscall(SYS_tgkill, pid, tid, SIGKILL);
}
}
Let it run for a while, at it should eventually terminate with Killed (SIGKILL), which is only possible if the thread still exists when the FUTEX_WAIT returns.
Before anyone goes assuming this is just the kernel waking the futex before it finishes destroying the thread (which might in fact be happening in my minimal test case here), please note that in my original code, I actually observed userspace code running in the thread well after FUTEX_WAIT returned.
Could you be dealing with a race condition between whether the parent or child operations complete first? You can probably investigate this theory by putting small sleeps at the beginning of your foo() or immediately after the clone() to determine if a forced sequencing of events masks the issue. I don't recommend fixing anything in that manner, but it could be helpful to investigate. Maybe the futex isn't ready to be waited upon until the child gets further through its initialization, but the parent's clone has enough to return to the caller?
Specifically, the CLONE_VFORK option's presence seems to imply this is a dangerous scenario. You may need a bi-directional signaling mechanism such that the child signals the parent that it has gotten far enough that it is safe to wait for the child.

How do I terminate a thread that is waiting for a semaphore operation

I am writing a program that uses shared memory and semaphores for ipc. There is one main server process that creates the shared memory and semaphores. Any number of client processes can attach to the shared memory and read and write to it when allowed. The semaphores provide the blocking mechanism to control reads and writes. Everything works fine except when a I try to terminate a client. The semaphore block to access the shared memory is in a thread and on process termination I have no way to release the semaphore block so the thread exits correctly. How would I go about this? This is for Linux.
To be specific, there is one shm and two sems. The first sem blocks writing, and the second blocks reading. When a client has something to write, it waits for the write sem to be 0, then sets it to 1, writes, then sets the read sem to 0 which releases the waiting server to read what the client wrote. once read the server sets the write sem back to 0 and the next client in line gets to write. It hangs on a semop call which releases when read sem is 0. This semop call is in a thread and I need to figure out how to exit that thread correctly before letting the main thread terminate.
Here is an example of what i want to do but isn't working (the sleep is pretending to be the hanging semop call):
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void termination_handler (int signum) {
printf( "Got Signal\n" );
}
void *threadfunc( void *parm ) {
struct sigaction action;
action.sa_handler = termination_handler;
sigemptyset( &action.sa_mask );
action.sa_flags = 0;
sigaction( SIGUSR1, &action, NULL );
printf("Thread executing\n");
sleep( 100 ); // pretending to be the semaphore
pthread_exit( NULL );
}
int main() {
int status;
pthread_t threadid;
int thread_stat;
status = pthread_create( &threadid, NULL, threadfunc, NULL );
if ( status < 0) {
perror("pthread_create failed");
exit(1);
}
sleep( 5 );
status = pthread_kill( threadid, SIGUSR1 );
if ( status < 0 )
perror("pthread_kill failed");
status = pthread_join( threadid, (void *)&thread_stat );
if ( status < 0 )
perror("pthread_join failed");
exit( 0 );
}
He said, this is for Linux.
It would be useful if you could say exactly how are you doing it. I assume you are blocking in sem_wait or sem_timedwait. If your thread is blocking there and you want to interrupt it, you can use pthread_kill.
pthread_kill(blocking_thread_id, SIGUSR1);
Of course, you need to setup the proper signal handler (man sigaction) to catch SIGUSR1 and you need to check the return code of sem_wait() for EINTR, in which case you can do whatever you want to do knowing that you were interrupted and did not get the lock.
In the case you are using processes you would use simply kill() and not pthread_kill() providing the process id. (sorry, initially I misread and thought you were using threads)
I have two and a half answers for you. :)
First, your example code works for me (on Linux): the pthread_kill successfully EINTRupts the worker thread's sleep as expected after about five seconds, as revealed with a few printfs and remembering the return value of sleep. AFAICT, if you want to signal-interrupt a specific thread, you've done it.
Second, try SEM_UNDO. This flag may be set in the sem_flg member passed in the sembuf argument semop, and it will, as the name suggests, undo semaphore adjustments upon process termination. IIUC, when you kill a client, that client leaves a semaphore inappropriately locked. SEM_UNDO was made for just this circumstance.
Finally and respectfully, have you perhaps inverted the logic of semaphores here? As I read your question, a semval of zero indicates "resource free" and a semval of one is "resource locked" (quote: "...[a client] waits for the write sem to be 0, then sets it to 1, writes..."). However, if two or more writing clients are waiting for a SysV sem to drop to zero, they will all be released together when that occurs. That's rather an unpleasant race condition, which might at the least result in unanticipated semaphore decrements and increments.
Depending on your environment perhaps you could only try to take the semaphore with a timeout. After each timeout check if a close thread has been requested and simply give up and shutdown.
It may not be the best idea to use blocking mutexes/semaphores if operations on protected area may last too long for your purposes.
You can solve the issue by putting read and write requests to a queue (linked list, for example) and let the first in the queue to operate on protected area and remove it from the list once it enters the area.
In case of read-only op you may access other reads enter the protected area as well as long as the first operation is read only. When the first operation is write, protected area must be empty before allowing it to access.
List modifications must be protected by mutex (or something alike) but that is near constant time and you probably can pay that.
When threads are sitting in a queue, each has its private condition variable which you can use to wake up any of them. Condition variable must be protected by mutex too. You may store condition variable, mutex etc into a structure and put the into an array or list and store thread id with each so that it will be easy to find the thread you want to wake up.
Once thread wakes up, it first checks what was the reason it had to wake up. If exit flag is set, then the thread know to exit.

Resources