The issue that concerns me is the ordering of memory operations on the node pointer and on the node itself. For instance, the write of the node's address to the ring could execute earlier than the writes setting up the node itself; and (less common but still possible) the read of the node's address could occur *after* the reads of the node's contents. The net result would be a reader reading garbage from a node.
Try Googling for "double-checked locking is broken" for why you need memory barriers to solve this issue; it cannot be solved in portable C.
Cheers,
I'm very sorry that I can not find my posted reply in this groups , this is third time .why ?Thank you , Chris . Sorry for my poor english , I will try my best to express my own opinion .
--- In liblf-dev@yahoogroups.com, Chris Purcell <chris.purcell.39@...> wrote:
>
> There don't appear to be any memory barriers in your code. How are you
> avoiding the issue of out-of-order execution on multiprocessor machines?
>
> Chris
It is true that I don't use any memory barriers in my code . First of all , we could assume that
the assignment is atomic in uniprocessor machine , Such as
int ret = 11 ;in asm compiled by gcc 3.4.6 , it isThere are two key ways I used in the implementation :
c7 45 fc 0b 00 00 00 movl $0xb,0xfffffffc(%ebp)
The enqueue function only use member enqueue/enlast/nodes , and the dequeue function only use member dequeue and nodes . Nodes is a small ring array , when enqueue function will put a node , it will find a NULL element of nodes , otherwise , it put this node into old link , pointed by member enlast ; if the dequeue want to get a node , it will get a node from a old link , indexed by member dequeue untill the link is NULL .
1. Combination of queue with ring array ;
2.There is almost no same memory which the enqueue thread and the dequeue need to access .
Look at the struct of queue_t :
#define MAX_RING_SIZE 3
typedef struct _queue_st queue_t ;
struct _queue_st{
qnode_t *nodes[MAX_RING_SIZE] ;
int enqueue ;
int dequeue ;
qnode_t *enlast ;
} ;
The enqueue function and dequeue function can not access the same memory at the same time , only if queue_t's member enqueue is equal to dequeue . I assume that the assignment is atomic in uniproccessor as before , so only after queue->nodes[queue->dequeue] = NULL is successful , then enqueue function can put its node to this link . On the other hand , only after queue->nodes[old] = node is successfull , then dequeue fucntion can get the node .
Even in multiproccessor machines , if movl instruction is atomic , the dequeue function only get the NULL value after nodes[old] = node is successfull .
Best Regards .