I got this simple C program that uses pthreads.
I basically want to call my_function() once I'm 100% sure that my_thread() gets called and is executed.
I need to know how to synchronize the main() function and the my_thread() function.
Please note that the my_thread() never returns.
#include <stdio.h>
#include <pthread.h>
void my_function (void);
void* my_thread (void* arg);
int main (int argc, char* argv[])
{
int rc;
pthread_t id;
rc = pthread_create(&id, NULL, my_thread, NULL);
if (rc != 0)
{
return -10;
}
/*
* I wanna call my_function() once I'm 100% sure my_thread() gets called and being executed
*/
/*
* Synchronization code to add here:
*/
my_function();
return 0;
}
void* my_thread (void* arg)
{
/*
* This pthread never returns
*/
while (1)
{
/* stuff */
};
}
void my_function (void)
{
printf("Hello\n");
}
Thanks for your help.
Can anybody check if this solution is correct?
It works using the debugger but I would like to have a comment from experienced programmers.
#include <stdio.h>
#include <pthread.h>
void my_function (void);
void* my_thread (void* arg);
int started;
pthread_mutex_t mutex;
pthread_t id;
int main (int argc, char* argv[])
{
int rc;
int done;
started = 0;
mutex = PTHREAD_MUTEX_INITIALIZER;
rc = pthread_create(&id, NULL, my_thread, NULL);
if (rc != 0)
{
return -10;
}
/*
* Synchronization code proposed:
*/
done = 0;
do
{
pthread_mutex_lock(&mutex);
if (started == 1)
{
done = 1;
}
pthread_mutex_unlock(&mutex);
}
while (done == 0);
/*
* I wanna call my_function() once I'm 100% sure
* that my_thread() is called and being executed
*/
my_function();
return 0;
}
void* my_thread (void* arg)
{
started = 1;
while (1)
{
/* stuff */
};
}
void my_function (void)
{
printf("Hello\n");
}
Related
This is my current code for the Producer-Consumer problem. I compiled it and ran it but nothing is printed. The command line takes in 3 arguments: Sleep time, producer threads, consumer threads. I've tried setting the values as 5, 1, 1 respectively, the sleep timer works but I'm unsure about the rest.
Code for buffer.h:
typedef int buffer_item;
#define BUFFER_SIZE 5
Code for buffer.c:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include "buffer.h"
buffer_item buffer[BUFFER_SIZE];
void *producer(void *param);
void *consumer(void *param);
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int insert_item(buffer_item item)
{
do
{
wait(empty);
wait(mutex);
signal(mutex);
signal(full);
}while(1);
return 0;
}
int remove_item(buffer_item *item)
{
do
{
wait(full);
wait(mutex);
signal(mutex);
signal(empty);
}while(1);
return 0;
}
int main(int argc, char *argv[])
{
int sleepTime;
int producerThreads;
int consumerThreads;
int counter_1;
int counter_2;
if(argc != 4)
{
return -1;
}
sleepTime = atoi(argv[1]);
producerThreads = atoi(argv[2]);
consumerThreads = atoi(argv[3]);
srand((unsigned)time(NULL));
for(counter_1 = 0; counter_1 < producerThreads; counter_1++)
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, producer, NULL);
}
for(counter_2 = 0; counter_2 < consumerThreads; counter_2++)
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, consumer, NULL);
}
sleep(sleepTime);
return 0;
}
void *producer(void *param)
{
buffer_item item;
int randomTime;
int counter_1 = 0;
while(1)
{
randomTime = rand() % 1000 + 1;
sleep(randomTime);
item = rand();
if(insert_item(item))
{
fprintf(stderr, "Error.");
}
else
{
printf("Producer ID: %lu, Produced Item: %d\n", pthread_self(), item);
printf("The buffer now contains %d items\n", counter_1);
++counter_1;
}
}
}
void *consumer(void *param)
{
buffer_item item;
int randomTime;
int counter_2 = 0;
while(1)
{
randomTime = rand() % 1000 + 1;
sleep(randomTime);
if(insert_item(item))
{
fprintf(stderr, "Error.");
}
else
{
printf("Consumer ID: %lu, Consumed Item: %d\n", pthread_self(), item);
printf("The buffer now contains %d items\n", counter_2);
++counter_2;
}
}
}
So far I've tried declaring the tid separately, skipping sleep and join the threads, but it still doesn't print.
Your code can't possibly run, indeed it doesn't even compile.
Here's a list of issues that need to be addressed:
wait should be sem_wait
signal should be sem_post for semaphores
int sem_wait(sem_t *sem); and int sem_post(sem_t *sem); take the pointer to a semaphore
sem_wait(mutex) and sem_post(mutex) give something like "incompatible type for argument 1 of sem_wait", I guess you want to acquire and release the lock on the mutex like pthread_mutex_lock(&mutex) and pthread_mutex_unlock(&mutex)
in the consumer if(insert_item(item)): item is used uninitialized
still in the consumer you use insert_item instead of remove_item
Coming to the main question "I compiled it and ran it but nothing is printed", it doesn't print anything because producer and consumer call, respectively, insert_item and remove_item and are trapped inside infinite loops (e.g. while(1))
I am new to C and trying out conditional critical region. I read up on a couple of sites about Wait() and Signal() but I just can't figure out what my issue is. Hopefully somebody here can point me in the right direction what I am doing wrong here.
I am trying to do make two threads in my sample program here. Thread 1 will assign a value to String stuff and Thread 2 will print the info of the String.
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
void Lock(pthread_mutex_t m);
void Unlock(pthread_mutex_t m);
void Wait(pthread_cond_t t, pthread_mutex_t m);
void Signal(pthread_cond_t);
void Broadcast(pthread_cond_t t);
void* First(void* args);
void* Second(void* args);
char* stuff;
int main(int argc, char** argv){
pthread_t r1, r2;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
if(pthread_create(&r1, NULL, First, NULL))
fprintf(stderr,"Error\n");
if(pthread_create(&r2, NULL, Second, NULL))
fprintf(stderr, "Error\n");
pthread_join(r1, NULL);
pthread_join(r2, NULL);
}
void* First(void* args){
Lock(mutex);
stuff = "Processed";
usleep(500000);
Broadcast(cond);
Unlock(mutex);
pthread_exit(NULL);
return NULL;
}
void* Second(void* args){
Lock(mutex);
Wait(cond, mutex);
usleep(500000);
printf("%s", stuff);
Unlock(mutex);
pthread_exit(NULL);
return NULL;
}
void Lock(pthread_mutex_t m){
pthread_mutex_lock(&m);
}
void Unlock(pthread_mutex_t m){
pthread_mutex_unlock(&m);
}
void Wait(pthread_cond_t t, pthread_mutex_t m){
pthread_cond_wait(&t, &m);
}
void Signal(pthread_cond_t t){
pthread_cond_signal(&t);
}
void Broadcast(pthread_cond_t t){
pthread_cond_broadcast(&t);
}
I face a deadlock when executing this code but I am not sure why. GDB mentions that it stops at Wait() but I am not sure why.
I am using ucontext along with pthread. The below program works OK on Linux, but has failed assertion on Mac.
The problem seems that thread local variables are not correctly accessed after resuming the context from another thread.
The program creates two threads, A and B. A sets the context ready before B could resume the context, for it's synced properly.
It's very appreciated if someone could shed some light on this behavior on mac.
ENV:
clang version 3.7.0 (http://llvm.org/git/llvm.git 8d70064a4ac2ae09b8003173e751cfad9dc15400)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
Program:
#define _XOPEN_SOURCE 800
#include <ucontext.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <assert.h>
static int flag = 0;
void swap(ucontext_t *old, ucontext_t *new)
{
int ret = swapcontext(old, new);
assert(ret == 0);
}
#define SSIZE MINSIGSTKSZ
static char stack[SSIZE];
static ucontext_t a_ctx[2];
static ucontext_t b_ctx[2];
volatile static __thread int bug = 0;
static void func(int b) { }
static void f1 (void)
{
assert(bug == 0);
func(bug);
swap(&a_ctx[1], &a_ctx[0]);
assert(bug == 1);
}
void *thread_a(void *arg)
{
printf("A is %lu\n", pthread_self());
bug = 0;
ucontext_t ctx = a_ctx[1];
getcontext(&ctx);
ctx.uc_stack.ss_sp = stack;
ctx.uc_stack.ss_size = sizeof stack;
makecontext(&ctx, f1, 0);
swap(&a_ctx[0], &ctx);
__atomic_store_n(&flag, 1, __ATOMIC_RELAXED);
sleep(1);
return NULL;
}
void *thread_b(void *arg)
{
printf("B is %lu\n", pthread_self());
bug = 1;
while(__atomic_load_n(&flag, __ATOMIC_RELAXED) == 0) ;
swap(&b_ctx[0], &a_ctx[1]);
return NULL;
}
int main(int argc, char **argv)
{
pthread_t a, b;
pthread_create(&b, NULL, &thread_b, NULL);
pthread_create(&a, NULL, &thread_a, NULL);
pthread_exit(NULL);
}
Why this code give me different outputs every time?
Why it doesnt finish the loop?
What should I do to make it finish the loop? (despite context switches)?
Anything else I'm doing wrong?
Any help would be appreciated!
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define MAX 10
int buffer[MAX];
int fill = 0;
int use = 0;
int count = 0;
int loops = 15;
void put(int value) {
buffer[fill] = value;
fill = (fill + 1) % MAX;
count++;
printf("putting %d\n", value);
}
int get() {
int tmp = buffer[use];
use = (use + 1) % MAX;
count--;
return tmp;
}
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c_empty = PTHREAD_COND_INITIALIZER;
pthread_cond_t c_fill = PTHREAD_COND_INITIALIZER;
void *producer(void *arg) {
printf("producer starts\n");
int i;
for (i = 0; i < loops; i++) {
pthread_mutex_lock(&mutex); // p1
while (count == MAX) // p2
pthread_cond_wait(&c_empty, &mutex); // p3
put(i); // p4
pthread_cond_signal(&c_fill); // p5
pthread_mutex_unlock(&mutex); // p6
}
return NULL;
}
void *consumer(void *arg) {
printf("consumer starts\n");
int i;
for (i = 0; i < loops; i++) {
pthread_mutex_lock(&mutex); // c1
while (count == 0) // c2
pthread_cond_wait(&c_fill, &mutex); // c3
int tmp = get(); // c4
pthread_cond_signal(&c_empty); // c5
pthread_mutex_unlock(&mutex); // c6
printf("consuming: %d\n", tmp);
}
return NULL;
}
int main(int argc, char *argv[]) {
printf("parent: begin\n");
pthread_t p, x;
pthread_create(&p, NULL, producer, NULL);
pthread_create(&x, NULL, consumer, NULL);
printf("parent: end\n");
return 0;
}
Makefile:
all: wcountb
wcountb: wcountb.c
gcc -g -Wall -o wcountb wcountb.c -lpthread
At the end of the main, you should call for pthread_join, like this:
...
pthread_join(p, NULL);
pthread_join(x, NULL);
return 0;
}
Without that call, the threads are created and when you reach the end of main(), then your program terminates, thus your threads may be able to finish their job, or not, which explains the fact that sometimes your code works.
The pthread_join() function shall suspend execution of the calling thread until the target thread terminates, unless the target thread has already terminated.
Taken from the manual of pthread_join().
An almost related question lies here.
In hello world example of pthread it is stated:
#include <pthread.h>
#include <stdio.h>
void * print_hello(void *arg)
{
printf("Hello world!\n");
return NULL;
}
int main(int argc, char **argv)
{
pthread_t thr;
if(pthread_create(&thr, NULL, &print_hello, NULL))
{
printf("Could not create thread\n");
return -1;
}
if(pthread_join(thr, NULL))
{
printf("Could not join thread\n");
return -1;
}
return 0;
}
As you can see print_hello in pthread_create() has no argument, however in the definition, it looks like void * print_hello(void *arg)
What does that mean?
Now assume I have this implementation
void * print_hello(int a, void *);
int main(int argc, char **argv)
{
pthread_t thr;
int a = 10;
if(pthread_create(&thr, NULL, &print_hello(a), NULL))
{
printf("Could not create thread\n");
return -1;
}
....
return 0;
}
void * print_hello(int a, void *arg)
{
printf("Hello world and %d!\n", a);
return NULL;
}
Now I get this error:
too few arguments to function print_hello
So how can I fix that?
pthread passes one argument of type void * to thread function, So you can pass a pointer to any type of data that you want as fourth argument of pthread_create function, look at the example below that fixes your code.
void * print_hello(void *);
int main(int argc, char **argv)
{
pthread_t thr;
int a = 10;
if(pthread_create(&thr, NULL, &print_hello, (void *)&a))
{
printf("Could not create thread\n");
return -1;
}
....
return 0;
}
void * print_hello(void *arg)
{
int a = (int)*arg;
printf("Hello world and %d!\n", a);
return NULL;
}