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