How to Know which Thread is executing a function? - c

So I have a scaled down version of an elevator program that uses pthreads in c. Each thread is an individual lift that calls function request(). I am not sure how to know which lift (1, 2 or 3) which are threads are using the function request. In the request function I need to print which thread used it at that time. Sorry if my explanation doesn't make complete sense.
void* request(void* abc)
{
int ii;
for(ii = 0; ii < 8; ii++)
{
sleep(1);
printf("REQUEST FROM LIFT COMPLETED\n");
}
}
int main()
{
pthread_t lift1;
pthread_t lift2;
pthread_t lift3;
pthread_create(&lift1, NULL, request, NULL);
pthread_create(&lift2, NULL, request, NULL);
pthread_create(&lift3, NULL, request, NULL);
pthread_join(lift1, NULL);
pthread_join(lift1, NULL);
pthread_join(lift1, NULL);
return 0;
}

You could do this in multiple ways, the simplest one is to pass some meaningful value as thread parameter to identify each thread.
Here's an example:
void *request(void *data)
{
const int id = *(const int *)data;
int ii;
for(ii = 0; ii < 8; ii++)
{
sleep(1);
printf("REQUEST FROM LIFT %d COMPLETED\n", id);
}
}
int main()
{
const int id1 = 1, id2 = 2, id3 = 3;
pthread_t lift1;
pthread_t lift2;
pthread_t lift3;
pthread_create(&lift1, NULL, request, (void *)&id1);
pthread_create(&lift2, NULL, request, (void *)&id2);
pthread_create(&lift3, NULL, request, (void *)&id3);
pthread_join(lift1, NULL);
pthread_join(lift2, NULL);
pthread_join(lift3, NULL);
return 0;
}
You could also define those id varibles as static globals:
// Outside main:
static const int id1 = 1, id2 = 2, id3 = 3;

Related

Reduce overhead in mutex

I am learning mutex currently and the following is the test code. It works perfectly fine. It creates another instance after one is done. Yet, it also introduces overhead according to here.
How efficient is locking an unlocked mutex? What is the cost of a mutex?. How can I modify my code to improve the efficiency?
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
typedef struct _context_t {
uint64_t id;
char *name;
bool initialized;
} context_t;
context_t *ctx = NULL;
context_t *get_instance() {
pthread_mutex_lock(&lock);
if (ctx == NULL) {
ctx = (context_t *)malloc(sizeof(context_t));
assert(ctx != NULL);
ctx->initialized = false;
}
pthread_mutex_unlock(&lock);
return ctx;
}
int id = 0;
void *do_work(void *arg) {
context_t *ctx = get_instance();
if (!ctx->initialized) {
ctx->name = (char *)arg;
ctx->id = ++id;
ctx->initialized = true;
}
printf("name=%s\tid=%ld\n", ctx->name, ctx->id);
return NULL;
}
int main() {
int rc;
pthread_t p1, p2;
rc = pthread_create(&p1, NULL, do_work, "A");
assert(rc == 0);
rc = pthread_create(&p2, NULL, do_work, "B");
assert(rc == 0);
rc = pthread_join(p1, NULL);
assert(rc == 0);
rc = pthread_join(p2, NULL);
assert(rc == 0);
if (ctx) {
free(ctx);
}
return 0;
}
Instead of having two threads racing to create the context_t, you should create it once before the threads start, and pass its address to the threads explicitly.
Note that you can pass multiple arguments via pthread_create() by putting them in a struct and passing its address.
Then you won't need a mutex at all, because the threads will only read from ctx rather than potentially writing to it.

How to get one correct value from a function which is parallelized by multi-threads

