Pthread lost signals / slow conditions?

I am writing a simple threadpool for some small jobs (from 100 to 700 microseconds). I only work with two threads (because there are only two jobs, and the processor has only two cores). My problem is that most of the time, both tasks are performed by the same thread. The problem does not occur when working with large jobs (a few milliseconds).

The expected behavior will be (in this case, the acceleration will be as expected:

  • Topic 1 after cond_wait
  • Work done: 1
  • Thread 0 after cond_wait
  • Task completed: 0
  • Topic 1 before cond_wait
  • Thread 0 before cond_wait

But sometimes (50%) (another thread is blocked before the mutex in cond not notified?):

  • Topic 1 after cond_wait
  • Work done: 1
  • Work done: 1
  • Thread 0 after cond_wait
  • Thread 0 before cond_wait
  • Topic 1 before cond_wait

Or worse (is the signal for another stream lost?):

  • Thread 0 after cond_wait
  • Task completed: 0
  • Task completed: 0
  • Thread 0 before cond_wait

, ( pthread_create):

pthread_mutex_lock(&pl->mutex);
for (;;) {
    /* wait on notification that a new job is available */
    while (pl->queue_head==NULL) {
        //printf("Thread %d before cond_wait\n",threadID);
        pthread_cond_wait(&pl->workcv, &pl->mutex);
        //printf("Thread %d after cond_wait\n",threadID);
    }
    /* get first job */
    job=pl->queue_head;
    if (job!=NULL) {
        /* remove job from the queue */
        pl->queue_head=job->next;
        if (job==pl->queue_tail){ 
            pl->queue_tail=NULL; 
        }
        pthread_mutex_unlock(&pl->mutex);
        /* get job parameter */
        func=job->func;
        arg=job->arg;
        /* Execute job */
        //printf("Job executed by: %d\n",threadID);
        func(arg, threadID);
        /* acquire lock */
        pthread_mutex_lock(&pl->mutex);
    }
}

int while . ( , ):

pthread_mutex_lock(&pl->mutex);
/* Append job to queue */
if (pl->queue_head==NULL) {
    pl->queue_head=job[numJobs-1];
}else {
    pl->queue_tail->next=job[numJobs-1];
}
pl->queue_tail=job[0];
/* Wake up thread if one is idle */
pthread_cond_broadcast(&pl->workcv);
pthread_mutex_unlock(&pl->mutex);

, . : Gcc 4.2.1, Mac OSX Snow Leopard

?

!

+3
1

pthread_cond_broadcast() pthread_cond_signal(). , , , :

    /* remove job from the queue */
    pl->queue_head=job->next;
    if (job==pl->queue_tail){ 
        pl->queue_tail=NULL; 
    }
    if (pl->queue_head != NULL)
        pthread_cond_signal(&pl->workcv);
    pthread_mutex_unlock(&pl->mutex);
+1

Source: https://habr.com/ru/post/1757792/


All Articles