I'm trying to write safe SIGINT handling for my multithreaded application and I'm using sleep() function to simulate entering "unsafe" zone - a place where a thread shouldn't be cancelled. Here's my code:
Global variables:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
pthread_mutex_t *global_mutex;
pthread_mutex_t **thread_mutexes;
pthread_mutex_t *firm_mutex;
pthread_attr_t *attr;
Thread:
void *thread(void *data)
{
int local_tid = *(int *) data;
printf("Starting thread %d\n", local_tid);
for (;;) {
pthread_mutex_lock(thread_mutexes[local_tid]);
int scnds = rand() % 5 + 1;
printf("%d locked\nSleeping for: %d seconds\n", local_tid, scnds);
sleep(scnds);
printf("%d woken up!\n", local_tid);
pthread_mutex_unlock(thread_mutexes[local_tid]);
}
}
Thread creation:
int main()
{
int n;
scanf("%d", &n);
printf("Starting signal handler with %d threads...\n",n);
global_mutex = malloc(sizeof(pthread_mutex_t));
firm_mutex = malloc(sizeof(pthread_mutex_t));
thread_mutexes = malloc(n * sizeof(pthread_mutex_t *));
for (int i = 0; i < n; i++) {
thread_mutexes[i] = malloc(sizeof(pthread_mutex_t));
}
attr = malloc(sizeof(pthread_attr_t));
if (pthread_attr_init(attr) != 0 ) {
perror("attrinit\n");
exit(1);
}
if (pthread_attr_setdetachstate (attr,PTHREAD_CREATE_JOINABLE) != 0) {
perror("setdetach\n");
exit(1);
}
for (int i = 0; i < n; i++) {
pthread_t tid;
if (pthread_mutex_init (thread_mutexes[i], 0) != 0) {
perror("mutexinit\n");
exit(1);
}
int *tdata = malloc(sizeof(int));
*tdata = i;
if (pthread_create (&tid, attr, watek, tdata) != 0) {
perror("pthread_create");
exit(1);
}
if (pthread_join (tid, 0) != 0) {
perror("join\n");
exit(1);
}
}
return 0;
}
So you would think that after launching with 10 threads, first thread should go to sleep immedietely and in the meantime another should start execution. Unfortuntely, after launching the program with 10 threads I get an output like this:
Starting signal handler with 10 threads...
Starting thread 0
0 locked
sleeping for: 4 seconds
0 woken up!
0 locked
sleeping for: 2 seconds
0 woken up!
0 locked
sleeping for: 3 seconds
0 woken up!
0 locked
sleeping for: 1 seconds
0 woken up!
0 locked
sleeping for: 4 seconds
0 woken up!
0 locked
Basically thread 0 steals all the time! Why aren't other threads executed when 0 sleeps?
if (pthread_create (&tid, attr, watek, tdata) != 0) {
perror("pthread_create");
exit(1);
}
if (pthread_join (tid, 0) != 0) {
perror("join\n");
exit(1);
}
You're creating the first thread and then waiting to pthread_join with it before creating the next one. The next loop iteration, therefore, (creating the next thread) won't happen until the first thread terminates.
If you want all the threads to start right away, just create and start them in the first loop - deal with waiting for them to complete later.
Related
#include<pthread.h>
#include<stdio.h>
#include<stdint.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
#define ERROR_CREATE 1
#define ERROR_JOIN 2
// create the function to be executed as a thread
void *thread(void *ptr)
{
uintptr_t type = (uintptr_t) ptr; // thread number
srand(time(NULL) + getpid());
int wait = rand() % 10; // randomizes numbers from 0 to 10
sleep(wait); // waits in time intervals of seconds
printf("Thread - %ld waiting for %d seconds\n",type, wait);
return ptr; // returns the thread number
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Error with command line arguments");
}
int num_threads = atoi(argv[1]);
pthread_t threads[num_threads]; // array of thread types
for (long i = 1; i <= num_threads; i++) {
if (pthread_create(&threads[i], NULL, thread, (void *)i) != 0)
// if there's an error creating thread
{
fprintf(stderr,"Error: could not create thread");
return ERROR_CREATE;
}
}
// terminate each thread assigned
for (int i = 1; i <= num_threads; i++) {
if (pthread_join(threads[i], NULL) != 0)
// if there's an error ending each thread
{
fprintf(stderr, "Error: could not terminate thread");
return ERROR_JOIN;
}
}
return 0;
}
Seeding the rand function, I am still getting the same number outputted. I understand the hardware is fast and therefore is getting the same answer as the clock speed is faster than seeding the rand function. Does anyone know another way of getting more variety from the rand function?
Return if argv[1] is not populated otherwise it segfaults.
srand() resets the sequence. As you call it multiple times with the same value this is not what you want. Moved it main().
The array threads is accessed out of bounds in the two loops.
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define ERROR_CREATE 1
#define ERROR_JOIN 2
// create the function to be executed as a thread
void *thread(void *ptr) {
uintptr_t type = (uintptr_t) ptr; // thread number
int wait = rand() % 10; // randomizes numbers from 0 to 10
sleep(wait); // waits in time intervals of seconds
printf("Thread - %ld waiting for %d seconds\n",type, wait);
return ptr; // returns the thread number
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Error with command line arguments\n");
return 1;
}
srand(time(NULL));
int num_threads = atoi(argv[1]);
pthread_t threads[num_threads]; // array of thread types
for (long i = 0; i < num_threads; i++) {
if (pthread_create(&threads[i], NULL, thread, (void *)i) != 0)
// if there's an error creating thread
{
fprintf(stderr,"Error: could not create thread");
return ERROR_CREATE;
}
}
// terminate each thread assigned
for (int i = 0; i < num_threads; i++) {
if (pthread_join(threads[i], NULL) != 0)
// if there's an error ending each thread
{
fprintf(stderr, "Error: could not terminate thread");
return ERROR_JOIN;
}
}
}
and here is a couple of sample runs:
$ ./a.out 2
Thread - 1 waiting for 3 seconds
Thread - 2 waiting for 7 seconds
$ ./a.out 2
Thread - 1 waiting for 3 seconds
Thread - 2 waiting for 6 seconds
I am trying to play with the priority with POSIX. My goal is to have the following program. Two thread are running Thread0 with a priority of 10 and Thread1 with the priority of 50. The Thread1 block in a finite loop (like 3 seconds) and in this time interval Thread0 try to execute himself. The result should be the the Thread0 will be blocked because a thread with higher priority is executing.
My result is that the priority doesn't change the behaviour of the thread... I compile with the following command gcc -Wall -o scheduling scheduling3.c -pthread
and with the sudo su command on ubuntu.
Result :
Prio min = 1, Prio max = 99
SCHED_FIFO
Priority of the thread 0 : 10
SCHED_FIFO
Priority of the thread 1 : 50
Value of test_thread_0 1
Value of test_thread_1 1
Result that I want :
Prio min = 1, Prio max = 99
SCHED_FIFO
Priority of the thread 0 : 10
SCHED_FIFO
Priority of the thread 1 : 50
Value of test_thread_0 1
Value of test_thread_1 1
Program :
// The thread with high priority wil block the thread with low priority
// Run with super user privilege (sudo su with ubuntu)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <pthread.h>
#include <errno.h>
#define NUM_THREADS 2
int test_thread_0 = 0;
int test_thread_1 = 0;
void *BlockThread0(void *threadid) {
test_thread_0 = 1;
}
void *BlockThread1(void *threadid) {
struct timeval start, end;
long secs_used;
gettimeofday(&start, NULL);
test_thread_1 = 1;
while(1) {
gettimeofday(&end, NULL);
secs_used=(end.tv_sec - start.tv_sec); //avoid overflow by subtracting first
if(secs_used > 3)
break;
}
}
int main(int argc, char *argv[]) {
int i, policy;
pthread_t tid[NUM_THREADS];
pthread_attr_t attr[NUM_THREADS];
struct sched_param param[NUM_THREADS], test;
int prio_max, prio_min;
// Get the range of the policy
prio_max = sched_get_priority_max(SCHED_FIFO);
prio_min = sched_get_priority_min(SCHED_FIFO);
printf("Prio min = %d, Prio max = %d \n", prio_min, prio_max);
// Set the different priority
param[0].sched_priority = 10;
param[1].sched_priority = 50;
// Set all the attribute (policy + priority)
for(i = 0; i < NUM_THREADS; i++) {
pthread_attr_init(&attr[i]);
if(pthread_attr_setinheritsched(&attr[i], PTHREAD_EXPLICIT_SCHED) != 0)
fprintf(stderr, "Unable to set EXPLICIT SCHEDULER.\n");
pthread_attr_setdetachstate(&attr[i], PTHREAD_CREATE_JOINABLE);
/* The attribute get the new policy */
if(pthread_attr_setschedpolicy(&attr[i], SCHED_FIFO) != 0)
fprintf(stderr, "Unable to set policy.\n");
/* Test to change the priority of each task */
if(pthread_attr_setschedparam(&attr[i], ¶m[i]) != 0)
fprintf(stderr, "Unable to set priority.\n");
}
// Get all the attribute (policy + priority)
for(i = 0; i < NUM_THREADS; i++) {
// Get the policy
if(pthread_attr_getschedpolicy(&attr[i], &policy) != 0)
fprintf(stderr, "Unable to get policy.\n");
else{
if(policy == SCHED_OTHER)
printf("SCHED_OTHER\n");
else if(policy == SCHED_RR)
printf("SCHED_RR\n");
else if(policy == SCHED_FIFO)
printf("SCHED_FIFO\n");
}
/* Get the priority */
pthread_attr_getschedparam(&attr[i], &test);
printf("Priority of the thread %d : %d \n",i,test.sched_priority);
}
// Thread1 with the most important priority is executing
pthread_create(&tid[1], &attr[1], BlockThread1, (void *)1);
// To be sure that the thread1 is running
sleep(1);
//Thread2 with lower priority attempt to execute himself but he is blocked because thread1 is executing
pthread_create(&tid[0], &attr[0], BlockThread0, (void *)0);
/* now join on each thread */
for(i = 0; i < NUM_THREADS; i++)
pthread_join(tid[i], NULL);
printf("Value of test_thread_0 %d \n",test_thread_0);
printf("Value of test_thread_1 %d \n",test_thread_1);
}
That loop is called a "busy loop", it does not give the OS' scheduler a way to schedule other threads. You should use some variant of sleep().
'The result should be the the Thread0 will be blocked because a thread with higher priority is executing'
No. Not with nearly all hardware commonly available today.
Threads will only remain ready, waiting for execution, if there are more ready/running threads than cores available to run them.
With two threads, you should notice something like you were expecting on a processor with only one core.
They are very rare now.
So I have this program that has 2 threads to increment from 0 to 100 a variable, and it works fine.
#include<stdio.h>
#include<stdlib.h>
#include<semaphore.h>
#include<pthread.h>
int contor;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *incrementare(void *args) {
int id = (int)args;
while(1) {
pthread_mutex_lock(&mutex);
if (contor >= 100) {
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
while (contor %2 == id) {
pthread_cond_wait(&cond,&mutex);
}
contor++;
printf("Thread %d increment: %d\n",id,contor);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
int main(void) {
pthread_t th1, th2,th3;
if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
perror("Error!\n");
exit(1);
}
if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
perror("Error!\n");
exit(2);
}
pthread_join(th1, NULL);
pthread_join(th2, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
The result is something like:
Thread 1 increment: 1
Thread 0 increment: 2
Thread 1 increment: 3
Thread 0 increment: 4
Thread 1 increment: 5
Thread 0 incre.. and so on ,which is nice.
But the problem is when I try with 3 threads, and it no longer works as they then come randomly. I only made 3 changes and I do not know what the issue is.
#include<stdio.h>
#include<stdlib.h>
#include<semaphore.h>
#include<pthread.h>
int contor;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *incrementare(void *args) {
int id = (int)args;
while(1) {
pthread_mutex_lock(&mutex);
if (contor >= 100) {
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
while (contor %3 == id) {
pthread_cond_wait(&cond,&mutex);
}
contor++;
printf("Thread %d increment: %d\n",id,contor);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
int main(void) {
pthread_t th1, th2,th3;
if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
perror("Error!\n");
exit(1);
}
if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
perror("Error!\n");
exit(2);
}
if(pthread_create(&th3, NULL, &incrementare, (void *)2) < 0) {
perror("Error!\n");
exit(3);
}
pthread_join(th1, NULL);
pthread_join(th2, NULL);
pthread_join(th3, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
It should do the same right? Only with 3 now. Why isn't it working? This is how it works
Thread 2 increment: 1
Thread 2 increment: 2
Thread 1 increment: 3
Thread 1 increment: 4
Thread 2 increment: 5
Thread 1 increment: 6
If you want the threads to guarantee a cycle, you need to make a thread wait until the counter modulo N (thread count) is a specific id, not until it is anything but that specific id. With two ids, if it wasn't one, it must be the other. But with three, there are two cases of breaking, and one case of waiting.
The scheduler is freely capable of choosing whichever of those two spare threads it wants to release.
But if you change this:
while (contor %3 == id)
to this:
while (contor %3 != id)
you will enforce that the given thread will only write values that are modulo its id.
However, this isn't enough. You also need to wake all waiters. Before, when you had only two threads, there was always the same waiter: the "other guy" that wasn't the active thread. This a pthread_cond_signal would be directed to a specific target thread (the only one not running) and it naturally was also the next one in line.
With three or more threads, there is the possibility that the single thread potentially awoken by pthread_cond_signal may not be the one that has has a contor modulo N id. In fact, the more threads you have, the more likely this will happen. In that case, the thread goes back to waiting, but no one else waiting is started up again. You do NOT want to leave this to chance. Make sure all the waiters are awoken to ensure the one that is next will get the signal.
Do not address this by just sending another pthread_cond_signal somewhere. Rather, send a broadcast instead: Change this:
pthread_cond_signal(&cond);
to this:
pthread_cond_broadcast(&cond);
This will ensure all actively waiting threads eventually get a crack at looking at contor and the one that matches contor modulo N will get the chance to bump, print, send the next broadcast, and head back to waiting.
Thus, the minimal change to your code would be:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h> // added for intptr_t
#include<inttypes.h> // added for printf formatter for intptr_t
#include<pthread.h>
int contor;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *incrementare(void *args) {
intptr_t id = (intptr_t)args; // proper way to pass an integer via thread param
while(1) {
pthread_mutex_lock(&mutex);
if (contor >= 100) {
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
while (contor %3 != id) {
pthread_cond_wait(&cond,&mutex);
}
contor++;
printf("Thread %"PRIdPTR " increment: %d\n",id,contor);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
return NULL; // should always have well-defined return value
}
int main(void) {
pthread_t th1, th2,th3;
if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
perror("Error!\n");
exit(1);
}
if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
perror("Error!\n");
exit(2);
}
if(pthread_create(&th3, NULL, &incrementare, (void *)2) < 0) {
perror("Error!\n");
exit(3);
}
pthread_join(th1, NULL);
pthread_join(th2, NULL);
pthread_join(th3, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
The result is below:
Thread 0 increment: 1
Thread 1 increment: 2
Thread 2 increment: 3
Thread 0 increment: 4
Thread 1 increment: 5
Thread 2 increment: 6
Thread 0 increment: 7
Thread 1 increment: 8
Thread 2 increment: 9
Thread 0 increment: 10
....
Thread 0 increment: 97
Thread 1 increment: 98
Thread 2 increment: 99
Thread 0 increment: 100
Thread 1 increment: 101
Thread 2 increment: 102
See it live
The extra two output are because the code checking the the ceiling-break condition is before the cvar-predicate loop. It should be after, but I leave that for you to address.
Keep in mind, however, that doing this ultimately defeats the purpose of turning multiple threads loose on a task. Ideally you want any thread available to perform work to actually do so. That your work affects just a single global somewhat defeats the real purpose of threading (obviously you would not use threading to count to 100; a single thread in a loop is ideal for that).
Regardless, a condensed version of your program appears below. Change the values of N_THREADS and N_COUNT to see differences in output.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <pthread.h>
#define N_THREADS 7
#define N_COUNT 100
int contor; // 0
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *incrementare(void *args)
{
intptr_t id = (intptr_t)args;
pthread_mutex_lock(&mutex);
while(1)
{
while (contor < N_COUNT && contor % N_THREADS != id)
pthread_cond_wait(&cond, &mutex);
if (contor == N_COUNT)
break;
printf("Thread %"PRIdPTR" increment: %d\n", id, ++contor);
pthread_cond_broadcast(&cond);
}
pthread_mutex_unlock(&mutex);
return NULL;
}
int main(void)
{
pthread_t ar[N_THREADS];
intptr_t id = 0;
for (int i=0; i<N_THREADS; ++i)
{
if(pthread_create(ar+i, NULL, &incrementare, (void *)id++) < 0) {
perror("Error!\n");
exit(1);
}
}
for (int i=0; i<N_THREADS; ++i)
pthread_join(ar[i], NULL);
return 0;
}
I'm currently working on custom thread scheduler project that uses pthreads in C. I have been struggling conceptually with it but am finally getting the behavior I expect to see, save for the segmentation fault.
My job is to register five child threads and schedule each one based on the order of their IDs stored in an array. What I do is call pthread_mutex_lock and tell whichever child thread that is not to be scheduled first to wait. I do some stuff to my counter to keep track of when the next child should be scheduled and after one child thread increments counter to five it should wake up other threads and do the same thing for as many times as main loop is defined.
all variables:
#define NTHREADS 5 /* Number of child threads */
#define NUM_LOOPS 10 /* Number of local loops */
#define SCHEDULE_INTERVAL 1 /* thread scheduling interval */
#define errexit(code,str) fprintf(stderr,"%s: %s\n",(str),strerror(code));exit(1);
int schedule_vector[NTHREADS]; /* The thread schedule vector */
int flag = 0;
pthread_cond_t cv; // condtitional variable
pthread_mutex_t mtx; // mutex semaphore 1
int globalcounter = 0;
int currentThread;
#define TASK_LIMIT 6
here is parent thread:
int main(int argc,char *argv[])
{
int i;
int worker;
int ids[NTHREADS];
int errcode;
int *status;
int policy;
pthread_t threads[NTHREADS];
/* Create child threads --------------------------------------------- */
for (worker = 0; worker < NTHREADS; worker++)
{
ids[worker] = worker;
printf("creating child thread using id %d\n", worker);
/* Create a child thread ----------------------------------------- */
pthread_create (
&threads[worker],
NULL,
my_thread,
&ids[worker]);
}
/* Initialize the thread schedule vector -------------------------- */
schedule_vector[0] = 0; /* First thread to be executed (0) */
schedule_vector[1] = 1; /* Second thread to be exceuted (1) */
schedule_vector[2] = 2; /* Third thread to be executed (2) */
schedule_vector[3] = 3; /* Fourth thread to be executed (3) */
schedule_vector[4] = 4; /* Fifth thread to be executed (4) */
signal(SIGALRM, clock_interrupt_handler);
alarm(SCHEDULE_INTERVAL);
printf("handler set up\n");
/* Reap the threads as they exit ----------------------------------- */
for (worker = 0; worker < NTHREADS; worker++)
{
/* Wait for thread to terminate --- */
if (errcode=pthread_join(threads[worker],(void *) &status))
{ errexit(errcode,"pthread_join"); }
/* Check thread's exit status and release its resources -------- */
if (*status != worker)
{
fprintf(stderr,"thread %d terminated abnormally\n",worker);
exit(1);
}
}
/* The main (parent) thread terminates itself ---------------------- */
return(0);
}
Here is the child thread function:
void *my_thread(void * arg)
{
long int i;
long int counter;
int myid=*(int *) arg;
counter = 0;
printf("\nI am thread #%d\n\n", myid);
/* Main loop ------------------------------------------ */
for (i = 0; i < NUM_LOOPS; i++)
{
currentThread = myid;
pthread_mutex_lock(&mtx);
while(myid != schedule_vector[flag]){
pthread_cond_wait(&cv, &mtx);
}
counter++;
globalcounter = counter;
printf("Thread: %d is running ...\n", myid);
usleep(100000);
}
return arg;
}
and here is my interrupt handler:
void clock_interrupt_handler(void)
{
printf("scheduler started ++++++++++++++++++++++++++++++++++ \n");
if (currentThread == schedule_vector[flag]) {
printf("scheduled thread received: thread %d, and it's counter is at %d\n", currentThread, globalcounter);
while(globalcounter < TASK_LIMIT){
if(globalcounter == 5){
flag++;
pthread_cond_broadcast(&cv);
}
pthread_mutex_unlock(&mtx);
alarm(SCHEDULE_INTERVAL);
}
} else {
printf("unscheduled thread received, putting thread %d with count %d to sleep...\n", currentThread, globalcounter);
alarm(SCHEDULE_INTERVAL);
}
}
This is the output:
scheduler started ++++++++++++++++++++++++++++++++++
scheduled thread received: thread 0, and it's counter is at 1
Thread: 0 is running ...
Thread: 0 is running ...
Thread: 0 is running ...
Thread: 0 is running ...
Segmentation fault (core dumped)
It basically repeats this behavior, but for each thread. I'd like to understand what is exactly causing the seg fault
Seems pthread_mutex_lock/pthread_mutex_unlock do not pair.
The correct code looks like
pthread_mutex_lock()
pthread_cond_broadcast()
pthread_mutex_unlock()
pthread_mutex_lock()
pthread_cond_wait()
pthread_mutex_unlock()
I want to finish my threads with a mutex. The first thread won't execute, thread 2 & 3 execute.
Does anyone know what this problem could be? Sometimes thread 1 is executed but then 2 or 3 is not executed. I don't know what the problem is here.
Thread created successfully
Thread created successfully
Thread created successfully
----------------------------------------------------
J:0
NUM_REQUESTS (before function): 0
J:0
----------------------------------------------------
----------------------------------------------------
J:1
Third thread processing done
WRITE DATA TO LIST!
NUM_REQUESTS(function): 1
NUM_REQUESTS (before function): 0
J:1
----------------------------------------------------
----------------------------------------------------
J:2
Second thread processing done
WRITE DATA TO LIST!
NUM_REQUESTS(function): 0
NUM_REQUESTS (before function): 0
J:2
----------------------------------------------------
Program:
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_mutex_t request_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t got_request = PTHREAD_COND_INITIALIZER;
pthread_t tid[3];
int thr_id[3];
int ret1,ret2,ret3;
int i = 0;
int err;
int *ptr[2];
int num_requests = 0;
int rc = 0;
This is the function of the threads, the first thread is not executed!
void* doSomeThing(void *arg)
{
unsigned long i = 0;
pthread_t id = pthread_self();
for(i=0; i<1000000;i++);
if(pthread_equal(id,tid[0]))
{
printf("First thread processing done\n");
printf("WRITE DATA TO LIST!\n");
num_requests--;
printf("NUM_REQUESTS(function): %d\n",num_requests);
rc = pthread_mutex_unlock(&request_mutex);
pthread_exit(&tid[0]);
}else if(pthread_equal(id,tid[1])){
printf("Second thread processing done\n");
num_requests--;
printf("WRITE DATA TO LIST!\n");
printf("NUM_REQUESTS(function): %d\n",num_requests);
rc = pthread_mutex_unlock(&request_mutex);
pthread_exit(&tid[1]);
}else if(pthread_equal(id,tid[2])){
printf("Third thread processing done\n");
printf("WRITE DATA TO LIST!\n");
printf("NUM_REQUESTS(function): %d\n",num_requests);
num_requests--;
rc = pthread_mutex_unlock(&request_mutex);
pthread_exit(&tid[2]);
}
return NULL;
}
This is where i create the output of the threads
void add_request(int j,pthread_mutex_t* p_mutex,pthread_cond_t* p_cond_var)
{
printf("----------------------------------------------------\n");
printf("J:%d\n",j);
if(num_requests > 3){
printf("WAIT TILL THREADS ARE FREE!\n");
}else{
rc = pthread_mutex_lock(&request_mutex);
printf("NUM_REQUESTS (before function): %d\n",num_requests);
num_requests++;
rc = pthread_mutex_unlock(&request_mutex);
rc = pthread_mutex_lock(&request_mutex);
rc = pthread_cond_signal(p_cond_var);
printf("J:%d\n",j);
printf("----------------------------------------------------\n");
}
}
In the main i only create the threads and use the add_request function to execute the threads
int main(void)
{
//create 3 threads
while(i < 3)
{
thr_id[i] = i;
err = pthread_create(&(tid[i]), NULL, &doSomeThing, (void*)&thr_id[i]);
if (err != 0)
printf("can't create thread :[%s]", strerror(err));
else
printf("Thread created successfully\n");
i++;
}
int j;
for(j=0;j<3;j++){
add_request(j, &request_mutex, &got_request);
}
return 0;
}
what are you trying to do?
At least one problem I see it that you unlock the mutex without locking it...
When you create a thread it starts spontaneously (more or less) so you can't assume add_request will be called after doSomething().
You can lock and then unlock. Also consider using ptheard_join if you want to wait until the threads finish.
EDIT
this is what you want to do https://computing.llnl.gov/tutorials/pthreads/samples/condvar.c
-taken from https://computing.llnl.gov/tutorials/pthreads/
Good luck