Global counters and concurrent threads. How to check counter progress? - c

I am trying to write a simple program to understand threads. I want each thread to increment a global variable 'counter' to 4 million. Each thread only counts to 2 million. I placed a print statement at the end of each function to see how many iterations and where the global counter is at upon completion of the function. But the global counter in thread1Func is always very high, like 3.8 - 3.9 million, and then in thread2Func the counter is always 4 mil (as expected).
Am I doing this correctly? Is there a reason thread1Func is always printing such a high value for 'counter'? I would imagine it should be somewhere between 2 mil - 4 mil more evenly. Any advice would be greatly appreciated!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define MAX 2000000UL
pthread_mutex_t lock;
//pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
struct shared_data
{
int value; /* shared variable to store result*/
};
struct shared_data *counter;
void* thread1Func(void * tid){
uint32_t i = 0;
while(i < MAX){
if(pthread_mutex_trylock(&lock) == 0){
counter->value++;
pthread_mutex_unlock(&lock);
i++;
}
}
printf("I am thread 1. I counted %d times. Global counter = %d\n", i, counter->value);
return NULL;
}
void* thread2Func(void * tid){
uint32_t i = 0;
while(i < MAX){
if(pthread_mutex_trylock(&lock) == 0){
counter->value++;
pthread_mutex_unlock(&lock);
i++;
}
}
printf("I am thread 2. I counted %d times. Global counter = %d\n", i, counter->value);
return NULL;
}
int main() {
counter = (struct shared_data *) malloc(sizeof(struct shared_data));
printf("Initial Counter Value: %d\n", counter->value);
pthread_t thread1;
pthread_t thread2;
pthread_mutex_init(&lock, NULL);
pthread_create(&thread1, NULL, thread1Func, NULL);
pthread_create(&thread2, NULL, thread2Func, NULL);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
printf("Final Counter: %d\n", counter->value);
return 0;
}

the global counter in thread1Func is always very high, like 3.8 - 3.9 million, and then in thread2Func the counter is always 4 mil
That is no surprise. If both threads are working at roughly the same speed, then when the first thread finishes, the second thread should be very nearly finished too. The first thread at that point has added its two million to the global counter, and then second thread already will have added almost two million of its own. You should totally expect the global counter to be almost four million when the first thread finishes.
The only way the first thread could print two million is if the first thread is finished before the second thread has begun to work.

Fun example, good work!
Try changing the thread priorities and see what happens to see different counts (see code below).
Maybe consider adding a semaphore to ping pong the count between the 2 threads so they execute equally and report 3999999 and 4000000 as the final counts.
I am sure you have other ideas too, thanks for posting.
gcc main.c -o main
./main
Initial Counter Value: 0
I am thread 2. I counted 2000000 times. Global counter = 3880728
I am thread 1. I counted 2000000 times. Global counter = 4000000
Final Counter: 4000000
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define MAX 2000000UL
pthread_mutex_t lock;
//pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
struct shared_data
{
int value; /* shared variable to store result*/
};
struct shared_data *counter;
void* thread1Func(void * tid){
uint32_t i = 0;
while(i < MAX){
if(pthread_mutex_trylock(&lock) == 0){
counter->value++;
pthread_mutex_unlock(&lock);
i++;
}
}
printf("I am thread 1. I counted %d times. Global counter = %d\n", i, counter->value);
return NULL;
}
void* thread2Func(void * tid){
uint32_t i = 0;
while(i < MAX){
if(pthread_mutex_trylock(&lock) == 0){
counter->value++;
pthread_mutex_unlock(&lock);
i++;
}
}
printf("I am thread 2. I counted %d times. Global counter = %d\n", i, counter->value);
return NULL;
}
int main() {
counter = (struct shared_data *) malloc(sizeof(struct shared_data));
printf("Initial Counter Value: %d\n", counter->value);
pthread_t thread1;
pthread_t thread2;
pthread_mutex_init(&lock, NULL);
pthread_attr_t attr;
struct sched_param sch_params;
pthread_attr_init(&attr);
pthread_attr_getschedparam(&attr, &sch_params);
sch_params.sched_priority = 99;
//pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &sch_params);
pthread_create(&thread1, &attr, thread1Func, NULL);
sch_params.sched_priority = 1;
pthread_create(&thread2, &attr, thread2Func, NULL);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
printf("Final Counter: %d\n", counter->value);
return 0;
}

