Mutual Exclusion (Mutex)

Given the following code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

#define NB_THREADS 5

typedef struct {
    int n;
} data;

void print_char_by_char(char *s, int n) {
    int i = 0;
    while (s[i] != '\0') {

        printf("%c", s[i]);
        fflush(stdout); // Forcing stdout to be displayed
        i++;

        // Sleep for 0.5 second
        struct timespec tim, tim2;
        tim.tv_sec  = 0;
        tim.tv_nsec = 500000000L;
        nanosleep(&tim , &tim2);
    }
    printf("%d \n", n);
    sleep(1);
}

void *mytask(void *p_data) {
    char *message = "Thread_n ";
    data *info = p_data;
    print_char_by_char(message, info->n);
}

int main(void) {
    printf("main start\n");
    int i;
    pthread_t threads[NB_THREADS];
    data infos[NB_THREADS];
    for (i = 0; i < NB_THREADS; i++) {
        infos[i].n = i;
        pthread_create(&threads[i], NULL, mytask, &infos[i]);
    }
    for (i = 0; i < NB_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    printf("main end\n");
}
  1. Compile and run this program. What is outputted on the standard output? Explain.
  2. Use a mutex so that every thread can display the message correctly: only one thread can be printing on stdout at a time.

Here is some help to manage mutex :

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // Create a mutex
pthread_mutex_lock(&mutex); // Get the mutex (locking every other callers)
pthread_mutex_unlock(&mutex); // Release the mutex (Unlock one caller)

Note: Mutex needs to be initialized in a global variable so that every thread can access it.

Semaphores

Update the previous program and use a semaphore instead of a mutex.

Here is some help to manage semaphores:

#define SEMNAME "monsem" 
sem_t *attente;
attente = sem_open(SEMNAME, O_CREAT|O_EXCL, 0777, 1); // Create the semaphore
if(attente == SEM_FAILED) {
    perror("unable to create semaphore"); 
    sem_unlink(SEMNAME);
    exit( -1 );
}
sem_wait(attente); // Decrease the semaphore counter
sem_post(attente); // Increase the semaphore counter
sem_close(attente); // Close the semaphore
sem_unlink(SEMNAME); // unlink the semaphore

Synchronization barrier

Create a program where 10 threads are executed. Each thread will sleep for a random time. Then each thread will wait for others using a semaphore. The last thread will wake all others so they can end normally.

Hint: You have to use one semaphore, one mutex and one global variable to to that.

Algorithm

// Considering there are N process / threads
// Considering Semaphore is initialized to 0
Lock(MUTEX)
finished_threads++;
if (finished_threads == N) {
    for (int i = 0; i < N -1; i++) {
        Post(Semaphore);
    }
    finished_threads = 0;
    Unlock(MUTEX)
} else {
    Unlock(MUTEX)
    Wait(Semaphore)
}