For faster calculation, trying to make my method parallelized by 4 threads. Where threads are making 4 separate calculation whether I was expecting concurrent operation and on single variable.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
static int x, j=5;
void *print_count (void *dummy)
{
for(int i=0;i<1000;i++){
x+=j;
}
}
int main ()
{
pthread_t p1, p2, p3, p4;
pthread_create (&p1, NULL, print_count, NULL);
pthread_create (&p2, NULL, print_count, NULL);
pthread_create (&p3, NULL, print_count, NULL);
pthread_create (&p4, NULL, print_count, NULL);
pthread_join (p1, NULL);
pthread_join (p2, NULL);
pthread_join (p3, NULL);
pthread_join (p4, NULL);
printf("Actual output: %d \nExpected output: 5000\n", x);
return 0;
}
I expect the output 5000 as the increment is 5 and loop for 1000 times.
But the actual output first of all not static, it always change and it is near 4 times of 5000 because threads are calculating the print_count separately.
Thank you
If you are under C11 you can use _Atomic
Of course each thread needs to work over a range of values (not with the complete set), pass a struct:
#include <stdio.h>
#include <stdatomic.h>
#include <pthread.h>
_Atomic int x;
static int j = 5;
struct range {
int from, to;
};
void *print_count(void *data)
{
struct range *range = data;
for (int i = range->from; i < range->to; i++) {
x += j;
}
return NULL;
}
int main(void)
{
pthread_t p1, p2, p3, p4;
struct range ranges[] = {
{0, 250},
{250, 500},
{500, 750},
{750, 1000}
};
pthread_create(&p1, NULL, print_count, &ranges[0]);
pthread_create(&p2, NULL, print_count, &ranges[1]);
pthread_create(&p3, NULL, print_count, &ranges[2]);
pthread_create(&p4, NULL, print_count, &ranges[3]);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
pthread_join(p3, NULL);
pthread_join(p4, NULL);
printf("Actual output: %d \nExpected output: 5000\n", x);
return 0;
}
Or a compound literal:
pthread_create(&p1, NULL, print_count, (int []){ 0, 250});
pthread_create(&p2, NULL, print_count, (int []){250, 500});
pthread_create(&p3, NULL, print_count, (int []){500, 750});
pthread_create(&p4, NULL, print_count, (int []){750, 1000});
...
void *print_count(void *data)
{
int *range = data;
for (int i = range[0]; i < range[1]; i++) {
x += j;
}
return NULL;
}
in order to divide the task.
Output:
Actual output: 5000
Expected output: 5000

Synchronize N-processes in strict order with Semaphores

I'm facing simple issue with Semaphore's task.
I am having N-processes (P1, P2, P3, P4...Pn). No matter in what order I create threads, I need them to execute in exact order (P1, P2, P3, P4...Pn). I need to come with solution, where I use minimum semaphores required.
It would be quite simple using Mutex, but the task says "use only semaphores".
I'm using only one semaphore. In while, within the condition, if order number is NOT equals your ID number, just unlock semaphore and cycle in while, till order number is equals to your ID number.
I think that problem might be with "Spurious wakeups".
Here is my code:
sem_t semvar;
int order = 0;
void *sayHello(void *thread_id){
int *my_id = (int *) thread_id;
while(1)
{
// take semaphore and close critical zone to read order variable to recognize who's on turn!
sem_wait(&semvar);
if(*my_id == order)
{
// if I'm on turn, then I shout my number and set order variable to someone behind me
printf("I'm thread no.: %d\n", *my_id);
order++;
break;
}
// release semaphore if I'm not on turn!
sem_post(&semvar);
}
// release semaphore if it was my turn, I shout my number and gonna end (die)!
sem_post(&semvar);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
int numbOfThreads = 13;
int *thread_id[numbOfThreads];
int new_thread, i;
pthread_t threads[numbOfThreads];
// generating thread numbers --> NOTE: you need this, if you use random thread generating!!!
for(i = 0; i < numbOfThreads; i++)
{
thread_id[i] = (int *) malloc(sizeof(int));
*thread_id[i] = i;
}
// random thread generating for testing to make sure it works
pthread_create(&threads[10], NULL, sayHello, (void *) thread_id[10]);
pthread_create(&threads[12], NULL, sayHello, (void *) thread_id[12]);
pthread_create(&threads[8], NULL, sayHello, (void *) thread_id[8]);
pthread_create(&threads[3], NULL, sayHello, (void *) thread_id[3]);
pthread_create(&threads[5], NULL, sayHello, (void *) thread_id[5]);
pthread_create(&threads[1], NULL, sayHello, (void *) thread_id[1]);
pthread_create(&threads[0], NULL, sayHello, (void *) thread_id[0]);
pthread_create(&threads[4], NULL, sayHello, (void *) thread_id[4]);
pthread_create(&threads[7], NULL, sayHello, (void *) thread_id[7]);
pthread_create(&threads[6], NULL, sayHello, (void *) thread_id[6]);
pthread_create(&threads[2], NULL, sayHello, (void *) thread_id[2]);
pthread_create(&threads[9], NULL, sayHello, (void *) thread_id[9]);
pthread_create(&threads[11], NULL, sayHello, (void *) thread_id[11]);
/*
// automatic thread generating
for(i = 0; i < numbOfThreads; i++)
{
thread_id[i] = (int *) malloc(sizeof(int));
*thread_id[i] = i;
new_thread = pthread_create(&threads[i], NULL, sayHello, (void *) thread_id[i]);
if(new_thread)
{
printf("Error has occured");
exit(-1);
}
}
*/
// do not end main function before all the threads are done with work!
for(i = 0; i < numbOfThreads; i++)
{
pthread_join( threads[i], NULL);
}
printf("All the threads are gone!");
return 1;
}

