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