我有以下代码,它运行在由主线程的init调用启动的2个线程中。一个用于写入设备,一个用于读取。其他线程调用我的应用程序将项添加到队列中。 pop_queue
处理所有锁定,push_queue
也是如此。每当我修改req r
时,我都会锁定它的互斥锁。 q->process
是指向write_sector
,read_setor
之一的函数指针。我需要防止同时调用这两个函数指针,所以我在实际的进程调用中使用了一个互斥锁,但这不起作用。
根据文本程序,我正在对进程函数进行并行调用。考虑到我之前立即锁定并在之后立即解锁,这怎么可能呢?
valgrind --tool=helgrind
的以下错误可能有帮助?
==3850== Possible data race during read of size 4 at 0xbea57efc by thread #2
==3850== at 0x804A290: request_handler (diskdriver.c:239)
第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 for a request
*/
pop_queue(q, &r, TRUE);
/*
* handle request
* req r is unattached to any lists, but 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 the SectorDescriptor
*/
if (writing) {
printf("Info: driver (write thread) has released a sector descriptor.\n");
blocking_put_sd(*sd_store, r->sd);
r->sd = NULL;
}
pthread_mutex_unlock(&r->lock);
pthread_cond_signal(&r->changed);
}
}
修改
这是读取req属性的另一个位置
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 for req %d to 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 to pool
*/
push_queue(&pool_q, r);
return result;
}
编辑2 这是push_和pop_queue函数
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) {
/* just removed last element */
q->tail = q->head;
}
*r = got;
pthread_mutex_unlock(&q->lock);
return TRUE;
}
/*
* perform a standard linked list insertion to the queue specified
* handles all required locking and signals any listeners
* return: int - if insertion was 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 {
/* was an empty queue */
q->tail = q->head = r;
}
pthread_mutex_unlock(&q->lock);
pthread_cond_signal(&q->wait);
return TRUE;
}
答案 0 :(得分:0)
根据可用信息,似乎可能的另一个线程正在修改*device
指向的数据。也许在q->processing
互斥锁未被保留的情况下进行修改。
答案 1 :(得分:0)
你的行
pthread_cond_signal(&r->changed);
让我怀疑您还有其他代码也在操纵r
指向的结构。在任何情况下,如果你没有人等待那个条件变量就没有多大意义。 (你应该反转解锁和信号线。)
因此,可能您的错误只是在其他地方,您可以同时访问r
而无需锁定互斥锁。你没有向我们展示你的其余代码,所以说更多的是更多的猜测工作。