Stop thread only if n threads are running including itself - c

I am requested to create some threads in a process(48), but thread number 14 must can stop only if 6 threads are running including itself. However they enter an infinite loop.
Here is the function my threads from the process should execute:
pthread_mutex_lock_t lock;
pthread_mutex_cond_t cond;
reached_6_threads = false;
void *thread_function_P6(void *args)
{
th *t = (th *)args;
printf("started thread %d", t->id);
if (t->id != 14)
{
pthread_mutex_lock(&lock);
while (th_no > 6)
{
pthread_cond_wait(&cond, &lock);
}
if(!reached_6_threads && th_no==6){
pthread_cond_wait(&cond, &lock);
th_no--;
reached_6_threads = true;
}
th_no++;
if (!reached_6_threads && th_no == 6)
{
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&lock);
}
}
printf("threads running: %d\n", th_no);
printf("stopped thread %d", t->id);
pthread_exit(0);
}
lock and cond are initrialized before creating the threads.

I am not sure I understand you, but note in your code that:
a) Most of the code is under mutex lock, which means they can't really run in parallel
b) Thread 14 runs regardless of the number of running threads
Anyway, the reason it gets stuck is:
a) Your threads are running almost sequentially
b) Threads 1-5 skip while and both ifs, th_no is now 5 (assuming it was initialized to 0?)
c) Thread 6 raises th_no to 6 and enters second if, performing broadcast but there are no threads stuck on that condition lock
d) Threads 7 and above enter first if and wait on a condition lock that will never break
I would suggest the following solution. Since I haven't understood you completely, in this example only 6 threads are allowed to run regardless of their id and you'll have to make only some minor changes.
pthread_mutex_lock(&lock);
while(th_no >= 6){pthread_cond_wait(&cond, &lock);}
th_no++;
pthread_mutex_unlock(&lock); //Raise counter and unlock the mutex
/*
Thread function code here. Pay attention to critical code and use mutex.
*/
pthread_mutex_lock(&lock); //Acquire lock once again, decrease counter and broadcast if number of threads is ok now
th_no--;
if(th_no <= 5){
if(pthread_cond_broadcast(&cond)){
// Error as it should return 0 on success
}
}
pthread_mutex_lock(&unlock);
Let me know if this helps

Related

Unique semaphore for each thread

