1 #include "lfds601_freelist_internal.h"
\r
7 /****************************************************************************/
\r
8 struct lfds601_freelist_element *lfds601_freelist_pop( struct lfds601_freelist_state *fs, struct lfds601_freelist_element **fe )
\r
10 LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_freelist_element
\r
11 *fe_local[LFDS601_FREELIST_PAC_SIZE];
\r
13 assert( fs != NULL );
\r
14 assert( fe != NULL );
\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
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
25 if( fe_local[LFDS601_FREELIST_POINTER] == NULL )
\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
33 *fe = (struct lfds601_freelist_element *) fe_local[LFDS601_FREELIST_POINTER];
\r
42 /****************************************************************************/
\r
43 struct lfds601_freelist_element *lfds601_freelist_guaranteed_pop( struct lfds601_freelist_state *fs, struct lfds601_freelist_element **fe )
\r
45 assert( fs != NULL );
\r
46 assert( fe != NULL );
\r
48 lfds601_freelist_internal_new_element( fs, fe );
\r
57 /****************************************************************************/
\r
58 void lfds601_freelist_push( struct lfds601_freelist_state *fs, struct lfds601_freelist_element *fe )
\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
64 assert( fs != NULL );
\r
65 assert( fe != NULL );
\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
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
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
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
84 while( 0 == lfds601_abstraction_dcas((volatile lfds601_atom_t *) fs->top, (lfds601_atom_t *) fe_local, (lfds601_atom_t *) original_fe_next) );
\r