1 #include "lfds611_freelist_internal.h"
\r
7 /****************************************************************************/
\r
8 struct lfds611_freelist_element *lfds611_freelist_pop( struct lfds611_freelist_state *fs, struct lfds611_freelist_element **fe )
\r
10 LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_freelist_element
\r
11 *fe_local[LFDS611_FREELIST_PAC_SIZE];
\r
13 assert( fs != NULL );
\r
14 assert( fe != NULL );
\r
16 LFDS611_BARRIER_LOAD;
\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
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
27 if( fe_local[LFDS611_FREELIST_POINTER] == NULL )
\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
35 *fe = (struct lfds611_freelist_element *) fe_local[LFDS611_FREELIST_POINTER];
\r
44 /****************************************************************************/
\r
45 struct lfds611_freelist_element *lfds611_freelist_guaranteed_pop( struct lfds611_freelist_state *fs, struct lfds611_freelist_element **fe )
\r
47 assert( fs != NULL );
\r
48 assert( fe != NULL );
\r
50 lfds611_freelist_internal_new_element( fs, fe );
\r
59 /****************************************************************************/
\r
60 void lfds611_freelist_push( struct lfds611_freelist_state *fs, struct lfds611_freelist_element *fe )
\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
66 assert( fs != NULL );
\r
67 assert( fe != NULL );
\r
69 LFDS611_BARRIER_LOAD;
\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
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
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
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
88 while( 0 == lfds611_abstraction_dcas((volatile lfds611_atom_t *) fs->top, (lfds611_atom_t *) fe_local, (lfds611_atom_t *) original_fe_next) );
\r