Reusable barrier implementation using POSIX semaphores - c

Need a solution that creates 5 pthreads. Each pthread executes a function that involves iterating through a loop 10 times. In each iteration of the loop, a thread increments an int from 0 to 0.9*MAX_INT and then prints the iteration number. Make sure that each of the 5 threads finish the ith iteration of the loop before they can start the (i+1)th iteration (i.e. all threads synchronize/rendezvous towards the end of each iteration). I need to use a two-phase barrier implemented using POSIX semaphores to enforce the synchronization constraint
I wrote following code am I correct ?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int thread_count;
void* MyThread(void* rank);
int main()
{
long thread;
pthread_t* thread_handles;
thread_count = 5;
thread_handles = malloc (thread_count*sizeof(pthread_t));
for (thread = 0; thread < thread_count; thread++)
pthread_create(&thread_handles[thread],NULL,MyThread,(void*) thread);
for (thread = 0; thread < thread_count; thread++)
pthread_join(thread_handles[thread], NULL);
free(thread_handles);
return 0;
}
void* Hello(void* rank)
{
long my_rank = (long) rank;
int a,i;
a=0;
for(i=0;i<10;i++)
{
int n = 5;
int count = 0;
pthread_mutex_t mutex = Semaphore(1)
barrier = Semaphore(0)
a = a + 0.9*MAX_INT;
printf("this is %d iteration\n",i);
mutex.wait()
count = count + 1
mutex.signal()
if count == n: barrier.signal() # unblock ONE thread
barrier.wait()
barrier.signal()
}
}
Edit:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <semaphore.h>
typedef struct {
int n;
int count;
sem_t mutex;
sem_t turnstyle;
sem_t turnstyle2;
} barrier_t;
void init_barrier(barrier_t *barrier, int n)
{
barrier->n = n;
barrier->count = 0;
sem_init(&barrier->mutex, 0, 1);
sem_init(&barrier->turnstyle, 0, 0);
sem_init(&barrier->turnstyle2, 0, 0);
}
void phase1_barrier(barrier_t *barrier)
{
sem_wait(&barrier->mutex);
if (++barrier->count == barrier->n) {
int i;
for (i = 0; i < barrier->n; i++) {
sem_post(&barrier->turnstyle);
}
}
sem_post(&barrier->mutex);
sem_wait(&barrier->turnstyle);
}
void phase2_barrier(barrier_t *barrier)
{
sem_wait(&barrier->mutex);
if (--barrier->count == 0) {
int i;
for (i = 0; i < barrier->n; i++) {
sem_post(&barrier->turnstyle2);
}
}
sem_post(&barrier->mutex);
sem_wait(&barrier->turnstyle2);
}
void wait_barrier(barrier_t *barrier)
{
phase1_barrier(barrier);
phase2_barrier(barrier);
}
#define NUM_THREADS 5
void *myThread(void *);
int main(int argc, char **argv)
{
pthread_t threads[NUM_THREADS];
barrier_t barrier;
int i;
init_barrier(&barrier, NUM_THREADS);
for (i = 0; i < NUM_THREADS; i++) {
pthread_create(&threads[i], NULL, myThread, &barrier);
}
for (i = 0; i < NUM_THREADS, i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
void *myThread(void *arg)
{
barrier_t *barrier = arg;
int i,a;
for(i=0;i<10;i++)
{
a = a + 0.9*MAX_INT;
printf("this is %d iteration\n",i);
}
return NULL;
}

OK, if we examine the Barrier object in, "The Little Book of Semaphores", section 3.7.7, we see that we need a mutex and 2 semaphores called turnstile and turnstile2 (a mutex can be a semaphore that is initialized to 1).
Since we have to use POSIX semaphores, pthreads, and INT_MAX, we start by including the requisite header files:
#include <pthread.h>
#include <semaphore.h>
#include <limits.h>
The book makes the Barrier an object; however, in C, we don't really have objects, but we can create a struct with some functions to operate on it:
typedef struct {
int n;
int count;
sem_t mutex;
sem_t turnstile;
sem_t turnstile2;
} barrier_t;
We can create a function to initialize a barrier:
void init_barrier(barrier_t *barrier, int n)
{
barrier->n = n;
barrier->count = 0;
sem_init(&barrier->mutex, 0, 1);
sem_init(&barrier->turnstile, 0, 0);
sem_init(&barrier->turnstile2, 0, 0);
}
And implement the phase1 function, as in the book:
void phase1_barrier(barrier_t *barrier)
{
sem_wait(&barrier->mutex);
if (++barrier->count == barrier->n) {
int i;
for (i = 0; i < barrier->n; i++) {
sem_post(&barrier->turnstile);
}
}
sem_post(&barrier->mutex);
sem_wait(&barrier->turnstile);
}
Note that the sem_post function only posts a single time, so a loop is required to post the turnstile n times.
The phase2 function also follows directly in the same manner:
void phase2_barrier(barrier_t *barrier)
{
sem_wait(&barrier->mutex);
if (--barrier->count == 0) {
int i;
for (i = 0; i < barrier->n; i++) {
sem_post(&barrier->turnstile2);
}
}
sem_post(&barrier->mutex);
sem_wait(&barrier->turnstile2);
}
Finally, we can implement the wait function:
void wait_barrier(barrier_t *barrier)
{
phase1_barrier(barrier);
phase2_barrier(barrier);
}
Now, in your main function, you can allocate and initialize a barrier and pass it to your spawned threads:
#define NUM_THREADS 5
void *myThread(void *);
int main(int argc, char **argv)
{
pthread_t threads[NUM_THREADS];
barrier_t barrier;
int i;
init_barrier(&barrier, NUM_THREADS);
for (i = 0; i < NUM_THREADS; i++) {
pthread_create(&threads[i], NULL, myThread, &barrier);
}
for (i = 0; i < NUM_THREADS, i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
And finally, implement the thread:
void *myThread(void *arg)
{
barrier_t *barrier = arg;
int i;
int a;
for (i = 0; i < 10; i++) {
for (a = 0; a < 0.9*INT_MAX; a++);
printf("this is %d iteration\n", i);
wait_barrier(barrier);
}
return NULL;
}

Related

pthread code and How to reach this output

I want to Interpret how to reach this output for at least 5 different outputs.
And Modify the program to fix this problem.How Can I do it?
#include <stdio.h>
#include <pthread.h>
#define NUM_THREADS 4
void *threadFunc(void *pArg)
{
int *p = (int*)pArg;
int myNum = *p;
printf("Thread number %d\n", myNum);
return 0;
}
int main(void)
{
int i;
pthread_t tid [NUM_THREADS];
for(i = 0; i < NUM_THREADS; i++)
{
pthread_create(&tid[i], NULL, threadFunc, &i);
}
for(i = 0; i < NUM_THREADS; i++)
{
pthread_join(tid [i], NULL);
}
return 0;
}
Thread function receives pointer to int. Memory it points to is shared between threads, so while thread function reads value of i it is changed by main thread. This is race condition.
You can fix it by storing individual i values for each thread:
#include <stdio.h>
#include <pthread.h>
#define NUM_THREADS 4
void *threadFunc(void *pArg)
{
int *p = (int*)pArg;
int myNum = *p;
printf("Thread number %d\n", myNum);
return NULL; // thread function returns a pointer
}
int main(void)
{
int i;
pthread_t tid[NUM_THREADS];
int data[NUM_THREADS];
for (i = 0; i < NUM_THREADS; i++)
{
data[i] = i;
pthread_create(&tid[i], NULL, threadFunc, data+i); // `data+i` is equivalent to `&data[i]`
}
for (i = 0; i < NUM_THREADS; i++)
{
pthread_join(tid [i], NULL);
}
return 0;
}
Another option is to pass an integer as a pointer value. It doesn't require storage for each thread but may cause truncating problems because of int<->intptr_t conversion.
#include <stdio.h>
#include <pthread.h>
#include <inttypes.h> // for intptr_t
#define NUM_THREADS 4
void *threadFunc(void *arg)
{
int myNum = (intptr_t)arg;
printf("Thread number %d\n", myNum);
return NULL; // thread function returns a pointer
}
int main(void)
{
int i;
pthread_t tid[NUM_THREADS];
for (i = 0; i < NUM_THREADS; i++)
{
pthread_create(&tid[i], NULL, threadFunc, (void *)(intptr_t)i);
}
for (i = 0; i < NUM_THREADS; i++)
{
pthread_join(tid [i], NULL);
}
return 0;
}

Strange behavior when functions created in pthread_create accept pointer-to-int

#include <stdio.h>
#include <pthread.h>
void *runner(void * p)
{
int *line = p;
printf("line: %d\n", *line);
}
int main()
{
pthread_t tid[2];
for (int i = 0; i < 2; i++)
pthread_create(&tid[i], 0, runner, &i);
for (int i = 0; i < 2; i++)
pthread_join(tid[i], NULL);
return 0;
}
For the above code I expect the output to be
line 0
line 1
But the output is actually
line 1
line 2
So what is wrong with this code? How did i get incremented? Do I have to pass structs to the runner function?
There's no guarantee that printf("line: %d\n", *line); line will finish before pthread_create returns, which means you have a race on i.
(The main thread tries to increment it and the new threads try to read it
via their argument pointer).
You can solve the problem by passing pointers to different objects (one per thread, optimally cache-aligned, but that hardly matters here):
#include <stdio.h>
#include <pthread.h>
void *runner(void * p)
{
int *line = p;
printf("line: %d\n", *line);
return 0;
}
int main()
{
pthread_t tid[2];
int ints[2];
for (int i = 0; i < 2; i++){
ints[i]=i;
if(pthread_create(&tid[i], 0, runner, &ints[i])) return 1;
}
for (int i = 0; i < 2; i++)
pthread_join(tid[i], NULL);
return 0;
}
or by passing the i by value (by casting it to void*):
#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
void *runner(void * p)
{
printf("line: %d\n", (int)(intptr_t)p);
return 0;
}
int main()
{
pthread_t tid[2];
int ints[2];
for (int i = 0; i < 2; i++){
if(pthread_create(&tid[i], 0, runner, (void*)(intptr_t)i)) return 1;
}
for (int i = 0; i < 2; i++)
pthread_join(tid[i], NULL);
return 0;
}

calling method from a new thread C

I'm working on a project (NOT HOMEWORK), building a multi-thread sudoku solution validator in C. I'm new to C so excuse the bad code quality as I'm still improving.
I want to call the method row_check 9 times from 9 separate threads. For the method as parameters I pass the row number (arg) and array name (arr). I have created the thread but I'm unsure how to pass the parameters properly to the method. Can anyone help me with this?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void* row_check(void* arg, int *arr)
{
int i = *((int *)arg); //trying to convert row number to int
int j, flag;
while(i < 9)
{
flag=0x0000;
for(j = 0; j < 9; j++)
flag |= 1 << (arr[i][j]-1);
if (flag != 0x01FF)
report("row", i, j-1);
}
}
void report(char *s, int i, int j)
{
printf("\nThe sudoku is INCORRECT");
printf("\nin %s. Row:%d,Column:%d", s, i+1, j+1);
getch();
exit(0);
}
int main(int argc, char* argv[])
{
int i,j;
char arr1[9][9];
FILE *file = fopen(argv[1], "r");
if (file == 0)
{
fprintf(stderr, "failed");
exit(1);
}
int col=0, row=0;
int num;
while(fscanf(file, "%d ", &num) == 1)
{
arr1[row][col] = num;
col++;
if(col == 9)
{
row++;
col = 0;
}
}
fclose(file);
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
int n;
for(n=0; n < 9; n++) //creating 9 threads
{
pthread_create(&tid, &attr, row_check, n);
pthread_join(tid, NULL);
}
return 0;
}
The thread entry function has to be of the format void *(*start_routine) (void *), which means it receives only one parameter - pointer to anything you like.
The most used technique is to define a struct with the values you want to pass to the thread entry function. Create a variable of that type, initialize it and pass its address to the thread entry function.
Example:
typedef thread_data_s
{
char *ptr;
int row_num; // I would prefer to define it as `unsigned int` but I stick to your example
// + any other data you want to pass to the thread
} thread_data_t;
....
thread_data_t data[NUM_OF_THREADS];
....
for(n=0; n < NUM_OF_THREADS; n++) //creating 9 threads
{
data[n].ptr = &arr1[n][0];
data[n].row_num = n;
pthread_create(&tid, &attr, row_check, &data[n]);
}
...
for(n=0; n < NUM_OF_THREADS; n++) // waiting for all the threads here
{
pthread_join(tid, NULL);
}
And your entry function should look something like this:
void* row_check(void* data)
{
//int i = *((int *)arg); //trying to convert row number to int
thread_data_t *my_data_ptr = data;
int j, flag;
while(i < 9)
{
flag=0x0000;
for(j = 0; j < 9; j++)
flag |= 1u << ( (my_data_ptr->ptr)[my_data_ptr->row_num][j] - 1 );
// Shouldn't it be under the `for` loop block? If so, please add `{}` to the `for` loop
if (flag != 0x01FF)
report("row", my_data_ptr->row_num, j-1);
}
return NULL;
}

How to make a code for critical section in c for n processes(Bakery algorithm)

I have got a project from my university for critical section problem of n processes. I have made a code for 2 processes in c But I could not figure out how to get it working for n process . The code is in C for linux threads.
Here is code for 2 Processes.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int flag[2];
int turn;
const int MAX = 1e9;
int ans = 0;
void lock_init(){
flag[0]=flag[1]=0;
turn = 0;
}
void lock(int self){
flag[self]=1;
turn = 1-self;
while(flag[1-self]==1 && turn == 1-self);
}
void unlock(int self){
flag[self]=0;
}
void* func(void *s){
int i=0;
int *limitptr = (int*) s;
int self = *limitptr;
printf("Thread %d in queue for critical section\n",self);
lock(self);
printf("Thread %d in critical section\n",self);
for(i=0;i<MAX;i++){
ans++;
}
printf("Thread %d done counting\n",self);
printf("Thread %d is exiting critical section\n",self);
unlock(self);
}
int main(){
pthread_t p1, p2;
int a=0,b=1;
lock_init();
pthread_create(&p1, NULL, func, &a);
pthread_create(&p2, NULL, func, &b);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
printf("Exiting Main\n");
return 0;
}
Any help would be appreciated.
Thank You. :)
use a mutex
#include <pthread.h>
declare the mutex like so:
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
then at the beginning of a critical section call:
pthread_mutex_lock( &myMutex );
and at the end of the critical section call:
pthread_mutex_unlock( &myMutex );
it does not matter how many threads are using that critical section, only one thread will be able to access it at a time
Thank You for your valuable time and answers.
I Found A solution for My problem and thought of sharing it.I Implemented Bakery Algorithm In C.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
int N;
int global = 10;
int entering[100];
int number[100];
int max(int number[100]) {
int i = 0;
int maximum = number[0];
for (i = 0; i < N; i++) {
if (maximum < number[i])
maximum = number[i];
}
return maximum;
}
void lock(int i) {
int j = 0;
entering[i] = TRUE;
number[i] = 1 + max(number);
entering[i] = FALSE;
for (j = 0; j < N; j++) {
while (entering[j]);
while (number[j] != 0 && (number[j] < number[i] || (number[i] == number[j]) && j < i)) {}
}
}
void unlock(int i) {
number[i] = 0;
}
void *fn(void *integer) {
int i = (int) integer;
lock(i);
printf("\n\n-----------Process %d---------",i);
printf("\nProcess %d is Entering Critical Section\n",i);
global++;
printf("%d is the value of global \n",global);
printf("Process %d is leaving Critical Section\n",i);
printf("----------------------------------\n\n");
unlock(i);
}
int main()
{
printf("Enter Number of Process\n");
scanf("%d",&N);
int th[N];
void *fn(void *);
pthread_t thread[N];
int i = 0;
for (i = 0; i < N; i++) {
th[i] = pthread_create(&thread[i], NULL, fn, (void *)i);
pthread_join(thread[i], NULL);
}
return EXIT_SUCCESS;
}
Again Thank You :)

producer and consumer with mutexes and pthreading

So I am having a little trouble with the producer and consumer problem with 2 threads and mutexes. What I am trying to do is have the producer fill an array with 10 1's. Then the consumer consumes each 1 and makes it a 0. This filling and emptying just repeats 10 times. Here is what I have so far but it gets stuck on the first cycle:
#include <stdio.h>
#include <pthread.h>
#define N 10
pthread_mutex_t mut;
pthread_cond_t condc,condp;
int queue[N];
int buffer;
void* prod() {
int i;
for(i = 0; i<10; i++) {
pthread_mutex_lock(&mut);
while(queue[N] != 0) {
pthread_cond_wait(&condp, &mut);
}
int k = 0;
for(k=0; k<10; k++) {
queue[k] = 1;
}
pthread_cond_signal(&condc);
pthread_mutex_unlock(&mut);
printf("\nproduced\n");
}
pthread_exit(0);
}
void* cons() {
int i;
for(i = 0; i<10; i++) {
pthread_mutex_lock(&mut);
while(queue[N] == 0) {
pthread_cond_wait(&condc, &mut);
}
int k = 0;
for(k=0; k<10; k++) {
queue[k] = 0;
}
pthread_cond_signal(&condp);
pthread_mutex_unlock(&mut);
printf("\nconsumed\n");
}
pthread_exit(0);
}
main() {
pthread_t producer, consumer;
pthread_mutex_init(&mut, 0);
pthread_cond_init(&condc, 0);
pthread_cond_init(&condp, 0);
pthread_create(&consumer,NULL,&cons, NULL);
pthread_create(&producer,NULL,&prod, NULL);
pthread_join(producer,0);
pthread_join(consumer,0);
pthread_cond_destroy(&condc);
pthread_cond_destroy(&condp);
pthread_mutex_destroy(&mut);
return 0;
}
You don't initialize the members of queue to any particular value before you start reading them. Also, you read queue out of range -- it has ten values but you read the eleventh. Lastly, you are never changing the value you read -- you set the first ten values, which you never look at.

Resources