]> pd.if.org Git - liblfds/blob - liblfds/liblfds6.1.1/liblfds611/src/lfds611_freelist/lfds611_freelist_pop_push.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds6.1.1 / liblfds611 / src / lfds611_freelist / lfds611_freelist_pop_push.c
1 #include "lfds611_freelist_internal.h"\r
2 \r
3 \r
4 \r
5 \r
6 \r
7 /****************************************************************************/\r
8 struct lfds611_freelist_element *lfds611_freelist_pop( struct lfds611_freelist_state *fs, struct lfds611_freelist_element **fe )\r
9 {\r
10   LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_freelist_element\r
11     *fe_local[LFDS611_FREELIST_PAC_SIZE];\r
12 \r
13   assert( fs != NULL );\r
14   assert( fe != NULL );\r
15 \r
16   LFDS611_BARRIER_LOAD;\r
17 \r
18   fe_local[LFDS611_FREELIST_COUNTER] = fs->top[LFDS611_FREELIST_COUNTER];\r
19   fe_local[LFDS611_FREELIST_POINTER] = fs->top[LFDS611_FREELIST_POINTER];\r
20 \r
21   /* TRD : note that lfds611_abstraction_dcas loads the original value of the destination (fs->top) into the compare (fe_local)\r
22            (this happens of course after the CAS itself has occurred inside lfds611_abstraction_dcas)\r
23   */\r
24 \r
25   do\r
26   {\r
27     if( fe_local[LFDS611_FREELIST_POINTER] == NULL )\r
28     {\r
29       *fe = NULL;\r
30       return( *fe );\r
31     }\r
32   }\r
33   while( 0 == lfds611_abstraction_dcas((volatile lfds611_atom_t *) fs->top, (lfds611_atom_t *) fe_local[LFDS611_FREELIST_POINTER]->next, (lfds611_atom_t *) fe_local) );\r
34 \r
35   *fe = (struct lfds611_freelist_element *) fe_local[LFDS611_FREELIST_POINTER];\r
36 \r
37   return( *fe );\r
38 }\r
39 \r
40 \r
41 \r
42 \r
43 \r
44 /****************************************************************************/\r
45 struct lfds611_freelist_element *lfds611_freelist_guaranteed_pop( struct lfds611_freelist_state *fs, struct lfds611_freelist_element **fe )\r
46 {\r
47   assert( fs != NULL );\r
48   assert( fe != NULL );\r
49 \r
50   lfds611_freelist_internal_new_element( fs, fe );\r
51 \r
52   return( *fe );\r
53 }\r
54 \r
55 \r
56 \r
57 \r
58 \r
59 /****************************************************************************/\r
60 void lfds611_freelist_push( struct lfds611_freelist_state *fs, struct lfds611_freelist_element *fe )\r
61 {\r
62   LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_freelist_element\r
63     *fe_local[LFDS611_FREELIST_PAC_SIZE],\r
64     *original_fe_next[LFDS611_FREELIST_PAC_SIZE];\r
65 \r
66   assert( fs != NULL );\r
67   assert( fe != NULL );\r
68 \r
69   LFDS611_BARRIER_LOAD;\r
70 \r
71   fe_local[LFDS611_FREELIST_POINTER] = fe;\r
72   fe_local[LFDS611_FREELIST_COUNTER] = (struct lfds611_freelist_element *) lfds611_abstraction_increment( (lfds611_atom_t *) &fs->aba_counter );\r
73 \r
74   original_fe_next[LFDS611_FREELIST_POINTER] = fs->top[LFDS611_FREELIST_POINTER];\r
75   original_fe_next[LFDS611_FREELIST_COUNTER] = fs->top[LFDS611_FREELIST_COUNTER];\r
76 \r
77   /* TRD : note that lfds611_abstraction_dcas loads the original value of the destination (fs->top) into the compare (original_fe_next)\r
78            (this happens of course after the CAS itself has occurred inside lfds611_abstraction_dcas)\r
79            this then causes us in our loop, should we repeat it, to update fe_local->next to a more\r
80            up-to-date version of the head of the lfds611_freelist\r
81   */\r
82 \r
83   do\r
84   {\r
85     fe_local[LFDS611_FREELIST_POINTER]->next[LFDS611_FREELIST_POINTER] = original_fe_next[LFDS611_FREELIST_POINTER];\r
86     fe_local[LFDS611_FREELIST_POINTER]->next[LFDS611_FREELIST_COUNTER] = original_fe_next[LFDS611_FREELIST_COUNTER];\r
87   }\r
88   while( 0 == lfds611_abstraction_dcas((volatile lfds611_atom_t *) fs->top, (lfds611_atom_t *) fe_local, (lfds611_atom_t *) original_fe_next) );\r
89 \r
90   return;\r
91 }\r
92 \r