How do you setup callback in reader/writer multi-threading program - c

I have written a reader/writer lock implementation and what I plan to do is to setup callback for each thread. Let's say we have 3 reader threads and 3 of them have read a value X. Now a writer thread updates the value X to X+100. This should send a callback to all the 3 reader threads that the value has changed. How do we implement such a callback in the multi-threading environment in C programming language?
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<stdint.h>
sem_t dbAccess;
sem_t readCountAccess;
int readCount=0;
void *Reader(void *arg);
void *Writer(void *arg);
int main(int argc, char* argv[])
{
int i=0, num_of_readers = 0, num_of_writers = 0;
//inititalizing semaphores
sem_init(&readCountAccess,0,1);
sem_init(&dbAccess,0,1);
pthread_t readers_tid[100], writer_tid[100];
num_of_readers = atoi(argv[1]);
num_of_writers = atoi(argv[2]);
for(i = 0; i < num_of_readers; i++)
{
pthread_create(&readers_tid[i], NULL , Reader, (void *) (intptr_t) i);
}
for(i = 0;i < num_of_writers; i++)
{
pthread_create(&writer_tid[i], NULL, Writer, (void *) (intptr_t) i);
}
for(i = 0; i < num_of_writers; i++)
{
pthread_join(writer_tid[i],NULL);
}
for(i = 0; i < num_of_readers; i++)
{
pthread_join(readers_tid[i], NULL);
}
sem_destroy(&dbAccess);
sem_destroy(&readCountAccess);
return 0;
}
void * Writer(void *arg)
{
sleep(1);
int temp=(intptr_t) arg;
printf("Writer %d is trying to enter into database for modifying the data\n",temp);
sem_wait(&dbAccess);
printf("Writer %d is writting into the database\n",temp);
printf("Writer %d is leaving the database\n");
sem_post(&dbAccess);
}
void *Reader(void *arg)
{
sleep(1);
int temp=(intptr_t) arg;
printf("Reader %d is trying to enter into the Database for reading the data\n",temp);
sem_wait(&readCountAccess);
readCount++;
if(readCount==1)
{
sem_wait(&dbAccess);
printf("Reader %d is reading the database\n",temp);
}
sem_post(&readCountAccess);
sem_wait(&readCountAccess);
readCount--;
if(readCount==0)
{
printf("Reader %d is leaving the database\n",temp);
sem_post(&dbAccess);
}
sem_post(&readCountAccess);
}

I can see 2 possible approaches:
1. Let the readers call a function when they'd like to be notified. The writer would have to mark something per-reader thread to say they have to call your CB on the shared variable. This would be my preferred approach, as I'd design readers to know when they need these updates.
2. Signal the readers to have them execute some code from a signal handler. You can use SIG_USR1/2 for that, and add some additional marking somewhere to know what changed and what to call. This is less clean, obviously, but I imagine would be more handy when these threads are created by 3rd party and you cannot control what they're doing.
HTH
EDIT
I forgot another important thing - if you're only updating a POD variable (int, etc) you may use the method 1 with a seqlock and a local copy per reader thread. This way every reader would know did the value change.
Another consideration is do you need readers to know only the last value or do they need to respond to every single change? if you need to respond to every change you can use a lock free queue, one per reader, and have the writer push into every one of them.

Related

is there a way to create a thread that will check other thread in C, dinning philosophers implementation

