pthread_join skipping first thread - multithreading

So I have the following code, some of it left out so it's easier to understand.
for (unsigned int t = 0; t < NUM_THREADS; t++)
{
if (pthread_create(&threads[t], NULL, thread_run, (void*) &threadData) != 0)
{
perror("pthread_create");
}//end if
}
for (unsigned int z = 0; z < NUM_THREADS; z++)
{
if (pthread_join(threads[z], NULL) != 0)
{
perror("pthread_join");
}
}
My Problem is the join function, it is skipping the first thread I create, and continuing on. The current solution I have is adding an extra thread and not making the first one do any work.
Any ideas why this might be happening?

IMO there is not pthreads problem; you are just creating NUM_THREADS + 1 threads and join only first NUM_THREADS of them.

Related

My semaphore module is not working properly(Dining philosopher)

I'm implementing a semaphore methods to understand synchronization and thread things.
By using my semaphore, I tried to solve the Dining Philosophers problem.
My plan was making deadlock situation first.
But I found that just only one philosopher eat repeatedly.
And I checked that my semaphore is working quite good by using other synchronization problems. I think there is some problem with grammar.
please let me know what is the problem.
Here is my code.
dinig.c (including main function)
#include "sem.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static tsem_t *chopstick[5];
static tsem_t *updating;
static int update_status (int i, int eating)
{
static int status[5] = { 0, };
static int duplicated;
int idx;
int sum;
tsem_wait (updating);
status[i] = eating;
/* Check invalid state. */
duplicated = 0;
sum = 0;
for (idx = 0; idx < 5; idx++)
{
sum += status[idx];
if (status[idx] && status[(idx + 1) % 5])
duplicated++;
}
/* Avoid printing empty table. */
if (sum == 0)
{
tsem_signal (updating);
return 0;
}
for (idx = 0; idx < 5; idx++)
fprintf (stdout, "%3s ", status[idx] ? "EAT" : "...");
/* Stop on invalid state. */
if (sum > 2 || duplicated > 0)
{
fprintf (stdout, "invalid %d (duplicated:%d)!\n", sum, duplicated);
exit (1);
}
else
fprintf (stdout, "\n");
tsem_signal (updating);
return 0;
}
void *thread_func (void *arg)
{
int i = (int) (long) arg;
int k = (i + 1) % 5;
do
{
tsem_wait (chopstick[i]);
tsem_wait (chopstick[k]);
update_status (i, 1);
update_status (i, 0);
tsem_signal (chopstick[i]);
tsem_signal (chopstick[k]);
}
while (1);
return NULL;
}
int main (int argc,
char **argv)
{
int i;
for (i = 0; i < 5; i++)
chopstick[i] = tsem_new (1);
updating = tsem_new (1);
for (i = 0; i < 5; i++)
{
pthread_t tid;
pthread_create (&tid, NULL, thread_func, (void *) (long) i);
}
/* endless thinking and eating... */
while (1)
usleep (10000000);
return 0;
}
sem.c(including semaphore methods)
#include "sem.h"
.
sem.h(Header for sem.c)
#ifndef __SEM_H__
#define __SEM_H__
#include <pthread.h>
typedef struct test_semaphore tsem_t;
tsem_t *tsem_new (int value);
void tsem_free (tsem_t *sem);
void tsem_wait (tsem_t *sem);
int tsem_try_wait (tsem_t *sem);
void tsem_signal (tsem_t *sem);
#endif /* __SEM_H__ */
compile command
gcc sem.c dining.c -pthread -o dining
One problem is that in tsem_wait() you have the following code sequence outside of a lock:
while(sem->count <= 0)
continue;
There's no guarantee that the program will actually re-read sem->count - the compiler is free to produce machine code that does something like the following:
int temp = sem->count;
while(temp <= 0)
continue;
In fact, this will likely happen in an optimized build.
Try changing your busy wait loop to something like this so the count is checked while holding the lock:
void tsem_wait (tsem_t *sem)
{
pthread_mutex_lock(&(sem->mutexLock));
while (sem->count <= 0) {
pthread_mutex_unlock(&(sem->mutexLock));
usleep(1);
pthread_mutex_lock(&(sem->mutexLock));
}
// sem->mutexLock is still held here...
sem->count--;
pthread_mutex_unlock(&(sem->mutexLock));
}
Strictly speaking, you should do something similar for tsem_try_wait() (which you're not using yet).
Note that you might want to consider using a pthread_cond_t to make waiting on the counter changing more efficient.
Finally, your code to 'get' the chopsticks in thread_func() has the classic Dining Philosopher deadlock problem in the situation where each philosopher simultaneously acquires the 'left' chopstick (chopstick[i]) and ends up waiting forever to get the 'right' chopstick (chopstick[k]) since all the chopsticks are in some philosopher's left hand.

mutex and its effect on execution time (and cpu usage)

I wrote a very simple test program to examine efficiency of pthread mutex. But I'm not able to analyse the results I get. (I can see 4 CPUs in Linux System Monitor and that's why I have at least 4 active threads, because I want to keep all of them busy.) The existence of mutex is not necessary in the code.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t lock1, lock2, lock3, lock4;
void do_sth() { /* just open a files, read it and copy to another file */
int i;
for (i = 0; i < 1; i++) {
FILE* fp = fopen("(2) Catching Fire.txt", "r");
if (fp == NULL) {
fprintf(stderr, "could not open file\n");
exit(1);
}
char filename[20];
sprintf(filename, "a%d", (int)pthread_self());
FILE* wfp = fopen(filename, "w");
if (wfp == NULL) {
fprintf(stderr, "could not open file for write\n");
exit(1);
}
int c;
while (c = fgetc(fp) != EOF) {
c++;
fputc(c, wfp);
}
close(fp);
close(wfp);
}
}
void* routine1(void* param) {
pthread_mutex_lock(&lock1);
do_sth();
pthread_mutex_unlock(&lock1);
}
void* routine2(void* param) {
pthread_mutex_lock(&lock2);
do_sth();
pthread_mutex_unlock(&lock2);
}
void* routine3(void* param) {
pthread_mutex_lock(&lock3);
do_sth();
pthread_mutex_unlock(&lock3);
}
void* routine4(void* param) {
pthread_mutex_lock(&lock4);
do_sth();
pthread_mutex_unlock(&lock4);
}
int main(int argc, char** argv) {
int i ;
pthread_mutex_init(&lock1, 0);
pthread_mutex_init(&lock2, 0);
pthread_mutex_init(&lock3, 0);
pthread_mutex_init(&lock4, 0);
pthread_t thread1[4];
pthread_t thread2[4];
pthread_t thread3[4];
pthread_t thread4[4];
for (i = 0; i < 4; i++)
pthread_create(&thread1[i], NULL, routine1, NULL);
for (i = 0; i < 4; i++)
pthread_create(&thread2[i], NULL, routine2, NULL);
for (i = 0; i < 4; i++)
pthread_create(&thread3[i], NULL, routine3, NULL);
for (i = 0; i < 4; i++)
pthread_create(&thread4[i], NULL, routine4, NULL);
for (i = 0; i < 4; i++)
pthread_join(thread1[i], NULL);
for (i = 0; i < 4; i++)
pthread_join(thread2[i], NULL);
for (i = 0; i < 4; i++)
pthread_join(thread3[i], NULL);
for (i = 0; i < 4; i++)
pthread_join(thread4[i], NULL);
printf("Hello, World!\n");
}
I execute this program in two ways, with and without all the mutex. and I measure time of execution (using time ./a.out) and average cpu load (using htop). here is the results:
first: when I use htop, I can see that loadavg of the system considerably increases when I do not use any mutex in the code. I have no idea why this happens. (is 4 active threads not enough to get the most out of 4 CPUs?)
second: It takes (a little) less time for the program to execute with all those mutex than without it. why does it happen? I mean, it should take some time to sleep and wake up a thread.
edit: I guess, when I use locks I put other threads to sleep and it eliminates a lot of context-switch (saving some time), could this be the reason?
You are using one lock per thread, so that's why when you use all the mutexes you don't see an increase in the execution time of the application: dosth() is not actually being protected from concurrent execution.
Since all the threads are working on the same file, all they should be accessing it using the same lock (otherwise you will have incorrect results: all the threads trying to modify the file at the same time).
Try running again the experiments using just one global lock.

