How can I have a shared counter in multithreading using structs? - c

I'm pretty new with multithreading and I was trying to increment a shared counter whithout using global variables, my goal is try to maximize the concurrency among the different threads and increment the variable until a number I give in arguments... Sorry if is a lame question, but I would like a help here, when I compile my code and run it i get a segmentation fault... I think the error is in the variable count that I create and the shared counter!
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex;
typedef struct {
long *cnt; /* pointer to shared counter */
long n; /* no of times to increment */
int nr;
pthread_t id; /* application-specific thread-id */
} targ_t;
void *sfun(void *arg) {
targ_t *est = (targ_t *) arg;
here:
pthread_mutex_lock(&mutex);
(*(est->cnt))++;
pthread_mutex_unlock(&mutex);
if(*(est->cnt)<est->n)
goto here;
return NULL;
}
int main(int argc, char *argv[]){
targ_t real[3];
int c=0;
long count=0;
real[0].cnt=&count;
pthread_mutex_init(&mutex, NULL);
for(c=0;c<3;c++){
real[c].n=atoi(argv[1]);
real[c].nr=c+1;
pthread_create(&real[c].id,NULL,&sfun,&real[c]);
}
for(c=0;c<3;c++){
pthread_join(real[c].id,NULL);
}
pthread_mutex_destroy(&mutex);
printf("OVERALL %lu\n", count);
return 0;
}
TY in advance.

There are a number of problems identified in the comments:
Writing out loops with a label here: and a goto here; is not a particularly good idea. There are occasions (some, but not many, occasions) when it is appropriate to use goto — this is not one of those rare occasions.
You don't actually validate that your code was given an argv[1] to convert; could it be that you forgot to pass that argument?
However, your primary problem is that you initialize real[0].cnt but you do not initialize real[1].cnt or real[2].cnt, so those threads are accessing who knows what memory — it might be that they're using null pointers, or they might be pointers to anywhere in memory, allocated or not, aligned or not, writable or not.
You're also missing <stdlib.h>
You're testing *(est->cnt) outside the scope of mutual exclusion.
This code fixes those and some other issues:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
typedef struct
{
long *cnt; /* pointer to shared counter */
long n; /* no of times to increment */
int nr;
pthread_t id; /* application-specific thread-id */
} targ_t;
static void *sfun(void *arg)
{
targ_t *est = (targ_t *)arg;
while (1)
{
pthread_mutex_lock(&mutex);
long cval = *est->cnt;
if (cval < est->n)
++*est->cnt;
pthread_mutex_unlock(&mutex);
if (cval >= est->n)
break;
}
return NULL;
}
int main(int argc, char *argv[])
{
targ_t real[3];
long count = 0;
if (argc != 2)
{
fprintf(stderr, "Usage: %s count\n", argv[0]);
return(EXIT_FAILURE);
}
for (int c = 0; c < 3; c++)
{
real[c].cnt = &count;
real[c].n = atoi(argv[1]);
real[c].nr = c + 1;
if (pthread_create(&real[c].id, NULL, &sfun, &real[c]) != 0)
break;
}
for (int c = 0; c < 3; c++)
pthread_join(real[c].id, NULL);
pthread_mutex_destroy(&mutex);
printf("OVERALL %lu\n", count);
return 0;
}
When run (for example, the program is pth59):
$ pth59 100
OVERALL 100
$
Before moving the test (now on cval) so that the read of *est->cnt was done inside the scope of the mutex, I got an output OVERALL 102 from the same command line. It is important to access shared variables with proper mutual exclusion, even if it is read-only access.

Related

How to properly sync multithreading with mutex in c?

How should i properly sync threads with mutex?
I'm trying a simple "sync" using mutex, something really small, like just printing a string containing the number of the thread. snippet here:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define MAX_RESOURCE 5
#define NO_THREADS 5
int res_available = MAX_RESOURCE;
pthread_mutex_t mtx;
struct count { int no;};
void *
use_res(void *v) {
pthread_mutex_lock(&mtx);
struct count *p = (struct count *) v;
printf("--thread no %d :" p->nr);
return NULL;
}
int main(){
pthread_t thr[NO_THREADS];
pthread_mutex_init(&mtx, NULL);
for(int i=0; i<N0_THREADS; i++){
struct count *c = malloc(sizeof(struct count));
c->nr = i;
pthread_create(thr[i], NULL, use_res, c))
}
for(int i=0; i<NO_THREADS; i++) {
pthread_join(thr[i], NULL);
}
return 0;
}
Fact is, when executed, the sync doesn't actually occur, actually, what it does occur, is still that "race condition", making the program to print something else everytime.
My question is, how do i stop this race condition? I don't know if i'm using correctly this lock and unlock thing.
You need to release mutex when your thread function finish, also add \n at the end of print, because stdout will buffer this text:
void *
use_res(void *v) {
pthread_mutex_lock(&mtx);
struct count *p = (struct count *) v;
printf("--thread no %d :\n" p->no);
pthread_mutex_unlock(&mtx);
return NULL;
}

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, Fibonacci Program

