I have blocked queues written in C as a linked list that contains requests from several threads sent and processed in one thread. After hours of stress, I end up with the last request, the next pointer points to itself, which creates an endless loop and blocks the flow of processing.
The application runs (and does not work) on Linux and Windows. I am debugging Windows where my COMPARE_EXCHANGE_PTRmaps to InterlockedCompareExchangePointer .
This is the code that pushes the request to the head of the list and is called from several threads:
void push_request(struct request * volatile * root, struct request * request)
{
assert(request);
do {
request->next = *root;
} while(COMPARE_EXCHANGE_PTR(root, request, request->next) != request->next);
}
This is the code that receives the request from the end of the list and is called by only one thread that processes them:
struct request * pop_request(struct request * volatile * root)
{
struct request * volatile * p;
struct request * request;
do {
p = root;
while(*p && (*p)->next) p = &(*p)->next;
request = *p;
} while(COMPARE_EXCHANGE_PTR(p, NULL, request) != request);
assert(request->next == NULL);
return request;
}
, , , push_request. , , .
, , :
struct request * request = malloc(sizeof(struct request));
if(request) {
push_request(&device->requests, request);
sem_post(device->request_sem);
}
, , , , :
if(sem_wait_timeout(device->request_sem, timeout) == sem_success) {
struct request * request = pop_request(&device->requests);
free(request);
}
, , , , , . ( , , .)
, pop_request . , . , 10, 1 3 .
, , , . , . ( ),