src/lib/ctx.c
changeset 20 f0d1011e8874
parent 19 ebcc49de97d0
child 21 47f15166e25a
equal deleted inserted replaced
19:ebcc49de97d0 20:f0d1011e8874
     4 #include <stdlib.h>
     4 #include <stdlib.h>
     5 #include <signal.h>
     5 #include <signal.h>
     6 #include <assert.h>
     6 #include <assert.h>
     7 #include <stdio.h> // for perror
     7 #include <stdio.h> // for perror
     8 
     8 
       
     9 static void pt_mutex_unlock (void *arg)
       
    10 {
       
    11     pthread_mutex_t *mutex = arg;
       
    12 
       
    13     assert(!pthread_mutex_unlock(mutex));
       
    14 }
       
    15 
     9 /**
    16 /**
    10  * Enqueue the given piece of work
    17  * Enqueue the given piece of work
    11  *
    18  *
    12  * This function always succeeds.
    19  * This function always succeeds.
    13  */
    20  */
    29 /**
    36 /**
    30  * Dequeue a piece of work
    37  * Dequeue a piece of work
    31  */
    38  */
    32 static void pt_work_dequeue (struct pt_ctx *ctx, struct pt_work **work_ptr)
    39 static void pt_work_dequeue (struct pt_ctx *ctx, struct pt_work **work_ptr)
    33 {
    40 {
    34     // acquire
    41     // acquire, cancel-safe
       
    42     pthread_cleanup_push(pt_mutex_unlock, &ctx->work_mutex);
    35     assert(!pthread_mutex_lock(&ctx->work_mutex));
    43     assert(!pthread_mutex_lock(&ctx->work_mutex));
    36 
    44 
    37     // idle?
    45     // idle?
    38     if (TAILQ_EMPTY(&ctx->work))
    46     if (TAILQ_EMPTY(&ctx->work))
    39         assert(!pthread_cond_signal(&ctx->idle_cond));
    47         assert(!pthread_cond_signal(&ctx->idle_cond));
    40 
    48 
    41     // wait for work
    49     // wait for work
    42     while (TAILQ_EMPTY(&ctx->work))
    50     while (TAILQ_EMPTY(&ctx->work))
       
    51         // we can expect to get pthread_cancel'd here
    43         assert(!pthread_cond_wait(&ctx->work_cond, &ctx->work_mutex));
    52         assert(!pthread_cond_wait(&ctx->work_cond, &ctx->work_mutex));
    44 
    53 
    45     // pop work
    54     // pop work
    46     *work_ptr = TAILQ_FIRST(&ctx->work);
    55     *work_ptr = TAILQ_FIRST(&ctx->work);
    47     TAILQ_REMOVE(&ctx->work, *work_ptr, ctx_work);
    56     TAILQ_REMOVE(&ctx->work, *work_ptr, ctx_work);
    48 
    57 
    49     // release
    58     // release
    50     assert(!pthread_mutex_unlock(&ctx->work_mutex));
    59     pthread_cleanup_pop(true);
    51 }
    60 }
    52 
    61 
    53 /**
    62 /**
    54  * Wait for work queue to become empty
    63  * Wait for work queue to become empty
    55  */
    64  */