I have a question regarding threads in C, I know that to create a thread the function pthread_create is needed and I'm currently working on the dining philosopher problem and in this implementation of that problem I have to look if a philosopher has died of starvation.
I tested my programs and it works well, but to look if a philosopher has died I create another thread that'll always run and check in it if a philosoper has died.
a philosopher will die of starvation if he has not eat during a certain amount of time since his last meal.
Defining the general structure of the program and headers.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <sys/time.h>
struct t_phil;
typedef struct t_info t_info;
typedef struct t_phil t_phil;
typedef struct t_info
{
int num_of_phil;
t_phil *philo;
int min_dinner;
pthread_mutex_t *mutex;
int plate_eaten;
int num_of_dead_phil;
int time_to_die;
int time_to_sleep;
int time_to_eat;
pthread_mutex_t t_mut;
} t_info;
typedef struct t_phil
{
int number;
int has_eaten_all;
int finished_meal;
int is_dead;
t_info *data;
pthread_mutex_t *right;
pthread_mutex_t *left;
struct timeval last_dinner;
pthread_t thread;
} t_phil;
int count = 0;
Here is the function, that'll simulate the dinner, this one works as intended but I am open to possible error or improvement.
void *routine(void *args)
{
t_phil *philo = (t_phil *)(args);
int i = philo->number;
if ((philo->number % 2))
sleep(1);
gettimeofday(&philo->last_dinner, 0);
while (!philo->is_dead)
{
pthread_mutex_lock(philo->left);
printf("Philosopher : %i has take left fork\n", philo->number + 1);
pthread_mutex_lock(philo->right);
printf("Philosopher : %i has take right fork\n", philo->number + 1);
gettimeofday(&philo->last_dinner, 0);
printf("Philosopher :%i is eating in at %li\n", philo->number + 1, philo->last_dinner.tv_sec * 1000);
pthread_mutex_lock(&philo->data->t_mut);
// if (philo->data->num_of_dead_phil && !philo->data->min_dinner)
// break;
if (philo->is_dead)
break;
gettimeofday(&philo->last_dinner, NULL);
philo->finished_meal++;
if (philo->finished_meal == philo->data->min_dinner)
{
philo->data->plate_eaten++;
philo->has_eaten_all = 1;
}
sleep(philo->data->time_to_eat);
pthread_mutex_unlock(&philo->data->t_mut);
pthread_mutex_unlock(philo->left);
pthread_mutex_unlock(philo->right);
if (philo->has_eaten_all)
break;
printf("Philosopher : %i is now sleeping at %li\n", philo->number + 1, philo->last_dinner.tv_sec * 1000);
sleep(philo->data->time_to_sleep);
printf("Philosopher : %i is now thinking at %li\n", philo->number + 1, philo->last_dinner.tv_sec * 1000);
}
return (NULL);
}
This one function is the one not working as intended, and I don't know why is this happening right now, as my if statement seems to have the right condition but I am never entering in the if statement meaning that condition is never met while it should be.
I tested a lot of value and the same result happen each time
void *watchers_phil(void *args)
{
t_info *data = (t_info *)args;
t_phil *phil = data->philo;
int i = 0;
struct timeval now;
while (1)
{
if (data->plate_eaten == data->num_of_phil)
break;
while (i < data->num_of_phil)
{
if ((phil[i].last_dinner.tv_sec) >= ((phil[i].last_dinner.tv_sec) + (long int)data->time_to_die))
{
gettimeofday(&now, NULL);
printf("Unfortunately Philosopher : %i, is dead because of starvation at %li....", phil[i].number, (now.tv_sec * 1000));
phil[i].is_dead = 1;
}
i++;
}
i = 0;
}
return (NULL);
}
int main(int argc, char *argv[])
{
t_info data;
pthread_t watchers;
memset(&data, 0, sizeof(t_info));
data.num_of_phil = atoi(argv[1]);
data.min_dinner = atoi(argv[2]);
data.time_to_eat = atoi(argv[3]);
data.time_to_die = atoi(argv[4]);
data.time_to_sleep = atoi(argv[5]);
t_phil *philo = malloc(sizeof(t_phil) * data.num_of_phil);
if (!philo)
return (1);
pthread_mutex_t *mutex = malloc(sizeof(pthread_mutex_t) * data.num_of_phil);
data.mutex = mutex;
if (!mutex)
{
free(philo);
return (1);
}
int i = 0;
while (i < data.num_of_phil)
{
pthread_mutex_init(&data.mutex[i], NULL);
i++;
}
printf("Number : %i\n", data.num_of_phil);
pthread_mutex_init(&data.t_mut, NULL);
i = 0;
while (i < data.num_of_phil)
{
philo[i].number = i;
philo[i].has_eaten_all = 0;
philo[i].data = &data;
philo[i].is_dead = 0;
philo[i].right = &data.mutex[i];
if (i == (data.num_of_phil - 1))
philo[i].left = &data.mutex[0];
else
philo[i].left = &data.mutex[i + 1];
i++;
}
data.philo = philo;
i = 0;
while (i < data.num_of_phil)
{
pthread_create(&data.philo[i].thread, NULL, routine, &data.philo[i]);
i++;
}
pthread_create(&watchers, NULL, watchers_phil, &data);
i = 0;
while (i < data.num_of_phil)
{
pthread_join(data.philo[i].thread, NULL);
i++;
}
pthread_join(watchers, NULL);
printf("Dinner eaten : %i\n", data.plate_eaten);
i = 0;
while (i < data.num_of_phil)
{
pthread_mutex_destroy(&data.mutex[i]);
i++;
}
pthread_mutex_destroy(&data.t_mut);
}
I recommend the following approach:
Have an array containing a timestamp for each philosopher thread.
Each philosopher thread updates its respective timestamp either on beginning or ending eating. To determine its own death it can use this timestamp as well. You could store the eating time or the time when starvation occurs, I personally would rather do the latter as it requires calculating this starvation time just once (and you don't need the eating time anywhere else) while the former would need to do it on every test for starvation.
The monitoring thread iterates over all these timestamps doing the following:
Determine if a thread has starved (current time – just get it once in front of the loop! – being after timestamp stored, if you follow my recommendation above). Flag the thread as starved by some suitable way so that you can ignore it next time.
From non-starved threads remember the minimum value.
After iteration sleep as long until this minimum time will be reached (maybe waking up minimally earlier for better precision). If a philosopher updates the timestamp corresponding to this minimum – never mind, the monitor will wake up in vain, just doing nothing, but that won't hurt apart from consuming a bit of CPU time.
Updating the timestamps: You need to be aware that – unless you can guarantee atomic timestamp update – you need to protect them against race conditions between philosopher threads and monitoring thread.
I see two options for:
One single mutex for the entire array. Easy to implement, but either of the involved threads might block another one (two philosophers, if both trying to update at the same time, a philosopher the monitor or the monitor one or more philosophers). If one thread is preempted right while holding this mutex the blocked one(s) need(s) to wait until this thread is scheduled again.
One mutex for each timestamp. The advantage is that blocking only can occur between the monitor and one single philosopher while all other philosophers can go on as usual. The implementation is more complex, though, and the monitor thread will run its tests a bit slower (you won't notice...) due to having to lock and unlock mutexes again and again (system calls involved, these are rather expensive).
Philosophers should hold the mutex over the entire time between reading the timestamp for checking own starvation until having written the updated starvation time. This assures the philosopher cannot starve right while eating, though in between you should do as little work as possible, especially if you opt for one single mutex (if you cannot avoid, then rather opt for multiple ones).

Changing A Value in Mulithread Programming

I have a project about marriage operations. In this program, a thread called registrar uses marriage function. In this marriage operations, we have brides and grooms. Marriage function does decrease bride count and groom count one by one. But i have a problem while i want to decrease these count.
MAIN.c
#include<pthread.h>
#include<stdlib.h>
#include<stdio.h>
#include<semaphore.h>
#include "bride.h"
#include "groom.h"
pthread_t groomThread;
pthread_t brideThread;
sem_t registrarSemaphore;
pthread_mutex_t lock;
int *groomCount = 14;
int *brideCount = 20;
int *availableRegistrar;
void createBride(int *brideCount) {
pthread_create(&brideThread, NULL, &increaseBrideCount, (void *) brideCount);
}
void createGroom(int *groomCount) {
pthread_create(&groomThread, NULL, &increaseGroomCount, (void *) groomCount);
}
void deleteGroom(int *groomCount) {
pthread_create(&groomThread, NULL, &decreaseGroomCount, (void *) groomCount);
}
void deleteBride(int *brideCount) {
pthread_create(&brideThread, NULL, &decreaseBrideCount, (void *) brideCount);
}
void marriage() {
sem_init(&registrarSemaphore, 0, 2);
while (1) {
sem_getvalue(&registrarSemaphore, &availableRegistrar);
printf("\nAvailable Registrar Number = %d\n", availableRegistrar);
printf("bride %d\n", brideCount);
printf("groom %d\n", groomCount);
if (brideCount > 0 && groomCount > 0) {
sem_wait(&registrarSemaphore);
sem_getvalue(&registrarSemaphore, &availableRegistrar);
printf("Available Registrar %d \n", availableRegistrar);
printf("Marriage Bride %d and Groom %d \n", brideCount, groomCount);
pthread_mutex_lock(&lock);
deleteBride(brideCount);
pthread_mutex_unlock(&lock);
//pthread_join(brideThread, &brideCount);
pthread_mutex_lock(&lock);
deleteGroom(groomCount);
pthread_mutex_unlock(&lock);
//pthread_join(groomThread, &groomCount);
printf("Exiting critical region...\n\n");
/* END CRITICAL REGION */
sem_post(&registrarSemaphore);
}
int random = rand() % 100;
if (random % 7 > 4) {
printf("Bride Created\n");
pthread_mutex_lock(&lock);
createBride(brideCount);
//pthread_join(brideThread, &brideCount);
pthread_mutex_unlock(&lock);
}
if (random % 7 < 2) {
printf("Groom Created\n");
pthread_mutex_lock(&lock);
createGroom(groomCount);
//pthread_join(groomThread, &groomCount);
pthread_mutex_unlock(&lock);
}
pthread_join(brideThread, &brideCount);
pthread_join(groomThread, &groomCount);
for (int i = 0; i < 100000000; i++);
printf("------------------------------");
}
}
int main(void) {
marriage();
}
In pthread_create part, there are some functions as you can see. It defined in .h part. For example in bride.h, there are 2 functions about bride.
BRIDE.H
#ifndef BRIDE_H
#define BRIDE_H
void* increaseBrideCount(void * bride);
void* decreaseBrideCount(void * bride);
#endif
BRIDE.C
#include <pthread.h>
#include "bride.h"
void* increaseBrideCount(void *bride){
int brideCount = (int)bride;
brideCount++;
pthread_exit(brideCount);
}
void* decreaseBrideCount(void* bride){
int brideCount = (int)bride;
brideCount--;
pthread_exit(brideCount);
}
While im creating new bride,i cant send the new value of bride to the function. For example :
I have 20 brides and 14 grooms at first.
I have 2 available registrar
Marraige does.
Bride count = 19, groom count = 13
Then, i want to create new bride.
It count goes to = 1 :( Im trying to make it 20 again.
If you can help, i would be very happy. Thank you
Semaphores are used to make sure only one of the threads that might make a particular change does so at a time. The things being changed in this case are the bride and groom counts, so you need to "protect" them using semaphores. You even seem to have created semaphores for this purpose (brideSemaphore and groomSemaphore); you just need to use them.
By the way: if you use a semaphore only in a single thread, you're wasting your time (as seems to be the case w/ your registrarSemaphore) in marriage()). Either it needs to be used elsewhere as well, or not at all.

Simple pipelining using pthreads

Very recently I have started working on pthreads and trying to implement software pipelining with pthreads. To do that I have a written a toy program myself, a similar of which would be a part of my main project.
So in this program the main thread creates and input and output buffer of integer type and then creates a single master thread and passes those buffers to the master thread. The master thread in turn creates two worker threads.
The input and the output buffer that is passed from the main to the master thread is of size nxk (e.g. 5x10 of size int). The master thread iterates over a chunk of size k (i.e. 10) for n (i.e. 5) number of times.
There is a loop running in the master thread for k (5 in here) number of times. In each iteration of k the master thread does some operation on a portion of input data of size n and place it in the common buffer shared between the master and the worker threads. The master thread then signals the worker threads that the data has been placed in the common buffer.
The two worker threads waits for the signal from the master thread if the common buffer is ready. The operation on the common buffer is divided into half among the worker threads. Which means one worker thread would work on the first half and the other worker thread would work on the next half of the common buffer.
Once the worker threads gets the signal from the master thread, each of the worker thread does some operation on their half of the data and copy it to the output buffer. Then the worker threads informs the master thread that their operation is complete on the common buffer by setting flag values. An array of flags are created for worker threads. The master thread keeps on checking if all the flags are set which basically means all the worker threads finished their operation on the common buffer and so master thread can place the next data chunk into the common buffer safely for worker thread's consumption.
So essentially there is communication between the master and the worker threads in a pipelined fashion. In the very end I am printing the output buffer in the main thread. But I am getting no output at all. I have copy pasted my code with full comments on almost all steps.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/time.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#define MthNum 1 //Number of Master threads
#define WthNum 2 //Number of Worker threads
#define times 5 // Number of times the iteration (n in the explanation)
#define elNum 10 //Chunk size during each iteration (k in the explanation)
pthread_mutex_t mutex; // mutex variable declaration
pthread_cond_t cond_var; //conditional variarble declaration
bool completion_flag = true; //This global flag indicates the completion of the worker thread. Turned false once all operation ends
//marking the completion
int *commonBuff; //common buffer between master and worker threads
int *commFlags; //array of flags that are turned to 1 by each worker threads. So worker thread i turns commFlags[i] to 1
// the master thread turns commFlags[i] = 0 for i =0 to (WthNum - 1)
int *commFlags_s;
int counter; // This counter used my master thread to count if all the commFlags[i] that shows
//all the threads finished their work on the common buffer
// static pthread_barrier_t barrier;
// Arguments structure passed to master thread
typedef struct{
int *input; // input buffer
int *output;// output buffer
}master_args;
// Arguments structure passed to worker thread
typedef struct{
int threadId;
int *outBuff;
}worker_args;
void* worker_func(void *arguments);
void *master_func(void *);
int main(int argc,char*argv[]){
int *ipData,*opData;
int i,j;
// allocation of input buffer and initializing to 0
ipData = (int *)malloc(times*elNum*sizeof(int));
memset(ipData,0,times*elNum*sizeof(int));
// allocation of output buffer and initializing to 0
opData = (int *)malloc(times*elNum*sizeof(int));
memset(opData,0,times*elNum*sizeof(int));
pthread_t thread[MthNum];
master_args* args[MthNum];
//creating the single master thread and passing the arguments
for( i=0;i<MthNum;i++){
args[i] = (master_args *)malloc(sizeof(master_args));
args[i]->input= ipData;
args[i]->output= opData;
pthread_create(&thread[i],NULL,master_func,(void *)args[i]);
}
//joining the master thred
for(i=0;i<MthNum;i++){
pthread_join(thread[i],NULL);
}
//printing the output buffer values
for(j =0;j<times;j++ ){
for(i =0;i<elNum;i++){
printf("%d\t",opData[i+j*times]);
}
printf("\n");
}
return 0;
}
//This is the master thread function
void *master_func(void *arguments){
//copying the arguments pointer to local variables
master_args* localMasterArgs = (master_args *)arguments;
int *indataArgs = localMasterArgs->input; //input buffer
int *outdataArgs = localMasterArgs->output; //output buffer
//worker thread declaration
pthread_t Workers[WthNum];
//worker thread arguments declaration
worker_args* wArguments[WthNum];
int i,j;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init (&cond_var, NULL);
counter =0;
commonBuff = (int *)malloc(elNum*sizeof(int));
commFlags = (int *)malloc(WthNum*sizeof(int));
memset(commFlags,0,WthNum*sizeof(int) );
commFlags_s= (int *)malloc(WthNum*sizeof(int));
memset(commFlags_s,0,WthNum*sizeof(int) );
for(i =0;i<WthNum;i++){
wArguments[i] = (worker_args* )malloc(sizeof(worker_args));
wArguments[i]->threadId = i;
wArguments[i]->outBuff = outdataArgs;
pthread_create(&Workers[i],NULL,worker_func,(void *)wArguments[i]);
}
for (i = 0; i < times; i++) {
for (j = 0; j < elNum; j++)
indataArgs[i + j * elNum] = i + j;
while (counter != 0) {
counter = 0;
pthread_mutex_lock(&mutex);
for (j = 0; j < WthNum; j++) {
counter += commFlags_s[j];
}
pthread_mutex_unlock(&mutex);
}
pthread_mutex_lock(&mutex);
memcpy(commonBuff, &indataArgs[i * elNum], sizeof(int));
pthread_mutex_unlock(&mutex);
counter = 1;
while (counter != 0) {
counter = 0;
pthread_mutex_lock(&mutex);
for (j = 0; j < WthNum; j++) {
counter += commFlags[j];
}
pthread_mutex_unlock(&mutex);
}
// printf("master broad cast\n");
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&cond_var);
//releasing the lock
pthread_mutex_unlock(&mutex);
}
pthread_mutex_lock(&mutex);
completion_flag = false;
pthread_mutex_unlock(&mutex);
for (i = 0; i < WthNum; i++) {
pthread_join(Workers[i], NULL);
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond_var);
return NULL;
}
void* worker_func(void *arguments){
worker_args* localArgs = (worker_args*)arguments;
//copying the thread ID and the output buffer
int tid = localArgs->threadId;
int *localopBuffer = localArgs->outBuff;
int i,j;
bool local_completion_flag=false;
while(local_completion_flag){
pthread_mutex_lock(&mutex);
commFlags[tid] =0;
commFlags_s[tid] =1;
pthread_cond_wait(&cond_var,&mutex);
commFlags_s[tid] =0;
commFlags[tid] =1;
if (tid == 0) {
for (i = 0; i < (elNum / 2); i++) {
localopBuffer[i] = commonBuff[i] * 5;
}
} else { // Thread ID 1 operating on the other half of the common buffer data and placing on the
// output buffer
for (i = 0; i < (elNum / 2); i++) {
localopBuffer[elNum / 2 + i] = commonBuff[elNum / 2 + i] * 10;
}
}
local_completion_flag=completion_flag;
pthread_mutex_unlock(&mutex);//releasing the lock
}
return NULL;
}
But I have no idea where I have done wrong in my implementation since logically it seems to be correct. But definitely there is something wrong in my implementation. I have spent a long time trying different things to fix it but nothing worked. Sorry for this long post but I am unable to determine a section where I might have done wrong and so I couldn't concise the post. So if anybody could take a look into the problem and implementation and can suggest what changes needed to be done to run it as intended then that it would be really helpful. Thank you for your help and assistance.
There are several errors in this code.
You may start from fixing creation of worker threads:
wArguments[i] = (worker_args* )malloc(sizeof(worker_args));
wArguments[i]->threadId = i;
wArguments[i]->outBuff = outdataArgs;
pthread_create(&Workers[i],NULL,worker_func, (void *)wArguments);
You are initializing worker_args structs but incorrectly - passing pointer to array (void *)wArguments instead of pointers to array elements you just initialized.
pthread_create(&Workers[i],NULL,worker_func, (void *)wArguments[i]);
// ^^^
Initialize counter before starting threads that use it's value:
void *master_func(void *arguments)
{
/* (...) */
pthread_mutex_init(&mutex, NULL);
pthread_cond_init (&cond_var, NULL);
counter = WthNum;
When starting master thread, you incorrectly pass pointer to pointer:
pthread_create(&thread[i],NULL,master_func,(void *)&args[i]);
Please change this to:
pthread_create(&thread[i],NULL,master_func,(void *) args[i]);
All accesses to counter variable (as any other shared memory) must be synchronized between threads.
I think you should use semaphore based producer- consumer model like this
https://jlmedina123.wordpress.com/2014/04/08/255/

threads have the same id

I learn threads. I have read that thread terminates after it is out of a function (that is passed as parameter to pthread_create function).
So I create threads in the loop, they are executed and afterwards they are terminated.
(sorry for some long code)
But when I call a function pthread_create, new threads get the same ids. Why?
struct data {
FILE *f;
};
void *read_line_of_file(void *gdata) {
pthread_mutex_lock(&g_count_mutex); // only one thread can work with file,
//doing so we block other threads from accessing it
data *ldata = (data *) gdata;
char line[80];
int ret_val =fscanf(ldata->f,"%s",line);
pthread_mutex_unlock(&g_count_mutex); // allow other threads to access it
if (ret_val != EOF)
printf("%s %lu\n ", line, pthread_self());
// some time consuming operations, while they are being executed by one thread,
// other threads are not influenced by it (if there are executed on different cores)
volatile int a=8;
for (int i=0;i <10000;i++ )
for (int i=0;i <10000;i++ ) {
a=a/7+i;
}
if (ret_val == EOF) // here thread ends
pthread_exit((void *)1);
pthread_exit((void *)0);
}
int main() {
int kNumber_of_threads=3, val=0;
pthread_t threads[kNumber_of_threads];
int ret_val_from_thread=0;
data mydata;
mydata.f = fopen("data.txt","r");
if ( mydata.f == NULL) {
printf("file is not found\n");
return 0;
}
for( ; val != 1 ;) {
// THIS IS THAT PLACE, IDs are the same (according to the number of processes),
// I expected them to be changing..
for(int i=0; i<kNumber_of_threads; i++) {
pthread_create(&threads[i],NULL,read_line_of_file, &mydata);
}
for(int i=0; i<kNumber_of_threads; i++) {
pthread_join(threads[i], (void **) &ret_val_from_thread);
if (ret_val_from_thread != 0)
val = ret_val_from_thread;
}
printf(" next %d\n",val);
}
printf("work is finished\n");
fclose(mydata.f);
return 0;
}
as result, I see that id of threads are not being changed:
I wonder, are new threads really created?
Thanks in advance!
Thread IDs are only guaranteed to be different among currently running threads. If you destroy a thread and create a new one, it may well be created with a previously used thread ID.

Wrong implementation of Peterson's algorithm?

I was trying to learn something about parallel programming, so I tried to implement Peterson's algorithm for an easy example where one shared counter is incremented by 2 threads. I know that Peterson's isn't optimal due to busy waiting but I tried it only for study reasons.
I supposed that the critical section of this code is in the thread function add where the shared counter is incremented. So i call the enter_section function before the counter incrementation and after it I called the leave_function. Is this part wrong? Did I asses the critical section wrong? Problem is that the counter sometimes gives an unexpectable value when these 2 threads are done. It has to be a synchronization problem between threads but I just don't see it... Thanks for any help.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int counter; /* global shared counter */
int flag[2] = {0, 0}; /* Variables for Peterson's algorithm */
int turn = 0;
typedef struct threadArgs
{
pthread_t thr_ID;
int num_of_repeats;
int id;
} THREADARGS;
void enter_section (int thread) {
int other = 1 - thread;
flag[thread] = 1;
turn = thread;
while ((turn == thread) && (flag[other] == 1));
return;
}
void leave_section (int thread) {
flag[thread] = 0;
return;
}
void * add (void * arg) {
int i;
THREADARGS * a = (THREADARGS *) arg;
for (i = 0; i < a->num_of_repeats; i++) {
enter_section(a->id);
counter++;
leave_section(a->id);
}
return NULL;
}
int main () {
int i = 1;
pthread_attr_t thrAttr;
THREADARGS threadargs_array[2];
pthread_attr_init (&thrAttr);
pthread_attr_setdetachstate (&thrAttr, PTHREAD_CREATE_JOINABLE);
/* creating 1st thread */
threadargs_array[0].id = 0;
threadargs_array[0].num_of_repeats = 1000000;
pthread_create(&threadargs_array[0].thr_ID, &thrAttr, add, &threadargs_array[0]);
/* creating 2nd thread */
threadargs_array[1].id = 1;
threadargs_array[1].num_of_repeats = 2000000;
pthread_create(&threadargs_array[1].thr_ID, &thrAttr, add, &threadargs_array[1]);
/* free resources for thread attributes */
pthread_attr_destroy (&thrAttr);
/* waiting for 1st thread */
pthread_join (threadargs_array[0].thr_ID, NULL);
printf("First thread is done.\n");
/* waiting for 2nd thread */
pthread_join (threadargs_array[1].thr_ID, NULL);
printf("Second thread is done.\n");
printf("Counter value is: %d \n", counter);
return (EXIT_SUCCESS);
}
You have several problems here:
the access to your variables will we subject to optimization, so you'd have to declare them volatile, at least.
Algorithms like this that access data between threads without any of the lock data structures that are provided by POSIX can only work if your primitive operations are guaranteed to be atomic, which they usually aren't on modern processors. In particular the ++ operator is not atomic.
There would be several ways around this, in particular the new C standard C11 offers atomic primitives. But if this is really meant for you as a start to learn parallel programming, I'd strongly suggest that you first look into mutexes, condition variables etc, to learn how POSIX is intended to work.

Resources