ROFL-pipeline  v0.6.0dev
threading.h
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
12 #ifndef __THREADING_PP_H__
13 #define __THREADING_PP_H__
14 
15 #include <assert.h>
16 #include <unistd.h>
17 #include <stdbool.h>
18 #include "rofl.h"
19 #include "platform/likely.h"
20 
21 #if !defined(__GNUC__) && !defined(__INTEL_COMPILER)
22  #error Unknown compiler; could not guess which compare-and-swap instructions to use
23 #else
24  #define CAS(ptr, oldval, newval) __sync_bool_compare_and_swap(ptr, oldval, newval)
25  #define tid_memory_barrier __sync_synchronize
26 #endif
27 
28 //Basic type
29 typedef uint64_t tid_presence_t;
30 
31 static inline void tid_init_presence_mask(tid_presence_t* presence_mask){
32  *presence_mask = 0x0ULL;
33 }
34 
38 static inline void tid_mark_as_present(unsigned int tid, volatile tid_presence_t* presence_mask){
39  tid_presence_t old_val, new_val;
40 
41  do{
42 
43 TID_MARK_AS_PRESENT_RETRY:
44  old_val = *presence_mask;
45 
46  //Check for other threads within
47  if( unlikely(tid == ROFL_PIPELINE_LOCKED_TID ) && unlikely( ( old_val & ( 1<<tid ) ) > 0)){
48  //There some other thread in ROFL_PIPELINE_LOCKED_TID
49  usleep(0);
50  goto TID_MARK_AS_PRESENT_RETRY;
51  }
52 
53  //Set our
54  new_val = old_val | ( 1<<tid );
55 
56  }while( CAS(presence_mask, old_val, new_val) == false);
57 
58  //Double check
59  assert( ( *presence_mask & (1<<tid) ) > 0);
60 }
61 
65 static inline void tid_mark_as_not_present(unsigned int tid, volatile tid_presence_t* presence_mask){
66  tid_presence_t old_val, new_val;
67 
68  do{
69  old_val = *presence_mask;
70 
71  //Double check
72  assert( ( old_val & (1<<tid) ) > 0);
73 
74  //Set our
75  new_val = old_val & ~(1 << tid);
76 
77  }while( CAS(presence_mask, old_val, new_val) == false);
78 }
79 
83 static inline void tid_wait_all_not_present(volatile tid_presence_t* presence_mask){
84  int i;
85  uint64_t tid;
86  tid_presence_t present;
87  tid_presence_t tmp;
88 
89  //Memory barrier first
90  tid_memory_barrier();
91 
92  //Recover current present
93  present = *presence_mask;
94 
95  for(i=0;i<ROFL_PIPELINE_MAX_TIDS;i++){
96  tid = 1 << i;
97 
98  if( unlikely( ( present & tid) > 0 ) ){
99  //Wait until the core is out of the pipeline
100  do{
101  tmp = *presence_mask;
102  if( likely( ( tmp&tid ) == 0) )
103  break;
104  usleep(0);
105  }while(1);
106  }
107  }
108 }
109 
110 #endif //THREADING_PP