ARGOBOTS  1.1
thread.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 ABTU_ret_err static inline int
9 ythread_create(ABTI_global *p_global, ABTI_local *p_local, ABTI_pool *p_pool,
10  void (*thread_func)(void *), void *arg, ABTI_thread_attr *p_attr,
11  ABTI_thread_type thread_type, ABTI_sched *p_sched,
12  ABT_bool push_pool, ABTI_ythread **pp_newthread);
13 static inline void thread_join(ABTI_local **pp_local, ABTI_thread *p_thread);
14 static inline void thread_free(ABTI_global *p_global, ABTI_local *p_local,
15  ABTI_thread *p_thread, ABT_bool free_unit);
16 static void thread_root_func(void *arg);
17 static void thread_main_sched_func(void *arg);
18 #ifndef ABT_CONFIG_DISABLE_MIGRATION
20  ABTI_local *p_local,
21  ABTI_thread *p_thread,
22  ABTI_pool *p_pool);
23 #endif
24 static inline ABT_unit_id thread_get_new_id(void);
25 
26 static void thread_key_destructor_stackable_sched(void *p_value);
30 static void thread_key_destructor_migration(void *p_value);
34 
88 int ABT_thread_create(ABT_pool pool, void (*thread_func)(void *), void *arg,
89  ABT_thread_attr attr, ABT_thread *newthread)
90 {
91 #ifndef ABT_CONFIG_ENABLE_VER_20_API
92  /* Argobots 1.x sets newthread to NULL on error. */
93  if (newthread)
94  *newthread = ABT_THREAD_NULL;
95 #endif
96  ABTI_global *p_global;
97  ABTI_SETUP_GLOBAL(&p_global);
98  ABTI_local *p_local = ABTI_local_get_local();
99  ABTI_ythread *p_newthread;
100 
101  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
102  ABTI_CHECK_NULL_POOL_PTR(p_pool);
103 
104  ABTI_thread_type unit_type =
105  (newthread != NULL)
108  int abt_errno = ythread_create(p_global, p_local, p_pool, thread_func, arg,
109  ABTI_thread_attr_get_ptr(attr), unit_type,
110  NULL, ABT_TRUE, &p_newthread);
111  ABTI_CHECK_ERROR(abt_errno);
112 
113  /* Return value */
114  if (newthread)
115  *newthread = ABTI_ythread_get_handle(p_newthread);
116  return ABT_SUCCESS;
117 }
118 
169  void (*thread_func)(void *), void *arg,
170  ABT_thread_attr attr, ABT_thread *newthread)
171 {
172 #ifndef ABT_CONFIG_ENABLE_VER_20_API
173  /* Argobots 1.x sets newthread to NULL on error. */
174  if (newthread)
175  *newthread = ABT_THREAD_NULL;
176 #endif
177  ABTI_global *p_global;
178  ABTI_SETUP_GLOBAL(&p_global);
179  ABTI_local *p_local = ABTI_local_get_local();
180  ABTI_ythread *p_newthread;
181 
182  ABTI_xstream *p_xstream = ABTI_xstream_get_ptr(xstream);
183  ABTI_CHECK_NULL_XSTREAM_PTR(p_xstream);
184 
185  /* TODO: need to consider the access type of target pool */
186  ABTI_pool *p_pool = ABTI_xstream_get_main_pool(p_xstream);
187  ABTI_thread_type unit_type =
188  (newthread != NULL)
191  int abt_errno = ythread_create(p_global, p_local, p_pool, thread_func, arg,
192  ABTI_thread_attr_get_ptr(attr), unit_type,
193  NULL, ABT_TRUE, &p_newthread);
194  ABTI_CHECK_ERROR(abt_errno);
195 
196  /* Return value */
197  if (newthread)
198  *newthread = ABTI_ythread_get_handle(p_newthread);
199 
200  return ABT_SUCCESS;
201 }
202 
251 int ABT_thread_create_many(int num_threads, ABT_pool *pool_list,
252  void (**thread_func_list)(void *), void **arg_list,
253  ABT_thread_attr attr, ABT_thread *newthread_list)
254 {
255  ABTI_global *p_global;
256  ABTI_SETUP_GLOBAL(&p_global);
257  ABTI_local *p_local = ABTI_local_get_local();
258  int i;
259 
260  if (attr != ABT_THREAD_ATTR_NULL) {
261  /* This implies that the stack is given by a user. Since threads
262  * cannot use the same stack region, this is illegal. */
263  ABTI_CHECK_TRUE(!(ABTI_thread_attr_get_ptr(attr)->thread_type &
267  }
268 
269  if (newthread_list == NULL) {
270  for (i = 0; i < num_threads; i++) {
271  ABTI_ythread *p_newthread;
272  ABT_pool pool = pool_list[i];
273  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
274  ABTI_CHECK_NULL_POOL_PTR(p_pool);
275 
276  void (*thread_f)(void *) = thread_func_list[i];
277  void *arg = arg_list ? arg_list[i] : NULL;
278  int abt_errno = ythread_create(p_global, p_local, p_pool, thread_f,
279  arg, ABTI_thread_attr_get_ptr(attr),
281  ABT_TRUE, &p_newthread);
282  ABTI_CHECK_ERROR(abt_errno);
283  }
284  } else {
285  for (i = 0; i < num_threads; i++) {
286  ABTI_ythread *p_newthread;
287  ABT_pool pool = pool_list[i];
288  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
289  ABTI_CHECK_NULL_POOL_PTR(p_pool);
290 
291  void (*thread_f)(void *) = thread_func_list[i];
292  void *arg = arg_list ? arg_list[i] : NULL;
293  int abt_errno = ythread_create(p_global, p_local, p_pool, thread_f,
294  arg, ABTI_thread_attr_get_ptr(attr),
297  NULL, ABT_TRUE, &p_newthread);
298  newthread_list[i] = ABTI_ythread_get_handle(p_newthread);
299  /* TODO: Release threads that have been already created. */
300  ABTI_CHECK_ERROR(abt_errno);
301  }
302  }
303 
304  return ABT_SUCCESS;
305 }
306 
356 int ABT_thread_revive(ABT_pool pool, void (*thread_func)(void *), void *arg,
357  ABT_thread *thread)
358 {
359  ABTI_global *p_global = ABTI_global_get_global();
360  ABTI_local *p_local = ABTI_local_get_local();
361 
362  ABTI_thread *p_thread = ABTI_thread_get_ptr(*thread);
363  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
364 
368 
369  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
370  ABTI_CHECK_NULL_POOL_PTR(p_pool);
371 
372  int abt_errno = ABTI_thread_revive(p_global, p_local, p_pool, thread_func,
373  arg, p_thread);
374  ABTI_CHECK_ERROR(abt_errno);
375  return ABT_SUCCESS;
376 }
377 
418 int ABT_thread_free(ABT_thread *thread)
419 {
420  ABTI_global *p_global;
421  ABTI_SETUP_GLOBAL(&p_global);
422  ABTI_local *p_local = ABTI_local_get_local();
423  ABT_thread h_thread = *thread;
424 
425  ABTI_thread *p_thread = ABTI_thread_get_ptr(h_thread);
426  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
428  p_thread != ABTI_local_get_xstream(p_local)->p_thread,
430  ABTI_CHECK_TRUE(!(p_thread->type &
433 
434  /* Wait until the thread terminates */
435  thread_join(&p_local, p_thread);
436  /* Free the ABTI_thread structure */
437  ABTI_thread_free(p_global, p_local, p_thread);
438 
439  /* Return value */
440  *thread = ABT_THREAD_NULL;
441 
442  return ABT_SUCCESS;
443 }
444 
478 int ABT_thread_free_many(int num_threads, ABT_thread *thread_list)
479 {
480  ABTI_global *p_global;
481  ABTI_SETUP_GLOBAL(&p_global);
482  ABTI_local *p_local = ABTI_local_get_local();
483  int i;
484 
485  for (i = 0; i < num_threads; i++) {
486  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread_list[i]);
487  thread_list[i] = ABT_THREAD_NULL;
488  if (!p_thread)
489  continue;
490  /* TODO: check input */
491  thread_join(&p_local, p_thread);
492  ABTI_thread_free(p_global, p_local, p_thread);
493  }
494  return ABT_SUCCESS;
495 }
496 
536 int ABT_thread_join(ABT_thread thread)
537 {
539  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
540  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
542  p_thread != ABTI_local_get_xstream(p_local)->p_thread,
544  ABTI_CHECK_TRUE(!(p_thread->type &
547 
548  thread_join(&p_local, p_thread);
549  return ABT_SUCCESS;
550 }
551 
583 int ABT_thread_join_many(int num_threads, ABT_thread *thread_list)
584 {
586  int i;
587  for (i = 0; i < num_threads; i++) {
588  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread_list[i]);
589  if (!p_thread)
590  continue;
591  /* TODO: check input */
592  thread_join(&p_local, p_thread);
593  }
594  return ABT_SUCCESS;
595 }
596 
625 int ABT_thread_exit(void)
626 {
627  ABTI_xstream *p_local_xstream;
628  ABTI_ythread *p_ythread;
629 #ifndef ABT_CONFIG_ENABLE_VER_20_API
630  ABTI_SETUP_GLOBAL(NULL);
631 #endif
632  ABTI_SETUP_LOCAL_YTHREAD(&p_local_xstream, &p_ythread);
635 
636  ABTI_ythread_exit(p_local_xstream, p_ythread);
637  return ABT_SUCCESS;
638 }
639 
672 int ABT_thread_cancel(ABT_thread thread)
673 {
674 #ifdef ABT_CONFIG_DISABLE_THREAD_CANCEL
676 #else
677  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
678  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
681 
682  /* Set the cancel request */
684  return ABT_SUCCESS;
685 #endif
686 }
687 
723 int ABT_thread_self(ABT_thread *thread)
724 {
725 #ifndef ABT_CONFIG_ENABLE_VER_20_API
726  *thread = ABT_THREAD_NULL;
727  ABTI_SETUP_GLOBAL(NULL);
728  ABTI_ythread *p_self;
729  ABTI_SETUP_LOCAL_YTHREAD(NULL, &p_self);
730  *thread = ABTI_thread_get_handle(&p_self->thread);
731 #else
732  ABTI_xstream *p_local_xstream;
733  ABTI_SETUP_LOCAL_XSTREAM(&p_local_xstream);
734  *thread = ABTI_thread_get_handle(p_local_xstream->p_thread);
735 #endif
736  return ABT_SUCCESS;
737 }
738 
773 {
774 #ifndef ABT_CONFIG_ENABLE_VER_20_API
775  ABTI_SETUP_GLOBAL(NULL);
776  ABTI_ythread *p_self;
777  ABTI_SETUP_LOCAL_YTHREAD(NULL, &p_self);
778  *id = ABTI_thread_get_id(&p_self->thread);
779 #else
780  ABTI_xstream *p_local_xstream;
781  ABTI_SETUP_LOCAL_XSTREAM(&p_local_xstream);
782  *id = ABTI_thread_get_id(p_local_xstream->p_thread);
783 #endif
784  return ABT_SUCCESS;
785 }
786 
816 {
817  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
818  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
819 
820  *xstream = ABTI_xstream_get_handle(p_thread->p_last_xstream);
821  return ABT_SUCCESS;
822 }
823 
857 {
858  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
859  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
860 
862  return ABT_SUCCESS;
863 }
864 
897 {
898  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
899  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
900 
901  *pool = ABTI_pool_get_handle(p_thread->p_pool);
902  return ABT_SUCCESS;
903 }
904 
936 int ABT_thread_get_last_pool_id(ABT_thread thread, int *id)
937 {
938  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
939  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
940  *id = (int)p_thread->p_pool->id;
941  return ABT_SUCCESS;
942 }
943 
966 int ABT_thread_get_unit(ABT_thread thread, ABT_unit *unit)
967 {
968  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
969  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
970  *unit = p_thread->unit;
971  return ABT_SUCCESS;
972 }
973 
1008 {
1009  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1010  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1011  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
1012  ABTI_CHECK_NULL_POOL_PTR(p_pool);
1013  ABTI_global *p_global = ABTI_global_get_global();
1014 
1015  int abt_errno = ABTI_thread_set_associated_pool(p_global, p_thread, p_pool);
1016  ABTI_CHECK_ERROR(abt_errno);
1017  return ABT_SUCCESS;
1018 }
1019 
1065 int ABT_thread_yield_to(ABT_thread thread)
1066 {
1067  ABTI_xstream *p_local_xstream;
1068  ABTI_ythread *p_cur_ythread;
1069 #ifndef ABT_CONFIG_ENABLE_VER_20_API
1071  if (ABTI_IS_EXT_THREAD_ENABLED && p_local_xstream == NULL) {
1072  return ABT_SUCCESS;
1073  } else {
1074  p_cur_ythread =
1075  ABTI_thread_get_ythread_or_null(p_local_xstream->p_thread);
1076  if (!p_cur_ythread)
1077  return ABT_SUCCESS;
1078  }
1079 #else
1080  ABTI_SETUP_LOCAL_YTHREAD(&p_local_xstream, &p_cur_ythread);
1081 #endif
1082 
1083  ABTI_thread *p_tar_thread = ABTI_thread_get_ptr(thread);
1084  ABTI_CHECK_NULL_THREAD_PTR(p_tar_thread);
1085  ABTI_ythread *p_tar_ythread = ABTI_thread_get_ythread_or_null(p_tar_thread);
1086  ABTI_CHECK_NULL_YTHREAD_PTR(p_tar_ythread);
1087  ABTI_CHECK_TRUE(p_cur_ythread != p_tar_ythread, ABT_ERR_INV_THREAD);
1092 
1093  LOG_DEBUG("[U%" PRIu64 ":E%d] yield_to -> U%" PRIu64 "\n",
1094  ABTI_thread_get_id(&p_cur_ythread->thread),
1095  p_cur_ythread->thread.p_last_xstream->rank,
1096  ABTI_thread_get_id(&p_tar_ythread->thread));
1097 
1098  /* If the target thread is not in READY, we don't yield. Note that ULT can
1099  * be regarded as 'ready' only if its state is READY and it has been
1100  * pushed into a pool. Since we set ULT's state to READY and then push it
1101  * into a pool, we check them in the reverse order, i.e., check if the ULT
1102  * is inside a pool and the its state. */
1103  if (!(p_tar_ythread->thread.p_pool->u_is_in_pool(
1104  p_tar_ythread->thread.unit) == ABT_TRUE &&
1105  ABTD_atomic_acquire_load_int(&p_tar_ythread->thread.state) ==
1107  /* This is undefined behavior. */
1108  return ABT_SUCCESS;
1109  }
1110 
1111  /* Remove the target ULT from the pool */
1113  /* This is necessary to prevent the size of this pool from 0. */
1114  ABTI_pool_inc_num_blocked(p_tar_ythread->thread.p_pool);
1115  }
1116  int abt_errno = ABTI_pool_remove(p_tar_ythread->thread.p_pool,
1117  p_tar_ythread->thread.unit);
1119  ABTI_pool_dec_num_blocked(p_tar_ythread->thread.p_pool);
1120  ABTI_CHECK_ERROR(abt_errno);
1121  }
1122 
1123  ABTD_atomic_release_store_int(&p_cur_ythread->thread.state,
1125 
1126  /* This operation is corresponding to yield */
1127  ABTI_tool_event_ythread_yield(p_local_xstream, p_cur_ythread,
1128  p_cur_ythread->thread.p_parent,
1129  ABT_SYNC_EVENT_TYPE_USER, NULL);
1130 
1131  /* Add the current thread to the pool again. */
1132  ABTI_pool_push(p_cur_ythread->thread.p_pool, p_cur_ythread->thread.unit);
1133 
1134  /* We set the last ES */
1135  p_tar_ythread->thread.p_last_xstream = p_local_xstream;
1136 
1137  /* Switch the context */
1138  ABTD_atomic_release_store_int(&p_tar_ythread->thread.state,
1140  ABTI_ythread *p_prev =
1141  ABTI_ythread_context_switch_to_sibling(&p_local_xstream, p_cur_ythread,
1142  p_tar_ythread);
1143  ABTI_tool_event_thread_run(p_local_xstream, &p_cur_ythread->thread,
1144  &p_prev->thread, p_cur_ythread->thread.p_parent);
1145  return ABT_SUCCESS;
1146 }
1147 
1179 int ABT_thread_yield(void)
1180 {
1181  ABTI_xstream *p_local_xstream;
1182  ABTI_ythread *p_ythread;
1183 #ifndef ABT_CONFIG_ENABLE_VER_20_API
1185  if (ABTI_IS_EXT_THREAD_ENABLED && ABTU_unlikely(p_local_xstream == NULL)) {
1186  return ABT_SUCCESS;
1187  } else {
1188  p_ythread = ABTI_thread_get_ythread_or_null(p_local_xstream->p_thread);
1189  if (ABTU_unlikely(!p_ythread)) {
1190  return ABT_SUCCESS;
1191  }
1192  }
1193 #else
1194  ABTI_SETUP_LOCAL_YTHREAD(&p_local_xstream, &p_ythread);
1195 #endif
1196 
1197  ABTI_ythread_yield(&p_local_xstream, p_ythread, ABT_SYNC_EVENT_TYPE_USER,
1198  NULL);
1199  return ABT_SUCCESS;
1200 }
1201 
1231 int ABT_thread_resume(ABT_thread thread)
1232 {
1234 
1235  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1236  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1237  ABTI_ythread *p_ythread;
1238  ABTI_CHECK_YIELDABLE(p_thread, &p_ythread, ABT_ERR_INV_THREAD);
1239 
1240 #ifndef ABT_CONFIG_ENABLE_VER_20_API
1241  /* The ULT must be in BLOCKED state. */
1244  ABT_ERR_THREAD);
1245 #endif
1246 
1247  ABTI_ythread_set_ready(p_local, p_ythread);
1248  return ABT_SUCCESS;
1249 }
1250 
1303 {
1304 #ifndef ABT_CONFIG_DISABLE_MIGRATION
1305  ABTI_global *p_global;
1306  ABTI_SETUP_GLOBAL(&p_global);
1307  ABTI_local *p_local = ABTI_local_get_local();
1308 
1309  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1310  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1311  ABTI_xstream *p_xstream = ABTI_xstream_get_ptr(xstream);
1312  ABTI_CHECK_NULL_XSTREAM_PTR(p_xstream);
1317  /* Check if a thread is associated with a pool of the main scheduler. */
1318  ABTI_sched *p_sched = p_xstream->p_main_sched;
1320  size_t p;
1321  for (p = 0; p < p_sched->num_pools; p++)
1322  ABTI_CHECK_TRUE(ABTI_pool_get_ptr(p_sched->pools[p]) !=
1323  p_thread->p_pool,
1325  }
1326  /* Get the target pool. */
1327  ABTI_pool *p_pool = NULL;
1328  int abt_errno;
1329  abt_errno =
1330  ABTI_sched_get_migration_pool(p_sched, p_thread->p_pool, &p_pool);
1331  ABTI_CHECK_ERROR(abt_errno);
1332  /* Request a migration. */
1333  abt_errno = thread_migrate_to_pool(p_global, p_local, p_thread, p_pool);
1334  ABTI_CHECK_ERROR(abt_errno);
1335  return ABT_SUCCESS;
1336 #else
1338 #endif
1339 }
1340 
1389 {
1390 #ifndef ABT_CONFIG_DISABLE_MIGRATION
1391  ABTI_global *p_global;
1392  ABTI_SETUP_GLOBAL(&p_global);
1393  ABTI_local *p_local = ABTI_local_get_local();
1394 
1395  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1396  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1397  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
1398  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
1403  /* Check if a thread is associated with a pool of the main scheduler. */
1405  size_t p;
1406  for (p = 0; p < p_sched->num_pools; p++)
1407  ABTI_CHECK_TRUE(ABTI_pool_get_ptr(p_sched->pools[p]) !=
1408  p_thread->p_pool,
1410  }
1411  /* Get the target pool. */
1412  ABTI_pool *p_pool;
1413  int abt_errno;
1414  abt_errno =
1415  ABTI_sched_get_migration_pool(p_sched, p_thread->p_pool, &p_pool);
1416  ABTI_CHECK_ERROR(abt_errno);
1417  /* Request a migration. */
1418  abt_errno = thread_migrate_to_pool(p_global, p_local, p_thread, p_pool);
1419  ABTI_CHECK_ERROR(abt_errno);
1420  return ABT_SUCCESS;
1421 #else
1423 #endif
1424 }
1425 
1472 {
1473 #ifndef ABT_CONFIG_DISABLE_MIGRATION
1474  ABTI_global *p_global;
1475  ABTI_SETUP_GLOBAL(&p_global);
1476  ABTI_local *p_local = ABTI_local_get_local();
1477 
1478  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1479  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1480  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
1481  ABTI_CHECK_NULL_POOL_PTR(p_pool);
1486  ABTI_CHECK_TRUE(p_thread->p_pool != p_pool, ABT_ERR_MIGRATION_TARGET);
1487  /* Request a migration. */
1488  int abt_errno = thread_migrate_to_pool(p_global, p_local, p_thread, p_pool);
1489  ABTI_CHECK_ERROR(abt_errno);
1490  return ABT_SUCCESS;
1491 #else
1493 #endif
1494 }
1495 
1548 int ABT_thread_migrate(ABT_thread thread)
1549 {
1550 #ifndef ABT_CONFIG_DISABLE_MIGRATION
1551  /* TODO: fix the bug(s) */
1552  ABTI_global *p_global;
1553  ABTI_SETUP_GLOBAL(&p_global);
1554 
1555  ABTI_local *p_local = ABTI_local_get_local();
1556  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1557  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1562 
1563  /* Copy the target execution streams. */
1564  int i, num_xstreams, abt_errno;
1565  ABTI_xstream **xstreams;
1567  num_xstreams = p_global->num_xstreams;
1568  abt_errno =
1569  ABTU_malloc(sizeof(ABTI_xstream *) * num_xstreams, (void **)&xstreams);
1570  if (!(ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS)) {
1571  ABTI_xstream *p_xstream = p_global->p_xstream_head;
1572  i = 0;
1573  while (p_xstream) {
1574  xstreams[i++] = p_xstream;
1575  p_xstream = p_xstream->p_next;
1576  }
1577  }
1579  ABTI_CHECK_ERROR(abt_errno);
1580 
1581  /* Choose the destination xstream. The user needs to maintain all the pools
1582  * and execution streams alive. */
1583  for (i = 0; i < num_xstreams; i++) {
1584  ABTI_xstream *p_xstream = xstreams[i];
1585  if (p_xstream == p_thread->p_last_xstream)
1586  continue;
1587  if (ABTD_atomic_acquire_load_int(&p_xstream->state) !=
1589  continue;
1590  /* Check if a thread is associated with a pool of the main scheduler. */
1591  ABTI_sched *p_sched = p_xstream->p_main_sched;
1592  ABT_bool is_valid = ABT_TRUE;
1593  size_t p;
1594  for (p = 0; p < p_sched->num_pools; p++) {
1595  if (ABTI_pool_get_ptr(p_sched->pools[p]) != p_thread->p_pool) {
1596  is_valid = ABT_FALSE;
1597  break;
1598  }
1599  }
1600  if (!is_valid)
1601  continue;
1602  /* Get the target pool. */
1603  ABTI_pool *p_pool = NULL;
1604  abt_errno =
1605  ABTI_sched_get_migration_pool(p_sched, p_thread->p_pool, &p_pool);
1606  if (abt_errno != ABT_SUCCESS)
1607  continue;
1608  /* Request a migration. */
1609  abt_errno = thread_migrate_to_pool(p_global, p_local, p_thread, p_pool);
1610  if (abt_errno != ABT_SUCCESS)
1611  continue;
1612  /* Succeeds. Return. */
1613  ABTU_free(xstreams);
1614  return ABT_SUCCESS;
1615  }
1616  /* All attempts failed. */
1617  ABTU_free(xstreams);
1618  return ABT_ERR_MIGRATION_NA;
1619 #else
1621 #endif
1622 }
1623 
1661  void (*cb_func)(ABT_thread thread, void *cb_arg),
1662  void *cb_arg)
1663 {
1664 #ifndef ABT_CONFIG_DISABLE_MIGRATION
1665  ABTI_global *p_global;
1666  ABTI_SETUP_GLOBAL(&p_global);
1667 
1668  ABTI_local *p_local = ABTI_local_get_local();
1669  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1670  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1671 
1672  ABTI_thread_mig_data *p_mig_data;
1673  int abt_errno =
1674  ABTI_thread_get_mig_data(p_global, p_local, p_thread, &p_mig_data);
1675  ABTI_CHECK_ERROR(abt_errno);
1676 
1677  p_mig_data->f_migration_cb = cb_func;
1678  p_mig_data->p_migration_cb_arg = cb_arg;
1679  return ABT_SUCCESS;
1680 #else
1682 #endif
1683 }
1684 
1722 int ABT_thread_set_migratable(ABT_thread thread, ABT_bool migratable)
1723 {
1724 #ifndef ABT_CONFIG_DISABLE_MIGRATION
1725  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1726  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1727 
1728 #ifndef ABT_CONFIG_ENABLE_VER_20_API
1729  if (p_thread->type &
1731  return ABT_SUCCESS;
1732 #else
1733  ABTI_CHECK_TRUE(!(p_thread->type &
1736 #endif
1737 
1738  if (migratable) {
1739  p_thread->type |= ABTI_THREAD_TYPE_MIGRATABLE;
1740  } else {
1741  p_thread->type &= ~ABTI_THREAD_TYPE_MIGRATABLE;
1742  }
1743  return ABT_SUCCESS;
1744 #else
1746 #endif
1747 }
1748 
1779 int ABT_thread_is_migratable(ABT_thread thread, ABT_bool *is_migratable)
1780 {
1781 #ifndef ABT_CONFIG_DISABLE_MIGRATION
1782  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1783  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1784 
1785  *is_migratable =
1787  return ABT_SUCCESS;
1788 #else
1790 #endif
1791 }
1792 
1821 int ABT_thread_is_primary(ABT_thread thread, ABT_bool *is_primary)
1822 {
1823  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1824  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1825 
1826  *is_primary =
1827  (p_thread->type & ABTI_THREAD_TYPE_PRIMARY) ? ABT_TRUE : ABT_FALSE;
1828  return ABT_SUCCESS;
1829 }
1830 
1859 int ABT_thread_is_unnamed(ABT_thread thread, ABT_bool *is_unnamed)
1860 {
1861  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1862  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1863 
1864  *is_unnamed =
1865  (p_thread->type & ABTI_THREAD_TYPE_NAMED) ? ABT_FALSE : ABT_TRUE;
1866  return ABT_SUCCESS;
1867 }
1868 
1906 int ABT_thread_equal(ABT_thread thread1, ABT_thread thread2, ABT_bool *result)
1907 {
1908  ABTI_thread *p_thread1 = ABTI_thread_get_ptr(thread1);
1909  ABTI_thread *p_thread2 = ABTI_thread_get_ptr(thread2);
1910  *result = (p_thread1 == p_thread2) ? ABT_TRUE : ABT_FALSE;
1911  return ABT_SUCCESS;
1912 }
1913 
1942 int ABT_thread_get_stacksize(ABT_thread thread, size_t *stacksize)
1943 {
1944  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1945  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1946  ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
1947  if (p_ythread) {
1948  *stacksize = p_ythread->stacksize;
1949  } else {
1950  *stacksize = 0;
1951  }
1952  return ABT_SUCCESS;
1953 }
1954 
1981 int ABT_thread_get_id(ABT_thread thread, ABT_unit_id *thread_id)
1982 {
1983  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
1984  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
1985 
1986  *thread_id = ABTI_thread_get_id(p_thread);
1987  return ABT_SUCCESS;
1988 }
1989 
2016 int ABT_thread_set_arg(ABT_thread thread, void *arg)
2017 {
2018  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
2019  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
2020 
2021  p_thread->p_arg = arg;
2022  return ABT_SUCCESS;
2023 }
2024 
2051 int ABT_thread_get_arg(ABT_thread thread, void **arg)
2052 {
2053  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
2054  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
2055 
2056  *arg = p_thread->p_arg;
2057  return ABT_SUCCESS;
2058 }
2059 
2082 int ABT_thread_get_thread_func(ABT_thread thread, void (**thread_func)(void *))
2083 {
2084  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
2085  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
2086 
2087  *thread_func = p_thread->f_thread;
2088  return ABT_SUCCESS;
2089 }
2090 
2117 int ABT_thread_set_specific(ABT_thread thread, ABT_key key, void *value)
2118 {
2119  ABTI_global *p_global;
2120  ABTI_SETUP_GLOBAL(&p_global);
2121 
2122  ABTI_local *p_local = ABTI_local_get_local();
2123 
2124  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
2125  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
2126 
2127  ABTI_key *p_key = ABTI_key_get_ptr(key);
2128  ABTI_CHECK_NULL_KEY_PTR(p_key);
2129 
2130  /* Set the value. */
2131  int abt_errno =
2132  ABTI_ktable_set(p_global, p_local, &p_thread->p_keytable, p_key, value);
2133  ABTI_CHECK_ERROR(abt_errno);
2134  return ABT_SUCCESS;
2135 }
2136 
2166 int ABT_thread_get_specific(ABT_thread thread, ABT_key key, void **value)
2167 {
2168  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
2169  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
2170 
2171  ABTI_key *p_key = ABTI_key_get_ptr(key);
2172  ABTI_CHECK_NULL_KEY_PTR(p_key);
2173 
2174  /* Get the value. */
2175  *value = ABTI_ktable_get(&p_thread->p_keytable, p_key);
2176  return ABT_SUCCESS;
2177 }
2178 
2212 {
2213  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
2214  ABTI_CHECK_NULL_THREAD_PTR(p_thread);
2215 
2216  ABTI_thread_attr thread_attr, *p_attr;
2217  ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
2218 #ifndef ABT_CONFIG_ENABLE_VER_20_API
2219  ABTI_CHECK_TRUE(p_ythread, ABT_ERR_INV_THREAD);
2220 #endif
2221 
2222  if (p_ythread) {
2223  thread_attr.p_stack = p_ythread->p_stack;
2224  thread_attr.stacksize = p_ythread->stacksize;
2225  } else {
2226  thread_attr.p_stack = NULL;
2227  thread_attr.stacksize = 0;
2228  }
2229  thread_attr.thread_type = p_thread->type;
2230 #ifndef ABT_CONFIG_DISABLE_MIGRATION
2231  thread_attr.migratable =
2233  ABTI_thread_mig_data *p_mig_data =
2236  if (p_mig_data) {
2237  thread_attr.f_cb = p_mig_data->f_migration_cb;
2238  thread_attr.p_cb_arg = p_mig_data->p_migration_cb_arg;
2239  } else {
2240  thread_attr.f_cb = NULL;
2241  thread_attr.p_cb_arg = NULL;
2242  }
2243 #endif
2244  int abt_errno = ABTI_thread_attr_dup(&thread_attr, &p_attr);
2245  ABTI_CHECK_ERROR(abt_errno);
2246 
2247  *attr = ABTI_thread_attr_get_handle(p_attr);
2248  return ABT_SUCCESS;
2249 }
2250 
2251 /*****************************************************************************/
2252 /* Private APIs */
2253 /*****************************************************************************/
2254 
2255 ABTU_ret_err int ABTI_thread_revive(ABTI_global *p_global, ABTI_local *p_local,
2256  ABTI_pool *p_pool,
2257  void (*thread_func)(void *), void *arg,
2258  ABTI_thread *p_thread)
2259 {
2262  /* Set the new pool */
2263  int abt_errno = ABTI_thread_set_associated_pool(p_global, p_thread, p_pool);
2264  ABTI_CHECK_ERROR(abt_errno);
2265 
2266  p_thread->f_thread = thread_func;
2267  p_thread->p_arg = arg;
2268 
2271  p_thread->p_last_xstream = NULL;
2272  p_thread->p_parent = NULL;
2273 
2274  ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
2275 
2276  if (p_ythread) {
2277  /* Create a ULT context */
2278  size_t stacksize = p_ythread->stacksize;
2279  ABTD_ythread_context_create(NULL, stacksize, p_ythread->p_stack,
2280  &p_ythread->ctx);
2281  }
2282 
2283  /* Invoke a thread revive event. */
2284  ABTI_tool_event_thread_revive(p_local, p_thread,
2286  ? ABTI_local_get_xstream(p_local)
2287  ->p_thread
2288  : NULL,
2289  p_pool);
2290 
2291  LOG_DEBUG("[U%" PRIu64 "] revived\n", ABTI_thread_get_id(p_thread));
2292 
2293  /* Add this thread to the pool */
2294  ABTI_pool_push(p_pool, p_thread->unit);
2295  return ABT_SUCCESS;
2296 }
2297 
2299  ABTI_local *p_local,
2300  ABTI_xstream *p_xstream,
2301  ABTI_ythread **p_ythread)
2302 {
2303  ABTI_thread_attr attr;
2304  ABTI_pool *p_pool;
2305 
2306  /* Get the first pool of ES */
2307  p_pool = ABTI_pool_get_ptr(p_xstream->p_main_sched->pools[0]);
2308 
2309  /* Allocate a ULT object */
2310 
2312  ABT_FALSE);
2313 
2314  /* Although this primary ULT is running now, we add this primary ULT to the
2315  * pool so that the scheduler can schedule the primary ULT when the primary
2316  * ULT is context switched to the scheduler for the first time. */
2317  ABT_bool push_pool = ABT_TRUE;
2318  int abt_errno =
2319  ythread_create(p_global, p_local, p_pool, NULL, NULL, &attr,
2321  NULL, push_pool, p_ythread);
2322  ABTI_CHECK_ERROR(abt_errno);
2323  return ABT_SUCCESS;
2324 }
2325 
2327  ABTI_local *p_local,
2328  ABTI_xstream *p_xstream,
2329  ABTI_ythread **pp_root_ythread)
2330 {
2331  ABTI_thread_attr attr;
2332  /* Create a ULT context */
2333  if (p_xstream->type == ABTI_XSTREAM_TYPE_PRIMARY) {
2334  /* Create a thread with its stack */
2335  ABTI_thread_attr_init(&attr, NULL, p_global->sched_stacksize,
2337  ABT_FALSE);
2338  } else {
2339  /* For secondary ESs, the stack of an OS thread is used. */
2341  ABT_FALSE);
2342  }
2343  ABTI_ythread *p_root_ythread;
2344  int abt_errno =
2345  ythread_create(p_global, p_local, NULL, thread_root_func, NULL, &attr,
2347  ABT_FALSE, &p_root_ythread);
2348  ABTI_CHECK_ERROR(abt_errno);
2349  *pp_root_ythread = p_root_ythread;
2350  return ABT_SUCCESS;
2351 }
2352 
2354  ABTI_local *p_local,
2355  ABTI_xstream *p_xstream,
2356  ABTI_sched *p_sched)
2357 {
2358  ABTI_thread_attr attr;
2359 
2360  /* Allocate a ULT object and its stack */
2361  ABTI_thread_attr_init(&attr, NULL, p_global->sched_stacksize,
2363  int abt_errno =
2364  ythread_create(p_global, p_local, p_xstream->p_root_pool,
2365  thread_main_sched_func, NULL, &attr,
2368  p_sched, ABT_TRUE, &p_sched->p_ythread);
2369  ABTI_CHECK_ERROR(abt_errno);
2370  return ABT_SUCCESS;
2371 }
2372 
2373 /* This routine is to create a ULT for the scheduler. */
2375  ABTI_local *p_local,
2376  ABTI_pool *p_pool,
2377  ABTI_sched *p_sched)
2378 {
2379  ABTI_thread_attr attr;
2380 
2381  /* Allocate a ULT object and its stack */
2382  ABTI_thread_attr_init(&attr, NULL, p_global->sched_stacksize,
2384  int abt_errno = ythread_create(p_global, p_local, p_pool,
2385  (void (*)(void *))p_sched->run,
2386  (void *)ABTI_sched_get_handle(p_sched),
2387  &attr, ABTI_THREAD_TYPE_YIELDABLE, p_sched,
2388  ABT_TRUE, &p_sched->p_ythread);
2389  ABTI_CHECK_ERROR(abt_errno);
2390  return ABT_SUCCESS;
2391 }
2392 
2393 void ABTI_thread_join(ABTI_local **pp_local, ABTI_thread *p_thread)
2394 {
2395  thread_join(pp_local, p_thread);
2396 }
2397 
2398 void ABTI_thread_free(ABTI_global *p_global, ABTI_local *p_local,
2399  ABTI_thread *p_thread)
2401  LOG_DEBUG("[U%" PRIu64 ":E%d] freed\n", ABTI_thread_get_id(p_thread),
2403  ? ABTI_local_get_xstream(p_local)->rank
2404  : -1);
2405  thread_free(p_global, p_local, p_thread, ABT_TRUE);
2406 }
2407 
2408 void ABTI_ythread_free_primary(ABTI_global *p_global, ABTI_local *p_local,
2409  ABTI_ythread *p_ythread)
2411  ABTI_thread *p_thread = &p_ythread->thread;
2412  LOG_DEBUG("[U%" PRIu64 ":E%d] primary ULT freed\n",
2413  ABTI_thread_get_id(p_thread), p_thread->p_last_xstream->rank);
2414  thread_free(p_global, p_local, p_thread, ABT_FALSE);
2415 }
2416 
2417 void ABTI_ythread_free_root(ABTI_global *p_global, ABTI_local *p_local,
2418  ABTI_ythread *p_ythread)
2420  thread_free(p_global, p_local, &p_ythread->thread, ABT_FALSE);
2421 }
2422 
2423 ABTU_noreturn void ABTI_ythread_exit(ABTI_xstream *p_local_xstream,
2424  ABTI_ythread *p_ythread)
2426  /* Set the exit request */
2428 
2429  /* Terminate this ULT */
2430  ABTD_ythread_exit(p_local_xstream, p_ythread);
2431  ABTU_unreachable();
2432 }
2433 
2435  ABTI_local *p_local,
2436  ABTI_thread *p_thread,
2437  ABTI_thread_mig_data **pp_mig_data)
2438 {
2439  ABTI_thread_mig_data *p_mig_data =
2442  if (!p_mig_data) {
2443  int abt_errno;
2444  abt_errno =
2445  ABTU_calloc(1, sizeof(ABTI_thread_mig_data), (void **)&p_mig_data);
2446  ABTI_CHECK_ERROR(abt_errno);
2447  abt_errno = ABTI_ktable_set(p_global, p_local, &p_thread->p_keytable,
2448  &g_thread_mig_data_key, (void *)p_mig_data);
2449  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
2450  /* Failed to add p_mig_data to p_thread's keytable. */
2451  ABTU_free(p_mig_data);
2452  return abt_errno;
2453  }
2454  }
2455  *pp_mig_data = p_mig_data;
2456  return ABT_SUCCESS;
2457 }
2458 
2459 void ABTI_thread_print(ABTI_thread *p_thread, FILE *p_os, int indent)
2460 {
2461  if (p_thread == NULL) {
2462  fprintf(p_os, "%*s== NULL thread ==\n", indent, "");
2463  } else {
2464  ABTI_xstream *p_xstream = p_thread->p_last_xstream;
2465  int xstream_rank = p_xstream ? p_xstream->rank : 0;
2466  const char *type, *yieldable, *state, *named, *migratable;
2467 
2468  if (p_thread->type & ABTI_THREAD_TYPE_PRIMARY) {
2469  type = "PRIMARY";
2470  } else if (p_thread->type & ABTI_THREAD_TYPE_MAIN_SCHED) {
2471  type = "MAIN_SCHED";
2472  } else if (p_thread->type & ABTI_THREAD_TYPE_ROOT) {
2473  type = "ROOT";
2474  } else {
2475  type = "USER";
2476  }
2477  if (p_thread->type & ABTI_THREAD_TYPE_YIELDABLE) {
2478  yieldable = "yes";
2479  } else {
2480  yieldable = "no";
2481  }
2482  if (p_thread->type & ABTI_THREAD_TYPE_NAMED) {
2483  named = "yes";
2484  } else {
2485  named = "no";
2486  }
2487  if (p_thread->type & ABTI_THREAD_TYPE_MIGRATABLE) {
2488  migratable = "yes";
2489  } else {
2490  migratable = "no";
2491  }
2492  switch (ABTD_atomic_acquire_load_int(&p_thread->state)) {
2494  state = "READY";
2495  break;
2497  state = "RUNNING";
2498  break;
2500  state = "BLOCKED";
2501  break;
2503  state = "TERMINATED";
2504  break;
2505  default:
2506  state = "UNKNOWN";
2507  break;
2508  }
2509  ABTI_thread_mig_data *p_mig_data =
2512  void *p_migration_cb_arg =
2513  p_mig_data ? p_mig_data->p_migration_cb_arg : NULL;
2514 
2515  fprintf(p_os,
2516  "%*s== Thread (%p) ==\n"
2517  "%*sid : %" PRIu64 "\n"
2518  "%*stype : %s\n"
2519  "%*syieldable : %s\n"
2520  "%*sstate : %s\n"
2521  "%*slast_ES : %p (%d)\n"
2522  "%*sparent : %p\n"
2523  "%*sp_arg : %p\n"
2524  "%*spool : %p\n"
2525  "%*snamed : %s\n"
2526  "%*smigratable : %s\n"
2527  "%*srequest : 0x%x\n"
2528  "%*smig_cb_arg : %p\n"
2529  "%*skeytable : %p\n",
2530  indent, "", (void *)p_thread, indent, "",
2531  ABTI_thread_get_id(p_thread), indent, "", type, indent, "",
2532  yieldable, indent, "", state, indent, "", (void *)p_xstream,
2533  xstream_rank, indent, "", (void *)p_thread->p_parent, indent,
2534  "", p_thread->p_arg, indent, "", (void *)p_thread->p_pool,
2535  indent, "", named, indent, "", migratable, indent, "",
2536  ABTD_atomic_acquire_load_uint32(&p_thread->request), indent, "",
2537  p_migration_cb_arg, indent, "",
2538  ABTD_atomic_acquire_load_ptr(&p_thread->p_keytable));
2539 
2540  if (p_thread->type & ABTI_THREAD_TYPE_YIELDABLE) {
2541  ABTI_ythread *p_ythread = ABTI_thread_get_ythread(p_thread);
2542  fprintf(p_os,
2543  "%*sstack : %p\n"
2544  "%*sstacksize : %zu\n",
2545  indent, "", p_ythread->p_stack, indent, "",
2546  p_ythread->stacksize);
2547  }
2548  }
2549  fflush(p_os);
2550 }
2551 
2555 {
2557 }
2558 
2560 {
2561  if (p_thread == NULL)
2562  return ABTI_THREAD_INIT_ID;
2563 
2564  if (p_thread->id == ABTI_THREAD_INIT_ID) {
2565  p_thread->id = thread_get_new_id();
2566  }
2567  return p_thread->id;
2568 }
2569 
2570 /*****************************************************************************/
2571 /* Internal static functions */
2572 /*****************************************************************************/
2573 
2574 ABTU_ret_err static inline int
2575 ythread_create(ABTI_global *p_global, ABTI_local *p_local, ABTI_pool *p_pool,
2576  void (*thread_func)(void *), void *arg, ABTI_thread_attr *p_attr,
2577  ABTI_thread_type thread_type, ABTI_sched *p_sched,
2578  ABT_bool push_pool, ABTI_ythread **pp_newthread)
2579 {
2580  int abt_errno;
2581  ABTI_ythread *p_newthread;
2582  ABTI_ktable *p_keytable = NULL;
2583 
2584  /* Allocate a ULT object and its stack, then create a thread context. */
2585  if (!p_attr) {
2586  abt_errno =
2587  ABTI_mem_alloc_ythread_default(p_global, p_local, &p_newthread);
2588  ABTI_CHECK_ERROR(abt_errno);
2589 #ifndef ABT_CONFIG_DISABLE_MIGRATION
2590  thread_type |= ABTI_THREAD_TYPE_MIGRATABLE;
2591 #endif
2592  } else {
2593  ABTI_thread_type attr_type = p_attr->thread_type;
2594  if (attr_type & ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC_STACK) {
2595 #ifdef ABT_CONFIG_USE_MEM_POOL
2596  abt_errno =
2597  ABTI_mem_alloc_ythread_mempool_desc_stack(p_global, p_local,
2598  p_attr, &p_newthread);
2599  ABTI_CHECK_ERROR(abt_errno);
2600 #else
2601  abt_errno =
2602  ABTI_mem_alloc_ythread_malloc_desc_stack(p_attr, &p_newthread);
2603 #endif
2604  ABTI_CHECK_ERROR(abt_errno);
2605  } else if (attr_type & ABTI_THREAD_TYPE_MEM_MALLOC_DESC_STACK) {
2606  abt_errno =
2607  ABTI_mem_alloc_ythread_malloc_desc_stack(p_attr, &p_newthread);
2608  ABTI_CHECK_ERROR(abt_errno);
2609  } else {
2612  /* Let's try to use mempool first since it performs better. */
2613  abt_errno = ABTI_mem_alloc_ythread_mempool_desc(p_local, p_attr,
2614  &p_newthread);
2615  ABTI_CHECK_ERROR(abt_errno);
2616  }
2617 #ifndef ABT_CONFIG_DISABLE_MIGRATION
2618  thread_type |= p_attr->migratable ? ABTI_THREAD_TYPE_MIGRATABLE : 0;
2619  if (ABTU_unlikely(p_attr->f_cb)) {
2620  ABTI_thread_mig_data *p_mig_data;
2621  abt_errno = ABTU_calloc(1, sizeof(ABTI_thread_mig_data),
2622  (void **)&p_mig_data);
2624  ABTU_unlikely(abt_errno != ABT_SUCCESS)) {
2625  ABTI_mem_free_thread(p_global, p_local, &p_newthread->thread);
2626  return abt_errno;
2627  }
2628  p_mig_data->f_migration_cb = p_attr->f_cb;
2629  p_mig_data->p_migration_cb_arg = p_attr->p_cb_arg;
2630  abt_errno = ABTI_ktable_set_unsafe(p_global, p_local, &p_keytable,
2632  (void *)p_mig_data);
2634  ABTU_unlikely(abt_errno != ABT_SUCCESS)) {
2635  if (p_keytable)
2636  ABTI_ktable_free(p_global, p_local, p_keytable);
2637  ABTU_free(p_mig_data);
2638  ABTI_mem_free_thread(p_global, p_local, &p_newthread->thread);
2639  return abt_errno;
2640  }
2641  }
2642 #endif
2643  }
2644 
2645  if (thread_type & (ABTI_THREAD_TYPE_PRIMARY | ABTI_THREAD_TYPE_ROOT)) {
2646  if (p_newthread->p_stack == NULL) {
2647  /* We don't need to initialize the context if a thread will run on
2648  * OS-level threads. Invalidate the context here. */
2649  ABTD_ythread_context_invalidate(&p_newthread->ctx);
2650  } else {
2651  /* Create the context. This thread is special, so dynamic promotion
2652  * is not supported. */
2653  size_t stack_size = p_newthread->stacksize;
2654  void *p_stack = p_newthread->p_stack;
2655  ABTD_ythread_context_create(NULL, stack_size, p_stack,
2656  &p_newthread->ctx);
2657  }
2658  } else {
2659 #if ABT_CONFIG_THREAD_TYPE != ABT_THREAD_TYPE_DYNAMIC_PROMOTION
2660  size_t stack_size = p_newthread->stacksize;
2661  void *p_stack = p_newthread->p_stack;
2662  ABTD_ythread_context_create(NULL, stack_size, p_stack,
2663  &p_newthread->ctx);
2664 #else
2665  /* The context is not fully created now. */
2666  ABTD_ythread_context_init(NULL, &p_newthread->ctx);
2667 #endif
2668  }
2669  p_newthread->thread.f_thread = thread_func;
2670  p_newthread->thread.p_arg = arg;
2671 
2675  p_newthread->thread.p_last_xstream = NULL;
2676  p_newthread->thread.p_parent = NULL;
2677  p_newthread->thread.type |= thread_type;
2678  p_newthread->thread.id = ABTI_THREAD_INIT_ID;
2679  if (p_sched && !(thread_type & (ABTI_THREAD_TYPE_PRIMARY |
2681  /* Set a destructor for p_sched. */
2682  abt_errno = ABTI_ktable_set_unsafe(p_global, p_local, &p_keytable,
2683  &g_thread_sched_key, p_sched);
2685  ABTU_unlikely(abt_errno != ABT_SUCCESS)) {
2686  if (p_keytable)
2687  ABTI_ktable_free(p_global, p_local, p_keytable);
2688  ABTI_mem_free_thread(p_global, p_local, &p_newthread->thread);
2689  return abt_errno;
2690  }
2691  }
2692  ABTD_atomic_relaxed_store_ptr(&p_newthread->thread.p_keytable, p_keytable);
2693 
2694 #ifdef ABT_CONFIG_USE_DEBUG_LOG
2695  ABT_unit_id thread_id = ABTI_thread_get_id(&p_newthread->thread);
2696  if (thread_type & ABTI_THREAD_TYPE_PRIMARY) {
2697  LOG_DEBUG("[U%" PRIu64 "] primary ULT created\n", thread_id);
2698  } else if (thread_type & ABTI_THREAD_TYPE_MAIN_SCHED) {
2699  LOG_DEBUG("[U%" PRIu64 "] main sched ULT created\n", thread_id);
2700  } else {
2701  LOG_DEBUG("[U%" PRIu64 "] created\n", thread_id);
2702  }
2703 #endif
2704 
2705  /* Create a wrapper unit */
2706  if (push_pool) {
2707  abt_errno =
2708  ABTI_thread_init_pool(p_global, &p_newthread->thread, p_pool);
2710  ABTU_unlikely(abt_errno != ABT_SUCCESS)) {
2711  if (p_keytable)
2712  ABTI_ktable_free(p_global, p_local, p_keytable);
2713  ABTI_mem_free_thread(p_global, p_local, &p_newthread->thread);
2714  return abt_errno;
2715  }
2716  /* Invoke a thread creation event. */
2717  ABTI_tool_event_thread_create(p_local, &p_newthread->thread,
2719  ? ABTI_local_get_xstream(p_local)
2720  ->p_thread
2721  : NULL,
2722  p_pool);
2723  /* Add this thread to the pool */
2724  ABTI_pool_push(p_pool, p_newthread->thread.unit);
2725  } else {
2726  p_newthread->thread.p_pool = p_pool;
2727  p_newthread->thread.unit = ABT_UNIT_NULL;
2728  /* Invoke a thread creation event. */
2729  ABTI_tool_event_thread_create(p_local, &p_newthread->thread,
2731  ? ABTI_local_get_xstream(p_local)
2732  ->p_thread
2733  : NULL,
2734  NULL);
2735  }
2736 
2737  /* Return value */
2738  *pp_newthread = p_newthread;
2739  return ABT_SUCCESS;
2740 }
2741 
2742 #ifndef ABT_CONFIG_DISABLE_MIGRATION
2743 ABTU_ret_err static int thread_migrate_to_pool(ABTI_global *p_global,
2744  ABTI_local *p_local,
2745  ABTI_thread *p_thread,
2746  ABTI_pool *p_pool)
2747 {
2748  /* Adding request to the thread. p_migration_pool must be updated before
2749  * setting the request since the target thread would read p_migration_pool
2750  * after ABTI_THREAD_REQ_MIGRATE. The update must be "atomic" (but does not
2751  * require acq-rel) since two threads can update the pointer value
2752  * simultaneously. */
2753 
2754  ABTI_thread_mig_data *p_mig_data;
2755  int abt_errno =
2756  ABTI_thread_get_mig_data(p_global, p_local, p_thread, &p_mig_data);
2757  ABTI_CHECK_ERROR(abt_errno);
2758 
2760  (void *)p_pool);
2762  return ABT_SUCCESS;
2763 }
2764 #endif
2765 
2766 static inline void thread_free(ABTI_global *p_global, ABTI_local *p_local,
2767  ABTI_thread *p_thread, ABT_bool free_unit)
2769  /* Invoke a thread freeing event. */
2770  ABTI_tool_event_thread_free(p_local, p_thread,
2772  ? ABTI_local_get_xstream(p_local)->p_thread
2773  : NULL);
2774 
2775  /* Free the unit */
2776  if (free_unit) {
2777  ABTI_thread_unset_associated_pool(p_global, p_thread);
2778  }
2779 
2780  /* Free the key-value table */
2781  ABTI_ktable *p_ktable = ABTD_atomic_acquire_load_ptr(&p_thread->p_keytable);
2782  /* No parallel access to TLS is allowed. */
2783  ABTI_ASSERT(p_ktable != ABTI_KTABLE_LOCKED);
2784  if (p_ktable) {
2785  ABTI_ktable_free(p_global, p_local, p_ktable);
2786  }
2787 
2788  /* Free ABTI_thread (stack will also be freed) */
2789  ABTI_mem_free_thread(p_global, p_local, p_thread);
2790 }
2791 
2792 static void thread_key_destructor_stackable_sched(void *p_value)
2793 {
2794  /* This destructor should be called in ABTI_ythread_free(), so it should not
2795  * free the thread again. */
2796  ABTI_sched *p_sched = (ABTI_sched *)p_value;
2797  p_sched->used = ABTI_SCHED_NOT_USED;
2798  if (p_sched->automatic == ABT_TRUE) {
2799  ABTI_global *p_global = ABTI_global_get_global();
2800  p_sched->p_ythread = NULL;
2801  ABTI_sched_free(p_global, ABTI_local_get_local_uninlined(), p_sched,
2802  ABT_FALSE);
2803  } else {
2804  /* If it is not automatic, p_ythread must be set to NULL to avoid double
2805  * free corruption. */
2806  p_sched->p_ythread = NULL;
2807  }
2808 }
2809 
2810 static void thread_key_destructor_migration(void *p_value)
2811 {
2812  ABTI_thread_mig_data *p_mig_data = (ABTI_thread_mig_data *)p_value;
2813  ABTU_free(p_mig_data);
2814 }
2815 
2816 static void thread_join_busywait(ABTI_thread *p_thread)
2817 {
2818  while (ABTD_atomic_acquire_load_int(&p_thread->state) !=
2821  }
2822  ABTI_tool_event_thread_join(NULL, p_thread, NULL);
2823 }
2824 
2825 #ifndef ABT_CONFIG_ACTIVE_WAIT_POLICY
2826 static void thread_join_futexwait(ABTI_thread *p_thread)
2827 {
2829  if (p_ythread) {
2830  /* tell that this thread will join */
2831  uint32_t req = ABTD_atomic_fetch_or_uint32(&p_ythread->thread.request,
2833  if (!(req & ABTI_THREAD_REQ_JOIN)) {
2834  ABTD_futex_single futex;
2835  ABTD_futex_single_init(&futex);
2836  ABTI_ythread dummy_ythread;
2837  dummy_ythread.thread.type = ABTI_THREAD_TYPE_EXT;
2838  /* Just arbitrarily choose p_arg to store futex. */
2839  dummy_ythread.thread.p_arg = &futex;
2841  .p_link,
2842  &dummy_ythread.ctx);
2843  ABTD_futex_suspend(&futex);
2844  /* Resumed. */
2845  } else {
2846  /* If request already has ABTI_THREAD_REQ_JOIN, p_ythread is
2847  * terminating. We can't suspend in this case. */
2848  }
2849  }
2850  /* No matter whether this thread has been resumed or not, we need to busy-
2851  * wait to make sure that the thread's state gets terminated. */
2852  thread_join_busywait(p_thread);
2853 }
2854 #endif
2855 
2856 static void thread_join_yield_thread(ABTI_xstream **pp_local_xstream,
2857  ABTI_ythread *p_self,
2858  ABTI_thread *p_thread)
2859 {
2860  while (ABTD_atomic_acquire_load_int(&p_thread->state) !=
2862  ABTI_ythread_yield(pp_local_xstream, p_self,
2863  ABT_SYNC_EVENT_TYPE_THREAD_JOIN, (void *)p_thread);
2864  }
2866  p_thread, &p_self->thread);
2867 }
2868 
2869 static inline void thread_join(ABTI_local **pp_local, ABTI_thread *p_thread)
2870 {
2873  ABTI_tool_event_thread_join(*pp_local, p_thread,
2875  ? ABTI_local_get_xstream(*pp_local)
2876  ->p_thread
2877  : NULL);
2878  return;
2879  }
2880  /* The primary ULT cannot be joined. */
2881  ABTI_ASSERT(!(p_thread->type & ABTI_THREAD_TYPE_PRIMARY));
2882 
2883  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(*pp_local);
2884  if (ABTI_IS_EXT_THREAD_ENABLED && !p_local_xstream) {
2885 #ifdef ABT_CONFIG_ACTIVE_WAIT_POLICY
2886  thread_join_busywait(p_thread);
2887 #else
2888  thread_join_futexwait(p_thread);
2889 #endif
2890  return;
2891  }
2892 
2893  ABTI_thread *p_self_thread = p_local_xstream->p_thread;
2894 
2895  ABTI_ythread *p_self = ABTI_thread_get_ythread_or_null(p_self_thread);
2896  if (!p_self) {
2897 #ifdef ABT_CONFIG_ACTIVE_WAIT_POLICY
2898  thread_join_busywait(p_thread);
2899 #else
2900  thread_join_futexwait(p_thread);
2901 #endif
2902  return;
2903  }
2904 
2905  /* The target ULT should be different. */
2906  ABTI_ASSERT(p_thread != p_self_thread);
2907 
2908  ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
2909  if (!p_ythread) {
2910  thread_join_yield_thread(&p_local_xstream, p_self, p_thread);
2911  *pp_local = ABTI_xstream_get_local(p_local_xstream);
2912  return;
2913  }
2914 
2915  /* Tell p_ythread that there has been a join request. */
2916  /* If request already has ABTI_THREAD_REQ_JOIN, p_ythread is
2917  * terminating. We can't block p_self in this case. */
2918  uint32_t req = ABTD_atomic_fetch_or_uint32(&p_ythread->thread.request,
2920  if (req & ABTI_THREAD_REQ_JOIN) {
2921  thread_join_yield_thread(&p_local_xstream, p_self, &p_ythread->thread);
2922  *pp_local = ABTI_xstream_get_local(p_local_xstream);
2923  return;
2924  }
2925 
2926  ABTI_ythread_set_blocked(p_self);
2927  LOG_DEBUG("[U%" PRIu64 ":E%d] blocked to join U%" PRIu64 "\n",
2928  ABTI_thread_get_id(&p_self->thread),
2929  p_self->thread.p_last_xstream->rank,
2930  ABTI_thread_get_id(&p_ythread->thread));
2931 
2932  /* Set the link in the context of the target ULT. This p_link might be
2933  * read by p_ythread running on another ES in parallel, so release-store
2934  * is needed here. */
2936  &p_self->ctx);
2937 
2938  /* Suspend the current ULT */
2939  ABTI_ythread_suspend(&p_local_xstream, p_self,
2940  ABT_SYNC_EVENT_TYPE_THREAD_JOIN, (void *)p_ythread);
2941  *pp_local = ABTI_xstream_get_local(p_local_xstream);
2942 
2943  /* Resume */
2944  /* If p_self's state is BLOCKED, the target ULT has terminated on the same
2945  * ES as p_self's ES and the control has come from the target ULT.
2946  * Otherwise, the target ULT had been migrated to a different ES, p_self
2947  * has been resumed by p_self's scheduler. In the latter case, we don't
2948  * need to change p_self's state. */
2949  if (ABTD_atomic_relaxed_load_int(&p_self->thread.state) ==
2954  LOG_DEBUG("[U%" PRIu64 ":E%d] resume after join\n",
2955  ABTI_thread_get_id(&p_self->thread),
2956  p_self->thread.p_last_xstream->rank);
2957  ABTI_tool_event_thread_join(*pp_local, p_thread, &p_self->thread);
2958  } else {
2959  /* Use a yield-based method. */
2960  thread_join_yield_thread(&p_local_xstream, p_self, &p_ythread->thread);
2961  *pp_local = ABTI_xstream_get_local(p_local_xstream);
2962  return;
2963  }
2964 }
2965 
2966 static void thread_root_func(void *arg)
2967 {
2968  /* root thread is working on a special context, so it should not rely on
2969  * functionality that needs yield. */
2970  ABTI_global *p_global = ABTI_global_get_global();
2971  ABTI_local *p_local = ABTI_local_get_local();
2972  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
2973  ABTI_ASSERT(ABTD_atomic_relaxed_load_int(&p_local_xstream->state) ==
2975 
2976  ABTI_ythread *p_root_ythread = p_local_xstream->p_root_ythread;
2977  p_local_xstream->p_thread = &p_root_ythread->thread;
2978  ABTI_pool *p_root_pool = p_local_xstream->p_root_pool;
2979 
2980  do {
2981  ABT_unit unit = ABTI_pool_pop(p_root_pool);
2982  if (unit != ABT_UNIT_NULL) {
2983  ABTI_xstream *p_xstream = p_local_xstream;
2984  ABTI_thread *p_thread =
2986  ABTI_xstream_run_thread(p_global, &p_xstream, p_thread);
2987  /* The root thread must be executed on the same execution stream. */
2988  ABTI_ASSERT(p_xstream == p_local_xstream);
2989  }
2991  &p_local_xstream->p_main_sched->p_ythread->thread.state) !=
2993  /* The main scheduler thread finishes. */
2994 
2995  /* Set the ES's state as TERMINATED */
2996  ABTD_atomic_release_store_int(&p_local_xstream->state,
2998 
2999  if (p_local_xstream->type == ABTI_XSTREAM_TYPE_PRIMARY) {
3000  /* Let us jump back to the primary thread (then finalize Argobots) */
3001  ABTD_ythread_finish_context(&p_root_ythread->ctx,
3002  &p_global->p_primary_ythread->ctx);
3003  }
3004 }
3005 
3006 static void thread_main_sched_func(void *arg)
3007 {
3009  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
3010 
3011  while (1) {
3012  /* Execute the run function of scheduler */
3013  ABTI_sched *p_sched = p_local_xstream->p_main_sched;
3014  ABTI_ASSERT(p_local_xstream->p_thread == &p_sched->p_ythread->thread);
3015 
3016  LOG_DEBUG("[S%" PRIu64 "] start\n", p_sched->id);
3017  p_sched->run(ABTI_sched_get_handle(p_sched));
3018  LOG_DEBUG("[S%" PRIu64 "] end\n", p_sched->id);
3019  /* The main scheduler's thread must be executed on the same execution
3020  * stream. */
3022 
3023  /* We free the current main scheduler and replace it if requested. */
3024  if (ABTD_atomic_relaxed_load_uint32(&p_sched->request) &
3026  ABTI_ythread *p_waiter = p_sched->p_replace_waiter;
3027  ABTI_sched *p_new_sched = p_sched->p_replace_sched;
3028  /* Set this scheduler as a main scheduler */
3029  p_new_sched->used = ABTI_SCHED_MAIN;
3030  /* Take the ULT of the current main scheduler and use it for the new
3031  * scheduler. */
3032  p_new_sched->p_ythread = p_sched->p_ythread;
3033  p_local_xstream->p_main_sched = p_new_sched;
3034  /* Now, we free the current main scheduler. p_sched->p_ythread must
3035  * be NULL to avoid freeing it in ABTI_sched_discard_and_free(). */
3036  p_sched->p_ythread = NULL;
3038  p_sched, ABT_FALSE);
3039  /* We do not need to unset ABTI_SCHED_REQ_REPLACE since that p_sched
3040  * has already been replaced. */
3041  p_sched = p_new_sched;
3042  /* Resume the waiter. */
3043  ABTI_ythread_set_ready(p_local, p_waiter);
3044  }
3045  ABTI_ASSERT(p_sched == p_local_xstream->p_main_sched);
3046  uint32_t request = ABTD_atomic_acquire_load_uint32(
3047  &p_sched->p_ythread->thread.request);
3048 
3049  /* If there is an exit or a cancel request, the ES terminates
3050  * regardless of remaining work units. */
3052  break;
3053 
3054  /* When join is requested, the ES terminates after finishing
3055  * execution of all work units. */
3056  if ((ABTD_atomic_relaxed_load_uint32(&p_sched->request) &
3058  ABTI_sched_get_effective_size(p_local, p_sched) == 0) {
3059  break;
3060  }
3061  }
3062  /* Finish this thread and goes back to the root thread. */
3063 }
3064 
3065 static inline ABT_unit_id thread_get_new_id(void)
3066 {
3068 }
ABTI_key
Definition: abti.h:413
ABTD_futex_single_init
static void ABTD_futex_single_init(ABTD_futex_single *p_futex)
Definition: abtd_futex.h:88
ABT_THREAD_STATE_TERMINATED
@ ABT_THREAD_STATE_TERMINATED
Definition: abt.h:423
ABT_thread_migrate_to_xstream
int ABT_thread_migrate_to_xstream(ABT_thread thread, ABT_xstream xstream)
Request a migration of a work unit to a specific execution stream.
Definition: thread.c:1304
ABT_SYNC_EVENT_TYPE_USER
@ ABT_SYNC_EVENT_TYPE_USER
Definition: abt.h:664
ABTI_CHECK_NULL_SCHED_PTR
#define ABTI_CHECK_NULL_SCHED_PTR(p)
Definition: abti_error.h:177
ABT_key
struct ABT_key_opaque * ABT_key
Work-unit-specific data key handle type.
Definition: abt.h:938
ABT_ERR_INV_THREAD
#define ABT_ERR_INV_THREAD
Error code: invalid work unit.
Definition: abt.h:176
ABTI_sched_get_ptr
static ABTI_sched * ABTI_sched_get_ptr(ABT_sched sched)
Definition: abti_sched.h:11
ABT_thread_get_arg
int ABT_thread_get_arg(ABT_thread thread, void **arg)
Retrieve an argument for a work-unit function of a work unit.
Definition: thread.c:2053
ABT_thread_resume
int ABT_thread_resume(ABT_thread thread)
Resume a ULT.
Definition: thread.c:1233
ABTI_ythread_free_root
void ABTI_ythread_free_root(ABTI_global *p_global, ABTI_local *p_local, ABTI_ythread *p_ythread)
Definition: thread.c:2419
ABTI_thread_print
void ABTI_thread_print(ABTI_thread *p_thread, FILE *p_os, int indent)
Definition: thread.c:2461
ABT_thread_is_primary
int ABT_thread_is_primary(ABT_thread thread, ABT_bool *is_primary)
Check if a work unit is the primary ULT.
Definition: thread.c:1823
ABTI_thread_mig_data::f_migration_cb
void(* f_migration_cb)(ABT_thread, void *)
Definition: abti.h:400
ABTD_futex_suspend
void ABTD_futex_suspend(ABTD_futex_single *p_futex)
Definition: abtd_futex.c:191
ABTI_mem_free_thread
static void ABTI_mem_free_thread(ABTI_global *p_global, ABTI_local *p_local, ABTI_thread *p_thread)
Definition: abti_mem.h:281
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1001
ABTD_atomic_release_store_ythread_context_ptr
static void ABTD_atomic_release_store_ythread_context_ptr(ABTD_ythread_context_atomic_ptr *ptr, ABTD_ythread_context *p_ctx)
Definition: abtd_context.h:49
ABTI_global::sched_stacksize
size_t sched_stacksize
Definition: abti.h:210
ABTI_XSTREAM_TYPE_PRIMARY
@ ABTI_XSTREAM_TYPE_PRIMARY
Definition: abti.h:71
ABTI_THREAD_REQ_TERMINATE
#define ABTI_THREAD_REQ_TERMINATE
Definition: abti.h:43
ABTI_SCHED_NOT_USED
@ ABTI_SCHED_NOT_USED
Definition: abti.h:76
ABTI_THREAD_TYPE_ROOT
#define ABTI_THREAD_TYPE_ROOT
Definition: abti.h:83
ABTI_SETUP_LOCAL_XSTREAM
#define ABTI_SETUP_LOCAL_XSTREAM(pp_local_xstream)
Definition: abti_error.h:73
ABTI_ktable_get
static void * ABTI_ktable_get(ABTD_atomic_ptr *pp_ktable, ABTI_key *p_key)
Definition: abti_key.h:287
ABT_THREAD_STATE_READY
@ ABT_THREAD_STATE_READY
Definition: abt.h:417
ABTD_ythread_context_init
static void ABTD_ythread_context_init(ABTD_ythread_context *p_link, ABTD_ythread_context *p_newctx)
Definition: abtd_ythread.h:47
ABTD_atomic_uint64
Definition: abtd_atomic.h:35
ABTD_atomic_acquire_load_uint32
static uint32_t ABTD_atomic_acquire_load_uint32(const ABTD_atomic_uint32 *ptr)
Definition: abtd_atomic.h:928
ABTD_ythread_exit
void ABTD_ythread_exit(ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread)
Definition: abtd_ythread.c:30
thread_main_sched_func
static void thread_main_sched_func(void *arg)
Definition: thread.c:3008
ABT_thread_attr
struct ABT_thread_attr_opaque * ABT_thread_attr
ULT attribute handle type.
Definition: abt.h:897
ABT_thread
struct ABT_thread_opaque * ABT_thread
Work unit handle type.
Definition: abt.h:890
ABTI_thread_mig_data::p_migration_pool
ABTD_atomic_ptr p_migration_pool
Definition: abti.h:403
g_thread_id
static ABTD_atomic_uint64 g_thread_id
Definition: thread.c:2554
ABT_thread_join_many
int ABT_thread_join_many(int num_threads, ABT_thread *thread_list)
Wait for a set of work units to terminate.
Definition: thread.c:585
ABTI_key_get_ptr
static ABTI_key * ABTI_key_get_ptr(ABT_key key)
Definition: abti_key.h:11
ABT_thread_create_many
int ABT_thread_create_many(int num_threads, ABT_pool *pool_list, void(**thread_func_list)(void *), void **arg_list, ABT_thread_attr attr, ABT_thread *newthread_list)
Create a set of new ULTs.
Definition: thread.c:253
ABTI_SETUP_GLOBAL
#define ABTI_SETUP_GLOBAL(pp_global)
Definition: abti_error.h:59
ABTI_ythread_context_switch_to_sibling
static ABTI_ythread * ABTI_ythread_context_switch_to_sibling(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_old, ABTI_ythread *p_new)
Definition: abti_ythread.h:326
ABTI_global::xstream_list_lock
ABTD_spinlock xstream_list_lock
Definition: abti.h:201
ABTI_thread::type
ABTI_thread_type type
Definition: abti.h:375
ABT_thread_get_stacksize
int ABT_thread_get_stacksize(ABT_thread thread, size_t *stacksize)
Get a stack size of a work unit.
Definition: thread.c:1944
ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC
#define ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC
Definition: abti.h:90
ABTI_thread_attr::migratable
ABT_bool migratable
Definition: abti.h:393
ABTI_global_get_global
static ABTI_global * ABTI_global_get_global(void)
Definition: abti_global.h:9
ABTI_ythread_exit
ABTU_noreturn void ABTI_ythread_exit(ABTI_xstream *p_local_xstream, ABTI_ythread *p_ythread)
Definition: thread.c:2425
ABTI_tool_event_thread_create
#define ABTI_tool_event_thread_create(p_local, p_thread, p_caller, p_pool)
Definition: abti_tool.h:258
ABT_thread_set_migratable
int ABT_thread_set_migratable(ABT_thread thread, ABT_bool migratable)
Set the migratability in a work unit.
Definition: thread.c:1724
ABT_ERR_POOL
#define ABT_ERR_POOL
Error code: error related to a pool.
Definition: abt.h:282
ABTI_THREAD_INIT_ID
#define ABTI_THREAD_INIT_ID
Definition: abti.h:53
ABTI_CHECK_ERROR
#define ABTI_CHECK_ERROR(abt_errno)
Definition: abti_error.h:120
ABTI_ythread::stacksize
size_t stacksize
Definition: abti.h:410
ABTI_ythread_free_primary
void ABTI_ythread_free_primary(ABTI_global *p_global, ABTI_local *p_local, ABTI_ythread *p_ythread)
Definition: thread.c:2410
ABTI_thread_attr_get_handle
static ABT_thread_attr ABTI_thread_attr_get_handle(ABTI_thread_attr *p_attr)
Definition: abti_thread_attr.h:27
ABTI_sched::num_pools
size_t num_pools
Definition: abti.h:299
ABTI_sched::automatic
ABT_bool automatic
Definition: abti.h:291
ABTI_xstream::rank
int rank
Definition: abti.h:269
ABT_thread_get_id
int ABT_thread_get_id(ABT_thread thread, ABT_unit_id *thread_id)
Get ID of a work unit.
Definition: thread.c:1983
ABTI_thread::p_arg
void * p_arg
Definition: abti.h:380
ABTI_sched_get_handle
static ABT_sched ABTI_sched_get_handle(ABTI_sched *p_sched)
Definition: abti_sched.h:26
ABTU_noreturn
#define ABTU_noreturn
Definition: abtu.h:118
ABTI_thread::unit
ABT_unit unit
Definition: abti.h:376
ABTI_xstream::type
ABTI_xstream_type type
Definition: abti.h:270
ABTI_THREAD_TYPE_YIELDABLE
#define ABTI_THREAD_TYPE_YIELDABLE
Definition: abti.h:86
ABTI_thread::request
ABTD_atomic_uint32 request
Definition: abti.h:382
ABTI_thread_get_ythread
static ABTI_ythread * ABTI_thread_get_ythread(ABTI_thread *p_thread)
Definition: abti_thread.h:52
ABTI_ythread_create_sched
ABTU_ret_err int ABTI_ythread_create_sched(ABTI_global *p_global, ABTI_local *p_local, ABTI_pool *p_pool, ABTI_sched *p_sched)
Definition: thread.c:2376
ABTI_unit_get_thread_from_builtin_unit
static ABTI_thread * ABTI_unit_get_thread_from_builtin_unit(ABT_unit unit)
Definition: abti_unit.h:37
ABTI_thread_mig_data
Definition: abti.h:399
ABTI_pool_push
static void ABTI_pool_push(ABTI_pool *p_pool, ABT_unit unit)
Definition: abti_pool.h:53
ABT_THREAD_NULL
#define ABT_THREAD_NULL
Definition: abt.h:1062
ABTI_thread_get_handle
static ABT_thread ABTI_thread_get_handle(ABTI_thread *p_thread)
Definition: abti_thread.h:24
ABTI_thread_set_associated_pool
static ABTU_ret_err int ABTI_thread_set_associated_pool(ABTI_global *p_global, ABTI_thread *p_thread, ABTI_pool *p_pool)
Definition: abti_unit.h:147
ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC_STACK
#define ABTI_THREAD_TYPE_MEM_MEMPOOL_DESC_STACK
Definition: abti.h:92
ABTI_thread_reset_id
void ABTI_thread_reset_id(void)
Definition: thread.c:2556
ABTI_thread
Definition: abti.h:371
ABTI_IS_ERROR_CHECK_ENABLED
#define ABTI_IS_ERROR_CHECK_ENABLED
Definition: abti.h:20
ABTI_CHECK_YIELDABLE
#define ABTI_CHECK_YIELDABLE(p_thread, pp_ythread, abt_errno)
Definition: abti_error.h:139
ABTD_ythread_context::p_link
ABTD_ythread_context_atomic_ptr p_link
Definition: abtd_fcontext.h:36
ABTI_thread_attr_get_ptr
static ABTI_thread_attr * ABTI_thread_attr_get_ptr(ABT_thread_attr attr)
Definition: abti_thread_attr.h:11
ABTI_KEY_STATIC_INITIALIZER
#define ABTI_KEY_STATIC_INITIALIZER(f_destructor, id)
Definition: abti_key.h:42
ABT_thread_get_state
int ABT_thread_get_state(ABT_thread thread, ABT_thread_state *state)
Get a state of a work unit.
Definition: thread.c:858
ABTI_xstream
Definition: abti.h:264
ABTI_tool_event_thread_revive
#define ABTI_tool_event_thread_revive(p_local, p_thread, p_caller, p_pool)
Definition: abti_tool.h:280
ABTI_THREAD_TYPE_EXT
#define ABTI_THREAD_TYPE_EXT
Definition: abti.h:81
ABT_pool
struct ABT_pool_opaque * ABT_pool
Pool handle type.
Definition: abt.h:841
ABT_ERR_THREAD
#define ABT_ERR_THREAD
Error code: error related to a work unit.
Definition: abt.h:292
ABTI_sched::p_ythread
ABTI_ythread * p_ythread
Definition: abti.h:300
ABTI_xstream::p_next
ABTI_xstream * p_next
Definition: abti.h:267
ABT_thread_state
ABT_thread_state
State of a work unit.
Definition: abt.h:415
ABT_thread_free
int ABT_thread_free(ABT_thread *thread)
Free a work unit.
Definition: thread.c:420
ABTI_thread_attr
Definition: abti.h:388
g_thread_sched_key
static ABTI_key g_thread_sched_key
Definition: thread.c:27
ABTI_sched::used
ABTI_sched_used used
Definition: abti.h:290
ABT_sched
struct ABT_sched_opaque * ABT_sched
Scheduler handle type.
Definition: abt.h:808
ABTI_ktable_set
static ABTU_ret_err int ABTI_ktable_set(ABTI_global *p_global, ABTI_local *p_local, ABTD_atomic_ptr *pp_ktable, ABTI_key *p_key, void *value)
Definition: abti_key.h:225
ABTI_pool
Definition: abti.h:327
ABTI_THREAD_TYPE_PRIMARY
#define ABTI_THREAD_TYPE_PRIMARY
Definition: abti.h:84
ABT_thread_migrate_to_sched
int ABT_thread_migrate_to_sched(ABT_thread thread, ABT_sched sched)
Request a migration of a work unit to a specific scheduler.
Definition: thread.c:1390
ABT_thread_exit
int ABT_thread_exit(void)
Terminate a calling ULT.
Definition: thread.c:627
ABTI_xstream_get_handle
static ABT_xstream ABTI_xstream_get_handle(ABTI_xstream *p_xstream)
Definition: abti_stream.h:26
ABTD_atomic_release_store_uint64
static void ABTD_atomic_release_store_uint64(ABTD_atomic_uint64 *ptr, uint64_t val)
Definition: abtd_atomic.h:1124
ABT_THREAD_STATE_BLOCKED
@ ABT_THREAD_STATE_BLOCKED
Definition: abt.h:421
abti.h
ABTI_CHECK_NULL_THREAD_PTR
#define ABTI_CHECK_NULL_THREAD_PTR(p)
Definition: abti_error.h:195
ABTI_THREAD_REQ_MIGRATE
#define ABTI_THREAD_REQ_MIGRATE
Definition: abti.h:45
ABT_thread_set_specific
int ABT_thread_set_specific(ABT_thread thread, ABT_key key, void *value)
Set a value with a work-unit-specific data key in a work unit.
Definition: thread.c:2119
thread_free
static void thread_free(ABTI_global *p_global, ABTI_local *p_local, ABTI_thread *p_thread, ABT_bool free_unit)
Definition: thread.c:2768
ABTI_SCHED_REQ_REPLACE
#define ABTI_SCHED_REQ_REPLACE
Definition: abti.h:40
ABTD_atomic_relaxed_store_uint32
static void ABTD_atomic_relaxed_store_uint32(ABTD_atomic_uint32 *ptr, uint32_t val)
Definition: abtd_atomic.h:1025
ABTI_sched_discard_and_free
static void ABTI_sched_discard_and_free(ABTI_global *p_global, ABTI_local *p_local, ABTI_sched *p_sched, ABT_bool force_free)
Definition: abti_sched.h:43
ABTD_atomic_relaxed_load_int
static int ABTD_atomic_relaxed_load_int(const ABTD_atomic_int *ptr)
Definition: abtd_atomic.h:763
ABTI_KEY_ID_STACKABLE_SCHED
#define ABTI_KEY_ID_STACKABLE_SCHED
Definition: abti_key.h:47
ABT_unit_id
uint64_t ABT_unit_id
Work unit ID type.
Definition: abt.h:879
ABT_xstream
struct ABT_xstream_opaque * ABT_xstream
Execution stream handle type.
Definition: abt.h:789
ABTI_thread_get_ythread_or_null
static ABTI_ythread * ABTI_thread_get_ythread_or_null(ABTI_thread *p_thread)
Definition: abti_thread.h:59
ABTI_thread::state
ABTD_atomic_int state
Definition: abti.h:381
ABTI_pool::u_is_in_pool
ABT_unit_is_in_pool_fn u_is_in_pool
Definition: abti.h:338
ABTD_spinlock_acquire
static void ABTD_spinlock_acquire(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:28
ABT_thread_yield
int ABT_thread_yield(void)
Yield the calling ULT to its parent ULT.
Definition: thread.c:1181
ABT_thread_get_last_pool
int ABT_thread_get_last_pool(ABT_thread thread, ABT_pool *pool)
Get the last pool of a work unit.
Definition: thread.c:898
ABTI_HANDLE_ERROR
#define ABTI_HANDLE_ERROR(n)
Definition: abti_error.h:114
thread_key_destructor_migration
static void thread_key_destructor_migration(void *p_value)
Definition: thread.c:2812
ABTD_atomic_pause
static void ABTD_atomic_pause(void)
Definition: abtd_atomic.h:1257
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:262
LOG_DEBUG
#define LOG_DEBUG(fmt,...)
Definition: abti_log.h:26
ABTI_THREAD_TYPE_MIGRATABLE
#define ABTI_THREAD_TYPE_MIGRATABLE
Definition: abti.h:88
ABTI_pool_remove
static ABTU_ret_err int ABTI_pool_remove(ABTI_pool *p_pool, ABT_unit unit)
Definition: abti_pool.h:68
ABTI_thread_join
void ABTI_thread_join(ABTI_local **pp_local, ABTI_thread *p_thread)
Definition: thread.c:2395
ABTD_atomic_relaxed_store_int
static void ABTD_atomic_relaxed_store_int(ABTD_atomic_int *ptr, int val)
Definition: abtd_atomic.h:996
ABT_thread_set_associated_pool
int ABT_thread_set_associated_pool(ABT_thread thread, ABT_pool pool)
Set an associated pool for the target work unit.
Definition: thread.c:1009
ABT_thread_join
int ABT_thread_join(ABT_thread thread)
Wait for a work unit to terminate.
Definition: thread.c:538
ABTD_ATOMIC_UINT64_STATIC_INITIALIZER
#define ABTD_ATOMIC_UINT64_STATIC_INITIALIZER(val)
Definition: abtd_atomic.h:67
ABTD_atomic_relaxed_load_uint32
static uint32_t ABTD_atomic_relaxed_load_uint32(const ABTD_atomic_uint32 *ptr)
Definition: abtd_atomic.h:804
ABTI_xstream::p_main_sched
ABTI_sched * p_main_sched
Definition: abti.h:272
ABTI_pool::p_remove
ABT_pool_remove_fn p_remove
Definition: abti.h:349
ABTI_thread_mig_data::p_migration_cb_arg
void * p_migration_cb_arg
Definition: abti.h:401
ABT_ERR_INV_THREAD_ATTR
#define ABT_ERR_INV_THREAD_ATTR
Error code: invalid ULT attribute.
Definition: abt.h:181
ABTI_thread_attr_init
static void ABTI_thread_attr_init(ABTI_thread_attr *p_attr, void *p_stack, size_t stacksize, ABTI_thread_type thread_type, ABT_bool migratable)
Definition: abti_thread_attr.h:42
ABTI_sched_get_migration_pool
ABTU_ret_err int ABTI_sched_get_migration_pool(ABTI_sched *, ABTI_pool *, ABTI_pool **)
Definition: sched.c:895
ABTI_thread_attr::p_cb_arg
void * p_cb_arg
Definition: abti.h:395
ABTI_thread_free
void ABTI_thread_free(ABTI_global *p_global, ABTI_local *p_local, ABTI_thread *p_thread)
Definition: thread.c:2400
thread_root_func
static void thread_root_func(void *arg)
Definition: thread.c:2968
ABT_unit
struct ABT_unit_opaque * ABT_unit
Work unit handle type for scheduling.
Definition: abt.h:869
thread_migrate_to_pool
static ABTU_ret_err int thread_migrate_to_pool(ABTI_global *p_global, ABTI_local *p_local, ABTI_thread *p_thread, ABTI_pool *p_pool)
Definition: thread.c:2745
thread_join
static void thread_join(ABTI_local **pp_local, ABTI_thread *p_thread)
Definition: thread.c:2871
ABTI_ythread::ctx
ABTD_ythread_context ctx
Definition: abti.h:408
ABTD_ythread_context_invalidate
static void ABTD_ythread_context_invalidate(ABTD_ythread_context *p_newctx)
Definition: abtd_ythread.h:34
ABT_thread_is_unnamed
int ABT_thread_is_unnamed(ABT_thread thread, ABT_bool *is_unnamed)
Check if a work unit is unnamed.
Definition: thread.c:1861
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABTD_futex_single
Definition: abtd_futex.h:84
ABTI_tool_event_ythread_yield
#define ABTI_tool_event_ythread_yield(p_local_xstream, p_ythread, p_parent, sync_event_type, p_sync)
Definition: abti_tool.h:312
ABTU_calloc
static ABTU_ret_err int ABTU_calloc(size_t num, size_t size, void **p_ptr)
Definition: abtu.h:272
ABT_ERR_MIGRATION_TARGET
#define ABT_ERR_MIGRATION_TARGET
Error code: error related to a migration target.
Definition: abt.h:360
ABTI_sched::pools
ABT_pool * pools
Definition: abti.h:298
ABTI_sched::p_replace_sched
ABTI_sched * p_replace_sched
Definition: abti.h:294
ABTI_mem_alloc_ythread_mempool_desc
static ABTU_ret_err int ABTI_mem_alloc_ythread_mempool_desc(ABTI_local *p_local, ABTI_thread_attr *p_attr, ABTI_ythread **pp_ythread)
Definition: abti_mem.h:256
ABT_THREAD_ATTR_NULL
#define ABT_THREAD_ATTR_NULL
Definition: abt.h:1063
ABTI_tool_event_thread_run
#define ABTI_tool_event_thread_run(p_local_xstream, p_thread, p_prev, p_parent)
Definition: abti_tool.h:288
ABTI_local_get_local
static ABTI_local * ABTI_local_get_local(void)
Definition: abti_local.h:41
ABTI_xstream_get_main_pool
static ABTI_pool * ABTI_xstream_get_main_pool(ABTI_xstream *p_xstream)
Definition: abti_stream.h:42
ABTI_xstream::state
ABTD_atomic_int state
Definition: abti.h:271
ABTI_CHECK_NULL_YTHREAD_PTR
#define ABTI_CHECK_NULL_YTHREAD_PTR(p)
Definition: abti_error.h:204
ABTI_global::num_xstreams
int num_xstreams
Definition: abti.h:198
ABTI_thread_revive
ABTU_ret_err int ABTI_thread_revive(ABTI_global *p_global, ABTI_local *p_local, ABTI_pool *p_pool, void(*thread_func)(void *), void *arg, ABTI_thread *p_thread)
Definition: thread.c:2257
ABT_thread_create_on_xstream
int ABT_thread_create_on_xstream(ABT_xstream xstream, void(*thread_func)(void *), void *arg, ABT_thread_attr attr, ABT_thread *newthread)
Create a new ULT associated with an execution stream.
Definition: thread.c:170
thread_key_destructor_stackable_sched
static void thread_key_destructor_stackable_sched(void *p_value)
Definition: thread.c:2794
ABTI_ktable_set_unsafe
static ABTU_ret_err int ABTI_ktable_set_unsafe(ABTI_global *p_global, ABTI_local *p_local, ABTI_ktable **pp_ktable, ABTI_key *p_key, void *value)
Definition: abti_key.h:271
ABTI_global::p_primary_ythread
ABTI_ythread * p_primary_ythread
Definition: abti.h:213
ABT_thread_set_arg
int ABT_thread_set_arg(ABT_thread thread, void *arg)
Set an argument for a work-unit function of a work unit.
Definition: thread.c:2018
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABTI_tool_event_thread_join
#define ABTI_tool_event_thread_join(p_local, p_thread, p_caller)
Definition: abti_tool.h:266
ABTI_xstream::p_root_pool
ABTI_pool * p_root_pool
Definition: abti.h:278
ABTI_local_get_local_uninlined
static ABTI_local * ABTI_local_get_local_uninlined(void)
Definition: abti_local.h:51
thread_get_new_id
static ABT_unit_id thread_get_new_id(void)
Definition: thread.c:3067
ABTU_ret_err
#define ABTU_ret_err
Definition: abtu.h:146
ABTI_thread_attr::stacksize
size_t stacksize
Definition: abti.h:390
ABT_thread_get_last_xstream
int ABT_thread_get_last_xstream(ABT_thread thread, ABT_xstream *xstream)
Get an execution stream associated with a work unit.
Definition: thread.c:817
ABTI_ythread_get_handle
static ABT_thread ABTI_ythread_get_handle(ABTI_ythread *p_thread)
ABTI_SETUP_LOCAL_YTHREAD
#define ABTI_SETUP_LOCAL_YTHREAD(pp_local_xstream, pp_ythread)
Definition: abti_error.h:88
ABTI_global::p_xstream_head
ABTI_xstream * p_xstream_head
Definition: abti.h:199
ABTD_atomic_acquire_load_int
static int ABTD_atomic_acquire_load_int(const ABTD_atomic_int *ptr)
Definition: abtd_atomic.h:878
ABTI_ythread_set_blocked
void ABTI_ythread_set_blocked(ABTI_ythread *p_ythread)
Definition: ythread.c:23
ABTI_THREAD_REQ_CANCEL
#define ABTI_THREAD_REQ_CANCEL
Definition: abti.h:44
ABT_thread_migrate
int ABT_thread_migrate(ABT_thread thread)
Request a migration of a work unit to any available execution stream.
Definition: thread.c:1550
ABTI_local_get_xstream_or_null
static ABTI_xstream * ABTI_local_get_xstream_or_null(ABTI_local *p_local)
Definition: abti_local.h:77
ABT_thread_self_id
int ABT_thread_self_id(ABT_unit_id *id)
Get ID of the calling work unit.
Definition: thread.c:774
ABTI_SCHED_MAIN
@ ABTI_SCHED_MAIN
Definition: abti.h:77
ABTI_IS_EXT_THREAD_ENABLED
#define ABTI_IS_EXT_THREAD_ENABLED
Definition: abti.h:28
ABTI_thread_attr_dup
ABTU_ret_err int ABTI_thread_attr_dup(const ABTI_thread_attr *p_attr, ABTI_thread_attr **pp_dup_attr) ABTU_ret_err
Definition: thread_attr.c:413
ABT_thread_self
int ABT_thread_self(ABT_thread *thread)
Get the calling work unit.
Definition: thread.c:725
ABTI_sched::run
ABT_sched_run_fn run
Definition: abti.h:305
ABTI_xstream_get_local
static ABTI_local * ABTI_xstream_get_local(ABTI_xstream *p_xstream)
Definition: abti_stream.h:68
ABTI_thread_type
uint32_t ABTI_thread_type
Definition: abti.h:126
ABT_thread_free_many
int ABT_thread_free_many(int num_threads, ABT_thread *thread_list)
Free a set of work units.
Definition: thread.c:480
ABTI_ythread_create_main_sched
ABTU_ret_err int ABTI_ythread_create_main_sched(ABTI_global *p_global, ABTI_local *p_local, ABTI_xstream *p_xstream, ABTI_sched *p_sched)
Definition: thread.c:2355
ABTU_unlikely
#define ABTU_unlikely(cond)
Definition: abtu.h:112
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:748
ABTI_pool_get_ptr
static ABTI_pool * ABTI_pool_get_ptr(ABT_pool pool)
Definition: abti_pool.h:11
ABTI_sched::request
ABTD_atomic_uint32 request
Definition: abti.h:297
ABTI_pool_pop
static ABT_unit ABTI_pool_pop(ABTI_pool *p_pool)
Definition: abti_pool.h:96
ABT_XSTREAM_STATE_RUNNING
@ ABT_XSTREAM_STATE_RUNNING
Definition: abt.h:406
ABTI_ktable
Definition: abti.h:426
ABT_thread_set_callback
int ABT_thread_set_callback(ABT_thread thread, void(*cb_func)(ABT_thread thread, void *cb_arg), void *cb_arg)
Register a callback function in a work unit.
Definition: thread.c:1662
ABTI_sched
Definition: abti.h:289
ABT_ERR_MIGRATION_NA
#define ABT_ERR_MIGRATION_NA
Error code: migration is not supported.
Definition: abt.h:369
ABTI_KTABLE_LOCKED
#define ABTI_KTABLE_LOCKED
Definition: abti_key.h:59
ABTI_tool_event_thread_free
#define ABTI_tool_event_thread_free(p_local, p_thread, p_caller)
Definition: abti_tool.h:273
ABT_SYNC_EVENT_TYPE_THREAD_JOIN
@ ABT_SYNC_EVENT_TYPE_THREAD_JOIN
Definition: abt.h:670
ABT_thread_get_thread_func
int ABT_thread_get_thread_func(ABT_thread thread, void(**thread_func)(void *))
Retrieve a work-unit function of a work unit.
Definition: thread.c:2084
ABTI_xstream::p_root_ythread
ABTI_ythread * p_root_ythread
Definition: abti.h:277
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:750
ABTI_ythread
Definition: abti.h:406
ABTI_ythread_set_ready
void ABTI_ythread_set_ready(ABTI_local *p_local, ABTI_ythread *p_ythread)
Definition: ythread.c:65
ABTI_ythread_create_primary
ABTU_ret_err int ABTI_ythread_create_primary(ABTI_global *p_global, ABTI_local *p_local, ABTI_xstream *p_xstream, ABTI_ythread **p_ythread)
Definition: thread.c:2300
ABT_thread_is_migratable
int ABT_thread_is_migratable(ABT_thread thread, ABT_bool *is_migratable)
Get the migratability of a work unit.
Definition: thread.c:1781
ABTI_THREAD_TYPE_MAIN_SCHED
#define ABTI_THREAD_TYPE_MAIN_SCHED
Definition: abti.h:85
ABTI_ythread_suspend
void ABTI_ythread_suspend(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_ythread, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: ythread.c:45
ABTD_ythread_context_create
static void ABTD_ythread_context_create(ABTD_ythread_context *p_link, size_t stacksize, void *p_stack, ABTD_ythread_context *p_newctx)
Definition: abtd_ythread.h:20
ABTI_CHECK_NULL_POOL_PTR
#define ABTI_CHECK_NULL_POOL_PTR(p)
Definition: abti_error.h:168
ABTD_atomic_fetch_add_uint64
static uint64_t ABTD_atomic_fetch_add_uint64(ABTD_atomic_uint64 *ptr, uint64_t v)
Definition: abtd_atomic.h:477
ABTI_CHECK_NULL_XSTREAM_PTR
#define ABTI_CHECK_NULL_XSTREAM_PTR(p)
Definition: abti_error.h:159
ABT_thread_create
int ABT_thread_create(ABT_pool pool, void(*thread_func)(void *), void *arg, ABT_thread_attr attr, ABT_thread *newthread)
Create a new ULT.
Definition: thread.c:89
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:217
ABTI_thread::p_parent
ABTI_thread * p_parent
Definition: abti.h:378
ABT_thread_get_unit
int ABT_thread_get_unit(ABT_thread thread, ABT_unit *unit)
Get a unit handle of the target work unit.
Definition: thread.c:968
ABTD_atomic_fetch_or_uint32
static uint32_t ABTD_atomic_fetch_or_uint32(ABTD_atomic_uint32 *ptr, uint32_t v)
Definition: abtd_atomic.h:631
ABTD_spinlock_release
static void ABTD_spinlock_release(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:42
ABTI_xstream_run_thread
void ABTI_xstream_run_thread(ABTI_global *p_global, ABTI_xstream **pp_local_xstream, ABTI_thread *p_thread)
Definition: stream.c:1554
ABTI_THREAD_TYPE_NAMED
#define ABTI_THREAD_TYPE_NAMED
Definition: abti.h:87
ABTI_thread_get_mig_data
ABTU_ret_err int ABTI_thread_get_mig_data(ABTI_global *p_global, ABTI_local *p_local, ABTI_thread *p_thread, ABTI_thread_mig_data **pp_mig_data)
Definition: thread.c:2436
ABTI_xstream_get_ptr
static ABTI_xstream * ABTI_xstream_get_ptr(ABT_xstream xstream)
Definition: abti_stream.h:11
ABTI_thread::p_last_xstream
ABTI_xstream * p_last_xstream
Definition: abti.h:377
ABTI_thread_attr::p_stack
void * p_stack
Definition: abti.h:389
ABTI_ythread::p_stack
void * p_stack
Definition: abti.h:409
ABTI_sched_free
void ABTI_sched_free(ABTI_global *p_global, ABTI_local *p_local, ABTI_sched *p_sched, ABT_bool force_free)
Definition: sched.c:834
ABTI_thread::p_keytable
ABTD_atomic_ptr p_keytable
Definition: abti.h:384
thread_join_futexwait
static void thread_join_futexwait(ABTI_thread *p_thread)
Definition: thread.c:2828
ABTI_ythread::thread
ABTI_thread thread
Definition: abti.h:407
ABTI_pool_inc_num_blocked
static void ABTI_pool_inc_num_blocked(ABTI_pool *p_pool)
Definition: abti_pool.h:42
ABTI_thread_attr::thread_type
ABTI_thread_type thread_type
Definition: abti.h:391
ABTI_local
struct ABTI_local ABTI_local
Definition: abti.h:110
thread_join_busywait
static void thread_join_busywait(ABTI_thread *p_thread)
Definition: thread.c:2818
ABTI_thread_attr::f_cb
void(* f_cb)(ABT_thread, void *)
Definition: abti.h:394
ABTI_thread_unset_associated_pool
static void ABTI_thread_unset_associated_pool(ABTI_global *p_global, ABTI_thread *p_thread)
Definition: abti_unit.h:200
ABTI_ythread_yield
static void ABTI_ythread_yield(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_ythread, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_ythread.h:372
ABTD_ythread_finish_context
static ABTU_noreturn void ABTD_ythread_finish_context(ABTD_ythread_context *p_old, ABTD_ythread_context *p_new)
Definition: abtd_ythread.h:80
ABTD_atomic_acquire_load_ptr
static void * ABTD_atomic_acquire_load_ptr(const ABTD_atomic_ptr *ptr)
Definition: abtd_atomic.h:979
ABTI_KEY_ID_MIGRATION
#define ABTI_KEY_ID_MIGRATION
Definition: abti_key.h:48
ABT_thread_yield_to
int ABT_thread_yield_to(ABT_thread thread)
Yield the calling ULT to another ULT.
Definition: thread.c:1067
g_thread_mig_data_key
static ABTI_key g_thread_mig_data_key
Definition: thread.c:31
ABT_thread_get_last_pool_id
int ABT_thread_get_last_pool_id(ABT_thread thread, int *id)
Get the last pool's ID of a work unit.
Definition: thread.c:938
ABTI_pool::id
uint64_t id
Definition: abti.h:335
ABTI_CHECK_TRUE
#define ABTI_CHECK_TRUE(cond, abt_errno)
Definition: abti_error.h:130
ABT_thread_revive
int ABT_thread_revive(ABT_pool pool, void(*thread_func)(void *), void *arg, ABT_thread *thread)
Revive a terminated work unit.
Definition: thread.c:358
ABTI_CHECK_NULL_KEY_PTR
#define ABTI_CHECK_NULL_KEY_PTR(p)
Definition: abti_error.h:231
ABTI_mem_alloc_ythread_malloc_desc_stack
static ABTU_ret_err int ABTI_mem_alloc_ythread_malloc_desc_stack(ABTI_thread_attr *p_attr, ABTI_ythread **pp_ythread)
Definition: abti_mem.h:236
ABTI_global
Definition: abti.h:196
ABT_thread_equal
int ABT_thread_equal(ABT_thread thread1, ABT_thread thread2, ABT_bool *result)
Compare two work unit handles for equality.
Definition: thread.c:1908
ABT_ERR_FEATURE_NA
#define ABT_ERR_FEATURE_NA
Error code: unsupported feature.
Definition: abt.h:381
ABTI_thread::f_thread
void(* f_thread)(void *)
Definition: abti.h:379
ABT_THREAD_STATE_RUNNING
@ ABT_THREAD_STATE_RUNNING
Definition: abt.h:419
ythread_create
static ABTU_ret_err int ythread_create(ABTI_global *p_global, ABTI_local *p_local, ABTI_pool *p_pool, void(*thread_func)(void *), void *arg, ABTI_thread_attr *p_attr, ABTI_thread_type thread_type, ABTI_sched *p_sched, ABT_bool push_pool, ABTI_ythread **pp_newthread)
Definition: thread.c:2577
thread_join_yield_thread
static void thread_join_yield_thread(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_self, ABTI_thread *p_thread)
Definition: thread.c:2858
ABTD_atomic_relaxed_store_ptr
static void ABTD_atomic_relaxed_store_ptr(ABTD_atomic_ptr *ptr, void *val)
Definition: abtd_atomic.h:1055
ABTI_ktable_free
void ABTI_ktable_free(ABTI_global *p_global, ABTI_local *p_local, ABTI_ktable *p_ktable)
Definition: key.c:232
ABT_thread_get_specific
int ABT_thread_get_specific(ABT_thread thread, ABT_key key, void **value)
Get a value associated with a work-unit-specific data key in a work unit.
Definition: thread.c:2168
ABTI_thread::p_pool
ABTI_pool * p_pool
Definition: abti.h:383
ABT_UNIT_NULL
#define ABT_UNIT_NULL
Definition: abt.h:1061
ABT_thread_migrate_to_pool
int ABT_thread_migrate_to_pool(ABT_thread thread, ABT_pool pool)
Request a migration of a work unit to a specific pool.
Definition: thread.c:1473
ABTD_atomic_release_store_uint32
static void ABTD_atomic_release_store_uint32(ABTD_atomic_uint32 *ptr, uint32_t val)
Definition: abtd_atomic.h:1100
ABTI_local_get_xstream
static ABTI_xstream * ABTI_local_get_xstream(ABTI_local *p_local)
Definition: abti_local.h:86
ABTU_unreachable
static ABTU_noreturn void ABTU_unreachable(void)
Definition: abtu.h:126
ABTI_thread_init_pool
static ABTU_ret_err int ABTI_thread_init_pool(ABTI_global *p_global, ABTI_thread *p_thread, ABTI_pool *p_pool)
Definition: abti_unit.h:122
ABTI_sched::p_replace_waiter
ABTI_ythread * p_replace_waiter
Definition: abti.h:296
ABTD_atomic_release_store_int
static void ABTD_atomic_release_store_int(ABTD_atomic_int *ptr, int val)
Definition: abtd_atomic.h:1065
ABTI_thread_get_id
ABT_unit_id ABTI_thread_get_id(ABTI_thread *p_thread)
Definition: thread.c:2561
ABT_thread_cancel
int ABT_thread_cancel(ABT_thread thread)
Send a cancellation request to a work unit.
Definition: thread.c:674
ABTI_thread::id
ABT_unit_id id
Definition: abti.h:385
ABTI_SCHED_REQ_FINISH
#define ABTI_SCHED_REQ_FINISH
Definition: abti.h:38
ABTI_thread_get_ptr
static ABTI_thread * ABTI_thread_get_ptr(ABT_thread thread)
Definition: abti_thread.h:9
ABTI_pool_get_handle
static ABT_pool ABTI_pool_get_handle(ABTI_pool *p_pool)
Definition: abti_pool.h:26
ABTI_ythread_create_root
ABTU_ret_err int ABTI_ythread_create_root(ABTI_global *p_global, ABTI_local *p_local, ABTI_xstream *p_xstream, ABTI_ythread **pp_root_ythread)
Definition: thread.c:2328
ABT_XSTREAM_STATE_TERMINATED
@ ABT_XSTREAM_STATE_TERMINATED
Definition: abt.h:408
ABTI_THREAD_TYPE_MEM_MALLOC_DESC_STACK
#define ABTI_THREAD_TYPE_MEM_MALLOC_DESC_STACK
Definition: abti.h:93
ABTI_sched_get_effective_size
size_t ABTI_sched_get_effective_size(ABTI_local *p_local, ABTI_sched *p_sched)
Definition: sched.c:929
ABTI_pool_dec_num_blocked
static void ABTI_pool_dec_num_blocked(ABTI_pool *p_pool)
Definition: abti_pool.h:48
ABTI_THREAD_TYPE_MEM_MALLOC_DESC
#define ABTI_THREAD_TYPE_MEM_MALLOC_DESC
Definition: abti.h:91
ABTI_thread_set_request
static void ABTI_thread_set_request(ABTI_thread *p_thread, uint32_t req)
Definition: abti_thread.h:68
ABT_thread_get_attr
int ABT_thread_get_attr(ABT_thread thread, ABT_thread_attr *attr)
Get attributes of a work unit.
Definition: thread.c:2213
ABTI_mem_alloc_ythread_default
static ABTU_ret_err int ABTI_mem_alloc_ythread_default(ABTI_global *p_global, ABTI_local *p_local, ABTI_ythread **pp_ythread)
Definition: abti_mem.h:168
ABTI_THREAD_REQ_JOIN
#define ABTI_THREAD_REQ_JOIN
Definition: abti.h:42