So I have this code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <semaphore.h>
#define nr_threads 3
sem_t semaphores[nr_threads];
typedef struct {
int id;
char *word;
}th_struct;
void *thread_function(void *arg)
{
th_struct *th_data = (th_struct *) arg;
sem_wait(&semaphores[th_data->id]);
printf("[thread#%d] %s\n", th_data->id, th_data->word);
sem_post(&semaphores[th_data->id + 1]);
return NULL;
}
int main(int argc, char **argv)
{
pthread_t tid[nr_threads];
th_struct th_data[nr_threads];
for(int i = 0; i < nr_threads; i++){
if (sem_init(&semaphores[i], 0, 1) != 0){
perror("Could not init semaphore");
return -1;
}
}
sem_post(&semaphores[0]);
for(int i = 0; i < nr_threads; i++){
th_data[i].id = i;
th_data[i].word = argv[i + 1];
pthread_create(&tid[i], NULL, thread_function, &th_data[i]);
}
for(int i = 0; i < nr_threads; i++){
pthread_join(tid[i], NULL);
}
for(int i = 0; i < nr_threads; i++)
sem_destroy(&semaphores[i]);
return 0;
}
I give from the command line 3 words, for example "one two three", and each thread prints one word, synchronized, so that the order will be always correct. I'm new to threads and semaphores, and my brain is currently used to sem_wait(sem) and after sem_post(sem), where sem is the same semaphore. What I'm asking is a complete explanation on why this code works and how it works. Why the semaphores are initialized with 0 permissions? Why there is sem_post(first_semaphore)? I'm very confused.
First of all, there's a bug in that code...
After it has done its job, each thread unconditionally calls sem_post() on the semaphore of the next thread. Therefore, the third thread will try to access semaphores[3] which doesn't exist.
Now what's going on (assuming the bug wasn't there) is this:
3 semaphores are created and initialized so that they are locked immediately
3 threads are created, each calling sem_wait() and blocking (because the semaphores are initialized to 0)
After a thread has done it's job, it calls sem_post() on the semaphore of the next one, which then returns from sem_wait()
This is the basic idea, but to get it running, someone needs to call sem_post() for the first semaphore. So that's why there is that sem_post(&semaphores[0]) in main().
Note: This is more of a long comment, not a complete answer.
I like to think of a semaphore as a blocking queue of informationless tokens. The semaphore's count is the number of tokens in the queue.
From that viewpoint, the main thread in your program creates a single token (from nothing, because the token is nothing), and it hands the token to the first worker thread by calling sem_post(&semaphores[0]);.
The first worker is able to do its job after taking the token from its input queue (i.e., when sem_wait(&semaphores[th_data->id]); returns. And after it has finished its work, it hands the token to the next thread: sem_post(&semaphores[th_data->id + 1]);
Related
First of all I am still new to posix programming and still understanding basic concepts. It is still not very clear for me how do pthread_mutex_lock
pthread_mutex_unlock do work.
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
#inlcude <stdio.h>
pthread_mutex_t_mtx;
void* routine(void* i){
int j;
for(j = 0; j < 1000000; ++j){
pthread_mutex_lock(&mtx);
printf("Inside thread %d\n", i);
pthread_mutex_unlock(&mtx);
}
return NULL;
}
int main()
{
pthread_t th[3];
int i;
pthread_mutex_init(&mtx, NULL);
for(i = 1; i <= 2; ++i)
{
if(pthread_create(th + i, NULL, routine, i){
perror(NULL); return 1;
}
}
for(i = 1; i <=2; ++i)
pthread_join(th[i], NULL);
return 0;
}
What should be the correct output of the above program ? I think that because of the lock and unlock of the mutex there would be 2000000 iterations, but it is not very clear for me the order that they are done in. Does the first thread execute the first 1000000 steps of the for? Does it even execute the first one of the 20000000 ? Or does this happen by a more chaotic order?
Assuming that the mutex is a global one, you will get 2000000 messages, with 1000000 from each thread. The order of those is random, however they will not interfere each other as each print is protected by the mutex
EDIT: I just noticed, that you are joining before creating the next thread. Therfore first there will be all messages of the first, then of the second thread. In this case the mutex has no effect at all. The reason for the ordering is simply that you will not have more then one worker-thread running at the same time.
pthread_create in a for loop, this is my code
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
pthread_mutex_t mutex;
void* helloWorld(void *i) {
pthread_mutex_lock(&mutex);
printf("This is a thread %d\n", *((int*) i));
pthread_mutex_unlock(&mutex);
return 0;
}
int main() {
pthread_mutex_init(&mutex, NULL);
pthread_t threads[4];
int i;
printf("Main Message\n");
for (i = 0; i < 4; i++) {
pthread_create(&threads[i], NULL, helloWorld, &i);
}
for (i = 0; i < 4; i++) {
pthread_join(threads[i], NULL);\
}
pthread_mutex_destroy(&mutex);
return 0;
}
The order doesn't really matter as long as all 4 threads are working.
I've tried to use mutex but it didn't solve the issue.
My current output is pretty random, it can be 0000 or 0112 or anything else.
The problem is two-fold:
First of all you don't have control over when the threads run or in which order.
You pass the same pointer to all threads.
You can solve the second issue by passing the value if i to the threads. This is one of the few cases where it's considered okay to pass values instead of pointers:
pthread_create(&threads[i], NULL, helloWorld, (void*)(uintptr_t) i);
Then in the thread
printf("This is a thread %d\n", (int)(uintptr_t) i);
The first issue, about the order, you have to come up with some other way to synchronize the threads and how they notify each other. For example by using four condition signals, one for each thread, that you signal in the order you want the threads to execute.
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've spent quite a few hours on trying to figure this one out and I'm completly stuck. The program is supposed to start 6 threads. Where some threads start where others end. Right now, I'm trying to get one single thread (thread 0) to execute. The caps lock commenting shows where I have added code and done my mistakes. My main struggle here is dealing with the pointers. Could anyone give me any pointers (ha..ha.. :c )?
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define SHARED 1
sem_t sem[6];
struct threadargs
{
int id; /* thread number */
int sec; /* how many sec to sleep */
int signal[6]; /* which threads to signal when done */
};
void *tfunc(void *arg)
{
int i;
struct threadargs *targs=arg;
sem_wait(sem); //WAIT FOR OWN SEMAPHORE
printf("Thread %d is running\n", targs->id);
sleep(targs->sec);
printf("Thread %d is completed and may wake others..\n", targs->id);
for(i=0; i<6; i++) //ITERATE OVER signal_ARRAY &
{ //WAKE THREAD NUMBER i IF
if(targs->signal[i] == 1) //signal[i] IS 1
pthread_cond_signal(&sem[i]);
}
}
int main(void)
{
int i, j;
struct threadargs *targs[6];
pthread_t tid[6];
for(i=0; i<6; i++)
{
targs[i] = (struct threadargs*) malloc(sizeof(struct threadargs));
for(j=0; j<6; j++)
{ targs[i]->signal[j]=0; }
}
targs[0]->id=1;
targs[0]->sec=1;
targs[0]->signal[1]=1;
targs[0]->signal[4]=1;
sem[0] = 0; //INITIALIZE THREAD'S SEMAPHORE TO 0 or 1
pthread_create(targs[0], NULL, tfunc, NULL) // START THREAD
for(i=0; i<6; i++)
pthread_join(tid[i], NULL);
return 0;
}
Alright. First things first, I do recommend taking a second look at your coding style. It is of course highly subjective and I won't say yours is bad, but it took me a while to figure it out (if you really want to know, I recommend the Linux coding style for C/C++ code).
Lets get on with your problem. As far as I can see, the main issue seems that you're basically comparing pointers to apples with pointers to banana's (in other words, you're using the wrong pointer type in the wrong place).
To make sure that calls to functions and the like are correct, make sure to look up the API documentation for functions that are new to you (examples: pthread_create, sem_init, sem_wait, sem_post, pthread_cond_signal).
As you can see, pthread_cond_signal doesn't take a sem_t* as argument, and therefore you can't pass one to it and expect it to work. Below you'll find an example program showing how semaphores are used.
First, a new thread is created which will be put in waiting state instantly. As soon as the main tread finished counting from 0 to 150, it will post ('unlock') the semaphore and allowing the second thread to finish its execution.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
static sem_t sem_thread_one;
static pthread_t thread_one_data;
static int x;
static void *tfunc(void *arg)
{
sem_wait(&sem_thread_one);
printf("Thread 1 is running. The value of x is %i\n", x);
return NULL;
}
int main(int argc, char **argv)
{
sem_init(&sem_thread_one, 0 /* don't share between processes */, 0);
if(pthread_create(&thread_one_data, NULL, &tfunc, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
while(x < 150) {
x++;
}
sem_post(&sem_thread_one);
if(pthread_join(thread_one_data, NULL)) {
fprintf(stderr, "Could not join threads, exiting!\n");
return -EXIT_FAILURE;
}
sem_destroy(&sem_thread_one);
printf("Program ran succesfully!\n");
return -EXIT_SUCCESS;
}
Save in a file sem.c and compile & link using:
gcc -Wall -Os -pthread -o sem_test sem.c
Now a second example, but now using pthread_cond_t. The functionality of the program is somewhat similar, it waits for a counter to reach a certain number.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
static pthread_t thread_one_data, thread_two_data;
static volatile int x, y, idx = 10;
static int count = 1;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t condition = PTHREAD_COND_INITIALIZER;
static void *cond_test_wait(void *arg)
{
pthread_mutex_lock(&mutex);
while(count < 10) {
printf("Waiting for `count < 10' to become true\n");
pthread_cond_wait(&condition, &mutex);
}
pthread_mutex_unlock(&mutex);
printf("Test wait thread finished. Value of count: %i\n", count);
return NULL;
}
static void *cond_test_signal(void *arg)
{
while(count < 10) {
pthread_mutex_lock(&mutex);
pthread_cond_signal(&condition);
/* do more intelligent things here */
count++;
pthread_mutex_unlock(&mutex);
}
printf("Test signal thread finished\n");
return NULL;
}
int main(int argc, char **argv)
{
if(pthread_create(&thread_one_data, NULL, &cond_test_wait, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
if(pthread_create(&thread_two_data, NULL, &cond_test_signal, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
pthread_join(thread_one_data, NULL);
pthread_join(thread_two_data, NULL);
pthread_cond_destroy(&condition);
pthread_mutex_destroy(&mutex);
printf("Program ran succesfully!\n");
return -EXIT_SUCCESS;
}
Save in a file cond.c and compile & link using:
gcc -o cond -pthread -Os -Wall cond.c
Do note how neat condition work in this example. You can use them to wait until any expression (= condition) becomes true. After the condition becomes true normal execution continue's.
If you need any more help, don't hesitate to ask in the comments. Good luck combining the above examples to fix up your program.
I am working a c- project which uses semaphores to handle the same function at the same time. When I run it, on linux, under the root user, it works perfect. But if I run it on another user, the script isn't executed and it leaves a semaphore in the semaphore array. Does anybody know a solution to this problem?
Here is my code:
int main(int argC, char* argv[]) {
pthread_t thr[argC-1];
int indexes[argC-1];
int i,j;
for(j=0; j<(argC-1); j++) {
indexes[j] = atoi(argv[j+1]);
pthread_create (&thr[j], NULL, (int *) &stabtest, (void *) &indexes[j]);
}
sem_init(&mutex, 0, 1);
for(j=0; j<(argC-1); j++) pthread_join(thr[j], NULL);
// Destroy semaphore
sem_destroy(&mutex);
// Exit
exit(0);
}
int stabtest(void *ptr) {
sem_wait(&mutex); // down semaphore
// Other code ...
sem_post(&mutex); // up semaphore
pthread_exit(0); // exit thread
}
This code I actually found on the internet because I have no experience with semaphores. So I am not sure of this code is the right one to run the function in parallel at the same time. But it works for the root user, so I guess the code is more or less ok.
Thank you!
If this is the code you are using, whatever you think is happening isn't happening. Permissions should have no effect on the semaphore you are using. And there is no semaphore array, you are using a single semaphore.
You seem to have a shaky grasp on command line parms. They are an array pointers to string. argc is the number of arguments. There will always be at least 1 argv, argv[0], which is the program name. Please don't rename argc. Everyone knows what argc is. Renaming it will just annoy people.
You start your threads and then you initialize your semaphore. That's a problem.
The start function of a pthread has to have the signature void* stabtest(void *ptr). Yours is int stabtest(void *ptr) and you are trying to cast your way out of a mistake. Don't do that. If you want to return something from a thread you do it through the void ptr used as the 4th parm in pthread_create. That is, allocate some memory, pass it in pthread_create, do whatever you need to in the thread to change the information pointed to, and then return the same void ptr from the thread. When you do your pthread_join you can access the returned pointer to the data in the second paramater in pthread_join.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
sem_t mutex;
void* stabtest(void *ptr)
{
sem_wait(&mutex); // down semaphore
printf("in thread %lu...\n", pthread_self());
sem_post(&mutex); // up semaphore
pthread_exit(0); // exit thread
}
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("usage: %s numThread\n", argv[0]);
exit(1);
}
int maxThreads = atoi(argv[1]);
pthread_t thr[maxThreads];
int indexes[maxThreads];
int i, j;
sem_init(&mutex, 0, 1);
for (j = 0; j < maxThreads; j++)
pthread_create (&thr[j], NULL, stabtest, NULL);
for (j = 0; j < maxThreads; j++)
pthread_join(thr[j], NULL);
// Destroy semaphore
sem_destroy(&mutex);
// Exit
exit(0);
}