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