Communication between two pthreads to display

I have looked at other questions and still cant seem to understand this concept. I have created four threads and each thread needs to communicate with the same thread. (Min and Display), (Max and Display), and so on..
I know I need to use:
pthread_mutex_t myLock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&myLock1);
(some global variable) = ....;
pthread_mutex_unlock(&myLock1);
Here is one of the threads I have created:
pthread_create(&minThread, NULL, (void *) mini, (void *) numbers);
pthread_join(minThread, (void *) &min);
void *mini(void *numbs1)
{
int *numbers = (int *) numbs1;
min = malloc(sizeof(int));
*min = (numbers[0]);
for (i = 0; i < length; i++) //Computing min value
{
if ( numbers[i] < *min )
{
*min = numbers[i];
}
}
printf("Min has been computed.\n");
pthread_exit(min);
}
I am now supposed to incorporate the use of another thread (disThread) to display the variable I have computed in minThread (min) and other similar threads that have done computations using those mutex system calls I have specified. How can I set this up correctly? Any tips are appreciated to further my understanding.
Turns out that using the mutex system calls are pretty simple. For anyone else who runs into a similar problem, the thread functions void *mini and void *disi follow this format:
void *mini(void *numbs1)
{
pthread_mutex_lock(&theLock);
int *numbers = (int *) numbs1;
min = malloc(sizeof(int));
*min = (numbers[0]);
for (i = 0; i < LENGTH; i++) //Computing min value
{
if ( numbers[i] < *min )
{
*min = numbers[i];
}
}
pthread_mutex_unlock(&theLock);
printf("Min has been computed.\n");
pthread_exit(min);
}
void *disi()
{
pthread_mutex_lock(&theLock);
x = *min; //Displaying min value (x initialized as global variable)
pthread_mutex_unlock(&theLock);
printf("The Minimum value is %d\n", x);
}
A mutex lock and mutex unlock should cover the range of a shared variable between two threads. This is so there is no interference between the two threads working simultaneously.

