c - Mutual exclusion isn't exclusive -
i have following code runs in 2 threads started init call main thread. 1 writing device, 1 reading. app called other threads add items queues. pop_queue
handles locking, push_queue
. whenever modify req r
, lock it's mutex. q->process
function pointer 1 of either write_sector
, read_setor
. need guard against simultaneous calls 2 function pointers, i'm using mutex on actual process call, not working.
according text program, making parallel calls process functions. how possible given lock immediatly before , unlock afterwards?
the following error valgrind --tool=helgrind
might help?
==3850== possible data race during read of size 4 @ 0xbea57efc thread #2 ==3850== @ 0x804a290: request_handler (diskdriver.c:239)
line 239 r->state = q->process(*device, &r->sd) +1
void * request_handler(void *arg) { req *r; queue *q = arg; int writing = !strcmp(q->name, "write"); for(;;) { /* * wait request */ pop_queue(q, &r, true); /* * handle request * req r unattached lists, must lock it's properties incase being redeemed */ printf("info: driver: (%s) handling req %d\n", q->name, r->id); pthread_mutex_lock(&r->lock); pthread_mutex_lock(&q->processing); r->state = q->process(*device, &r->sd) +1; pthread_mutex_unlock(&q->processing); /* * if writing, return sectordescriptor */ if (writing) { printf("info: driver (write thread) has released sector descriptor.\n"); blocking_put_sd(*sd_store, r->sd); r->sd = null; } pthread_mutex_unlock(&r->lock); pthread_cond_signal(&r->changed); } }
edit
here 1 other location req's properties read
int redeem_voucher(voucher v, sectordescriptor *sd) { int result; if (v == null){ printf("driver: null voucher redeemed!\n"); return 0; } req *r = v; pthread_mutex_lock(&r->lock); /* if state = 0 job still running/queued */ while(r->state==0) { printf("driver: blocking req %d finish\n", r->id); pthread_cond_wait(&r->changed, &r->lock); } sd = &r->sd; result = r->state-1; r->sd = null; r->state = wait; //printf("driver: req %d completed\n", r->id); pthread_mutex_unlock(&r->lock); /* * return req pool */ push_queue(&pool_q, r); return result; }
edit 2 here's push_ , pop_queue functions
int pop_queue(struct queue *q, req **r, int block) { pthread_mutex_lock(&q->lock); while(q->head == null) { if(block) { pthread_cond_wait(&q->wait, &q->lock); } else { pthread_mutex_unlock(&q->lock); return false; } } req *got = q->head; q->head = got->next; got->next = null; if(!q->head) { /* removed last element */ q->tail = q->head; } *r = got; pthread_mutex_unlock(&q->lock); return true; } /* * perform standard linked list insertion queue specified * handles required locking , signals listeners * return: int - if insertion successful */ int push_queue(queue *q, req *r) { /* * push never blocks, */ if(!r || !q) return false; pthread_mutex_lock(&q->lock); if(q->tail) { q->tail->next = r; q->tail = r; } else { /* empty queue */ q->tail = q->head = r; } pthread_mutex_unlock(&q->lock); pthread_cond_signal(&q->wait); return true; }
based on available information, seems possibility thread modifying data pointed *device
. perhaps being modified while q->processing
mutex not held.
Comments
Post a Comment