I'm implementing the Dining Philosophers problem in c using pthreads.
Each philosopher is represented by a thread.
Each thread needs to be able to execute four different functions.
I'm aware that I can set a thread to execute a function with:
pthread_create(&tid, &atr, func1, NULL);
That's fine, but how do I make the thread execute a different function later on (i.e. func2).
Is there a way to change the function that a thread is executing or am I off the ball entirely?
Thanks
Here's a possibility, demonstrated with a single thread (aside from the main thread).
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int to_run = 0;
void func0() {
to_run = -1;
while (to_run == -1) putchar('-');
}
void func1() {
to_run = -1;
while (to_run == -1) putchar('*');
}
void *func(void *data) {
while (1) {
switch (to_run) {
case 0:
func0();
break;
case 1:
func1();
break;
case 2:
printf("\nDONE\n");
return NULL;
}
}
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, func, NULL);
int i;
for (i=0; i<3; i++) {
sleep(1);
to_run = 1;
sleep(1);
to_run = 0;
}
to_run = 2;
pthread_join(tid, NULL);
return 0;
}
You shouldn't need to change the function the thread is running. You should represent each philosopher with a thread (as you said) and each fork with a mutex.
The philosopher threads will simply run a loop of 2 functions think then eat.
think is just a call to sleep.
eat will try to acquire the 2 mutexes that represent his adjacent forks. The philosopher thread will be blocked waiting for the mutexes to unlock. once they unlock then he can lock them himself (pickup_forks) and wait a short period of time (sleep) then unlock them (return_forks).
There is more to it than that, but it should get you past your current problem.
If your program freezes on a mutex lock. Its a deadlock and you may have to revise your algorithm to stop the deadlock.
Related
Here is my code. The sum part is not working. I need some controls for that but I couldn't do it.
I tried make number variable number=-1, but that also didn't work and I had an infinite loop.
By the way this is my first question that i ask here, so i can make mistakes. Sorry for that.
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdbool.h>
int number = 0, sum = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *threadFunction1()
{
pthread_mutex_lock(&mutex);
while (true)
{
printf("Number:");
scanf("%d", &number);
if (number == 0) break;
}
pthread_exit(NULL);
}
void *threadFunction2()
{
pthread_mutex_lock(&mutex);
while (true)
{
sum += number;
printf("Sum is:%d\n", sum);
if (number == 0) break;
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main()
{
pthread_t thread1, thread2;
int case1, case2;
case1 = pthread_create(&thread1, NULL, threadFunction1, NULL);
case2 = pthread_create(&thread2, NULL, threadFunction2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("It's over..\n");
pthread_mutex_destroy(&mutex);
return 0;
}
Here is the output
An immediately obvious issue is that threadFunction1 locks the mutex
pthread_mutex_lock(&mutex);
while (true)
{
printf("Number:");
scanf("%d", &number);
if (number == 0) break;
}
pthread_exit(NULL);
but never unlocks it. It is impossible to share a resource when one thread takes complete control over it.
The next issue is that the locking and unlocking of the mutex occurs outside of the while loop.
pthread_mutex_lock(&mutex);
while (true)
{
sum += number;
printf("Sum is:%d\n", sum);
if (number == 0) break;
}
pthread_mutex_unlock(&mutex);
This means whichever thread gets CPU time first will lock the mutex, and enter a potentially long running loop, only unlocking the mutex when that loop ends:
If threadFunction1 is the first to lock the mutex, this loop lasts until the user enters 0, wherein the loop is broken and the thread is terminated. After this, threadFunction2 never gets a turn, due to the lack of an unlock.
If threadFunction2 is the first to lock the mutex, this loop is broken after during its first iteration, as number is initialized to 0. After this the thread is terminated, and threadFunction1 would get a turn, since the mutex is unlocked.
The final issue is that a single mutex alone is not the correct tool to use here.
Even moving the locks and unlocks inside the loop, so that each thread has a chance to lock the mutex, do some work, and then unlock, there is no guarantee that both threads will get equal access to the lock.
while (true)
{
pthread_mutex_lock(&mutex);
sum += number;
printf("Sum is:%d\n", sum);
pthread_mutex_unlock(&mutex);
if (number == 0) break;
}
In fact, the opposite will probably occur. By default, it is very likely for one thread to be granted some CPU time, lock the mutex, do some work, unlock the mutex, and with its remaining time immediately lock the mutex again.
So we need a way to make two threads evenly share a resource.
One way is, instead of using a mutex, to use two semaphores to create a lockstep. This means one thread waits to for a semaphore which the other thread posts, and vice versa.
Note that in main we start the to_read semaphore with a value of 1, meaning the scanning thread effectively "goes first".
#include <pthread.h>
#include <semaphore.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
static int number = 0;
static int sum = 0;
static sem_t to_read;
static sem_t to_write;
static void *scanning(void *arg) {
while (true) {
sem_wait(&to_read);
printf("Enter a number: ");
if (1 != scanf("%d", &number))
number = 0;
sem_post(&to_write);
if (number == 0)
break;
}
return NULL;
}
static void *adding(void *arg) {
while (true) {
sem_wait(&to_write);
sum += number;
printf("Sum is: %d\n", sum);
sem_post(&to_read);
if (number == 0)
break;
}
return NULL;
}
int main(void) {
pthread_t thread1, thread2;
sem_init(&to_read, 0, 1);
sem_init(&to_write, 0, 0);
pthread_create(&thread1, NULL, scanning, NULL);
pthread_create(&thread2, NULL, adding, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
puts("It's over...");
sem_destroy(&to_read);
sem_destroy(&to_write);
}
Note that this will surely perform worse than a single threaded loop in main, doing the same amount of work, due to the overhead of context switching. That said, it is just a toy example.
I am working with multi-threading in Linux using Pthread.
Thread1 waits for an IRQ from Driver by polling a character device file (my driver has ISR to catch IRQ from HW).
IRQ -----> Thread1 |-----> Thread2
|-----> Thread3
|-----> Thread4
Whenever Thread1 gets an IRQ, I want send a signal to Thread2, Thread3 and Thread4 to wake them up and then work.
Now, I am trying to use "pthread conditional variable" and "pthread mutex". But it seems that is not good approach.
What is efficient way for synchronization in this case? Please help.
Thank you very much.
As I understand it, your problem is that your child threads (Threads 2 through 4) don't always wake up exactly once for every IRQ that Thread1 receives -- in particular, it might be that an IRQ is received while the child threads are already awake and working on an earlier IRQ, and that causes them not to be awoken for the new IRQ.
If that's correct, then I think a simple solution is to use a counting semaphore for each child-thread, rather than a condition variable. A semaphore is a simple data structure that maintains an integer counter, and supplies two operations, wait/P and signal/V. wait/P decrements the counter, and if the counter's new value is negative, it blocks until the counter has become non-negative again. signal/V increments the counter, and in the case where the counter was negative before the increment, awakens a waiting thread (if one was blocked inside wait/P).
The effect of this is that in the case where your main thread gets multiple IRQs in quick succession, the semaphore will "remember" the multiple signal/V calls (as a positive integer value of the counter), and allow the worker-thread to call wait/P that-many times in the future without blocking. That way no signals are ever "forgotten".
Linux supplies a semaphore API (via sem_init(), etc), but it's designed for inter-process synchronization and is therefore a little bit heavy-weight for synchronizing threads within a single process. Fortunately, it's easy to implement your own semaphore using a pthreads mutex and condition-variable, as shown below.
Note that in this toy example, the main() thread is playing the part of Thread1, and it will pretend to have received an IRQ every time you press return in the terminal window. The child threads are playing the part of Threads2-4, and they will pretend to do one second's worth of "work" every time Thread1 signals them. In particular note that if you press return multiple times in quick succession, the child threads will always do that many "work units", even though they can only perform one work-unit per second.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
struct example_semaphore
{
pthread_cond_t cond;
pthread_mutex_t mutex;
int count; // acccess to this is serialized by locking (mutex)
};
// Initializes the example_semaphore (to be called at startup)
void Init_example_semaphore(struct example_semaphore * s)
{
s->count = 0;
pthread_mutex_init(&s->mutex, NULL);
pthread_cond_init(&s->cond, NULL);
}
// V: Increments the example_semaphore's count by 1. If the pre-increment
// value was negative, wakes a process that was waiting on the
// example_semaphore
void Signal_example_semaphore(struct example_semaphore * s)
{
pthread_mutex_lock(&s->mutex);
if (s->count++ < 0) pthread_cond_signal(&s->cond);
pthread_mutex_unlock(&s->mutex);
}
// P: Decrements the example_semaphore's count by 1. If the new value of the
// example_semaphore is negative, blocks the caller until another thread calls
// Signal_example_semaphore()
void Wait_example_semaphore(struct example_semaphore * s)
{
pthread_mutex_lock(&s->mutex);
while(--s->count < 0)
{
pthread_cond_wait(&s->cond, &s->mutex);
if (s->count >= 0) break;
}
pthread_mutex_unlock(&s->mutex);
}
// This is the function that the worker-threads run
void * WorkerThreadFunc(void * arg)
{
int workUnit = 0;
struct example_semaphore * my_semaphore = (struct example_semaphore *) arg;
while(1)
{
Wait_example_semaphore(my_semaphore); // wait here until it's time to work
printf("Thread %p: just woke up and is working on work-unit #%i...\n", my_semaphore, workUnit++);
sleep(1); // actual work would happen here in a real program
}
}
static const int NUM_THREADS = 3;
int main(int argc, char ** argv)
{
struct example_semaphore semaphores[NUM_THREADS];
pthread_t worker_threads[NUM_THREADS];
// Setup semaphores and spawn worker threads
int i = 0;
for (i=0; i<NUM_THREADS; i++)
{
Init_example_semaphore(&semaphores[i]);
pthread_create(&worker_threads[i], NULL, WorkerThreadFunc, &semaphores[i]);
}
// Now we'll pretend to be receiving IRQs. We'll pretent to
// get one IRQ each time you press return.
while(1)
{
char buf[128];
fgets(buf, sizeof(buf), stdin);
printf("Main thread got IRQ, signalling child threads now!\n");
for (i=0; i<NUM_THREADS; i++) Signal_example_semaphore(&semaphores[i]);
}
}
I like jeremy's answer, but it does have some lacking in that the interrupt dispatcher needs to know how many semaphores to increment on each interrupt.
Also each increment is potentially a kernel call, so you have a lot of kernel calls for each interrupt.
An alternate is to understand how pthread_cond_broadcast() works. I have put an example below:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#ifndef NTHREAD
#define NTHREAD 5
#endif
pthread_mutex_t Lock;
pthread_cond_t CV;
int GlobalCount;
int Done;
#define X(y) do { if (y == -1) abort(); } while (0)
void *handler(void *x) {
unsigned icount;
X(pthread_mutex_lock(&Lock));
icount = 0;
while (!Done) {
if (icount < GlobalCount) {
X(pthread_mutex_unlock(&Lock));
icount++;
X(pthread_mutex_lock(&Lock));
} else {
X(pthread_cond_wait(&CV, &Lock));
}
}
X(pthread_mutex_unlock(&Lock));
return NULL;
}
int
main()
{
X(pthread_mutex_init(&Lock, NULL));
X(pthread_cond_init(&CV, NULL));
pthread_t id[NTHREAD];
int i;
for (i = 0; i < NTHREAD; i++) {
X(pthread_create(id+i, NULL, handler, NULL));
}
int c;
while ((c = getchar()) != EOF) {
X(pthread_mutex_lock(&Lock));
GlobalCount++;
X(pthread_mutex_unlock(&Lock));
X(pthread_cond_broadcast(&CV));
}
X(pthread_mutex_lock(&Lock));
Done = 1;
X(pthread_cond_broadcast(&CV));
X(pthread_mutex_unlock(&Lock));
for (i = 0; i < NTHREAD; i++) {
X(pthread_join(id[i], NULL));
}
return 0;
}
I'm really struggling with understanding how to lock and unlock mutexes in a way that lets threads run at the same time. Right now I'm trying to have every thread do something, then wait until all threads are ready, and then repeat it. This should happen repeatedly, so I have it all in a conditioned loop. My problem is, it seems like my broadcast is never received by any threads, as every thread that waits for the signal waits forever, while the thread that sent the signal continues.
I've dumbed my code down to make it as simple as possible while still being compileable and runnable:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#define num_threads 4
int repeat = 1;
int timesLooped = 0;
int waitingThreads = 0;
int threadNo = -1;
pthread_mutex_t mutex1;
pthread_cond_t condition;
//thread body
void* threadBody(void* arg){
//sensitive info: requires lock
if(pthread_mutex_lock(&mutex1)){ printf("error1\n"); }
threadNo++;
int threadId = threadNo;
//other info is set here as well in my code
if(pthread_mutex_unlock(&mutex1)){ printf("error2\n"); }
//main loop in the thread body
while(repeat == 1){
if(pthread_mutex_lock(&mutex1)){ printf("error3\n"); }
//wait until all threads are ready
while(waitingThreads < num_threads - 1){
printf(" %d! ", threadId);
waitingThreads++;
pthread_cond_wait(&condition, &mutex1);
printf(" %d ", threadId);
if(pthread_mutex_unlock(&mutex1)){ printf("error4\n"); }
}
//last thread will broadcast
if(waitingThreads == num_threads - 1){
printf("\n\nthread %d was last! broadcasting to let everyone proceed...", threadId);
timesLooped++;
waitingThreads = 0;
if(timesLooped == 3){
repeat = 0;
}
sleep(1);
pthread_cond_broadcast(&condition);
if(pthread_mutex_unlock(&mutex1)){ printf("error5\n"); }
}
}
printf("\n\nexiting thread %d\n", threadId);
pthread_exit((void*) arg);
}
int main(int argc, char** argv){
pthread_t threads[num_threads];
void* retval;
//create threads
for(long i = 0; i < num_threads; i++){
pthread_create(&threads[i], NULL, threadBody, (void*) i);
}
//join threads
for(long j = 0; j < num_threads; j++){
pthread_join(threads[j], &retval);
}
printf("\n\nDONE\n");
}
This gives me an output of:
thread 3 was last! broadcasting to let everyone proceed...
thread 2 was last! broadcasting to let everyone proceed...
thread 1 was last! broadcasting to let everyone proceed...
exiting thread 1 (deadlock, other threads never exit)
There are at least two bugs in your program.
You have a data race (see this blog post).
When threads 0 through num_threads - 1 access waitingThreads in if (waitingThreads == num_threads - 1) ..., they do so outside of the lock (i.e. they race).
You don't allow threads other than the last one to run (this is your primary question).
pthread_cond_wait returns when both condition has been signaled and the mutex can be re-acquired.
But your last thread immediately re-acquires the mutex upon releasing it, so no other thread can proceed.
I expect that if you add sleep or usleep after pthread_mutex_unlock in the last thread, your program will start working as you expect it to.
I have a threadpool of workers. Each worker executes this routine:
void* worker(void* args){
...
pthread_mutex_lock(&mtx);
while (queue == NULL && stop == 0){
pthread_cond_wait(&cond, &mtx);
}
el = pop(queue);
pthread_mutex_unlock(&mtx);
...
}
main thread:
int main(){
...
while (stop == 0){
...
pthread_mutex_lock(&mtx);
insert(queue, el);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);
...
}
...
}
Then I have a signal handler that executes this code when it receives a signal:
void exit_handler(){
stop = 1;
pthread_mutex_lock(&mtx);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mtx);
}
I have omitted declarations and initialization, but the original code has them.
After a signal is received most of the time it's all ok, but sometimes it seems that some worker threads stay in the wait loop because they don't see that the variable stop is changed and/or they are not waken up by the broadcast.
So the threads never end.
What I am missing?
EDIT: stop=1 moved inside the critical section in exit_handler. The issue remains.
EDIT2: I was executing the program on a VM with Ubuntu. Since the code appears to be totally right I tried to change VM and OS (XUbuntu) and now it seems to work correctly. Still don't know why, anyone has an idea?
Some guessing here, but it's too long for a comment, so if this is wrong, I will delete. I think you may have a misconception about how pthread_cond_broadcast works (at least something I've been burned with in the past). From the man page:
The pthread_cond_broadcast() function shall unblock all threads
currently blocked on the specified condition variable cond.
Ok, that make sense, _broadcast awakens all threads currently blocked on cond. However, only one of the awakened threads will then be able to lock the mutex after they're all awoken. Also from the man page:
The thread(s) that are unblocked shall contend for the mutex according
to the scheduling policy (if applicable), and as if each had called
pthread_mutex_lock().
So this means that if 3 threads are blocked on cond and _broadcast is called, all 3 threads will wake up, but only 1 can grab the mutex. The other 2 will still be stuck in pthread_cond_wait, waiting on a signal. Because of this, they don't see stop set to 1, and exit_handler (I'm assuming a Ctrl+c software signal?) is done signaling, so the remaining threads that lost the _broadcast competition are stuck in limbo, waiting on a signal that will never come, and unable to read that the stop flag has been set.
I think there are 2 options to work-around/fix this:
Use pthread_cond_timedwait. Even without being signaled, this will return from waiting at the specified time interval, see that stop == 1, and then exit.
Add pthread_cond_signal or pthread_cond_broadcast at the end of your worker function. This way, right before a thread exits, it will signal the cond variable allowing any other waiting threads to grab the mutex and finish processing. There is no harm in signaling a conditional variable if no threads are waiting on it, so this should be fine even for the last thread.
EDIT: Here is an MCVE that proves (as far as I can tell) that my answer above is wrong, heh. As soon as I press Ctrl+c, the program exits "immediately", which says to me all the threads are quickly acquiring the mutex after the broadcast, seeing that stop is false, and exiting. Then main joins on the threads and it's process over.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#define NUM_THREADS 3
#define STACK_SIZE 10
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c = PTHREAD_COND_INITIALIZER;
volatile bool stop = false;
int stack[STACK_SIZE] = { 0 };
int sp = 0; // stack pointer,, also doubles as the current stack size
void SigHandler(int sig)
{
if (sig == SIGINT)
{
stop = true;
}
else
{
printf("Received unexcepted signal %d\n", sig);
}
}
void* worker(void* param)
{
long tid = (long)(param);
while (stop == false)
{
// acquire the lock
pthread_mutex_lock(&m);
while (sp <= 0) // sp should never be < 0
{
// there is no data in the stack to consume, wait to get signaled
// this unlocks the mutex when it is called, and locks the
// mutex before it returns
pthread_cond_wait(&c, &m);
}
// when we get here we should be guaranteed sp >= 1
printf("thread %ld consuming stack[%d] = %d\n", tid, sp-1, stack[sp-1]);
sp--;
pthread_mutex_unlock(&m);
int sleepVal = rand() % 10;
printf("thread %ld sleeping for %d seconds...\n", tid, sleepVal);
sleep(sleepVal);
}
pthread_exit(NULL);
}
int main(void)
{
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
srand(time(NULL));
for (long i=0; i<NUM_THREADS; i++)
{
int rc = pthread_create(&threads[i], &attr, worker, (void*)i);
if (rc != 0)
{
fprintf(stderr, "Failed to create thread %ld\n", i);
}
}
while (stop == false)
{
// produce data in bursts
int numValsToInsert = rand() % (STACK_SIZE - sp);
printf("main producing %d values\n", numValsToInsert);
// acquire the lock
pthread_mutex_lock(&m);
for (int i=0; i<numValsToInsert; i++)
{
// produce values for the stack
int val = rand() % 10000;
// I think this should already be guaranteed..?
if (sp+1 < STACK_SIZE)
{
printf("main pushing stack[%d] = %d\n", sp, val);
stack[sp++] = val;
// signal the workers that data is ready
//printf("main signaling threads...\n");
//pthread_cond_signal(&c);
}
else
{
printf("stack full!\n");
}
}
pthread_mutex_unlock(&m);
// signal the workers that data is ready
printf("main signaling threads...\n");
pthread_cond_broadcast(&c);
int sleepVal = 1;//rand() % 5;
printf("main sleeping for %d seconds...\n", sleepVal);
sleep(sleepVal);
}
for (long i=0; i<NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
I have three integers (a, b and c), and I'd like to create two threads (POSIX pthreads) to access them in this particular sequence to keep the results consistent:
Thread 1 | Thread 2
---------------------
a=1 b=5
c=7
c=c+10
b=a+c*2
a=b+b*10
That is, c=c+10 in thread2 must wait until c=7 in thread1 finishes. Also a=b+b*10 in thread1 must wait until b=a+c*2 in thread2 finished.
I have tried using mutexes, but it does not work as I intend (code below). If thread2 starts first, it can lock mutex1 before thread1 has locked it, so the sequencing is lost. Locking the mutex from the main thread is not an option, as it would yield an undefined behavior (mutex locked and then unlocked by a different thread). I've also tried using conditional variables, but a similar problem arises: a signal can happen before the associated wait.
#include <pthread.h>
#include <stdio.h>
int a, b, c;
pthread_mutex_t mutex1, mutex2 = PTHREAD_MUTEX_INITIALIZER;
void *thread1(void *arg) {
pthread_mutex_lock(&mutex1);
a = 1;
c = 7;
pthread_mutex_unlock(&mutex1);
pthread_mutex_lock(&mutex2);
a = b + b*10;
pthread_exit(NULL);
}
void *thread2(void *arg) {
pthread_mutex_lock(&mutex2);
b = 5;
pthread_mutex_lock(&mutex1);
c = c + 10;
b = a + c*2;
pthread_mutex_unlock(&mutex2);
pthread_exit(NULL);
}
int main() {
pthread_t t1, t2;
if(pthread_create(&t1, NULL, thread1, NULL)) {
fprintf(stderr, "Error creating Thread 1\n");
return 0;
}
if(pthread_create(&t2, NULL, thread2, NULL)) {
fprintf(stderr, "Error creating Thread 2\n");
return 0;
}
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return a;
}
My question is, what is correct way to achieve the thread sequencing I want using pthreads? Thanks in advance.
pthread_mutex_t mutex1, mutex2 = PTHREAD_MUTEX_INITIALIZER
Only initializes the second one; but that is a nit. Depending upon the system you are running, you might not notice this, because mutex1 is uninitialized, thus the operations on it may be failing, or the initializer constant could be zero....
The signal/wait problem is not a problem -- you wait upon a condition protected by a mutex, in this pattern:
lock();
while (check() == false) {
wait();
}
func();
signal();
unlock();
so thread1’s check would be true, and func would be c = 7
while thread2’s check would be (c == 7) and func would be c += 10