implementing a barrier issue

static int barrier_counter = 0;
pthread_cond_t condition;
pthread_mutex_t local_lock;
int init_barrier(int n) {
if (n < 0) {
return -1;
}
barrier_counter = n;
pthread_mutex_init(&local_lock, NULL);
pthread_cond_init(&condition, NULL);
return 0;
}
int barrier() {
pthread_mutex_trylock(&local_lock);
barrier_counter--;
printf("inside barrier befor the while n is : %d \n",barrier_counter );
while (0 < barrier_counter) {
printf("inside the barrier n is : %d\n", barrier_counter);
pthread_cond_wait(&condition,&local_lock);
}
printf("befor bordcast : %d \n",barrier_counter );
pthread_cond_broadcast(&condition);
printf("done the brodcast when n is : %d \n",barrier_counter );
pthread_mutex_unlock(&local_lock);
return 0;
}
we tried to implement barrier but somehow we dont get to do broadcast and we finish anyway.
we dont even get deadlock, there are few threads that are actually waiting but not the amount we specified in init_barrier.
pthread_cond_wait() requires a locked mutex. Your call to pthread_mutex_trylock() might fail, and so continue without acquiring the mutex.
I suggest you use pthread_mutex_lock() instead.
Also, unless you're looking to re-implement barriers, You should use pthread_barrier_init() and pthread_barrier_wait().

How to implement barrier using posix semaphores?

How to implement barrier using posix semaphores?
void my_barrier_init(int a){
int i;
bar.number = a;
bar.counter = 0;
bar.arr = (sem_t*) malloc(sizeof(sem_t)*bar.number);
bar.cont = (sem_t*) malloc(sizeof(sem_t)*bar.number);
for(i = 0; i < bar.number; i++){
sem_init(&bar.arr[i], 0, 0);
sem_init(&bar.cont[i], 0, 0); }
}
void my_barrier_wait(){
int i;
bar.counter++;
if(bar.number == bar.counter){
for(i = 0; i < bar.number-1; i++){ sem_wait(&bar.arr[i]); }
for(i = 0; i < bar.number-1; i++){ sem_post(&bar.cont[i]); }
bar.counter = 0;
}else{
sem_post(&bar.arr[pthread_self()-2]);
sem_wait(&bar.cont[pthread_self()-2]);
}
}
When function my_barrier_wait is called, first (N-1) times it would set(+1) for semaphores in array 'arr' and go to sleep(calling sem_wait). N-th time it decrements semaphores in 'arr' and SHOULD (as I expect) wake up [0..bar.number-1] threads posting +1 for semaphores in 'cont' array. It doesn't work like barrier.
You need to look at this (PDF), The Little Book of Semaphores by Allen Downey. Specifically section 3.6.7. It's in Python, but gist of it should be clear enough.

Resources