I have been assigned a modified version of the "Santa Claus" semaphore problem.
Santa Claus is a thread that randomly wakes up to check how many and what kind of threads are waiting to report to him (Work elves and Collecting elves)
What I have made are work elf and collecting elf threads:
void *collectingElf(void *arg, int semaphoreIndex) {
while (1) {
sem_wait(&elveCountMutex); //semaphore for critical section, the number of elves
printf("\nCollecting! %d\n", (int) pthread_self()); // thread is collecting stuff
sleep((unsigned int) (rand() % 4)); // thread sleeps for a random amount of time
printf("Done collecting! %d\n", (int) pthread_self()); // Print process ID, just for easier tracking
sem_post(&elveCountMutex); // Release the elve count semaphore
sem_wait(&collectingElveSem);
}
}
void *workingElf(void *arg) //same as collecting elf
{
while (1) {
sem_wait(&elveCountMutex);
printf("\nWorking! %d\n", pthread_self());
sleep(1);
workingElveCount++;
printf("Done working! %d\n", pthread_self());
sem_wait(&workElfSem);
sem_post(&elveCountMutex);
}
}
So here the elve counts are protected, since the threads can only access the counters when elveCountMutex is locked. This I can understand and this seems logical. Afterwards the thread should block and wait for Santa to unblock it.
So, from what I read, once semaphore reaches value 0, thread will block. Anything above 0 will not block it, and negative value indicates how many threads are waiting for the semaphore to be unlocked.
So, once the threads running are finished, they decrement the semaphore, and block.
However, what I cannot seem to grasp is this part of the assignment:
For a collecting meeting to start, at least one work elf and three collecting elves are necessary. • If enough elves are present that both meetings could start, the collecting-meeting
always has priority, and all work-elves not needed anymore resume their work.
Say if I have 3 work elves, and I need only 1, how do I release the remaining 2 threads? Do I need a separate semaphore for each thread? Or am I missing something?
Edit: My bad, I completely forgot to tell about the Santa implementation.
Santa wakes up and releases the semaphores, in this way:
void* Santa(void *arg)
{
while (1) {
sleep((unsigned)rand() % 4); //Santa sleeps randomly between 0 and 3 seconds;
sem_wait(&elveCountMutex); //access both elf counters
if(workingElveCount>=2 && collectingElveCount >= 3) //decide which meeting should commence
{
int releaseWorkElveCount = workingElveCount-1;
for(int i = 0;i<releaseWorkElveCount;i++)
{
sem_post(&workElfSem);
}
sleep(5);
collectingMeeting(&collectingMeetingThread); //This just prints that we are in a collecting meeting
pthread_join(collectingMeetingThread,0);
sem_wait(&elveCountMutex);
for(int i=0;i<workingElveCount;i++)
{
sem_post(&workElfSem);
}
for(int i=0;i<collectingElveCount;i++)
{
sem_post(&collectingElveSem);
}
workingElveCount=0;
collectingElveCount=0;
}
}
I do not understand your management of semaphore
In
void *collectingElf(void *arg, int semaphoreIndex) {
while (1) {
...
sem_wait(&collectingElveSem);
}
}
that gets but never releases collectingElveSem, and that in an infinite loop ?
In
void *workingElf(void *arg) //same as collecting elf
{
while (1) {
sem_wait(&elveCountMutex);
...
sem_wait(&workElfSem);
}
}
that get but never release elveCountMutex and workElfSem, and that in an infinite loop. collectingElf also (try to) get elveCountMutex but I will not able to do after one turn in workingElf
If your semaphore are not recursive workingElf will also be blocked after one turn because not able to get again the semaphores. If the semaphore are recursive this cannot be for an infinite deep and workingElf will block itself after enough loops

Pthread synchronization - print even odd numbers

I am new to pthreads. I am trying to print even and odd numbers from two threads. What is wrong with below code? Its intention is to create two threads - one will print odd numbers and other will print even numbers. The numbers have to be printed in order. It seems to get stuck (time limit exceeded in ideone).. I have spent a lot of time staring at it. Just can't figure out what is wrong..
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t lock;
int n = 0;
int max = 10;
pthread_cond_t even;
pthread_cond_t odd;
void* print_odd(void *x)
{
while(1)
{
pthread_mutex_lock(&lock);
while(n%2 != 0)
{
pthread_cond_wait(&even, &lock);
}
if(n >= max)
{
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
printf("Thread A : %d", ++n);
pthread_cond_signal(&odd);
pthread_mutex_unlock(&lock);
}
}
void* print_even(void *x)
{
while(1)
{
pthread_mutex_lock(&lock);
while(n%2 == 0)
{
pthread_cond_wait(&odd, &lock);
}
if(n >= max)
{
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
printf("Thread B : %d", ++n);
pthread_cond_signal(&even);
pthread_mutex_unlock(&lock);
}
}
main()
{
pthread_t t1, t2;
pthread_create(&t1, NULL, print_odd, NULL);
pthread_create(&t2, NULL, print_even, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
exit(0);
}
There are multiple issues with your program-
As suggested in the comments, the lock and the conditional variables need to be initialized.
pthread_mutex_t lock = PTHREAD_LOCK_INITIALIZER;
pthread_cond_t even = PTHREAD_COND_INITIALIZER;
pthread_cond_t odd = PTHREAD_COND_INITIALIZER;
You might get lucky accidentally here even without initialization since you've declared them as global and they will be zero-inited and pthread implementations might actually be zero-initing when you properly initialize them.
Your printf doesn't have \n and hence output is not flushed to screen. Just add the newline and you'll see your threads are indeed running.
When n reaches 10, ie when print_odd threads increments from 9, it simply exits without signaling the even thread. Hence your even thread is hung in the cond_wait and your main thread is hung in pthread_join. You can fix this by waking up the even thread by signalling it before exiting the odd thread.
EDIT I found one more issue
Even if the odd thread signals the even thread just before exiting, since n=10, the even thread does NOT exit the while(n%2 == 0) loop and goes back to sleep again. This time, there's no one to wake up the poor soul. It is for this reason that you need to test the termination condition n>=max inside the while loop
pthread_cond_wait is blocking the calling threads. In your case, you have asked the threads to wait on the true conditions of odd and even. Instead, they should wait on the incorrect conditions.
While i%2 == 0, the odd thread should call the wait function inside of the routine.
While i!=2, the even thread should call wait function.

unexpected behavior when using conditional variables (c, gcc)

I am trying to learn how to use conditional variables properly in C.
As an exercise for myself I am trying to make a small program with 2 threads that print "Ping" followed by "Pong" in an endless loop.
I have written a small program:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* T1(){
printf("thread 1 started\n");
while(1)
{
pthread_mutex_lock(&lock);
sleep(0.5);
printf("ping\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
pthread_cond_wait(&cond,&lock);
}
}
void* T2(){
printf("thread 2 started\n");
while(1)
{
pthread_cond_wait(&cond,&lock);
pthread_mutex_lock(&lock);
sleep(0.5);
printf("pong\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
int main(void)
{
int i = 1;
pthread_t t1;
pthread_t t2;
printf("main\n");
pthread_create(&t1,NULL,&T1,NULL);
pthread_create(&t2,NULL,&T2,NULL);
while(1){
sleep(1);
i++;
}
return EXIT_SUCCESS;
}
And when running this program the output I get is:
main
thread 1 started
thread 2 started
ping
Any idea what is the reason the program does not execute as expected?
Thanks in advance.
sleep takes an integer, not a floating point. Not sure what sleep(0) does on your system, but it might be one of your problems.
You need to hold the mutex while calling pthread_cond_wait.
Naked condition variables (that is condition variables that don't indicate that there is a condition to read somewhere else) are almost always wrong. A condition variable indicates that something we are waiting for might be ready to be consumed, they are not for signalling (not because it's illegal, but because it's pretty hard to get them right for pure signalling). So in general a condition will look like this:
/* consumer here */
pthread_mutex_lock(&something_mutex);
while (something == 0) {
pthread_cond_wait(&something_cond, &something_mutex);
}
consume(something);
pthread_mutex_unlock(&something_mutex);
/* ... */
/* producer here. */
pthread_mutex_lock(&something_mutex);
something = 4711;
pthread_cond_signal(&something_cond, &something_mutex);
pthread_mutex_unlock(&something_mutex);
It's a bad idea to sleep while holding locks.
T1 and T2 are not valid functions to use as functions to pthread_create they are supposed to take arguments. Do it right.
You are racing yourself in each thread between cond_signal and cond_wait, so it's not implausible that each thread might just signal itself all the time. (correctly holding the mutex in the calls to pthread_cond_wait may help here, or it may not, that's why I said that getting naked condition variables right is hard, because it is).
First of all you should never use sleep() to synchronize threads (use nanosleep() if you need to reduce output speed). You may need (it's a common use) a shared variable ready to let each thread know that he can print the message. Before you make a pthread_cond_wait() you must acquire the lock because the pthread_cond_wait() function shall block on a condition variable. It shall be called with mutex locked by the calling thread or undefined behavior results.
Steps are:
Acquire the lock
Use wait in a while with a shared variable in guard[*]
Do stuffs
Change the value of shared variable for synchronize (if you've one) and signal/broadcast that you finished to work
Release the lock
Steps 4 and 5 can be reversed.
[*]You use pthread_cond_wait() to release the mutex and block the thread on the condition variable and when using condition variables there is always a Boolean predicate involving shared variables associated with each condition wait that is true if the thread should proceed because spurious wakeups may occur. watch more here
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ready = 0;
void* T1(){
printf("thread 1 started\n");
while(1)
{
pthread_mutex_lock(&lock);
while(ready == 1){
pthread_cond_wait(&cond,&lock);
}
printf("ping\n");
ready = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
void* T2(){
printf("thread 2 started\n");
while(1)
{
pthread_mutex_lock(&lock);
while(ready == 0){
pthread_cond_wait(&cond,&lock);
}
printf("pong\n");
ready = 0;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
int main(void)
{
int i = 1;
pthread_t t1;
pthread_t t2;
printf("main\n");
pthread_create(&t1,NULL,&T1,NULL);
pthread_create(&t2,NULL,&T2,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return EXIT_SUCCESS;
}
You should also use pthread_join() in main instead of a while(1)

Explanation why conditional variable in C does not work correctly

I want to write a simple multithreaded program making use of conditional variables in C.
I want to have main thread (thread A) which sleeps 5 sec and then wake up waiting clients (therads B, possible many) that print a message. This should be repeated all the time.
I have already read the manual but I don't understand why this does not work.
Let's assume that I have those variables given to all threads via pointers (properly, I have checked that):
pthread_mutex_t* mutex;
pthread_cond_t* cond;
int* variable;
I have the following code:
THREAD A (sleeping):
while(1)
{
lockMutex(mutex);
(*variable) = 1;
pthread_cond_broadcast(cond);
unlockMutex(mutex);
sleep(5);
lockMutex(mutex);
(*variable) = 0;
pthread_cond_broadcast(cond);
unlockMutex(mutex);
}
THREAD B (printing):
while(1)
{
lockMutex(mutex);
while((*variable) == 1)
pthread_cond_wait(cond, mutex);
unlockMutex(mutex);
fprintf("Active thread! Number: %d\n", id);
lockMutex(mutex);
while((*(variable))==0)
pthread_cond_wait(cond, mutex);
unlockMutex(mutex);
}
I don't have deadlock, but unfortunatelly this doesn't work as I expected. Can somebody give me an explanation what should I do? I would be grateful for any help.
The likely problem is that Thread A is immediately setting *variable = 1 before any of the sleeping threads have a chance to see it as 0. Just because the condition variable will wake up waiting threads doesn't mean those woken threads will get scheduled fast enough to prevent Thread A from writing to *variable again.

PThread Mutex Not Working as Hoped

I'm using mutexes to try to restrict access to certain part of the codes to one thread, but instead of locking once and blocking the others, it seems to allow all threads to "lock". Following is my code, and then a section of the output showing that the code is not working.
//headers defined, etc
pthread_mutex_t queuemutex = PTHREAD_MUTEX_INITIALIZER;
// other code with various functions
int main(void) {
//unrelated code
threadinformation **threadArray = (threadinformation **)malloc( POOLSIZE * sizeof(threadinformation) );
int k;
for (k = 0; k < POOLSIZE; k++) {
pthread_t thread;
threadinformation *currentThread = (threadinformation *)malloc(sizeof(threadinformation));
currentThread->state = (int *)malloc(sizeof(int));
currentThread->state[0] = 0;
currentThread->currentWaiting = currentWaiting;
currentThread->number = k;
threadArray[k] = currentThread;
pthread_create(&thread, NULL, readWriteToClient, threadArray[k]); //thread is created here
currentThread->thread = thread;
joinArray[k] = thread;
}
//unrelated code
}
static void* readWriteToClient(void *inputcontent) {
while(1){
//unrelated code
pthread_mutex_lock(&queuemutex); //problem happens here
fprintf(stderr,"Thread %d got locked \n",threadInput->number);
while((threadInput->currentWaiting->status) == 0){
pthread_cond_wait(&cond, &queuemutex);
fprintf(stderr,"Thread %d got signalled \n",threadInput->number);
}
connfd = threadInput->currentWaiting->fd;
threadInput->currentWaiting->status = 0;
pthread_cond_signal(&conncond);
pthread_mutex_unlock(&queuemutex);
//unrelated code
}
}
Output.
Thread 0 got locked
Thread 7 got locked
Thread 25 got locked
Thread 97 got locked
Thread 6 got locked
Thread 5 got locked
Thread 4 got locked
Thread 3 got locked
Thread 8 got locked
Thread 9 got locked
Thread 10 got locked
Thread 11 got locked
Thread 12 got locked
Thread 13 got locked
Thread 14 got locked
Thread 15 got locked
Thread 16 got locked
Thread 17 got locked
Thread 18 got locked
Thread 19 got locked
Thread 20 got locked
And so on...
There is no problem.
pthread_cond_wait(&cond, &queuemutex);
waiting on a condition variable RELEASES the mutex.
The longer version of what fceller said is that, pthread_cond_wait(&cond, &mutex) does three things before it returns: It releases the lock, and then it waits for a signal, and then it waits (if necessary) to re-acquire the lock.
Your example does not show what (if anything) ever sends the first signal, and it does not show what (if anything) ever sets the status that the worker threads are waiting for.
Here is a more typical use-case for pthread_cond_wait() and pthread_cond_signal().
void producer() {
pthread_mutex_lock(&mutex);
push_something_on_the_queue();
ptherad_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void consumer() {
pthread_mutex_lock(&mutex);
while (! time_to_quit) {
if (queue_is_empty) {
pthread_cond_wait(&cond, &mutex);
} else {
thing = take_something_from_the_queue();
pthread_mutex_unlock(&mutex);
do_something_with(thing);
pthread_mutex_lock(&mutex);
}
}
pthread_mutex_unlock(&mutex);
}
A producer thread puts things in a queue. A consumer thread waits for things to appear in the queue, and then it pops them off and does something with them. The consumer waits in a loop, and it checks the status of the queue each time it wakes up (A thread may be "falsely" signalled even when there is nothing in the queue).
The mutex is locked when the consumer is checking the queue, and it remains locked until the consumer either sleeps or pops a thing off the queue. The mutex is not locked while the consumer is sleeping, and it is not locked while the consumer is doing whatever it does with a thing.
Any number of consumers can be in the consumer() method at the same time. They may be operating on different things, or they may be sleeping; but the mutex is insures that no more than one thread (producer or consumer) can touch the queue at any given time.

Resources