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);
}
Related
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]);
I have a question about this piece of code I have. It is the classic readers-writers problem. I followed the pseudo-code found on this wikipedia page for the first problem that has writers starving. I would like to know how I would actually notice the starvation of the writers going on.
I tried putting print statements of the shared_variable in various places, but this didn't give me much insight. But maybe I just didn't understand what was going on. Would someone be able to explain to me how I could visually see the starvation happening? Thank you!
The number of attempts that the reader or writer would attempt to read or write is given as a command line argument.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
// Compile it like so: gcc assignment2.c -lpthread
// Shared variables (semaphore and integer)
static sem_t rw_mutex;
static sem_t mutex;
static int read_count = 0;
// Shared variable
int shared_variable = 0;
static void *writerAction(void *arg){
int number_attempt = *((int *) arg);
int attempt = 0;
do{
sem_wait(&rw_mutex);
shared_variable = shared_variable + 10;
sem_post(&rw_mutex);
attempt++;
}while(attempt < number_attempt);
}
static void *readerAction(void *arg){
int number_attempt = *((int *) arg);
int attempt = 0;
do{
sem_wait(&mutex);
read_count++;
// waiting to be able to read for the possible writer
if (read_count == 1 ){
sem_wait(&rw_mutex); // get the lock so that writter can't write!
}
// Release the read_count variable
sem_post(&mutex);
sem_wait(&mutex);
read_count--;
if (read_count == 0){
sem_post(&rw_mutex); // release the lock so that writter can write
}
sem_post(&mutex);
attempt++;
} while(attempt < number_attempt);
}
int main(int argc, char *argv[]) {
int number_writers = 10;
int number_readers = 500;
int reader_repeat_count = atoi(argv[2]);
int writer_repeat_count = atoi(argv[1]);
// Instantiating the threads for the writters and readers
pthread_t writer_threads[number_writers];
pthread_t reader_threads[number_readers];
// Initation of semaphores
sem_init(&rw_mutex, 0, 1);
sem_init(&mutex, 0, 1);
printf("Start creation of Readers\n");
for(int i = 0; i <number_readers; i++){
pthread_create(&reader_threads[i], NULL, readerAction, &reader_repeat_count);
}
printf("Start creation of Writers\n");
for(int i = 0; i < number_writers; i++){
pthread_create(&writer_threads[i], NULL, writerAction, &writer_repeat_count);
}
// All the actions is hapenning here
printf("Wait for Readers\n");
for(int i = 0; i < number_readers; i++){
printf("Waiting for : %d\n",i);
pthread_join(reader_threads[i], NULL);
}
printf("Wait for Writers\n");
// Collect all the writers
for(int i = 0; i < number_writers; i++){
printf("Waiting for : %d\n",i);
pthread_join(writer_threads[i], NULL);
}
// Results
printf("The shared variable is : %d\n",shared_variable);
}
First of all there is a syntax error, the return type of writerAction and readerAction should be void not void*
In order to see writer starvation you can print "writer trying to write" just before writer is trying to acquire the rw_mutex, the call to sem_wait(&rw_mutex). Add another print when the writer has updated the shared variable, inside the critical section. Add one more printf just after the the entry section of the reader. Which is this code.
// Release the read_count variable
sem_post(&mutex);
printf("reader reading shared value %d\n", shared_variable);
Now when you run the code with large repeat count, You will see "writer trying to write" then you will see a large number of reader printouts instead of the one from writer updating the shared variables, which will prove that the readers are starving the writer by not allowing it to update the variable.
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 want to use a bunch of pthreads in my application. To get familiar with the pthread library, I started with a small demo application (see attached sourcecode).
If I create 200 threads, all works well. However, if I increase the number of threads to 2000 the application crashes with a segfault. According to gdb the segfault happens at pthread_join. Unfortunately I could'nt figure out why this is happening.
First, I thought, that my linux machine could'nt handle that many threads, so I increased the value in /proc/sys/kernel/threads-max, but that didn't change anything.
What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define THREADS 200 //If I increase this value to 2000, the application crashes with a segfault
struct tInfo_t{
int sockfd;
};
pthread_t workerThreads[THREADS];
struct tInfo_t tInfo[THREADS];
void *handle(void *arg){
struct tInfo_t threadArgs = *((struct tInfo_t*)arg);
pthread_exit(0); //do nothing, just exit
return NULL; //to make the compiler happy
}
int main(int argc, char *argv[])
{
int i = 0;
//create a few threads
for(i = 0; i < THREADS; i++){
if(pthread_create(&workerThreads[i], 0, handle, (void*)&tInfo[i]) == -1){
printf("couldn't create thread. %d \n", workerThreads[i]);
return EXIT_FAILURE;
}
printf("Thread #%d spawned\n", i);
}
//wait until all threads finished their job
for(i = 0; i < THREADS; i++){
pthread_join(workerThreads[j], NULL);
}
return EXIT_SUCCESS;
}
I am learning multithreading performance in C. When I tried to write a sample code, I bumped into a problem:
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
typedef struct{
int a;
char b;
} args;
void* some_func (void* arg)
{
args *argsa = malloc(sizeof(args));
//copy the content of arg to argsa,
//so changes to arg in main would not affect argsa
*argsa = *(args*) arg;
int i = 10;
for (; i > 0; i--)
{
usleep (1); //to give other threads chances to cut in
printf ("This is from the thread %d\n", argsa->a);
}
free (argsa);
}
int main()
{
pthread_t thread[3];
args ss;
int index = 0;
ss.b = 's';
for (; index <3 ; index++)
{
ss.a = index;
if (pthread_create (thread+index, NULL, some_func, (void*)&ss ))
{
usleep(10);
printf ("something is wrong creating the thread");
}
}
pthread_join ( thread[0], NULL);
pthread_join ( thread[1], NULL);
pthread_join ( thread[2], NULL);
return 0;
}
I know char b in the struct is useless, but I just want to practice passing a structure.
I expect the code to print out "This is from the thread x", where x is 0, 1 or 2, alternatively. However, the code currently only gives me "This is from the thread 2" 30 times. I believe there is something wrong with
*argsa = *(args*) arg;
But I can't find a way to solve this and get the desired output.
Any help would be appreciated!
Because you are passing the same pointer to all the threads. By the time thread 0 has started, you have already incremented the value of ss.a to 1 (and then 2).
This is a bit more correct:
void* some_func (void* arg)
{
args *argsa = (args*)arg;
int i;
for (i = 0; i < 10; i++)
{
usleep (1); //to give other threads chances to cut in
printf ("This is from the thread %d\n", argsa->a);
}
}
int main()
{
pthread_t thread[3];
args ss[3];
int index;
for (index = 0; index < 3; index++)
{
ss[index].a = index;
if (pthread_create(&thread[index], NULL, some_func, &ss[index] ))
{
printf ("something is wrong creating the thread");
}
}
pthread_join ( thread[0], NULL);
pthread_join ( thread[1], NULL);
pthread_join ( thread[2], NULL);
return 0;
}
The pattern to use to solve this kind of problem is as follows:
Create a structure that will hold the parameters you want to pass to the thread.
Allocate such a structure with malloc.
Fill in the structure.
Pass the pointer to the structure to the thread.
When the thread is finished with the structure, the thread frees it.
This assumes you don't need to get any information back from the thread. If you do, you can change it so that the code that joins the thread frees the structure. That allows the structure to hold a reply as well -- you join the thread, read the response information, and then free the structure.
No special locking or synchronization is required because while the newly-created thread exists, it is the only thread that touches the structure.
Sorry guys, but I was trying to solve the same issue and I don't think a proper answer was given yet, in order to solve the problem. I tried this on my own and I came up with the following code. Now, I compiled and run it and it pretty worked as I expected, still I not that confident that the "lock in main and unlock in child process" is the most elegant solution, so I'd like to know what you think about it. Thank you very much in advance for any clarification.
Here is the code:
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
typedef struct{
int a;
char b;
} args;
pthread_mutex_t lock;
void* some_func (void *arg) {
args argsa = *(args*)arg;
pthread_mutex_unlock(&lock);
printf ("This is from the thread %d\n", argsa.a);
}
int main() {
pthread_t thread[10];
args ss;
int i, index=0;
ss.b = 's';
if (pthread_mutex_init(&lock, NULL) != 0) {
printf("\n mutex init failed\n");
return 1;
}
for (index = 0; index < 10 ; index++)
{
pthread_mutex_lock(&lock);
ss.a = index;
printf("index=%d, ", ss.a);
if (pthread_create (thread+index, NULL, some_func, (void*)&ss ))
{
usleep(10);
printf ("something is wrong creating the thread");
}
}
for(i=0;i<10;i++)
pthread_join ( thread[0], NULL);
return 0;
}
Output:
#./program
index=0, This is from the thread 0
index=1, This is from the thread 1
index=2, This is from the thread 2
index=3, This is from the thread 3
index=4, This is from the thread 4
index=5, This is from the thread 5
index=6, This is from the thread 6
index=7, This is from the thread 7
index=8, This is from the thread 8
index=9, This is from the thread 9