p2  0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bags.c
Go to the documentation of this file.
1 
7 // Shared variables
8 block_t * globalHeadBlock[NR_THREADS];
9 
10 // Thread-local storage
12 bool foundAdd;
14 int threadID; // Unique number between 0 ... NR_THREADS
15 
16 struct blockp_t {block_t * p; bool mark2 :1; bool mark1 :1;};
17 struct block_t : public node_t {
18  void * nodes[BLOCK_SIZE];
19  long notifyAdd[NR_THREADS/WORD_SIZE];
21 };
22 void Mark1Block(block_t *block) {
23  for(;;) {
24  blockp_t next = block->next;
25  if(next.p == NULL || next.mark1 || CAS(&block->next,next,{next.p,next.mark2,true})) break;
26  }
27 }
29  block_t * block = NewNode(sizeof(block_t));
30  block->next = NULL;
31  NotifyAll(block);
32  for(int i=0;i<BLOCK_SIZE;i++) block->nodes[i]=NULL;
33  return block;
34 }
35 void NotifyAll(block_t *block) {
36  for(int i=0;i<NR_THREADS/WORD_SIZE;i++)
37  block->notifyAdd[i] = 0;
38 }
39 void NotifyStart(block_t *block, int Id) {
40  do {
41  long old = block->notifyAdd[Id/WORD_SIZE];
42  } while(!CAS(&block->notifyAdd[Id/WORD_SIZE],old,old|(1<<(Id%WORD_SIZE))));
43 }
44 
45 bool NotifyCheck(block_t *block, int Id) {
46  return (block->notifyAdd[Id/WORD_SIZE]&(1<<(Id%WORD_SIZE)))==0;
47 }
48 
49 void InitBag() {
50  for(int i=0;i<NR_THREADS;i++) globalHeadBlock[i]=NULL;
51 }
52 void InitThread() {
53  threadBlock = globalHeadBlock[threadID];
54  threadHead = BLOCK_SIZE;
55  stealIndex = 0;
56  stealBlock = NULL; stealPrev = NULL;
57  stealHead = BLOCK_SIZE;
58 }
59 
60 void Add(void *item) {
61  int head = threadHead;
62  block_t * block = threadBlock;
63  for(;;) {
64  if(head==BLOCK_SIZE) {
65  block_t *oldblock = block;
66  block = NewBlock();
67  block->next=oldblock;
68  globalHeadBlock[threadID]=block;
69  threadBlock = block;
70  head = 0;
71  }
72  else if(block->nodes[head]==NULL) {
73  NotifyAll(block);
74  block->nodes[head]=item;
75  threadHead = head+1;
76  return;
77  }
78  else head++;
79  }
80 }
81 
82 void * TryRemoveAny() {
83  int head = threadHead-1;
84  block_t * block = threadBlock;
85  int round = 0;
86  for(;;) {
87  if(block == NULL || (head<0 && block->next.p ==NULL)) {
88  do {
89  int i=0;
90  do {
91  void *result = TryStealBlock(round);
92  if(result!=NULL) return result;
93  if(foundAdd) {
94  round=0; i=0;
95  }
96  else if(stealBlock==NULL) i++;
97  } while(i<NR_THREADS);
98  } while(++round<=NR_THREADS);
99  return NULL;
100  }
101  if(head<0) {
102  Mark1Block(block);
103  for(;;) {
104  blockp_t next=DeRefLink(&block->next);
105  if(next.mark2) Mark1Block(next.p);
106  if(next.mark1) {
107  if(next.p) NotifyAll(next.p);
108  if(CAS(&globalHeadBlock[threadId],block,next.p)) {
109  block->next = {NULL,false,true};
110  DeleteNode(block); ReScan(next);
111  block=next.p;
112  }
113  else block=DeRefLink(&globalHeadBlock[threadId]);
114  }
115  else break;
116  }
117  threadBlock = block;
118  threadHead = BLOCK_SIZE;
119  head = BLOCK_SIZE-1;
120  }
121  else {
122  void *data = block->nodes[head];
123  if(data==NULL) head--;
124  else if(CAS(&block->nodes[head],data,NULL)) {
125  threadHead = head;
126  return data;
127  }
128  }
129  }
130 }
131 
132 /*
133 gc api:
134 node_t * NewNode(int size);
135 void DeleteNode(node_t *node);
136 node_t * DeRefLink(node_t **link);
137 void ReleaseRef(node_t *node);
138 void ReScan(node_t *node);
139 */
140 
141 void * TryStealBlock(int round) {
142  int head = stealHead;
143  block_t * block = stealBlock;
144  foundAdd = false;
145  if(block==NULL) {
146  block = DeRefLink(&globalHeadBlock[stealIndex]);
147  stealBlock = block;
148  stealHead = head = 0;
149  }
150  if(head==BLOCK_SIZE) {
151  stealBlock = block = NextStealBlock(block);
152  head = 0;
153  }
154  if(block==NULL) {
155  stealIndex = (stealIndex+1)%NR_THREADS;
156  stealHead = 0;
157  stealBlock = NULL; stealPrev = NULL;
158  return NULL;
159  }
160  if(round==1) NotifyStart(block,threadId);
161  else if(round>1 && NotifyCheck(block,threadId))foundAdd = true;
162  for(;;) {
163  if(head==BLOCK_SIZE) {
164  stealHead = head;
165  return NULL;
166  }
167  else {
168  void *data = block->nodes[head];
169  if(data==NULL) head++;
170  else if(CAS(&block->nodes[head],data,NULL)) {
171  stealHead = head;
172  return data;
173  }
174  }
175  }
176 }
177 
179  blockp_t next;
180  for(;;) {
181  if(block==NULL) {
182  block = DeRefLink(&globalHeadBlock[stealIndex]);
183  break;
184  }
185  next = DeRefLink(&block->next);
186  if(next.mark2) Mark1Block(next.p);
187  if(stealPrev == NULL || next.p == NULL) {
188  if(next.mark1) {
189  if(next.p) NotifyAll(next.p);
190  if(CAS(&globalHeadBlock[stealIndex],block,next.p)) {
191  block->next = {NULL,false,true};
192  DeleteNode(block); ReScan(next);
193  }
194  else {
195  stealPrev = NULL;
196  block = DeRefLink(&globalHeadBlock[stealIndex]);
197  continue;
198  }
199  }
200  else stealPrev = block;
201  }
202  else {
203  if(next.mark1) {
204  blockp_t prevnext = {block,stealPrev->next.mark2,false};
205  if(CAS(&stealPrev->next,prevnext,next.p)){
206  block->next = {NULL,false,true};
207  DeleteNode(block); ReScan(next);
208  }
209  else {
210  stealPrev = NULL;
211  block = DeRefLink(&globalHeadBlock[stealIndex]);
212  continue;
213  }
214  }
215  else if(block==stealBlock) {
216  if(CAS(&stealPrev->next,block,{block,true,false})) {
217  Mark1Block(block);
218  continue;
219  }
220  else {
221  stealPrev = NULL;
222  block = DeRefLink(&globalHeadBlock[stealIndex]);
223  continue;
224  }
225  }
226  else stealPrev = block;
227  }
228  if(block == stealBlock || next.p == stealBlock) {
229  block=next.p;
230  break;
231  }
232  block=next.p;
233  }
234  return block;
235 }
bool mark2
Definition: bags.c:16
int threadID
Definition: bags.c:14
block_t stealBlock
Definition: bags.c:11
void NotifyAll(block_t *block)
Definition: bags.c:35
void NotifyStart(block_t *block, int Id)
Definition: bags.c:39
block_t * threadBlock
Definition: bags.c:11
bool mark1
Definition: bags.c:16
block_t stealPrev
Definition: bags.c:11
block_t * p
Definition: bags.c:16
bool NotifyCheck(block_t *block, int Id)
Definition: bags.c:45
void Add(void *item)
Definition: bags.c:60
void * nodes[BLOCK_SIZE]
Definition: bags.c:18
block_t * globalHeadBlock[NR_THREADS]
Definition: bags.c:8
block_t * NewBlock()
Definition: bags.c:28
long notifyAdd[NR_THREADS/WORD_SIZE]
Definition: bags.c:19
Definition: bags.c:16
void InitThread()
Definition: bags.c:52
void * TryStealBlock(int round)
Definition: bags.c:141
static unsigned long * next
Definition: mt19937ar.c:63
int stealIndex
Definition: bags.c:13
int threadHead
Definition: bags.c:13
Definition: bags.c:17
void Mark1Block(block_t *block)
Definition: bags.c:22
blockp_t next
Definition: bags.c:20
void InitBag()
Definition: bags.c:49
block_t * NextStealBlock(block_t *block)
Definition: bags.c:178
int stealHead
Definition: bags.c:13
void * TryRemoveAny()
Definition: bags.c:82
bool foundAdd
Definition: bags.c:12