#include "lfds611_stack_internal.h" /****************************************************************************/ int lfds611_stack_push( struct lfds611_stack_state *ss, void *user_data ) { LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE]; assert( ss != NULL ); // TRD : user_data can be NULL lfds611_stack_internal_new_element_from_freelist( ss, se, user_data ); if( se[LFDS611_STACK_POINTER] == NULL ) return( 0 ); lfds611_stack_internal_push( ss, se ); return( 1 ); } /****************************************************************************/ int lfds611_stack_guaranteed_push( struct lfds611_stack_state *ss, void *user_data ) { LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE]; assert( ss != NULL ); // TRD : user_data can be NULL /* TRD : this function allocated a new lfds611_freelist element and uses that to push onto the lfds611_stack, guaranteeing success (unless malloc() fails of course) */ lfds611_stack_internal_new_element( ss, se, user_data ); // TRD : malloc failed if( se[LFDS611_STACK_POINTER] == NULL ) return( 0 ); lfds611_stack_internal_push( ss, se ); return( 1 ); } /****************************************************************************/ void lfds611_stack_internal_push( struct lfds611_stack_state *ss, struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE] ) { LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_stack_element *original_se_next[LFDS611_STACK_PAC_SIZE]; assert( ss != NULL ); assert( se != NULL ); LFDS611_BARRIER_LOAD; original_se_next[LFDS611_STACK_POINTER] = ss->top[LFDS611_STACK_POINTER]; original_se_next[LFDS611_STACK_COUNTER] = ss->top[LFDS611_STACK_COUNTER]; do { se[LFDS611_STACK_POINTER]->next[LFDS611_STACK_POINTER] = original_se_next[LFDS611_STACK_POINTER]; se[LFDS611_STACK_POINTER]->next[LFDS611_STACK_COUNTER] = original_se_next[LFDS611_STACK_COUNTER]; } while( 0 == lfds611_abstraction_dcas((volatile lfds611_atom_t *) ss->top, (lfds611_atom_t *) se, (lfds611_atom_t *) original_se_next) ); return; } /****************************************************************************/ int lfds611_stack_pop( struct lfds611_stack_state *ss, void **user_data ) { LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) struct lfds611_stack_element *se[LFDS611_STACK_PAC_SIZE]; assert( ss != NULL ); assert( user_data != NULL ); LFDS611_BARRIER_LOAD; se[LFDS611_STACK_COUNTER] = ss->top[LFDS611_STACK_COUNTER]; se[LFDS611_STACK_POINTER] = ss->top[LFDS611_STACK_POINTER]; do { if( se[LFDS611_STACK_POINTER] == NULL ) return( 0 ); } while( 0 == lfds611_abstraction_dcas((volatile lfds611_atom_t *) ss->top, (lfds611_atom_t *) se[LFDS611_STACK_POINTER]->next, (lfds611_atom_t *) se) ); *user_data = se[LFDS611_STACK_POINTER]->user_data; lfds611_freelist_push( ss->fs, se[LFDS611_STACK_POINTER]->fe ); return( 1 ); }