why doesn't sem_wait block

static int res1 = 0;
static int res2 = 0;
static int res3 = 0;
static int counter = 0;
static sem_t sem;
void * func_thread1(void *p)
{
sleep(2);
res1 = 1;
printf("func_thread1\n");
sem_post(&sem);
return NULL;
}
void * func_thread2(void *p)
{
sleep(2);
res2 = 2;
printf("func_thread2\n");
sem_post(&sem);
return NULL;
}
void * func_thread3(void *p)
{
sem_wait(&sem);
sem_wait(&sem);
res3 = res1 + res2;
printf("func_thread3\n");
return NULL;
}
void main()
{
sem_init(&sem, 0, counter);
pthread_t pd1, pd2, pd3;
pthread_create(&pd1, NULL, func_thread1, NULL);
pthread_create(&pd2, NULL, func_thread2, NULL);
pthread_create(&pd3, NULL, func_thread3, NULL);
//pthread_join(pd3, NULL);
printf("main_thread\n");
printf("%d", res3);
}
I'm trying to understand how semaphore works.
I'm trying to make the td3 block to wait for the td1 and the td2.
In my opinion, the sem_wait will block twice. If the sem_posts in func_thread1 and in func_thread2 are executed, func_thread3 could continue.
However, it doesn't work unless I add pthread_join(td3, NULL) in main. I think the join is not necessary because sem_wait can block.
So pthread_join is necessary or I use semaphore incorrectly?
pthread_join is mandatory in your implementation.
Otherwise your process finishes (ie. main returns), and all tasks (ie. threads) are killed before thread 3 prints anything.

Race Condition C thread

So two threads should call two runTimes functions and runTimes function should call increase_count and decrease_count. At the end the result should be 3. The problem is that the last line of code doesn't get executed when I run the program and I can't really identify what causes the race condition.
#define MAX_RESOURCES 5
int available_resources = MAX_RESOURCES;
int times = 100000;
pthread_mutex_t mutex;
sem_t semaphore;
/* decrease available_resources by count resources
* return 0 if sufficient resources available,
* otherwise return -1 */
int decrease_count(int count) {
if (available_resources < count) {
return -1;
} else {
available_resources -= count;
printf("Locked %i resources, now available: %i\n" , count , available_resources);
return 0;
}
}
/* increase available resources by count */
int increase_count(int count) {
if (count + available_resources > 5) {
return -1;
} else {
available_resources += count;
printf("Freed %i resources, now available: %i\n" , count , available_resources);
return 0;
}
}
void *runTimes(void *null) {
int i = 0 , result;
while (i < times) {
result = -1;
while (result < 0) {result = decrease_count(1);}
result = -1;
while (result < 0) {result = increase_count(1);}
i += 1;
printf("Count; %i\n",i );
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t thread1 , thread0;
pthread_t threads [2];
decrease_count(2);
pthread_create(&thread0, NULL, runTimes, NULL);
pthread_create(&thread1, NULL, runTimes, NULL);
int i = 0;
while( i < 2) {
pthread_join(threads[i], NULL);
i++;
}
pthread_exit(NULL);
printf("Currently available resources (should be 3): %i\n" , available_resources);
return 0;
}
the last line of code doesn't get executed
This is beacuse you call
pthread_exit(NULL);
before calling this
printf("Currently available resources (should be 3): %i\n" , available_resources);
(last) line.
pthread_exit() exits the current thread, that is the thread that calls function.
The race in the code you show is unrelated to this. It might occur because the code does not implement any protection against concurrently accessing the same variables.
Also you want to join the threads you created.
To do so change
pthread_create(&thread0, NULL, runTimes, NULL);
pthread_create(&thread1, NULL, runTimes, NULL);
to be
pthread_create(&threads[0], NULL, runTimes, NULL);
pthread_create(&threads[1], NULL, runTimes, NULL);

Resources