I have newly started studying operating systems and creating processes/threads on Linux system by using C programming language(thats what is expected us to use) but I have some problems on the code that I've been trying to write:
Here is my code written on an Ubuntu system:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
int total = 0;
typedef struct
{
int start;
int end;
int threadNo;
}THREAD_PARAMETERS;
void *work(void *parameters);
int threadCount;
int main(int argc, char* argv[])
{
printf("please give the number of terms you want to diplay..");
scanf("%d", &threadCount);
pthread_t tid[threadCount];
pthread_attr_t attr[threadCount];
THREAD_PARAMETERS* lpParameter;
int n;
lpParameter = malloc(sizeof(THREAD_PARAMETERS)* threadCount);
int i=0;
for(i=0; i<threadCount; i++)
{
lpParameter[i].start = 0;
lpParameter[i].end = 1;
lpParameter[i].threadNo = i + 1;
pthread_attr_init(&attr[i]);
pthread_create(&tid[i],&attr[i],work,&lpParameter[i]);
}
for(i=0; i<threadCount; i++)
{
pthread_join(tid[i],NULL);
}
return 1;
}
void fibonacci(int a)
{
int prev_term = 0, current_term = 1, next_term = 0;
if(a==0){
printf("%d\n",prev_term);
}
else if(a==1){
next_term=current_term+prev_term;
printf("%d\n",current_term);
prev_term=current_term;
current_term=next_term;
void *work(void * parameters)
{
THREAD_PARAMETERS* param = (THREAD_PARAMETERS*)parameters;
fibonacci(threadCount);
pthread_exit(0);
}
The problem is the program counts with the threadCount variable but what the program prints is just threadCount times zeros.
And the main question is how can I make each of the threads write "only one term" of the Fibonacci series depending on the number of terms (which is at the same time the number of threads) entered by the user? Is there any other more logical way to implement this kind of program?
You are using lpParameter[i] as the argument to each thread's work, but then ignore its contents when calling fibonacci.

C program for counting the number of occurrences of a word in a file using threads getting segmentation fault error

So i have the following problem: Implement a program that gets as arguments a file name followed by words. For each word, create a separate thread that counts its appearances in the given file.Print out the sum of the appearances of all words.
I'm also not sure if my code is really formatted correctly. I'm trying to figure out how to get each word to be counted in the given text file. I am trying to test out this code but I am getting a couple errors from it, the biggest being a segmentation error. If you have any pointers or advice or help, please let me know.
my code is:
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mtx; // used by each of the three threads to prevent other threads from accessing global_sum during their additions
int global_sum = 0;
typedef struct{
char* word;
char* filename;
}MyStruct;
void *count(void*str)
{
MyStruct *struc;
struc = (MyStruct*)str;
const char *myfile = struc->filename;
FILE *f;
int count=0, j;
char buf[50], read[100];
// myfile[strlen(myfile)-1]='\0';
if(!(f=fopen(myfile,"rt"))){
printf("Wrong file name");
}
else
printf("File opened successfully\n");
for(j=0; fgets(read, 10, f)!=NULL; j++){
if (strcmp(read[j],struc->word)==0)
count++;
}
printf("the no of words is: %d \n",count);
pthread_mutex_lock(&mtx); // lock the mutex, to prevent other threads from accessing global_sum
global_sum += count; // add thread's count result to global_sum
pthread_mutex_unlock(&mtx); // unlock the mutex, to allow other threads to access the variable
}
int main(int argc, char* argv[]) {
int i;
MyStruct str;
pthread_mutex_init(&mtx, NULL); // initialize mutex
pthread_t threads[argc-1]; // declare threads array
for (i=0;i<argc-2;i++){
str.filename = argv[1];
str.word = argv[i+2];
pthread_create(&threads[i], NULL, count, &str);
}
for (i = 0; i < argc-1; ++i)
pthread_join(threads[i], NULL);
printf("The global sum is %d.\n", global_sum); // print global sum
pthread_mutex_destroy(&mtx); // destroy the mutex
return 0;
}
The second good bit of advice for today is to look carefully at the warnings that your compiler gives you and take heed of them. strcmp(read[j],struc->word) Your compiler must have warned you that that is wrong. You are passing a single char as the first parameter instead of const char *. That'll almost certainly result in a seg fault. – kaylum

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