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.
Related
I'm trying to create 3 thread task with different priorities. The task will only wait or signal other thread tasks, and save the execution in char array to see that they executed as supposed.
Here is the code
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <time.h>
#include <pthread.h>
static void *pT1();
static void *pT2();
static void *pT3();
static void trigT3();
static void trigT2();
pthread_cond_t gCondVar1;
pthread_cond_t gCondVar2;
pthread_cond_t gCondVar3;
pthread_cond_t gFinish;
pthread_mutex_t gLock1;
pthread_mutex_t gLock2;
pthread_mutex_t gLock3;
pthread_mutex_t gLockF;
static char savedExe[4];
static int gPos = 0;
static bool gSignalT2 = false;
static bool gSignalT3 = false;
int main(int argc, char const *argv[])
{
struct sched_param param1;
struct sched_param param2;
struct sched_param param3;
pthread_attr_t attr1;
pthread_attr_t attr2;
pthread_attr_t attr3;
pthread_t tid1;
pthread_t tid2;
pthread_t tid3;
pthread_attr_init(&attr1);
pthread_attr_init(&attr2);
pthread_attr_init(&attr3);
pthread_attr_setschedpolicy(&attr1, SCHED_FIFO);
pthread_attr_setschedpolicy(&attr2, SCHED_FIFO);
pthread_attr_setschedpolicy(&attr3, SCHED_FIFO);
param1.sched_priority = 10;
param2.sched_priority = 20;
param3.sched_priority = 30;
pthread_attr_setschedparam(&attr1, ¶m1);
pthread_attr_setschedparam(&attr2, ¶m2);
pthread_attr_setschedparam(&attr3, ¶m3);
pthread_create(&tid1, &attr1, pT1, NULL);
pthread_create(&tid2, &attr2, pT2, NULL);
pthread_create(&tid3, &attr3, pT3, NULL);
for (int i = 0; i < sizeof(savedExe); ++i) {
printf("%c, ", savedExe[i]);
}
printf("\b\b\n");
pthread_cond_signal(&gCondVar1);
/*.
.
.
.*/
pthread_cond_wait(&gFinish, &gLockF);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
for (int i = 0; i < sizeof(savedExe); ++i) {
printf("%c, ", savedExe[i]);
}
printf("\b\b\n");
return 0;
}
static void trigT3(){
pthread_mutex_lock(&gLock3);
pthread_cond_signal(&gCondVar3);
gSignalT3 = true;
pthread_mutex_unlock(&gLock3);
}
static void trigT2(){
pthread_mutex_lock(&gLock2);
pthread_cond_signal(&gCondVar2);
gSignalT2 = true;
pthread_mutex_unlock(&gLock2);
}
static void *pT1(){
pthread_mutex_lock(&gLock1);
pthread_cond_wait(&gCondVar1, &gLock1);
trigT3();
gPos++;
savedExe[gPos] = '1';
pthread_mutex_unlock(&gLock1);
pthread_cond_signal(&gFinish);
return NULL;
}
static void *pT3(){
//printf("T3\n");
pthread_mutex_lock(&gLock3);
if(!gSignalT3){
pthread_cond_wait(&gCondVar3, &gLock3);
gSignalT3 = false;
}
trigT2();
gPos++;
savedExe[gPos] = '3';
pthread_mutex_unlock(&gLock3);
return NULL;
}
static void *pT2(){
pthread_mutex_lock(&gLock2);
if(!gSignalT2){
pthread_cond_wait(&gCondVar2, &gLock2);
gSignalT3 = false;
}
gPos++;
savedExe[gPos] = '2';
pthread_mutex_unlock(&gLock2);
return NULL;
}
In the main, I create the 3 different tasks and assign them with different priorities. pT1 has the lowest priority = 10, pT2 = 20 and pT3 = 30.
pT1 starts the execution first and since its a lower priority and it triggers pT3, pT3 will start executing. pT3 will trigger pT2 but since pT2 is lower priority, pT3 will finish executing and then it will trigger pT2.
The output of this should be 3, 2, 1.
But what I get is 1, 2, 3, as if it does not take care to any priority at all and just executes the tasks in the given order.
Priority affects how much CPU time a thread gets when multiple threads want to use the CPU at once. It's not relevant here.
The problem is that you call trig too soon! You want T2 to run after T3, but you trigger T2 before T3 does its thing. Both end up trying to modify savedExe and gPos at the same time, which is bad. Both problems are avoided by properly ordering the statements.
static void *pT3() {
wait_for_trigger(&gLock3, &gCondVar3, &gSignalT3);
savedExe[gPos++] = '3';
trigger(&gLock2, &gCondVar2, &gSignalT2);
return NULL;
}
Demo on Compiler Explorer
Note that you don't need so many mutexes and conv vars. You could use a single mutex and condvar for all signals.
static void wait_for_trigger(bool *flag) {
pthread_mutex_lock(&mutex);
while (!*flag)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
}
static void trigger(bool *flag) {
pthread_mutex_lock(&mutex);
*flag = true;
pthread_mutex_unlock(&mutex);
pthread_cond_broadcast(&cond);
}
Demo on Compiler Explorer
You could even use a single variable for the different priority levels!
static void wait_for_level(int a_prio_lvl) {
pthread_mutex_lock(&mutex);
while (prio_lvl > a_prio_lvl)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
}
static void switch_to_level(int a_prio_lvl) {
pthread_mutex_lock(&mutex);
prio_lvl = a_prio_lvl;
pthread_mutex_unlock(&mutex);
pthread_cond_broadcast(&cond);
}
Demo on Compiler Explorer
You have numerous other problems covered below. These are all fixed in this demo.
Improper prototype
static void *pT1();
should be
static void *pT1(void);
Empty parens in a declaration doesn't mean no arguments. You need to use void to mean that.
Improper arguments
static void *pT1() { ... }
should be
static void *pT1(void *arg) { ... }
pthread_create calls the function with a void * argument.
You can use (void)arg to silence the unused argument warning.
Uninitialized mutexes
pthread_mutex_t gLock1;
should be
pthread_mutex_t gLock1 = PTHREAD_MUTEX_INITIALIZER;
Mutex need to be initialized before they are used!
Uninitialized cond vars
pthread_cond_t gCondVar1;
should be
pthread_cond_t gCondVar1 = PTHREAD_COND_INITIALIZER;
Cond vars need to be initialized before they are used!
Incorrect expectations from pthread_cond_wait
if (!gSignalT3){
pthread_cond_wait(&gCondVar3, &gLock3);
}
should be
while (!gSignalT3){
pthread_cond_wait(&gCondVar3, &gLock3);
}
pthread_cond_wait can return at any time. To be clear, pthread_cond_wait can return even if pthread_cond_signal hasn't been used. So it must always be called in a loop that checks some external condition.
Passing unlocked mutex to pthread_cond_wait
pthread_cond_wait(&gFinish, &gLockF);
This suffers from four problems we've already covered:
Lack of initializing of gFinish
Lack of initialization of gLockF
Lack of a required loop
Lack of an external condition
But that's not it.
pthread_cond_wait requires a locked mutex, but you are passing an unlocked mutex. It will return immediately with error EINVAL.
Useless code
This is again about
pthread_cond_wait(&gFinish, &gLockF);
It's completely unneeded. pthread_join already waits for the thread to finish. So this serves no purpose.
Full final code:
#include <stdio.h>
#include <stdbool.h>
#include <pthread.h>
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int prio_lvl = 3;
static int gPos = 0;
static char savedExe[3];
static void wait_for_level(int a_prio_lvl) {
pthread_mutex_lock(&mutex);
while (prio_lvl > a_prio_lvl)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
}
static void switch_to_level(int a_prio_lvl) {
pthread_mutex_lock(&mutex);
prio_lvl = a_prio_lvl;
pthread_mutex_unlock(&mutex);
pthread_cond_broadcast(&cond);
}
static void *pT1(void *arg) {
(void)arg;
wait_for_level(1);
savedExe[gPos++] = '1';
return NULL;
}
static void *pT2(void *arg) {
(void)arg;
wait_for_level(2);
savedExe[gPos++] = '2';
switch_to_level(1);
return NULL;
}
static void *pT3(void *arg) {
(void)arg;
wait_for_level(3);
savedExe[gPos++] = '3';
switch_to_level(2);
return NULL;
}
int main(void) {
pthread_t tid1;
pthread_t tid2;
pthread_t tid3;
pthread_create(&tid1, NULL, pT1, NULL);
pthread_create(&tid2, NULL, pT2, NULL);
pthread_create(&tid3, NULL, pT3, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
{
const char *format = "%c";
for (size_t i = 0; i < sizeof(savedExe); ++i) {
printf(format, savedExe[i]);
format = ", %c";
}
printf("\n");
}
return 0;
}
Ok, as i understood your requirements. You want to make priority based thread initiation and storing result in what so ever form.
You can achive this by making a simple priority queue of struct having the priority value and the ptherad variable to hold thread information.
only catch is that you need to make a custom priority queue in c over a structure of roughly of this kind
typedef struct prt_qu{
uint8_t prty;
pthread th;
} ptr_qu;
Upon execution you just need to enqueue all tasks in priority queue and make the main thread call these threads one by one. You can make main wait for current thread wait by just using pthread_join().
I am making a raytracer, im trying to use pthread to divide the rendering. i noticed that isnt helping with the speed because the function pthread_join is to slow, if i use a loop to make the 'await' is way faster and works almost every time fine. But i cant use that because the time of rendering changes with the scene.
Is there a way to check if a thread is finished, on a more efficient way. This is the code.
`
int threats(t_file *c) //this function creates the threads
{
int i;
int err;
pthread_t th[THREADS];
i = 0;
printf("1\n");
c->thread = -1;
mlx_clear_window(c->mlx_ptr, c->win_ptr);
while (i < THREADS)
{
err = pthread_create(&th[i], 0, (void *)paint_scene, (void *)c);
if (err)
return parse_error("Thread Error: CAN NOT CREATE THREAD");
i++;
}
// while (i-- >= 0)
// pthread_join(th[i], 0);
//my await function xd
while (i < 200000000)
i++;
mlx_put_image_to_window(c->mlx_ptr, c->win_ptr, c->img.mlx_img, 0, 0);
c->thread = 0;
return 1;
}
void paint_scene(void *a)
{
int y;
int x;
t_ray ray;
int color;
t_file *c;
c = (t_file *)a;
color = 0;
c->thread++;
y = (c->thread * (c->win_heigth / THREADS));
printf("y:%d,hilo%d\n", y, c->thread);
while (y < (c->thread + 1) * (c->win_heigth / THREADS))
{
x = 0;
while (x < c->win_width)
{
ray = generate_ray(x, y, *c);
color = get_intersections(&ray, c);
if (c->ligth)
color = shading(&ray, color, c);
my_mlx_pixel_put(&c->img, x, y, color);
x++;
}
//ft_printf("\rLoading%d: %d%%", c->thread, y / (c->win_heigth / 100));
y++;
}
pthread_exit(0);
}
`
You have a concurrency problem here in your thread function:
c->thread++;
y = (c->thread * (c->win_heigth / THREADS));
printf("y:%d,hilo%d\n", y, c->thread);
while (y < (c->thread + 1) * (c->win_heigth / THREADS))
{
....
}
c->thread is shared between all threads, and based on likely thread timings and current face of the moon, I can make an educated guess and say that the first thread is calculating the whole image. When starting up, the first thread might see c->thread == -1, but later (if thread startup is faster than the while loop) other thread increase the value until the first thread sees c->thread == THREADS-1
To fix this, each call to create_thread must pass a pointer to a unique parameter object that holds that threads id. So remove the thread member from t_file. It probably serves no purpose there. And create a type of struct that holds the parameters to the thread function:
struct thread_param
{
unsigned int thread;
file_t *c;
}
You use it like this when starting threads:
struct thread_param params[THREADS];
while (i < THREADS)
{
params[i].thread = i;
params[i].c = c;
err = pthread_create(&th[i], 0, (void *)paint_scene, (void *)&(params[i]));
if (err)
return parse_error("Thread Error: CAN NOT CREATE THREAD");
i++;
}
And you access the data in your thread function:
void paint_scene(void *a)
{
struct thread_param *param = (struct thread_param *)a;
unsigned int thread = param->thread;
t_file *c = param->c;
/*
in the rest of the code you remove `c->thread++`
and replace `c->thread` with `thread`
*/
....
}
If you have atomic data types (C11, #ifndef __STDC_NO_ATOMICS__) then implement a global counter and wait until it hits zero (if decreasing) or the amount of threads (if increasing).
e.g.
#include <stdatomic.h>
atomic_int num_jobs;
void* thread_func(void*)
{
//the work to do in the thread function
//before exit decrease counter
--num_jobs;
pthread_exit(0);
}
int main()
{
num_jobs = THREADS; // same as your number of threads
create_threads(THREADS); // number of threads = THREADS
while (num_jobs) { // loop while threads running
//sleep for a while
}
join_threads(); // join threads for cleanup
return 0;
}
Otherwise classic lock mechanics,
e.g.
#include <pthread.h>
pthread_spinlock_t lock;
int num_jobs;
// called by main
int numJobs()
{
pthread_spin_lock(&lock);
int res = num_jobs;
pthread_spin_unlock(&lock);
return res;
}
// called by thread_func
void decNumJobs()
{
pthread_spin_lock(&lock);
--num_jobs;
pthread_spin_unlock(&lock);
}
int main()
{
pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
// the other stuff as before
pthread_spin_destroy(&lock);
return 0;
}
Another alternative would be with pthread_cond_wait and pthread_cond_signal (mainly to avoid the sleep in the while loop, continue after receiving the signal and not based on a fixed amount of time).
e.g.
#include <pthread.h>
int num_jobs;
pthread_cond_t cond;
pthread_mutex_t lock;
void decNumJobs()
{
pthread_mutex_lock(&lock);
if (--num_jobs == 0)
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
void* thread_func(void*)
{
//the work to do in the thread function
//before exit decrease counter
decNumJobs();
pthread_exit(0);
}
int main()
{
num_jobs = THREADS;
pthread_cond_init(&cond, NULL);
pthread_mutex_init(&lock, NULL);
pthread_mutex_lock(&lock);
create_threads(THREADS);
pthread_cond_wait(&cond, &lock);
pthread_mutex_unlock(&lock);
join_threads();
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&lock);
return 0;
}
Note: For the sake of simplicity, there is no error checking nor handling. Reading the documentation of the pthread_* functions (return values, interrupted wait, etc) is strongly advised.
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.
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;
assume creating 3 worker threads by pthread_create,
in these worker thread routine, each call a simple infinite loop function which do not have a return to do counting
how to make worker thread gain control after calling infinite loop function and save the context of infinite loop function for calling in worker thread again?
Let me rephrase to see if I understood the problem.
You have a master thread which spawns 3 worker threads which each do a long running (infinite) job.
At a certain point you want to interrupt processing, save the state of all threads to resume where they left off at a later time.
I think the best way of doing this is organize your threads work in transactionally bound chunks. When restarting, you check the last completed transaction, and go from there.
But since I suspect this to be a homework assignment in low level thread plumbing, may i suggest a shared boolean which is checked on every time you go through the loop to exit and store the state afterwards. Aternatively "kill" the thread and catch the exception and store the state. The last option is messy.
I think you should clarify your question.
If every worker thread calls an infinite loop then I suppose that your master thread would have to call pthread_cancel() on each of them. From what I gather this might require calls to other pthread_*() functions to set the "cancelability" of the target threads.
Of course this suggestion begs the question. The vastly preferable approach would be to prevent those infinite loops. Write your code so that it has exit conditions ... so that the work is bounded by some sort of input or has some sort of event handling.
want to do the effect of a threadpool, after calling infinite loop function, each worker thread can change other tasks(other infinite loop function) to run
for example 3 worker thread can run 4 tasks(infinite loop functions)
#ifndef JOB_CPP
#define JOB_CPP
#include "job.h"
#define NUM_OF_TASKS 4
#define NUM_OF_WORKERS 3
void (* job_queue[NUM_OF_TASKS])(void*);
void (* fp[NUM_OF_WORKERS])(void*); // original running job
int running_task[NUM_OF_WORKERS];
int idle[NUM_OF_TASKS];
int last_running_task[NUM_OF_WORKERS];
int no_of_tasks_running[NUM_OF_WORKERS];
my_struct_t data = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
void func1(void *arg)
{
int count = 0;
int status;
while(true)
{
//if((count % 100) == 0)
//printf("func1 run %d\n", count);
count = count + 1;
//status = pthread_cond_signal(&data.cv);
}
}
void func2(void *arg)
{
int count = 0;
int status;
while(true)
{
//printf("func2 run %d\n", count);
count = count + 1;
//status = pthread_cond_signal(&data.cv);
}
}
void func3(void *arg)
{ int count = 0;
int status;
while(true)
{
//printf("func3 run %d\n", count);
count = count + 1;
//status = pthread_cond_signal(&data.cv);
}
}
void func4(void *arg)
{ int count = 0;
int status;
while(true)
{
//printf("func4 run %d\n", count);
count = count + 1;
//status = pthread_cond_signal(&data.done);
}
}
void jobinit()
{
for(int i=0; i<NUM_OF_TASKS; i++)
{
job_queue[i] = NULL;
idle[i] = 0;
}
for(int i=0; i<NUM_OF_WORKERS; i++)
{
fp[i] = NULL;
running_task[i] = 0;
last_running_task[i] = 0;
no_of_tasks_running[i] = 0;
}
jobadd(func1);
jobadd(func2);
jobadd(func3);
jobadd(func4);
jobrun();
}
void jobadd(void (*job)(void*))
{
for(int i=0; i<4; i++)
{
if(job_queue[i] == NULL)
{
job_queue[i] = job;
return;
}
}
}
void* workserver(void *arg);
void* workserver(void *arg)
{
int status, timedout;
struct timespec timeout;
status = pthread_mutex_lock(&data.mutex);
while(true)
{
timedout = 0;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += 2;
sleep(1);
//void (* clean)(void*);
status = pthread_cond_timedwait(&data.cv, &data.mutex, &timeout);
if(status == ETIMEDOUT){
printf("worker wait timed out %d\n", (int)arg);
timedout = 1;
}else if(status != 0){
printf("worker wait failed %d\n", (int)arg);
status = pthread_mutex_unlock(&data.mutex);
return NULL;
}
printf("workserver number: %d\n", (int)arg);
status = pthread_mutex_unlock(&data.mutex);
printf("function run %d\n", (int)arg);
(* job_queue[(int)arg])(NULL);
printf("cond wait start %d\n", (int)arg);
status = pthread_cond_wait(&data.done, &data.mutex);
printf("cond wait end\n");
status = pthread_mutex_lock(&data.mutex);
}
}
void jobrun()
{
for(int i=0; i<3; i++) {idle[i] = 0;}
pthread_t r1_threadid[3];
for(int i=0; i<3; i++)
{
pthread_create(&r1_threadid[i], NULL, workserver, (void*)i);
}
int status;
struct timespec timeout;
timeout.tv_sec = time (NULL) + 2;
timeout.tv_nsec = 0;
while(true)
{
status = pthread_mutex_lock(&data.mutex);
while(data.value == 0)
{
status = pthread_cond_timedwait(&data.cond, &data.mutex, &timeout);
}
if(data.value != 0)
{
//printf("condition was signaled\n");
data.value = 0;
}
status = pthread_mutex_unlock(&data.mutex);
if(status != 0)
printf("unlock mutex error");
}
}
#endif