I'm currently reading the book APUE. When I read the chapter about pthread reader/writer-lock, I have a question about its implementation of concurrent queue using reader/writer-lock.
struct queue {
struct job *q_head;
struct job *q_tail;
pthread_rwlock_t q_lock;
};
/*
* Remove the given job from a queue.
*/
void
job_remove(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_lock);
if (jp == qp->q_head) {
qp->q_head = jp->j_next;
if (qp->q_tail == jp)
qp->q_tail = NULL;
else
jp->j_next->j_prev = jp->j_prev;
} else if (jp == qp->q_tail) {
qp->q_tail = jp->j_prev;
jp->j_prev->j_next = jp->j_next;
} else {
jp->j_prev->j_next = jp->j_next;
jp->j_next->j_prev = jp->j_prev;
}
pthread_rwlock_unlock(&qp->q_lock);
}
My question is that how this implementation can ensure that a struct job
is removed from the linked list only once. From my understanding, two threads can be scheduled so that they are just before the line pthread_rwlock_wrlock
. Then the struct job *jp
might be freed twice. If struct job *
is a dynamically allocated data structure, this might lead to a double-free bug. Any advice?