-
Notifications
You must be signed in to change notification settings - Fork 52
/
Copy pathabti_unit.h
229 lines (217 loc) · 9 KB
/
abti_unit.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* See COPYRIGHT in top-level directory.
*/
#ifndef ABTI_UNIT_H_INCLUDED
#define ABTI_UNIT_H_INCLUDED
/* A hash table is heavy. It should be avoided as much as possible. */
#define ABTI_UNIT_BUILTIN_POOL_BIT ((uintptr_t)0x1)
static inline ABT_bool ABTI_unit_is_builtin(ABT_unit unit)
{
if (((uintptr_t)unit) & ABTI_UNIT_BUILTIN_POOL_BIT) {
/* This must happen only when unit is associated with a built-in pool.
* See ABT_pool_def's u_create_from_thread() for details. */
return ABT_TRUE;
} else {
return ABT_FALSE;
}
}
static inline ABT_unit ABTI_unit_get_builtin_unit(ABTI_thread *p_thread)
{
ABTI_ASSERT(!(((uintptr_t)p_thread) & ABTI_UNIT_BUILTIN_POOL_BIT));
return (ABT_unit)(((uintptr_t)p_thread) | ABTI_UNIT_BUILTIN_POOL_BIT);
}
static inline void ABTI_unit_init_builtin(ABTI_thread *p_thread)
{
p_thread->p_prev = NULL;
p_thread->p_next = NULL;
ABTD_atomic_relaxed_store_int(&p_thread->is_in_pool, 0);
p_thread->unit = ABTI_unit_get_builtin_unit(p_thread);
}
static inline ABTI_thread *ABTI_unit_get_thread_from_builtin_unit(ABT_unit unit)
{
ABTI_ASSERT(ABTI_unit_is_builtin(unit));
return (ABTI_thread *)(((uintptr_t)unit) & (~ABTI_UNIT_BUILTIN_POOL_BIT));
}
static inline ABTI_thread *ABTI_unit_get_thread(ABTI_global *p_global,
ABT_unit unit)
{
if (ABTU_likely(ABTI_unit_is_builtin(unit))) {
/* This unit is associated with a built-in pool. */
return ABTI_unit_get_thread_from_builtin_unit(unit);
} else {
return ABTI_unit_get_thread_from_user_defined_unit(p_global, unit);
}
}
ABTU_ret_err static inline int
ABTI_unit_set_associated_pool(ABTI_global *p_global, ABT_unit unit,
ABTI_pool *p_pool, ABTI_thread **pp_thread)
{
if (ABTU_likely(ABTI_unit_is_builtin(unit))) {
ABTI_thread *p_thread = ABTI_unit_get_thread_from_builtin_unit(unit);
if (ABTU_likely(p_pool->is_builtin)) {
/* Do nothing since built-in pools share the implementation of
* ABT_unit. */
p_thread->p_pool = p_pool;
*pp_thread = p_thread;
return ABT_SUCCESS;
} else {
/* The new pool is a user-defined pool. */
ABT_pool pool = ABTI_pool_get_handle(p_pool);
ABT_unit new_unit =
p_pool->required_def.p_create_unit(pool, ABTI_thread_get_handle(
p_thread));
if (new_unit == ABT_UNIT_NULL)
return ABT_ERR_OTHER;
int ret = ABTI_unit_map_thread(p_global, new_unit, p_thread);
if (ret != ABT_SUCCESS) {
p_pool->required_def.p_free_unit(pool, new_unit);
return ret;
}
p_thread->unit = new_unit;
p_thread->p_pool = p_pool;
*pp_thread = p_thread;
return ABT_SUCCESS;
}
} else {
/* Currently, unit is associated with a user-defined pool. */
ABTI_thread *p_thread =
ABTI_unit_get_thread_from_user_defined_unit(p_global, unit);
if (p_pool->is_builtin) {
/* The old unit is associated with a custom pool. Remove the
* existing mapping. */
ABTI_unit_unmap_thread(p_global, unit);
ABT_pool old_pool = ABTI_pool_get_handle(p_thread->p_pool);
p_thread->p_pool->required_def.p_free_unit(old_pool, unit);
ABTI_unit_init_builtin(p_thread);
p_thread->p_pool = p_pool;
*pp_thread = p_thread;
return ABT_SUCCESS;
} else if (p_thread->p_pool == p_pool) {
/* Both are associated with the same custom pool. */
*pp_thread = p_thread;
return ABT_SUCCESS;
} else {
/* Both are associated with different custom pools. */
ABT_pool pool = ABTI_pool_get_handle(p_pool);
ABT_unit new_unit =
p_pool->required_def.p_create_unit(pool, ABTI_thread_get_handle(
p_thread));
if (new_unit == ABT_UNIT_NULL)
return ABT_ERR_OTHER;
int ret = ABTI_unit_map_thread(p_global, new_unit, p_thread);
if (ret != ABT_SUCCESS) {
p_pool->required_def.p_free_unit(pool, new_unit);
return ret;
}
ABTI_unit_unmap_thread(p_global, unit);
ABT_pool old_pool = ABTI_pool_get_handle(p_thread->p_pool);
p_thread->p_pool->required_def.p_free_unit(old_pool, unit);
p_thread->unit = new_unit;
p_thread->p_pool = p_pool;
*pp_thread = p_thread;
return ABT_SUCCESS;
}
}
}
/* The following functions have ABTI_thread prefix, but they mainly manage
* thread-unit mapping, so they are placed in this header file so far. */
ABTU_ret_err static inline int ABTI_thread_init_pool(ABTI_global *p_global,
ABTI_thread *p_thread,
ABTI_pool *p_pool)
{
if (ABTU_likely(p_pool->is_builtin)) {
ABTI_unit_init_builtin(p_thread);
p_thread->p_pool = p_pool;
return ABT_SUCCESS;
} else {
ABT_pool pool = ABTI_pool_get_handle(p_pool);
ABT_unit new_unit =
p_pool->required_def.p_create_unit(pool, ABTI_thread_get_handle(
p_thread));
if (new_unit == ABT_UNIT_NULL)
return ABT_ERR_OTHER;
int ret = ABTI_unit_map_thread(p_global, new_unit, p_thread);
if (ret != ABT_SUCCESS) {
p_pool->required_def.p_free_unit(pool, new_unit);
return ret;
}
p_thread->unit = new_unit;
p_thread->p_pool = p_pool;
return ABT_SUCCESS;
}
}
ABTU_ret_err static inline int
ABTI_thread_set_associated_pool(ABTI_global *p_global, ABTI_thread *p_thread,
ABTI_pool *p_pool)
{
ABT_unit unit = p_thread->unit;
if (ABTU_likely(ABTI_unit_is_builtin(unit) && p_pool->is_builtin)) {
/* Do nothing since built-in pools share the implementation of
* ABT_unit. */
p_thread->p_pool = p_pool;
return ABT_SUCCESS;
} else if (ABTI_unit_is_builtin(unit)) {
/* The new unit is associated with a custom pool. Add a new mapping. */
ABT_pool pool = ABTI_pool_get_handle(p_pool);
ABT_unit new_unit =
p_pool->required_def.p_create_unit(pool, ABTI_thread_get_handle(
p_thread));
if (new_unit == ABT_UNIT_NULL)
return ABT_ERR_OTHER;
int ret = ABTI_unit_map_thread(p_global, new_unit, p_thread);
if (ret != ABT_SUCCESS) {
p_pool->required_def.p_free_unit(pool, new_unit);
return ret;
}
p_thread->unit = new_unit;
p_thread->p_pool = p_pool;
return ABT_SUCCESS;
} else if (p_pool->is_builtin) {
/* The old unit is associated with a custom pool. Remove the existing
* mapping. */
ABTI_unit_unmap_thread(p_global, unit);
ABT_pool old_pool = ABTI_pool_get_handle(p_thread->p_pool);
p_thread->p_pool->required_def.p_free_unit(old_pool, unit);
ABTI_unit_init_builtin(p_thread);
p_thread->p_pool = p_pool;
return ABT_SUCCESS;
} else if (p_thread->p_pool == p_pool) {
/* Both are associated with the same custom pool. */
return ABT_SUCCESS;
} else {
/* Both are associated with different custom pools. */
ABT_pool pool = ABTI_pool_get_handle(p_pool);
ABT_unit new_unit =
p_pool->required_def.p_create_unit(pool, ABTI_thread_get_handle(
p_thread));
if (new_unit == ABT_UNIT_NULL)
return ABT_ERR_OTHER;
int ret = ABTI_unit_map_thread(p_global, new_unit, p_thread);
if (ret != ABT_SUCCESS) {
p_pool->required_def.p_free_unit(pool, new_unit);
return ret;
}
ABTI_unit_unmap_thread(p_global, unit);
ABT_pool old_pool = ABTI_pool_get_handle(p_thread->p_pool);
p_thread->p_pool->required_def.p_free_unit(old_pool, unit);
p_thread->unit = new_unit;
p_thread->p_pool = p_pool;
return ABT_SUCCESS;
}
}
static inline void ABTI_thread_unset_associated_pool(ABTI_global *p_global,
ABTI_thread *p_thread)
{
ABT_unit unit = p_thread->unit;
if (ABTU_unlikely(!ABTI_unit_is_builtin(unit))) {
ABTI_unit_unmap_thread(p_global, unit);
ABT_pool old_pool = ABTI_pool_get_handle(p_thread->p_pool);
p_thread->p_pool->required_def.p_free_unit(old_pool, unit);
}
#if ABTI_IS_ERROR_CHECK_ENABLED
p_thread->unit = ABT_UNIT_NULL;
p_thread->p_pool = NULL;
#endif
}
#endif /* ABTI_UNIT_H_INCLUDED */