Related

How to implement the pseudocode in the book of semaphores?

Lately i followed a course of Operating Systems that sent me to the barrier pseudocode from the little book of semaphores. But for a few hours now i'm struggling to implement this barrier, i can't seem to understand it properly. To understand it, i tried a simple program that lets threads come to barrier, and when all threads arrived, let them pass.
Here's my code:
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#define NR_MAX 5
int n=NR_MAX;
int entered = 0;
pthread_mutex_t mtx;
sem_t smph;
void* bariera(void *v){
pthread_mutex_lock(&mtx);
entered++ ;
printf("thread %d have entered\n", entered);
pthread_mutex_unlock(&mtx);
if(entered == n) {
sem_post(&smph); printf("Out %d \n", entered);}
sem_wait(&smph);
sem_post(&smph);
}
int main() {
pthread_t thr[NR_MAX];
pthread_mutex_init(&mtx, NULL);
sem_init(&smph, 0, 1);
for (int i=0; i<NR_MAX; i ){
pthread_create(&thr[i], NULL, bariera, NULL);
}
for(int i=0; i<NR_MAX; i ){
pthread_join(thr[i], NULL);
}
return 0;
}
How should this be actually implemented? Cause for now, it only prints the order they arrive at the barrier and then it only prints the last one that arrived.
EDIT: Totally forgot, here's the pseudocode:
n = the number of threads
count = 0 - keeps track of how many threads arrived at the barrier
mutex = Semaphore (1) - provides exclusive acces to count
barrier = Semaphore (0) - barrier is locked (zero or negative) until all threads arrive; then it should be unlocked(1 or more)
rendezvous
2
3 mutex.wait()
4 count = count + 1
5 mutex.signal ()
6
7 if count == n: barrier.signal ()
8
9 barrier.wait()
10 barrier.signal ()
11
12 critical point
expected output:
Out 5
Out 4
Out 3
Out 2
Out 1
(the order doesn't have to be the same)
Actual output:
Out 5
Three issues:
Incorrectly initialized semaphore.
Accessing entered outside of the critical section.
Misplaced printf.
Missing return.
Missing increment in for loops.
void* bariera(void *v) {
int id = (int)(uintptr_t)v;
printf("[%d] Before barrier.\n", id);
pthread_mutex_lock(&mtx);
if(++entered == n)
sem_post(&smph); // Wake up a thread.
pthread_mutex_unlock(&mtx);
sem_wait(&smph); // Barrier.
sem_post(&smph); // Wake up another thread.
// Do something after the barrier.
printf("[%d] After barrier.\n", id);
return NULL;
}
sem_init(&smph, 0, 0); // Should initially be zero.
for (int i=0; i<NR_MAX; ++i) {
pthread_create(&thr[i], NULL, bariera, (void*)(intptr_t)i);
}
Output:
[0] Before barrier.
[2] Before barrier.
[3] Before barrier.
[4] Before barrier.
[1] Before barrier.
[1] After barrier.
[0] After barrier.
[3] After barrier.
[2] After barrier.
[4] After barrier.
That leaves the barrier semaphore un-reusuable. To fix that because it posts n+1 times. To leave it back in its original state, we need to post only n times.
void* bariera(void *v) {
int id = (int)(uintptr_t)v;
printf("[%d] Before barrier.\n", id);
pthread_mutex_lock(&mtx);
if(++entered == n)
for (int i=n; i--; )
sem_post(&smph); // Wake up every thread.
pthread_mutex_unlock(&mtx);
sem_wait(&smph); // Barrier.
// Do something after the barrier.
printf("[%d] After barrier.\n", id);
return NULL;
}
With C11 atomic types, you actually don't need the separate mutex to protect access to the barrier counter, as demonstrated below. This version also encapsulates the barrier-related variables and operations into a struct and functions, and doesn't require that the last thread to hit the barrier also have to wait on the semaphore.
#include <stdatomic.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
struct barrier {
int maxcount;
_Atomic int count;
sem_t sem;
};
void barrier_init(struct barrier *b, int count) {
b->maxcount = b->count = count;
sem_init(&b->sem, 0, 0);
}
void barrier_destroy(struct barrier *b) {
sem_destroy(&b->sem);
}
void barrier_wait(struct barrier *b) {
// Atomically subtract a number and return the *old* value
if (atomic_fetch_sub_explicit(&b->count, 1, memory_order_acq_rel) == 1) {
// Wake up all waiting threads as they're all at the barrier now
for (int n = 0; n < b->maxcount - 1; n += 1) {
sem_post(&b->sem);
}
} else {
sem_wait(&b->sem); // Actual barrier; wake for wakeup
}
}
void* wait_func(void *vb) {
struct barrier *b = vb;
printf("Thread 0x%x before barrier.\n", (unsigned)pthread_self());
barrier_wait(b);
printf("Thread 0x%x after barrier.\n", (unsigned)pthread_self());
return NULL;
}
#define NTHREADS 5
int main(void) {
pthread_t threads[NTHREADS];
struct barrier b;
barrier_init(&b, NTHREADS);
for (int n = 0; n < NTHREADS; n += 1) {
pthread_create(&threads[n], NULL, wait_func, &b);
}
for (int n = 0; n < NTHREADS; n += 1) {
pthread_join(threads[n], NULL);
}
barrier_destroy(&b);
return 0;
}

C pthreads threads not executing functions for producer-consumer problem

Hi I am trying to implement an solution to producer consumer problem with threads and semaphores.
I have the two functions that the threads consumer and producer will call but they aren't executing. I am not sure what I am doing wrong as I am not getting any errors, my program is just not executing the thread functions. I am creating and joining the thread, I am not sure what is causing the issue
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <errno.h>
#include "buffer.h"
struct bufferStruct *item; //calls buffer structure from buffer.h
pthread_mutex_t mutex; //lock for synchronizing execution of threads(producer and consumer)
sem_t empty; //indicates buffer is empty
sem_t full; //indicates buffer is full
int input = 0;
int newitem;
pthread_attr_t attr;
void *producer(void *param)
{
for(int i = 0; i < 5; i++)
{
sem_wait(&empty);
pthread_mutex_lock(&mutex);
newitem = rand();
item->content[item->in] = newitem;
printf("Producer prouced item %d at position %d in buffer\n", newitem, item->in);
item->in = (item->in+1) % MAX_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
sleep(1);
}
}
void *consumer(void * param)
{
for(int i =0; i< 5; i++)
{
sem_wait(&full);
pthread_mutex_lock(&mutex);
newitem = item->content[item->out];
printf("Consumer has consumed item %d at position %d in buffer\n", newitem, item->out);
item->out = (item->out+1) % MAX_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
sleep(1);
}
}
int main()
{
int initval = 1;
int initval2 = 2;
sem_init(&full, 1, 0);
sem_init(&empty, 1, MAX_SIZE);
if(pthread_mutex_init(&mutex,NULL)!=0){
printf("Mutex init failed\n");
return 1;
}
pthread_attr_init(&attr);
pthread_t thread_produce, thread_consume;
printf("Starting threads...\n");
pthread_create(&thread_produce, &attr, producer, (void*)&(initval));
pthread_create(&thread_consume, &attr, consumer, (void*)&(initval2));
pthread_join(thread_produce, NULL);
pthread_join(thread_consume, NULL);
printf("Threads done executing...\n");
pthread_mutex_destroy(&mutex);
sem_destroy(&empty);
sem_destroy(&full);
exit(0);
}
You declare
struct bufferStruct *item;
then you use item without ever assigning it to point to anything. Undefined behavior results.
If I fix that (first synthesizing a version struct bufferStruct and choosing a MAX_SIZE) then the program compiles without error and seems to run successfully.

Real time task (periodic task)

Good evening everyone,
I'm still learning real-time programming, and I'm trying to synchronize two threads using semaphores, the first thread calculates the sum and returns a value (sum). the sum will be passed as a parameter to the 2nd thread that will use it to calculate an average (this is just an example for manipulating semaphores). my problem now and that the two tasks are not periodic because once the thread returns a result it leaves the loop while and the main() finishes the work !!! now how to make the tasks period ?? thank you for helping me and here is my source code.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
sem_t evt;
//first task
void *tache1(void *arg)
{
int j;
int s=0;
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
while(1){
printf("first THREADDDDDDDDD \n");
for(j=0; j<100; j++)
s= s + j;
return (void*) s;
sem_post(&evt);
sleep(3);
}
}
//second task
void *tache2(void *arg){
int moyenne = 1;
int sum = *((int*) arg);
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
while(3){
sem_wait(&evt);
printf("second THREADDDDDDDDD \n");
moyenne= sum/10;
return(void*)moyenne;
sleep(2);
}
}
int main()
{
pthread_t th1, th2;
int sum;
int moyenne;
int status;
sem_init(&evt, 0,0);
printf("start main\n") ;
pthread_create(&th1, NULL, tache1, NULL);
pthread_join(th1, (void*) &sum);
pthread_create(&th2, NULL, tache2, &sum);
pthread_join(th2, (void*) &moyenne);
printf("the sum in the main is %d.\n", sum);
printf("AVG %d.\n", moyenne);
printf("End main\n") ;
return 0;
}
When you do this:
pthread_create(&th1, NULL, tache1, NULL);
pthread_join(th1, (void*) &sum);
pthread_create(&th2, NULL, tache2, &sum);
pthread_join(th2, (void*) &moyenne);
You start a thread, wait for it to finish, then start another thread, then wait for that to finish. That's not multithreading. You want both threads to be active at the same time.
Also, both of your thread functions include a return statement with more statements after them. Once a return statement is hit, the entire function returns immediately. No statements after them are executed. Note also that you don't need a while (1) (or while (3)) loop in either of these functions.
The idea behind semaphores (and mutexes) is that multiple threads are running at once, and both thread need to operate on global data so one thread needs to wait for the other thread to do something before it can access the global data.
So make sum and moyenne global variables, start both threads at once, and get rid of the extra loops in the thread functions.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
sem_t evt;
int sum;
int moyenne;
void *tache1(void *arg)
{
int j;
int s=0;
printf("first THREADDDDDDDDD \n");
for(j=0; j<100; j++)
s= s + j;
sum = s;
sem_post(&evt);
return NULL;
}
void *tache2(void *arg)
{
sem_wait(&evt);
printf("second THREADDDDDDDDD \n");
moyenne= sum/10;
return NULL;
}
int main()
{
pthread_t th1, th2;
sem_init(&evt, 0,0);
printf("start main\n") ;
pthread_create(&th1, NULL, tache1, NULL);
pthread_create(&th2, NULL, tache2, NULL);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
printf("the sum in the main is %d.\n", sum);
printf("AVG %d.\n", moyenne);
printf("End main\n") ;
return 0;
}

C - synchronizing multiple threads w/ mutexs

I'm trying to synchronize multiple (7) threads. I thought I understood how they work until I was trying it on my code and my threads were still printing out of order. Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
void *text(void *arg);
long code[] = {4,6,3,1,5,0,2}; //Order in which to start threads
int num = 0;
pthread_mutex_t lock; //Mutex variable
int main()
{
int i;
pthread_t tid[7];
//Check if mutex worked
if (pthread_mutex_init(&lock, NULL) != 0){
printf("Mutex init failed\n");
return 1;
}
//Initialize random number generator
time_t seconds;
time(&seconds);
srand((unsigned int) seconds);
//Create our threads
for (i=0; i<7; i++)
pthread_create(&tid[i], NULL, text, (void*)code[i]);
//Wait for threads to finish
for (i=0; i<7; i++){
if(pthread_join(tid[i], NULL)){
printf("A thread failed to join\n");
}
}
//Destroy mutex
pthread_mutex_destroy(&lock);
//Exit main
return 0;
}
void *text (void *arg)
{
//pthread_mutex_lock(&lock); //lock
long n = (long) arg;
int rand_sec = rand() % (3 - 1 + 1) + 1; //Random num seconds to sleep
while (num != n) {} //Busy wait used to wait for our turn
num++; //Let next thread go
sleep(rand_sec); //Sleep for random amount of time
pthread_mutex_lock(&lock); //lock
printf("This is thread %d.\n", n);
pthread_mutex_unlock(&lock); //unlock
//Exit thread
pthread_exit(0);
}
So here I am trying to make threads 0-6 print IN ORDER but right now they are still scrambled. The commented out mutex lock is where I originally had it, but then moved it down to the line above the print statement but I'm having similar results. I am not sure where the error in my mutex's are, could someone give a hint or point me in the right direction? I really appreciate it. Thanks in advance!
You cannot make threads to run in order with only a mutex because they go in execution in an unpredictable order.
In my approach I use a condition variable and a shared integer variable to create a queueing system. Each thread takes a number and when the current_n number is equal to the one of the actual thread, it enters the critical section and prints its number.
#include <pthread.h>
#include <stdio.h>
#define N_THREAD 7
int current_n = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t number = PTHREAD_COND_INITIALIZER;
void *text (void *arg) {
int i = (int)arg;
pthread_mutex_lock(&mutex);
while ( i > current_n ) {
pthread_cond_wait(&number, &mutex);
}
//i = current_n at this point
/*I use stderr because is not buffered and the output will be printed immediately.
Alternatively you can use printf and then fflush(stdout).
*/
fprintf(stderr, "I'm thread n=%d\n", i);
current_n ++;
pthread_cond_broadcast(&number);
pthread_mutex_unlock(&mutex);
return (void*)0;
}
int main() {
pthread_t tid[N_THREAD];
int i = 0;
for(i = 0; i < N_THREAD; i++) {
pthread_create(&tid[i], NULL, text, (void *)i);
}
for(i = 0; i < N_THREAD; i++) {
if(pthread_join(tid[i], NULL)) {
fprintf(stderr, "A thread failed to join\n");
}
}
return 0;
}
The output is:
I'm thread n=0
I'm thread n=1
I'm thread n=2
I'm thread n=3
I'm thread n=4
I'm thread n=5
I'm thread n=6
Compile with
gcc -Wall -Wextra -O2 test.c -o test -lpthread
Don't worry about the warnings.

UNIX Pthreads & mutex; program locks up

Following scenario:
We are supposed to make x Threads maximum. Our main-function is supposed to make a single new thread with a pointer to the function 'makeThreads'. This function is supposed to make up to 2 threads, depending on how many threads are already there. Race conditions are to avoid.
I'm stuck. I'm not exactly sure how to solve the problem I'm running into, partly because I don't can't identify the problem itself.
Suggestions are greatly appreciated!
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#define MAX_THR 20
pthread_mutex_t mutex;
int threadCount = 0;
int randomNbr(){
int number = (rand() % 10) + 1;
return number;
}
void *makeThreads(void* number){
int rndnmb = *((int *) number);
pthread_mutex_lock(&mutex);
sleep(rndnmb);
pthread_t threadDummy;
int thread1, i, threadID, rndnbr;
threadID = threadCount;
printf("Hello from Thread %d!\n", threadID);
for(i = 0; i < 2; i++){
if(threadCount < MAX_THR){
rndnbr = randomNbr();
int *rnd = &rndnbr;
threadCount++;
thread1 = pthread_create(&threadDummy, NULL, *makeThreads, (void *) rnd);
pthread_join(threadDummy, NULL);
}
}
pthread_mutex_unlock(&mutex);
printf("Goodbye from Thread %d!\n", threadID);
}
int main(){
int t1, rndnbr;
pthread_t threadOne;
pthread_mutex_init(&mutex, NULL);
srand(time(NULL));
rndnbr = randomNbr();
int *rnd = &rndnbr;
threadCount++;
t1 = pthread_create(&threadOne, NULL, *makeThreads, (void *) rnd);
pthread_join(threadOne, NULL);
}

Resources