]> pd.if.org Git - liblfds/blob - liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_push_pop.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds6.1.0 / liblfds610 / src / lfds610_stack / lfds610_stack_push_pop.c
1 #include "lfds610_stack_internal.h"
2
3
4
5
6
7 /****************************************************************************/
8 int lfds610_stack_push( struct lfds610_stack_state *ss, void *user_data )
9 {
10   LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_stack_element
11     *se[LFDS610_STACK_PAC_SIZE];
12
13   assert( ss != NULL );
14   // TRD : user_data can be NULL
15
16   lfds610_stack_internal_new_element_from_freelist( ss, se, user_data );
17
18   if( se[LFDS610_STACK_POINTER] == NULL )
19     return( 0 );
20
21   lfds610_stack_internal_push( ss, se );
22
23   return( 1 );
24 }
25
26
27
28
29
30 /****************************************************************************/
31 int lfds610_stack_guaranteed_push( struct lfds610_stack_state *ss, void *user_data )
32 {
33   LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_stack_element
34     *se[LFDS610_STACK_PAC_SIZE];
35
36   assert( ss != NULL );
37   // TRD : user_data can be NULL
38
39   /* TRD : this function allocated a new lfds610_freelist element and uses that
40            to push onto the lfds610_stack, guaranteeing success (unless malloc()
41            fails of course)
42   */
43
44   lfds610_stack_internal_new_element( ss, se, user_data );
45
46   // TRD : malloc failed
47   if( se[LFDS610_STACK_POINTER] == NULL )
48     return( 0 );
49
50   lfds610_stack_internal_push( ss, se );
51
52   return( 1 );
53 }
54
55
56
57
58
59 /****************************************************************************/
60 void lfds610_stack_internal_push( struct lfds610_stack_state *ss, struct lfds610_stack_element *se[LFDS610_STACK_PAC_SIZE] )
61 {
62   LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_stack_element
63     *original_se_next[LFDS610_STACK_PAC_SIZE];
64
65   assert( ss != NULL );
66   assert( se != NULL );
67
68   LFDS610_BARRIER_LOAD;
69
70   original_se_next[LFDS610_STACK_POINTER] = ss->top[LFDS610_STACK_POINTER];
71   original_se_next[LFDS610_STACK_COUNTER] = ss->top[LFDS610_STACK_COUNTER];
72
73   do
74   {
75     se[LFDS610_STACK_POINTER]->next[LFDS610_STACK_POINTER] = original_se_next[LFDS610_STACK_POINTER];
76     se[LFDS610_STACK_POINTER]->next[LFDS610_STACK_COUNTER] = original_se_next[LFDS610_STACK_COUNTER];
77   }
78   while( 0 == lfds610_abstraction_dcas((volatile lfds610_atom_t *) ss->top, (lfds610_atom_t *) se, (lfds610_atom_t *) original_se_next) );
79
80   return;
81 }
82
83
84
85
86
87 /****************************************************************************/
88 int lfds610_stack_pop( struct lfds610_stack_state *ss, void **user_data )
89 {
90   LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_stack_element
91     *se[LFDS610_STACK_PAC_SIZE];
92
93   assert( ss != NULL );
94   assert( user_data != NULL );
95
96   LFDS610_BARRIER_LOAD;
97
98   se[LFDS610_STACK_COUNTER] = ss->top[LFDS610_STACK_COUNTER];
99   se[LFDS610_STACK_POINTER] = ss->top[LFDS610_STACK_POINTER];
100
101   do
102   {
103     if( se[LFDS610_STACK_POINTER] == NULL )
104       return( 0 );
105   }
106   while( 0 == lfds610_abstraction_dcas((volatile lfds610_atom_t *) ss->top, (lfds610_atom_t *) se[LFDS610_STACK_POINTER]->next, (lfds610_atom_t *) se) );
107
108   *user_data = se[LFDS610_STACK_POINTER]->user_data;
109
110   lfds610_freelist_push( ss->fs, se[LFDS610_STACK_POINTER]->fe );
111
112   return( 1 );
113 }
114