![]() |
Helixis 1.0
Task Programming API
|
00001 #include "freelist_internal.h" 00002 #if defined(HLX_BUILD_WITH_PARALLEL_THREADING) 00003 00004 extern hlx_api gl_api; 00005 00006 /****************************************************************************/ 00007 struct freelist_element *freelist_pop( struct freelist_state *fs, struct freelist_element **fe ) 00008 { 00009 ALIGN(ALIGN_DOUBLE_POINTER) struct freelist_element 00010 *fe_local[FREELIST_PAC_SIZE]; 00011 00012 fe_local[FREELIST_COUNTER] = fs->top[FREELIST_COUNTER]; 00013 fe_local[FREELIST_POINTER] = fs->top[FREELIST_POINTER]; 00014 00015 /* TRD : note that abstraction_dcas loads the original value of the destination (fs->top) into the compare (fe_local) 00016 (this happens of course after the CAS itself has occurred inside abstraction_dcas) 00017 */ 00018 00019 do 00020 { 00021 if( fe_local[FREELIST_POINTER] == 0 ) 00022 { 00023 *fe = 0; 00024 return( *fe ); 00025 } 00026 } 00027 while( 0 == gl_api.atomic_dcas_entry((volatile atom_t *) fs->top, (atom_t *) fe_local[FREELIST_POINTER]->next, (atom_t *) fe_local) ); 00028 00029 *fe = (struct freelist_element *) fe_local[FREELIST_POINTER]; 00030 00031 return( *fe ); 00032 } 00033 00034 00035 00036 00037 00038 /****************************************************************************/ 00039 struct freelist_element *freelist_guaranteed_pop( struct freelist_state *fs, struct freelist_element **fe ) 00040 { 00041 00042 freelist_internal_new_element( fs, fe ); 00043 00044 return( *fe ); 00045 } 00046 00047 00048 00049 00050 00051 /****************************************************************************/ 00052 void freelist_push( struct freelist_state *fs, struct freelist_element *fe ) 00053 { 00054 ALIGN(ALIGN_DOUBLE_POINTER) struct freelist_element 00055 *fe_local[FREELIST_PAC_SIZE], 00056 *original_fe_next[FREELIST_PAC_SIZE]; 00057 00058 fe_local[FREELIST_POINTER] = fe; 00059 fe_local[FREELIST_COUNTER] = (struct freelist_element *) gl_api.atomic_incr_entry( (atom_t *) &fs->aba_counter ); 00060 00061 original_fe_next[FREELIST_POINTER] = fs->top[FREELIST_POINTER]; 00062 original_fe_next[FREELIST_COUNTER] = fs->top[FREELIST_COUNTER]; 00063 00064 /* TRD : note that abstraction_dcas loads the original value of the destination (fs->top) into the compare (original_fe_next) 00065 (this happens of course after the CAS itself has occurred inside abstraction_dcas) 00066 this then causes us in our loop, should we repeat it, to update fe_local->next to a more 00067 up-to-date version of the head of the freelist 00068 */ 00069 00070 do 00071 { 00072 fe_local[FREELIST_POINTER]->next[FREELIST_POINTER] = original_fe_next[FREELIST_POINTER]; 00073 fe_local[FREELIST_POINTER]->next[FREELIST_COUNTER] = original_fe_next[FREELIST_COUNTER]; 00074 } 00075 while( 0 == gl_api.atomic_dcas_entry((volatile atom_t *) fs->top, (atom_t *) fe_local, (atom_t *) original_fe_next) ); 00076 00077 return; 00078 } 00079 00080 #endif /* !HLX_BUILD_WITH_PARALLEL_THREADING */