How to implement semaphores with threads without global variables - c

My current code answers the producer consumer question, but I want to implement it in a different way. I do not want to use a global variable to keep track of the count in my buffer stack . What should my thought process be?
typedef int semaphore;
semaphore mutex, full, empty;
int count = 0;
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
} arg;
int buffer[N];
These are the functions that use count
int remove_item()
{
int ret = buffer[--count];
buffer[count] = 0;
return ret;
}
void insert_item(int item)
{
buffer[count++] = item;
}
int produce_item(){
int item = rand()%50 +1;
printf("Producer produces %d\n",item);
sleep(1);
return item;
}
And my producer consumer functions
void* consumer(void * arg) {
int item = 0;
while(1){
down(full);
down(mutex);
item = remove_item();
buffer[count++] = item;
up(mutex);
up(empty);
consume_item(item);
}
return 0;
}
void* producer(void* arg) {
int item, i =0;
while(1){
item = produce_item();
down(empty);
down(mutex);
insert_item(item);
up(mutex);
up(full);
sleep(1);
}

The usual way is to pass the variables used by the thread as a parameter. Most thread libraries (POSIX pthread, Windows CreateThread etc) support this by allowing a void pointer to any form of data to get passed to the thread upon creation - that's what the "arg" parameter in your thread callback functions is for.

Related

Bounded buffer sharing with Pthread and mutex locks busy waiting

I am trying to create a producer consumer queue, using mutex locks, creating busy waiting between threads. My Main file takes X amount of integer arguments, pushes them onto a BOUNDED BUFFER of size 50. I am using a while loop to do this since you do not know the amount before hand. I am not sure when and where to create my producer thread.
NOTE: Main is a "producer" in the sense it fills the buffer, but my actual producer function is going to pass onto my consumer function later in my code, so disregard the names. Main is going to "Produce" numbers by pushing and producer is going to pop those numbers for later use. My question is where and when do I make my Pthread_create in my code for producer and am I using the Mutex locks correctly to have synchronization between the two threads?
#include <pthread.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#define BUFFER_SIZE (50)
typedef struct {
int buffer[BUFFER_SIZE];
int count;
int top;
int next;
pthread_mutex_t count_lock;
} prodcons;
void pc_init(prodcons *pc);
int pc_pop(prodcons *pc);
void pc_push(prodcons *pc, int val);
void factor2pc(prodcons *pc, int number);
void *producer(void *data);
void *consumer(void *data);
int main(int argc, char *argv[])
{
int index = 1;
int num;
prodcons pc_nums;
//pthread_t tid[argc - 1];
pthread_t tid;
pthread_attr_t attr;
if (argc < 2) {
fprintf(stderr, "usage: No arguments\n");
return -1;
}
if (atoi(argv[1]) <= 0)
{
fprintf(stderr, "%d not > 0 or you must provide a positive integer.\n", atoi(argv[1]));
return -1;
}
pthread_attr_init(&attr);
pc_init(&pc_nums);
//DO I PUT THIS HERE or WHILE LOOP?
pthread_create(&tid, &attr, *producer, &pc_nums);
while (index < argc)
{
num = atoi(argv[index]);
pc_push(&pc_nums, num);
index++;
}
}
void *producer(void *data)
{
prodcons *dataStruct = data;
while (dataStruct->count < BUFFER_SIZE)
{
number = pc_pop(data);
//This print is just here to make sure I am correctly "poping" from buffer
printf("%d\n", number);
}
}
void pc_init(prodcons *pc)
{
pc->count = 0;
pc->top = 0;
pc->next = 0;
if (pthread_mutex_init(&pc->count_lock, NULL) != 0)
{
printf("\n mutex init has failed\n");
}
}
int pc_pop(prodcons *pc)
{
int val;
pthread_mutex_lock(&pc->count_lock);
if (pc->count > pc->top)
{
val = pc->buffer[pc->count];
printf("%d\n", val);
pc->buffer[pc->count] = 0;
pc->count--;
}
pthread_mutex_unlock(&pc->count_lock);
return val;
}
void pc_push(prodcons *pc, int val)
{
pthread_mutex_lock(&pc->count_lock);
if (pc->count < BUFFER_SIZE)
{
pc->buffer[pc->count] = val;
pc->count++;
}
pthread_mutex_unlock(&pc->count_lock);
}
My question is where and when do I make my Pthread_create in my code for producer and am I using the Mutex locks correctly to have synchronization between the two threads?
As long as all is properly initialized and synchronized, you can put the pthread_create() call wherever you want, including where it's placed in the given program. But at least two things are wrong:
pc_pop() behaves undefined (by return of an uninitialized value) if there is no number in the buffer to pop.
Since dataStruct->count is accessed by producer() without locking, the declaration should be _Atomic(int) count;.

Multithreading in c using a thread safe random numbers

I have been trying to get this to pass valgrind leak check and also pass in 2 billion random numbers and divide them between the threads. I keep getting a seg fault once I get to 1 billion random numbers. Where am I allocating wrong or what am I doing wrong?
struct thread
{
long long int threadID; //The thread id
long long int operations; //The number of threads
};
void *generateThreads(void *ptr)
{
struct thread *args = ptr;
struct random_data *rdata = (struct random_data *) calloc(args->operations*64,sizeof(struct random_data));
char *statebuf = (char*) calloc(args->operations*64,BUFSIZE);
long long int i;
int32_t value;
for(i = 0; i < args->operations; i++)
{
initstate_r(args->threadID,&statebuf[i],BUFSIZE,&rdata[i]);
random_r(rdata,&value);
}
if(DEBUG > 1)
printf("I am thread %lld with thread id %X\n", args->threadID, (unsigned int) pthread_self());
free(rdata);
free(statebuf);
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
long long int numRandoms;
long long int numThreads;
double timeStart = 0;
double timeElapsed = 0;
pthread_t *tid;
struct thread args;
if (argc != 3)
{
fprintf(stderr, "Usage: %s <Number of Randoms> <Number of Threads>\n" ,argv[0]);
exit(1);
}
/* Assign the arg values to appropriate variables */
sscanf(argv[1],"%lld",&numRandoms); /* lld for long long int */
sscanf(argv[2],"%lld",&numThreads); /* lld for long long int */
/* Number of threads must be less than or equal to the number of random numbers */
if(numRandoms < numThreads)
{
fprintf(stderr,"Number of threads must be less than or equal to the number of random numers.\n");
exit(1);
}
/*Start*/
long long int i;
args.operations = numRandoms/numThreads;
timeStart = getMilliSeconds();
tid = (pthread_t *) calloc(numThreads,sizeof(pthread_t));
/* value is the thread id, creating threads */
for(i = 0; i < numThreads; i++)
{
args.threadID = i;
pthread_create(&tid[i],NULL,generateThreads,(void *) &args);
}
/* Joining the threads */
for(i = 0; i < numThreads; i++)
{
pthread_join(tid[i],NULL);
}
/*Output*/
timeElapsed = getMilliSeconds() - timeStart;
printf("%lf\n",(double)(timeElapsed/1000.0));
free(tid);
fflush(stdout);
exit(0);
}
OK I figured out what you were trying to do. The problem was that whatever code you copied from used initstate_r in main to set up the states for all threads. It called initstate_r once per thread to set up the rng for that thread. But you copied that loop into each thread, so you were calling initstate_r many times per thread which is useless. The *64 was there originally to make each state occupy 64 bytes in order to keep them on separate cache lines. You probably were referring to this stackoverflow question.
Here is your function rewritten to make much more sense:
void *generateThreads(void *ptr)
{
struct thread *args = ptr;
struct random_data *rdata = calloc(1,sizeof(struct random_data));
char statebuf[BUFSIZE];
long long int i;
int32_t value;
initstate_r((int) pthread_self(),statebuf,BUFSIZE,rdata);
for(i = 0; i < args->operations; i++)
{
random_r(rdata,&value);
if(DEBUG > 1)
printf("%d\n", value);
}
if(DEBUG > 1)
printf("I am thread %lld with thread id %X\n", args->threadID, (unsigned int) pthread_self());
free(rdata);
pthread_exit(NULL);
}
By the way, the way you pass your arguments to your threads is wrong. You pass the same args to each thread, which means they are sharing the same args structure, which means they each share the same args->threadID. You should instead pass each thread its own args structure.
My answer to question link provides thread safe pseudo-random number generator designed for __uint64/__uint128 integers using xorshift algorithm.
Additional properties:
shared-reentrant
lock-free
thread-safe
ultrafast
seeded from two variant sources of enthropy

Thread struct as function parameter C

I'm having a trouble passing a struct pointer into a function because I'm a bit confused with those pointers and references. I want to modify the thread.thread_num value from the thread_startfunction.
#include <stdio.h>
#include <stdlib.h> //malloc, free
#include <pthread.h>
#define N 5
// void *malloc(size_t);
struct thread {
pthread_t thread_id;
int thread_num;
// int thread_sum;
};
void *thread_start(void *thread)
{
struct thread *my_data;
my_data = (struct thread *)thread;
printf("num T: %i\n", my_data->thread_num);
my_data->thread_num=4;
printf("num T: %i\n", my_data->thread_num);
return NULL;
}
int main(int argc, char *argv[])
{
int i;
struct thread pthread_data;
struct thread *thread = &pthread_data;
thread->thread_num=2;
pthread_create(&thread->thread_id, NULL, thread_start, (void *)&thread);
printf("num: %i\n",thread->thread_num);
pthread_exit(NULL);
return 0;
}
But the value that print the main doesn't change (2).
And then I want to create an array of thread struct, but I don't know how exactly do that:
I guess it should be something like this:
int main(int argc, char *argv[])
{
int i;
struct thread pthread_data;
struct thread *thread[N-1] = &pthread_data; // I don't know how to manage this.
for(i=0; i<N; i++)
{
thread->thread_num=i;
pthread_create(&thread[i]->thread_id, NULL, thread_start, (void *)&thread[i]);
printf("num %i: %i\n",i,thread[i]->thread_num);
}
pthread_exit(NULL);
return 0;
}
Any thoughts?
I recommend you to read http://www.advancedlinuxprogramming.com/alp-folder/alp-ch04-threads.pdf
And here what you wanted:
#define N 5
typedef struct thread {
pthread_t thread_id;
int thread_num;
// int thread_sum;
} ThreadData;
void *thread_start(void *thread)
{
ThreadData *my_data = (ThreadData*)thread;
//there is no guarantee that prints will be in order
// we will use its initial thread->num ,cause it differs for each thread
//plus you will see how threads will behave
int order=my_data->thread_num;
printf("%i) before num T: %i\n",order, my_data->thread_num);
my_data->thread_num=4;
printf("%i) after assignment num T: %i\n",order ,my_data->thread_num);
return NULL;
}
int main(int argc, char *argv[])
{
int i;
ThreadData thread[N];
for(i=0; i<N; i++)
{
thread[i].thread_num=i;
pthread_create(&(thread[i].thread_id), NULL, thread_start, (void *)(thread+i));
}
//wait for all threads
for (i = 0; i < N; i++)
pthread_join(thread[i].thread_id, NULL);
//print results of each thread
for (i = 0; i < N; i++)
printf(" %i)thread: number %i\n",i,thread[i].thread_num);
return 0;
}
I can see multiple mistakes in your code.
First you have your pointers wrong. In the first example, it is enough to pass &pthread_data to pthread_create, &thread is the address of the thread pointer, so you are passing struct thread ** to your function instead of struct thread *. In the second example you should use (void *) thread[i]. &thread[i] is again struct thread **.
When you want each thread to write to its own thread data, then you should make an array of thread data, so that each thread has its own piece, else you will run into race conditions.
As others have already pointed out, you should call pthread_join before calling printf to ensure that the main thread will wait for all worker threads.
Also note that if you are calling pthread_join from other function that the one that spawned those threads, you have to ensure that the array of tread data will not go out of scope (in this case it would be probably better to use malloc or a global array).
You can't. As soon as main exits, which it does when you call pthread_exit, pthread_data ceases to exist, since it's local to the main function. So it can't be modified.

Creating Pthreads

I'm trying to create a thread for the function *producer, but the line for creating the thread is showing in error. I starred the line, but I'm having trouble figuring out what is wrong with it...
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#define TOTALLOOPS 100 /*Num of loops run*/
#define NUMOFPAIRS 4 /*For each 1 it produces 1 consumer and 1 producer*/
typedef struct {
int q[NUMOFPAIRS];
int head;
int tail;
int full;
int empty;
pthread_mutex_t mut; /*Creates a mutex Lock*/
pthread_cond_t notFull; /*Creates conditional*/
}Queue;
int main(void)
{
Queue buf; /* Declare and initialize parts of struct */
buf.head = 0;
buf.tail = 0;
buf.full = 0;
buf.empty = 0;
pthread_mutex_init(&buf.mut, NULL);/*intitializes mutex for struct*/
//pthread_cond_init(&buf.nutFull, NULL);
pthread_t pro;
**pthread_create(&pro, NULL, producer, &buf);**
pthread_mutex_destroy(&buf.mut);
return 0;
}
void *producer(int x, Queue *buf){
int id = x;
int i;
for(i = 0; i < TOTALLOOPS; i++){
while(buf->full == 1){
//do nothing
}
mClock();
printf(" - Producer%d:\n", id);
}
}
void* consumer(int x, Queue *buf){
int id = x;
int i;
for(i = 0; i < TOTALLOOPS; i++){
while(buf->empty == 1){
//do nothing
}
mClock();
printf(" - Consumer%d:\n", id);
}
}
void addToQueue(Queue *buf, int x){
//Checks if empty flag is triggered, if so un triggers
if(buf->empty) buf->empty = 0;
buf->q[buf->tail] = x;
if(buf->tail == 3) buf->tail = 0; /*Resets to beginning if at end*/
else buf->tail += 1; /*else just moves to next*/
//Checks if full flag needs to be triggered, if so triggers
if(buf->tail == buf->head) buf->full = 1;
}
int removeFromQueue(Queue *buf){
int t; /*return value from queue*/
//Checks if full flag is triggered, if so un triggers
if(buf->full == 1)buf->full = 0;
t = buf->q[buf->head];
if(buf->head == 3) buf->head = 0; /*Resets to beginning if at end*/
else buf->head += 1; /*else just moves to next*/
//Checks if full flag needs to be triggered, if so triggers
if(buf->tail == buf->head) buf->empty = 1;
return t;
}
void mClock(){
struct timeval tv;
gettimeofday(&tv,NULL);
long time_in_micros = 1000000 * tv.tv_sec + tv.tv_usec;
printf("%u", time_in_micros);
}
You have to declare producer before the pthread_create call.
void *producer(int x, Queue *buf);
should show up first.
Likewise, mClock has to be declared first.
Also, the function should only take one argument
I don't see where you're calling the initializers for pthread_mutex_t mut and pthread_cond_t notFull in your structure anywhere.
PTHREAD_MUTEX
PTHREAD_COND
Also, you need to change the order of declaration of your functions, or add prototypes to the top of the file.

C - Pthreads mutex and general headaches

Hey guys I was wondering if someone could provide a little help.
I've been trying to teach myself pthreads and with that, mutex locks to get threads running together and using the same structure, whilst not reading and writing to bad data.
My problem at the moment is,
From my thread function, if i call a helper function that might look something similar to the following:
void foo(void *arg)
{
Bar *bar = arg;
pthread_mutex_lock(&mutex);
bar->something = 1;
pthread_mutex_unlock(&mutex);
}
This above helper method doesn't seem to "update" the structure.
But if I run the same code in the thread function, the exact same 4 lines, than this seems to work.
What am I doing wrong? Or how do I fix this? If anyone could provide some reading as well that would be perfect.
EDIT: Sorry guys that was a typo in my code.
Here is the actual code I'm using for the structure.
typedef struct {
char *buffer[CAR_PARK_SIZE];
char *arrival_time[CAR_PARK_SIZE];
int keep_running;
int size;
int index;
} CarStorage;
typedef struct {
CarStorage parks;
CarStorage queue;
int busy;
} CarPark;
pthread_mutex_t mutex;
void addCar(char *car, void *arg)
{
CarPark *_cp = arg;
pthread_mutex_lock(&mutex);
printf("Trying to increase size\n");
_cp->parks.size = _cp->parks.size+1;
pthread_mutex_unlock(&mutex);
}
If the same lines in addCar are in the thread function, it will increase the size, if its in this helper function, it won't.
Here is the calling code
void *carpark_t(void *arg)
{
CarPark *_cp = arg;
while (_cp->parks.keep_running)
{
if (_cp->queue.size > 0)
{
addCar(_cp->queue.buffer[_cp->queue.index % MAX_QUEUE], &_cp);
sleep(1);
}
else
{
printf("[C] no cars in queue\n");
sleep(5);
}
}
}
---- Snipped because it no longer applies and didn't work anyway ----
---- Snipped some more because it no longer applies and didn't work anyway ----
And here is your error:
addCar(_cp->queue.buffer[_cp->queue.index % MAX_QUEUE], &_cp);
That &_cp is passing in the address of _cp, which is a pointer to _cp. but _cp is already a pointer, so you're passing in a pointer to a pointer. Either change &_cp to regular _cp, or change void addCar(char *car, void *arg) to void addCar(char *car, void **arg) (and edit addCar() accordingly). Either one should work, but I'd recommend the first one, as it's easier.
What you're doing in addCar with the locking is fine. Your problem is somewhere in the code that you haven't posted. Without access to that, I'm not really sure what your problem is. The following code that I've written works as, I think, intended. If I had to guess what the problem is though, I'd imagine you're not passing around the structure you want to update, but instead copying it over. Hope this helps.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define CAR_PARK_SIZE 10
typedef struct {
char *buffer[CAR_PARK_SIZE];
char *arrival_time[CAR_PARK_SIZE];
int keep_running;
int size;
int index;
} CarStorage;
typedef struct {
CarStorage parks;
CarStorage queue;
int busy;
} CarPark;
pthread_mutex_t mutex;
void *addCar( void *arg)
{
CarPark *_cp = arg;
pthread_mutex_lock(&mutex);
sleep(1);
printf("Trying to increase size\n");
_cp->parks.size = _cp->parks.size+1;
printf("new size: %d\n", _cp->parks.size);
pthread_mutex_unlock(&mutex);
}
#define NUM_THREADS 5
int main()
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
CarPark c;
c.parks.size = 0;
pthread_mutex_init(&mutex, NULL);
for(t=0; t<NUM_THREADS; t++)
{
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, addCar, (void *)&c);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
return 0;
}

Resources