ARGOBOTS  1.1
unit.c
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 #include "abti.h"
7 
8 static void unit_init_hash_table(ABTI_global *p_global);
9 static void unit_finalize_hash_table(ABTI_global *p_global);
10 ABTU_ret_err static inline int
11 unit_map_thread(ABTI_global *p_global, ABT_unit unit, ABTI_thread *p_thread);
12 static inline void unit_unmap_thread(ABTI_global *p_global, ABT_unit unit);
13 static inline ABTI_thread *
15 
49 {
50  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
53  return ABT_SUCCESS;
54 }
55 
79 {
80  ABTI_global *p_global = ABTI_global_get_global();
82  ABTI_thread *p_thread = ABTI_unit_get_thread(p_global, unit);
83  *thread = ABTI_thread_get_handle(p_thread);
84  return ABT_SUCCESS;
85 }
86 
87 /*****************************************************************************/
88 /* Private APIs */
89 /*****************************************************************************/
90 
92 {
93  unit_init_hash_table(p_global);
94 }
95 
97 {
98  unit_finalize_hash_table(p_global);
99 }
100 
102  ABTI_thread *p_thread)
103 {
104  return unit_map_thread(p_global, unit, p_thread);
105 }
106 
108 {
109  unit_unmap_thread(p_global, unit);
110 }
111 
113  ABT_unit unit)
114 {
115  return unit_get_thread_from_user_defined_unit(p_global, unit);
116 }
117 
118 /*****************************************************************************/
119 /* Internal static functions */
120 /*****************************************************************************/
121 
122 static inline size_t unit_get_hash_index(ABT_unit unit)
123 {
124  size_t val = (uintptr_t)unit;
125  /* Let's ignore the first 3 bits and use the next 29 bits. */
126  size_t base_val = val >> 3;
127 #if ABTI_UNIT_HASH_TABLE_SIZE_EXP <= 14
128  base_val += val >> (ABTI_UNIT_HASH_TABLE_SIZE_EXP + 3);
129 #endif
130 #if ABTI_UNIT_HASH_TABLE_SIZE_EXP <= 9
131  base_val += val >> (ABTI_UNIT_HASH_TABLE_SIZE_EXP * 2 + 3);
132 #endif
133  return base_val & (ABTI_UNIT_HASH_TABLE_SIZE - 1);
134 }
135 
136 typedef struct atomic_unit {
138 } atomic_unit;
139 
140 static inline ABT_unit atomic_relaxed_load_unit(const atomic_unit *p_ptr)
141 {
142  return (ABT_unit)ABTD_atomic_relaxed_load_ptr(&p_ptr->val);
143 }
144 
145 static inline void atomic_relaxed_store_unit(atomic_unit *p_ptr, ABT_unit val)
146 {
147  ABTD_atomic_relaxed_store_ptr(&p_ptr->val, (void *)val);
148 }
149 
150 typedef struct unit_to_thread {
151  /* This is updated in a relaxed manner. Relaxed access is fine since the
152  * semantics guarantees that all operations that "hit" are performed after
153  * map() from the memory order viewpoint; we just need to guarantee that the
154  * other parallel entities that call unmap() and get() (consequently, they
155  * do not "hit") do not see a corrupted value that is neither a new ABT_unit
156  * handle nor ABT_UNIT_NULL. */
161 
162 static inline unit_to_thread *
164 {
166 }
167 
168 static inline unit_to_thread *
170 {
172 }
173 
174 static inline void
176  unit_to_thread *val)
177 {
178  ABTD_atomic_release_store_ptr(&p_ptr->val, (void *)val);
179 }
180 
181 static inline void
183  unit_to_thread *val)
184 {
185  ABTD_atomic_relaxed_store_ptr(&p_ptr->val, (void *)val);
186 }
187 
188 static void unit_init_hash_table(ABTI_global *p_global)
189 {
190  int i;
191  for (i = 0; i < (int)ABTI_UNIT_HASH_TABLE_SIZE; i++) {
193  .list,
194  NULL);
196  }
197 }
198 
199 static void unit_finalize_hash_table(ABTI_global *p_global)
200 {
201  int i;
202  for (i = 0; i < (int)ABTI_UNIT_HASH_TABLE_SIZE; i++) {
204  &p_global->unit_to_thread_entires[i].lock));
206  &p_global->unit_to_thread_entires[i].list);
207  while (p_cur) {
209  ABT_UNIT_NULL);
210  unit_to_thread *p_next = p_cur->p_next;
211  ABTU_free(p_cur);
212  p_cur = p_next;
213  }
214  }
215 }
216 
217 ABTU_ret_err static inline int
219 {
221  size_t hash_index = unit_get_hash_index(unit);
222  ABTI_unit_to_thread_entry *p_entry =
223  &p_global->unit_to_thread_entires[hash_index];
224 
225  ABTD_spinlock_acquire(&p_entry->lock);
227  while (p_cur) {
228  if (atomic_relaxed_load_unit(&p_cur->unit) == ABT_UNIT_NULL) {
229  /* Empty element has been found. Let's use this. */
231  /* p_cur is associated with this unit. */
232  p_cur->p_thread = p_thread;
233  ABTD_spinlock_release(&p_entry->lock);
234  return ABT_SUCCESS;
235  }
236  p_cur = p_cur->p_next;
237  }
238  /* It seems that all the elements are in use. Let's allocate a new one. */
239  unit_to_thread *p_new;
240  p_cur = atomic_relaxed_load_unit_to_thread(&p_entry->list);
241  /* Let's dynamically allocate memory. */
242  int ret = ABTU_malloc(sizeof(unit_to_thread), (void **)&p_new);
243  if (ret != ABT_SUCCESS) {
244  ABTD_spinlock_release(&p_entry->lock);
245  return ret;
246  }
247  /* Initialize the new unit. */
248  atomic_relaxed_store_unit(&p_new->unit, unit);
249  p_new->p_thread = p_thread;
250  p_new->p_next = p_cur;
251  atomic_release_store_unit_to_thread(&p_entry->list, p_new);
252  ABTD_spinlock_release(&p_entry->lock);
253  return ABT_SUCCESS;
254 }
255 
256 static inline void unit_unmap_thread(ABTI_global *p_global, ABT_unit unit)
257 {
259  size_t hash_index = unit_get_hash_index(unit);
260  ABTI_unit_to_thread_entry *p_entry =
261  &p_global->unit_to_thread_entires[hash_index];
262 
263  ABTD_spinlock_acquire(&p_entry->lock);
265  /* Update the corresponding unit to "NULL". */
266  while (1) {
267  if (atomic_relaxed_load_unit(&p_cur->unit) == unit) {
269  break;
270  }
271  p_cur = p_cur->p_next;
272  ABTI_ASSERT(p_cur); /* unmap() must succeed. */
273  }
274  ABTD_spinlock_release(&p_entry->lock);
275 }
276 
277 static inline ABTI_thread *
279 {
281  /* Find an element. */
282  size_t hash_index = unit_get_hash_index(unit);
283  ABTI_unit_to_thread_entry *p_entry =
284  &p_global->unit_to_thread_entires[hash_index];
285  /* The first element must be accessed in a release-acquire manner. The new
286  * element is release-stored to the head, so acquire-load can always get a
287  * valid linked-list chain. */
289  while (1) {
290  ABTI_ASSERT(p_cur); /* get() must succeed. */
291  if (atomic_relaxed_load_unit(&p_cur->unit) == unit) {
292  return p_cur->p_thread;
293  }
294  p_cur = p_cur->p_next;
295  }
296 }
ABTI_unit_is_builtin
static ABT_bool ABTI_unit_is_builtin(ABT_unit unit)
Definition: abti_unit.h:12
ABTI_unit_to_thread_entry::lock
ABTD_spinlock lock
Definition: abti.h:193
ABT_thread
struct ABT_thread_opaque * ABT_thread
Work unit handle type.
Definition: abt.h:890
unit_map_thread
static ABTU_ret_err int unit_map_thread(ABTI_global *p_global, ABT_unit unit, ABTI_thread *p_thread)
Definition: unit.c:218
ABTI_global_get_global
static ABTI_global * ABTI_global_get_global(void)
Definition: abti_global.h:9
ABT_unit_set_associated_pool
int ABT_unit_set_associated_pool(ABT_unit unit, ABT_pool pool)
No operation.
Definition: unit.c:48
ABTI_atomic_unit_to_thread
Definition: abti.h:187
atomic_acquire_load_unit_to_thread
static unit_to_thread * atomic_acquire_load_unit_to_thread(const ABTI_atomic_unit_to_thread *p_ptr)
Definition: unit.c:163
ABTI_thread::p_next
ABTI_thread * p_next
Definition: abti.h:373
unit_get_hash_index
static size_t unit_get_hash_index(ABT_unit unit)
Definition: unit.c:122
ABTI_unit_init_hash_table
void ABTI_unit_init_hash_table(ABTI_global *p_global)
Definition: unit.c:91
ABTI_thread_get_handle
static ABT_thread ABTI_thread_get_handle(ABTI_thread *p_thread)
Definition: abti_thread.h:24
ABTI_thread
Definition: abti.h:371
ABT_pool
struct ABT_pool_opaque * ABT_pool
Pool handle type.
Definition: abt.h:841
ABTI_pool
Definition: abti.h:327
abti.h
ABTI_unit_finalize_hash_table
void ABTI_unit_finalize_hash_table(ABTI_global *p_global)
Definition: unit.c:96
ABTI_global::unit_to_thread_entires
ABTI_unit_to_thread_entry unit_to_thread_entires[ABTI_UNIT_HASH_TABLE_SIZE]
Definition: abti.h:249
atomic_relaxed_store_unit_to_thread
static void atomic_relaxed_store_unit_to_thread(ABTI_atomic_unit_to_thread *p_ptr, unit_to_thread *val)
Definition: unit.c:182
unit_to_thread::p_thread
ABTI_thread * p_thread
Definition: unit.c:158
ABTD_spinlock_acquire
static void ABTD_spinlock_acquire(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:28
unit_to_thread::unit
atomic_unit unit
Definition: unit.c:157
ABTI_UNIT_HASH_TABLE_SIZE_EXP
#define ABTI_UNIT_HASH_TABLE_SIZE_EXP
Definition: abti.h:58
ABTI_unit_map_thread
ABTU_ret_err int ABTI_unit_map_thread(ABTI_global *p_global, ABT_unit unit, ABTI_thread *p_thread)
Definition: unit.c:101
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:262
ABTD_atomic_ptr
Definition: abtd_atomic.h:39
ABT_ERR_INV_UNIT
#define ABT_ERR_INV_UNIT
Error code: invalid work unit for scheduling.
Definition: abt.h:171
atomic_relaxed_load_unit
static ABT_unit atomic_relaxed_load_unit(const atomic_unit *p_ptr)
Definition: unit.c:140
atomic_relaxed_store_unit
static void atomic_relaxed_store_unit(atomic_unit *p_ptr, ABT_unit val)
Definition: unit.c:145
ABT_unit
struct ABT_unit_opaque * ABT_unit
Work unit handle type for scheduling.
Definition: abt.h:869
unit_unmap_thread
static void unit_unmap_thread(ABTI_global *p_global, ABT_unit unit)
Definition: unit.c:256
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABTI_atomic_unit_to_thread::val
ABTD_atomic_ptr val
Definition: abti.h:188
ABTD_atomic_release_store_ptr
static void ABTD_atomic_release_store_ptr(ABTD_atomic_ptr *ptr, void *val)
Definition: abtd_atomic.h:1136
unit_to_thread
struct unit_to_thread unit_to_thread
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABTU_ret_err
#define ABTU_ret_err
Definition: abtu.h:146
atomic_relaxed_load_unit_to_thread
static unit_to_thread * atomic_relaxed_load_unit_to_thread(const ABTI_atomic_unit_to_thread *p_ptr)
Definition: unit.c:169
unit_get_thread_from_user_defined_unit
static ABTI_thread * unit_get_thread_from_user_defined_unit(ABTI_global *p_global, ABT_unit unit)
Definition: unit.c:278
atomic_unit
struct atomic_unit atomic_unit
ABTI_pool_get_ptr
static ABTI_pool * ABTI_pool_get_ptr(ABT_pool pool)
Definition: abti_pool.h:11
ABTD_spinlock_clear
static void ABTD_spinlock_clear(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:23
ABTI_unit_to_thread_entry::list
ABTI_atomic_unit_to_thread list
Definition: abti.h:192
ABTI_CHECK_NULL_POOL_PTR
#define ABTI_CHECK_NULL_POOL_PTR(p)
Definition: abti_error.h:168
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:217
unit_to_thread
Definition: unit.c:150
ABTD_spinlock_release
static void ABTD_spinlock_release(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:42
ABTI_unit_get_thread
static ABTI_thread * ABTI_unit_get_thread(ABTI_global *p_global, ABT_unit unit)
Definition: abti_unit.h:43
ABTI_UNIT_HASH_TABLE_SIZE
#define ABTI_UNIT_HASH_TABLE_SIZE
Definition: abti.h:59
ABTI_unit_unmap_thread
void ABTI_unit_unmap_thread(ABTI_global *p_global, ABT_unit unit)
Definition: unit.c:107
atomic_release_store_unit_to_thread
static void atomic_release_store_unit_to_thread(ABTI_atomic_unit_to_thread *p_ptr, unit_to_thread *val)
Definition: unit.c:175
ABTI_unit_get_thread_from_user_defined_unit
ABTI_thread * ABTI_unit_get_thread_from_user_defined_unit(ABTI_global *p_global, ABT_unit unit)
Definition: unit.c:112
ABTD_atomic_acquire_load_ptr
static void * ABTD_atomic_acquire_load_ptr(const ABTD_atomic_ptr *ptr)
Definition: abtd_atomic.h:979
atomic_unit::val
ABTD_atomic_ptr val
Definition: unit.c:137
ABTI_CHECK_TRUE
#define ABTI_CHECK_TRUE(cond, abt_errno)
Definition: abti_error.h:130
ABTD_spinlock_is_locked
static ABT_bool ABTD_spinlock_is_locked(const ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:18
ABTI_global
Definition: abti.h:196
unit_init_hash_table
static void unit_init_hash_table(ABTI_global *p_global)
Definition: unit.c:188
ABTD_atomic_relaxed_store_ptr
static void ABTD_atomic_relaxed_store_ptr(ABTD_atomic_ptr *ptr, void *val)
Definition: abtd_atomic.h:1055
ABT_UNIT_NULL
#define ABT_UNIT_NULL
Definition: abt.h:1061
unit_finalize_hash_table
static void unit_finalize_hash_table(ABTI_global *p_global)
Definition: unit.c:199
unit_to_thread::p_next
struct unit_to_thread * p_next
Definition: unit.c:159
ABTI_unit_to_thread_entry
Definition: abti.h:191
ABT_unit_get_thread
int ABT_unit_get_thread(ABT_unit unit, ABT_thread *thread)
Get a thread handle of the target work unit.
Definition: unit.c:78
atomic_unit
Definition: unit.c:136
ABTD_atomic_relaxed_load_ptr
static void * ABTD_atomic_relaxed_load_ptr(const ABTD_atomic_ptr *ptr)
Definition: abtd_atomic.h:846