I'm trying to implement merge sort with semaphores and I have some troubles making my code running:
sem_t *sem;
pthread_t *t;
void *parallel_merge_sort(void *thread_id)
{
int a = *((int *) thread_id);
printf("%d. in sort\n",a);
fflush(stdout);
sem_post(&(sem[a]));
if(a % 2)
sem_wait(&(sem[a-1]));
else
sem_wait(&(sem[a+1]));
printf("%d. out sort\n",a);
fflush(stdout);
}
void main()
{
int P = 2,i;
t = calloc(P,sizeof(pthread_t));
sem = calloc(P,sizeof(sem_t));
printf("threads created\n");
fflush(stdout);
for(i=0;i<P;i++)
pthread_create(&(t[i]),NULL,(void*) ¶llel_merge_sort,(void *) &i);
for(i=0;i<P;i++)
pthread_join(t[i], NULL);
printf("threads end\n");
fflush(stdout);
}
This code produces output like the following one:
threads created
0. in sort
0. in sort
After this, it doesn't continue to run and wait.
What can the problem be and how can I fix it?
There's no guarantee that a new thread starts immediately. This means that you can't use a pointer to the index as the variable may change before the thread starts.
In this case it seems that the threads doesn't start until the main thread have entered the second loop, in which the variable i is reset to zero, so both threads will have the same index, making both threads to try to wait on the same semaphore.
You can bypass this by using a "hack" and pass i directly as the pointer:
pthread_create(&(t[i]),NULL,(void*) ¶llel_merge_sort,(void *) i);
And in the thread function do:
int a = (int) thread_id;
Related
So i have this program that makes 2 threads and one of those adds 5 to the global variable number while the other substracts 5
int number = 0;
bool flag = true;
pthread_mutex_t mutex;
void* change_number(void *x) {
int num = *(int *)x;
if(flag) {
flag = false;
printf("hi from thread 1\n");
time_t now = time(NULL);
while(now + 1 > time(NULL)) {
pthread_mutex_lock(&mutex);
number += num;
pthread_mutex_unlock(&mutex);
}
}
else
{
printf("hi from thread 2\n");
time_t now2 = time(NULL);
while(now2 + 1 > time(NULL)) {
pthread_mutex_lock(&mutex);
number += num;
pthread_mutex_unlock(&mutex);
}
}
}
int main(int argc, char* argv[])
{
int id = fork();
if(id==0) {
int par1 = 5;
int par2 = -5; //-(rand() % 11);
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex, NULL);
printf("1) SUccess code: %d\n", pthread_create(&t1, NULL, change_number, (void *) &par1));
printf("2) Success code: %d\n", pthread_create(&t2, NULL, change_number, (void *) &par2));
pthread_join(t1, NULL);
printf("thread 1 finished\n");
pthread_join(t2, NULL);
printf("thread 2 finished\n");
printf("Final number is: %d\n", number);
}
pthread_mutex_destroy(&mutex);
wait();
return 0;
}
Judging from the prints, i think it runs as intended but the results are very inconsistent (also i would expect the number to be close zero since they add/substract the same value). Here are some outputs:
Final number is: 8272054
Final number is: -253453
Final number is: 3405063
Am i doing something wrong? Or the output depends on the specifics of my OS?
The biggest source of inconsistency in your results is the number of times you let each thread add/subtract to/from the global value. The now + 1 > time(NULL) style doesn't guarantee at all that both the threads would execute their respective loops for the same number of times since the threads being scheduled to execute their loops is independent from the progression of system time. Either of the threads might thus lose out on its shot at executing the loop. To make this more consistent and yield the expected 0, you could perhaps have something like
int count = 5000; // or whatever number you choose
while(count--) {
pthread_mutex_lock(&mutex);
number += num;
pthread_mutex_unlock(&mutex);
}
This ensures that the threads perform the operations an equal number of times irrespective of scheduling concerns and system time.
NOTE: There is a subtle bug in your program. It might so happen that both the threads handlers are executed at the same time and both see the value of flag as true and end up in the hi from thread 1 block. Of course, the value at the end would still be 0 since one is adding +5 and another -5 but this is probably not something you'd want. Try looking at other constructs (e.g. atomic_bool etc.)
A nitpick: Try having the call to wait(NULL) in the parent process rather than calling it from both the child and parent. The call from the child process would anyway exit with an error.
I want a routine to be done by multiple threads, once they are created they need their work to be all finished before copying their calculated things. So a thread is on cond_wait once it has its work done.
A piece of code that works now:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_RAYCAST_THREADS 2
typedef struct s_thread_env
{
int id;
pthread_t thread;
int work_done;
void *shared_data;
} t_thread_env;
typedef struct s_shared_data
{
t_thread_env *tab_thread_env;
int max_thread;
int all_work_done;
pthread_mutex_t mutex;
pthread_cond_t cond;
int stop;
} t_shared_data;
void set_threads_again(int id, t_shared_data *shared_data)
{
int i;
shared_data->all_work_done = 0;
i = -1;
while (++i < shared_data->max_thread)
shared_data->tab_thread_env[i].work_done = 0;
//i = -1;
//while (++i < shared_data->max_thread)
//{
//if (i != id)
//{
//printf("cond_signal to thread %i\n", i);
//pthread_cond_signal(&shared_data->cond);
//}
//}
pthread_cond_broadcast(&shared_data->cond);
}
void wait_or_signal(t_thread_env *thread_env, t_shared_data *shared_data)
{
int i;
i = 0;
while (i < shared_data->max_thread && shared_data->tab_thread_env[i].work_done)
i++;
if (i == shared_data->max_thread)
{
printf(" allworkdone sent by thread %i\n", thread_env->id);
//printf(" copy_screenpixels() by thread %i\n", thread_env->id);
set_threads_again(thread_env->id, shared_data);
}
else
{
printf(" thread number %i is waiting for other threads\n", thread_env->id);
pthread_cond_wait(&shared_data->cond, &shared_data->mutex);
printf("ENFIN ! thread number %i woke up from condwait\n", thread_env->id);
}
}
void *routine(void *arg)
{
t_thread_env *thread_env;
t_shared_data *shared_data;
int stop;
thread_env = (t_thread_env *)arg;
shared_data = (t_shared_data *)thread_env->shared_data;
pthread_mutex_lock(&shared_data->mutex);
while (!shared_data->stop)
{
printf("new frame> thread_id = %i, thread_env->work_done = %i\n", thread_env->id, thread_env->work_done);
pthread_mutex_unlock(&shared_data->mutex);
printf(" raycast() in routine thread %i\n", thread_env->id);
pthread_mutex_lock(&shared_data->mutex);
thread_env->work_done++;
wait_or_signal(thread_env, shared_data);
}
pthread_mutex_unlock(&shared_data->mutex);
return (0);
}
void init_thread_env(t_shared_data *shared_data, int i)
{
t_thread_env *thread_env;
thread_env = &shared_data->tab_thread_env[i];
thread_env->id = i;
thread_env->shared_data = shared_data;
if (pthread_create(&thread_env->thread, NULL, routine, thread_env) != 0)
printf("Error pthread_create for %i\n", i);
}
void free_all(t_shared_data *shared_data)
{
int i;
pthread_mutex_lock(&shared_data->mutex);
shared_data->stop = 1;
pthread_mutex_unlock(&shared_data->mutex);
i = -1;
while (++i < shared_data->max_thread)
pthread_join(shared_data->tab_thread_env[i].thread, NULL);
printf("\nEND\n\n");
//free etc
}
int main()
{
int i;
t_shared_data *shared_data;
shared_data = (t_shared_data*)malloc(sizeof(t_shared_data)); // if (!shared data){free etc}
shared_data->max_thread = MAX_RAYCAST_THREADS;
pthread_mutex_init(&shared_data->mutex, 0);
pthread_cond_init(&shared_data->cond, 0);
shared_data->tab_thread_env = (t_thread_env*)malloc(sizeof(t_thread_env) * shared_data->max_thread);
i = -1;
while (++i < shared_data->max_thread)
init_thread_env(shared_data, i);
while (1)
sleep(1); //program is turning
free_all(shared_data);
return (0);
}
The correct output:
new frame> thread_id = 0, thread_env->work_done = 0
raycast() in routine thread 0
thread number 0 is waiting for other threads
new frame> thread_id = 1, thread_env->work_done = 0
raycast() in routine thread 1
allworkdone sent by thread 1
cond_signal to thread 0
new frame> thread_id = 1, thread_env->work_done = 0
ENFIN ! thread number 0 woke up from condwait
new frame> thread_id = 0, thread_env->work_done = 0
raycast() in routine thread 0
thread number 0 is waiting for other threads
raycast() in routine thread 1
allworkdone sent by thread 1
cond_signal to thread 0
new frame> thread_id = 1, thread_env->work_done = 0
ENFIN ! thread number 0 woke up from condwait
new frame> thread_id = 0, thread_env->work_done = 0
raycast() in routine thread 0
thread number 0 is waiting for other threads
raycast() in routine thread 1
Thank you for reading me, have a good day!
EDIT: I made a more readable and compilable version with only 1 mutex (old version: https://pastebin.com/4zMyBJi2).
EDIT2: deleted some parts of the original post, and tried to avoid every data races, my code still has some (as it still does not work). But I think I am close to get something working
EDIT3: Ok it is working now, I edited the code. The main issue was my disastrous use of the shared_data variables.
I tried to make my raycasting threads work using 1 call of
pthread_create for each thread (in an initialisation function). Is
it possible to do it?
Each successful call to pthread_create creates exactly one thread, so this is the only way to do it. But do not get confused between threads' start functions and threads themselves. Multiple threads can be created to run the same thread function, but this requires multiple calls to pthread_create, one for each thread.
I guess it is better (for performances) to do
it in this way (rather than an enormous amount of pthread_create and
pthread_join calls), is this correct?
Having chosen to use a certain number of threads to do certain pieces of work, the number of pthread_create calls is already determined. If you have performance concerns then they should be about how many threads to use, the details of the work they are to perform, and the nature and granularity of their synchronization.
In order to make it happen, the last thread (number n) to finish his
job has to tell the other ones that every thread has finished, so
there is a pthread_cond_wait for the (n - 1) first threads, and the
last thread (number n) calls pthread_cond_signal for each (n - 1)
first ones. Each thread has his own mutex.
That seems a little overkill, even if you can make it technically correct. It doesn't make much sense to have a mutex per thread, because mutexes are useful only when different threads use the same one. It may make sense to have different mutexes for protecting different shared resources, however. You would probably want CVs for some of those, but not all of them.
This appears to be (at least one area) where your code is failing. Your threads are not properly synchronized because they all rely on different mutexes to protect the same resources. It's not clear to me whether it makes sense for your program to have any more than just one mutex, but I would start by reducing your usage to that.
In this code, I'm trying to create an array of threads. I've set the pthreads value to 1. In the for loop, the address, ID, and "created" gets printed, but the function never seems to execute as I don't get a print.
The seg fault actually happens at pthread_join at the bottom, but it certainly has to be caused by the creation since the function never runs, right? producers[0] is the only thread since I'm just testing 1. The create function passes an (ID address, NULL, the void * function(), and void* arguments) like it's supposed to. It has to be something obvious but I've tried to figure it out for so long I'm empty.
typedef struct ThreadStruct {
int threadIndex;
} ThreadStruct;
void *producer(void* ts){
printf("in producer\n");
FILE* inputfp = threadstruct->inputFiles[0];
hostname = (char*)malloc((MAXNAME+1)*sizeof(char));
while(fscanf(inputfp, hostname) > 0){
printf("%s",hostname);
}
return 0;
}
int main(int argc, char *argv[]){
int pthreads = atoi(argv[1]); //always 1
ThreadStruct threadstruct;
pthread_t producers[pthreads];
for(int i=0;i<pthreads;i++){
printf("in pthread loop\n");
printf("%p \n",&producers[i]);
printf("%ld \n",producers[i]);
pthread_create(&producers[i], NULL, producer, (void *) &threadstruct);
}
pthread_join(producers[0], NULL);
}
Your code works in my side and would not produce the seg fault.
Here is the print out info:
$ ./pthread
in pthread loop
0xffffcb70
6444554784
in pthread loop
in producer
0xffffcb78
64
in pthread loop
in producer
0xffffcb80
1
in pthread loop
in producer
0xffffcb88
4299166064
in pthread loop
in producer
0xffffcb90
6443761969
in pthread loop
in producer
0xffffcb98
6445451520
in pthread loop
in producer
0xffffcba0
314761761601
in producer
exit main thread
Your code here:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
typedef struct ThreadStruct {
int threadIndex;
} ThreadStruct;
void *producer(void* ts){
printf("in producer\n");
return 0;
}
int main(int argc, char *argv[]){
int pthreads = 7;
ThreadStruct threadstruct;
pthread_t producers[pthreads];
for(int i=0;i<pthreads;i++){
printf("in pthread loop\n");
printf("%p \n",&producers[i]);
printf("%ld \n",producers[i]);
pthread_create(&producers[i], NULL, producer, (void *) &threadstruct);
}
pthread_join(producers[0], NULL);
printf("exit main thread\n");
}
you don't seem to check if the thread is actually created or not, in other words you don't seem to validate the return type of pthread_create and straight calling pthread_join probably leading to Undefined behavior, in case pthread_create fails.
pthread_create(&producers[i], NULL, producer, (void *) &threadstruct);
from pthread_join
The pthread_join() function shall fail if:
EINVAL The implementation has detected that the value specified by thread does not refer to a joinable thread.
ESRCH No thread could be found corresponding to that specified by the given thread ID.
however there are cases where pthread_join with invalid thread handle seg faults.
a piece of extract from the link above
"*Passing invalid handle to pthread_join is like passing invalid pointer to a system call.
The implementation may detect it and signal it in errno, but it may crash as
well.
There are 2 different POSIX threads implementations on Red Hat Linux
linuxthreads, where pthread_t handle is a small integer (and the number of
threads is substantially limited)
NPTL (the default, pthread_t is internally a pointer so that there are no
arbitrary thread limits)
You can request the old-fashioned threading library with LD_ASSUME_KERNEL=2.4.19
in the environment.
For NPTL where pthread_t is a pointer, pthread_join detects some invalid
handles where it can be done cheaply. But detecting all possible invalid
handles would be very costly (the implementation would basically have to take
a global lock and iterate over all currently running threads, comparing the
handle with each of them. With say 100000 running threads you can see how
costly it is).
This testcase works on SuSE since SuSE only ships the old-fashioned non-scalable
linuxthreads implementation.*"
from pthead_create
RETURN VALUE
On success, pthread_create() returns 0; on error, it returns an error number, and the contents of *thread are undefined.
perhaps something like this
if( pthread_create(&producers[i], NULL, producer, (void *) &threadstruct) ) {
perror("something wrong .. ");
exit(1);
}
Firstly check the return value of pthread_create() to check whether it was successful or not. For e.g
int ret = pthread_create(&producers[i], NULL, producer, (void *) &threadstruct);
if(ret) {
fprintf(stderr, "failed to create thread %s\n",strerror(ret));
exit(EXIT_FAILURE);
}
And Also it's advised to use pthread_join() for all the threads not only first thread, as if you want to wait for thread/s to terminate before further processing in main thread as mentioned here. Also check the return value of pthread_join().
Sample Code
#include<stdio.h>
#include<string.h>
#include<stdint.h>
#include<stdlib.h>
#include<pthread.h>
typedef struct ThreadStruct {
int threadIndex;
} ThreadStruct;
void *producer(void* ts){
printf("in producer\n");
return 0;
}
int main(int argc, char *argv[]){
int pthreads = 5;
int ret;
ThreadStruct threadstruct;
pthread_t producers[pthreads];
/* create threads */
for(intptr_t itr = 0;itr < pthreads; itr++){
printf("in pthread loop\n");
//printf("%p \n",&producers[itr]);
//printf("%ld \n",producers[itr]);
ret = pthread_create(&producers[itr], NULL, producer, (void *) &threadstruct);
if (ret) {
fprintf(stderr, "failed to create thread #%ld - %s\n",(long)itr, strerror(ret));
exit(EXIT_FAILURE);
}
}
/* join all threads */
for(intptr_t itr = 0; itr < pthreads; itr++){
printf("In main: joining thread #%ld\n", (long)itr);
ret = pthread_join(producers[itr], NULL);
if (ret) {
fprintf(stderr, "failed to join thread #%ld - %s\n",(long)itr, strerror(ret));
exit(EXIT_FAILURE);
}
}
//pthread_exit();
return 0;
}
it works in my system, hope it works for you also.
I am writing a c program to create three threads(1,2,3) such that at any given point of time only one thread must execute and print the output on console in the order 123123123123.........
I am making use of semaphore for synchronization.
I am having an issue with the code i have written. the code doesn't print it in the order 123123... the order is random and stops after a while.
#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#include<unistd.h>
#include<assert.h>
#include<stdlib.h>
sem_t sem_1;
void *func1(void *arg){
int err1=0;
while(1){
err1=sem_wait(&sem_1);
assert(err1==0);
printf("thread 1\n");
}
//return NULL;
}
void *func2(void *arg){
int err2=0;
while(1){
err2=sem_wait(&sem_1);
assert(err2==0);
printf("thread 2\n");
}
// return NULL;
}
void *func3(void *arg){
int err3=0;
while(1){
err3=sem_wait(&sem_1);
assert(err3==0);
printf("thread 3\n");
}
// return NULL;
}
int main(){
pthread_t *t1,*t2,*t3;
int i=0,rc=0,c1=0,c2=0,c3=0;
t1=(pthread_t *)malloc(sizeof(*t1));
t2=(pthread_t *)malloc(sizeof(*t2));
t3=(pthread_t *)malloc(sizeof(*t3));
i=sem_init(&sem_1,0,1);
assert(i==0);
c1=pthread_create(t1,NULL,func1,NULL);
assert(c1==0);
c2=pthread_create(t2,NULL,func2,NULL);
assert(c2==0);
c3=pthread_create(t3,NULL,func3,NULL);
assert(c3==0);
while(1){
rc=sem_post(&sem_1);
assert(rc==0);
sleep(1);
}
return 0;
}
Why would you even expect them in in an order?
Your threads do things inbetween the different waits, and according to the system scheduler, these can take different amount of time.
printf is a buffered operation that gives you exclusive access to a shared resource. So in addition to your semaphore there is a hidden lock somewhere, that also regulates the progress of your threads. Don't expect the prints to appear in order, even if the calls themselves are.
Then, for the end, using assert here is really a very bad idea. All sem_t operations can (and will) fail spuriously, so it is really bad to abort, just because such a failure.
In fact, sem_t is really a low level tool, and you should never use it without checking return values and without having a fall back strategy if such a call fails.
Of course. I can't see any order related synchronization mechanism.
One of the options to achieve the strict order is to have one semaphore per thread:
sem_t sem[3];
// ...
while(1) {
for(n = 0; n < 3; n++) {
rc=sem_post(&sem[n]);
assert(rc==0);
}
sleep(1);
}
Below Code will help to solve the problem, one semaphore for each thread used to achieve synchronization. The initial value of the semaphore does the job. used usleep to launch thread in sequence manner for needed output. The same can be done by using Mutex lock and cond variables
//declaring semaphore
sem_t sema1;
sem_t sema2;
sem_t sema3;
void* t1(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema1);
printf("Thread 1 \n");
sem_post(&sema2);
}
printf("T1 return\n");
return NULL;
}
void* t2(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema2);
printf("Thread 2 \n");
sem_post(&sema3);
}
printf("T2 return\n");
return NULL;
}
void* t3(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema3);
printf("Thread 3 \n");
sem_post(&sema1);
}
printf("T3 return \n");
return NULL;
}
int main()
{
pthread_t tid1, tid2,tid3;
sem_init(&sema1,0,1);
sem_init(&sema2,0,0);
sem_init(&sema3,0,0);
pthread_create(&tid1, NULL, t1, NULL);
usleep(100);
pthread_create(&tid2, NULL, t2, NULL);
usleep(100);
pthread_create(&tid3, NULL, t3, NULL);
pthread_join(tid3, NULL);
pthread_join(tid2, NULL);
pthread_join(tid1, NULL);
sem_destroy(&sema1);
sem_destroy(&sema2);
sem_destroy(&sema3);
return 0;
}
I'm trying to make a simple program using pthreads, want to make 6 threads and pass index to all of them. here's the code:
#include <pthread.h>
#include <stdio.h>
#define num_students 6
void thread_starter();
int main() {
pthread_t thread1[num_students];
int i = 0;
for(i = 0; i<num_students; i++) {
int q = i;
pthread_create(&thread1[i], NULL, (void *) &thread_starter, (void *)&q);
}
sleep(1);
}
void thread_starter(void* a) {
printf("Thread %i \n", *((int*)a));
}
And the output:
Thread 2
Thread 3
Thread 2
Thread 4
Thread 5
Thread 5
why do they have commmon names? what's wrong?
Thanks
You're passing a stack address from the main thread into all the child threads. There is no guarantee when these threads will be scheduled so you have no way of knowing whether the main thread will have updated its stack variable by the time each child gets around to reading it.
To avoid this, you need to allocate memory for the data being passed to each thread.
The easiest way to do this in your example is to use another automatic variable to store the data being passed to the new threads
void thread_starter(void* a);
int main() {
pthread_t thread1[num_students];
int thread_data[num_students];
int i = 0;
for(i = 0; i<num_students; i++) {
thread_data[i] = i;
pthread_create(&thread1[i], NULL, thread_starter, &thread_data[i]);
}
sleep(1);
}
Note also that you can avoid having to cast thread_starter if you give it the correct signature in your forward declaration.
For more complex programs you may need to dynamically allocate memory for each thread instead, passing ownership of that memory to the new threads.
int main() {
pthread_t thread1[num_students];
int i = 0;
for(i = 0; i<num_students; i++) {
int* data = malloc(sizeof(*data));
*data = i;
pthread_create(&thread1[i], NULL, thread_starter, data);
}
sleep(1);
}
void thread_starter(void* a) {
printf("Thread %i \n", *((int*)a));
free(a);
}
Finally, using sleep(1) isn't a very rigorous way of ensuring that all your threads will be run. It'd be better to use pthread_join instead
for(i = 0; i<num_students; i++) {
pthread_join(thread1[i], NULL);
}
sleep is not the correct tool to wait for spawned threads, use pthread_join for this.
Your main function terminating is equivalent to calling exit for the whole program and killing all the other threads.
Try This for Variation
void thread_starter(void* a) {
// Put a sleep(1) Here and see you will get even bizarre results
printf("Thread %i \n", *((int*)a));
}
Ok the problem here is of course
the race condition at this point here
int q = i;
pthread_create(&thread1[i], NULL, (void *) &thread_starter, (void *)&q);
lets say the first thread is created and the value at q is 0
now assume that before executing the statement Here
printf("Thread %i \n", *((int*)a));
if the main thread loops further and executes this statement here
int q = i;
again, then the q value changes (because its a reference) hence the problem
well one way to avoid this is to copy this reference variable in a local variable in thread routine also use mutex.
Sorry I was on a Hurry some more tips from my side
#define num_students 6
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // A Global Mutex
Will aquire a lock Here
pthread_mutex_lock( &mutex );
printf("\n Got Mutex %d\n", i);
int q = i;
pthread_create(&thread1[i], NULL, (void *) &thread_starter, (void *)&q);
and will release the lock Here in child Routine
int i = *((int*)a);
sleep(1);
pthread_mutex_unlock( &mutex );
printf("Thread %i \n", i);
P.S - Remove un necessary Prints and Sleeps where ever not applicable