ARGOBOTS
sched.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 #ifdef ABT_CONFIG_USE_DEBUG_LOG
9 static inline uint64_t ABTI_sched_get_new_id(void);
10 #endif
11 
36 int ABT_sched_create(ABT_sched_def *def, int num_pools, ABT_pool *pools,
37  ABT_sched_config config, ABT_sched *newsched)
38 {
39  int abt_errno = ABT_SUCCESS;
40  ABTI_sched *p_sched;
41 
42  ABTI_CHECK_TRUE(newsched != NULL, ABT_ERR_SCHED);
43  /* TODO: the default value of automatic is different from
44  * ABT_sched_create_basic(). Make it consistent. */
45  const ABT_bool def_automatic = ABT_FALSE;
46  abt_errno = ABTI_sched_create(def, num_pools, pools, config, def_automatic,
47  &p_sched);
48  ABTI_CHECK_ERROR(abt_errno);
49 
50  /* Return value */
51  *newsched = ABTI_sched_get_handle(p_sched);
52 
53 fn_exit:
54  return abt_errno;
55 
56 fn_fail:
57  *newsched = ABT_SCHED_NULL;
58  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
59  goto fn_exit;
60 }
61 
93 int ABT_sched_create_basic(ABT_sched_predef predef, int num_pools,
94  ABT_pool *pools, ABT_sched_config config,
95  ABT_sched *newsched)
96 {
97  int abt_errno = ABT_SUCCESS;
98  ABTI_sched *p_newsched;
99  abt_errno =
100  ABTI_sched_create_basic(predef, num_pools, pools, config, &p_newsched);
101  ABTI_CHECK_ERROR(abt_errno);
102  *newsched = ABTI_sched_get_handle(p_newsched);
103 
104 fn_exit:
105  return abt_errno;
106 
107 fn_fail:
108  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
109  *newsched = ABT_SCHED_NULL;
110  goto fn_exit;
111 }
112 
128 {
129  int abt_errno = ABT_SUCCESS;
130  ABTI_local *p_local = ABTI_local_get_local();
131  ABTI_sched *p_sched = ABTI_sched_get_ptr(*sched);
132  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
133 
134  /* Free the scheduler */
135  abt_errno = ABTI_sched_free(p_local, p_sched);
136  ABTI_CHECK_ERROR(abt_errno);
137 
138  /* Return value */
139  *sched = ABT_SCHED_NULL;
140 
141 fn_exit:
142  return abt_errno;
143 
144 fn_fail:
145  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
146  goto fn_exit;
147 }
148 
162 int ABT_sched_get_num_pools(ABT_sched sched, int *num_pools)
163 {
164  int abt_errno = ABT_SUCCESS;
165 
166  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
167  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
168 
169  *num_pools = p_sched->num_pools;
170 
171 fn_exit:
172  return abt_errno;
173 
174 fn_fail:
175  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
176  goto fn_exit;
177 }
178 
190 int ABT_sched_get_pools(ABT_sched sched, int max_pools, int idx,
191  ABT_pool *pools)
192 {
193  int abt_errno = ABT_SUCCESS;
194 
195  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
196  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
197 
198  ABTI_CHECK_TRUE(idx + max_pools <= p_sched->num_pools, ABT_ERR_SCHED);
199 
200  int p;
201  for (p = idx; p < idx + max_pools; p++) {
202  pools[p - idx] = p_sched->pools[p];
203  }
204 
205 fn_exit:
206  return abt_errno;
207 
208 fn_fail:
209  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
210  goto fn_exit;
211 }
212 
224 {
225  int abt_errno = ABT_SUCCESS;
226 
227  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
228  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
229 
230  ABTI_sched_finish(p_sched);
231 
232 fn_exit:
233  return abt_errno;
234 
235 fn_fail:
236  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
237  goto fn_exit;
238 }
239 
253 {
254  int abt_errno = ABT_SUCCESS;
255  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
256  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
257 
258  ABTI_sched_exit(p_sched);
259 
260 fn_exit:
261  return abt_errno;
262 
263 fn_fail:
264  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
265  goto fn_exit;
266 }
267 
286 {
287  int abt_errno = ABT_SUCCESS;
288  ABTI_local *p_local = ABTI_local_get_local();
289 
290  *stop = ABT_FALSE;
291 
292  /* When this routine is called by an external thread, e.g., pthread */
293  if (p_local == NULL) {
294  abt_errno = ABT_ERR_INV_XSTREAM;
295  goto fn_exit;
296  }
297 
298  ABTI_xstream *p_xstream = p_local->p_xstream;
299 
300  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
301  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
302 
303  *stop = ABTI_sched_has_to_stop(&p_local, p_sched, p_xstream);
304 
305 fn_exit:
306  return abt_errno;
307 
308 fn_fail:
309  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
310  goto fn_exit;
311 }
312 
313 ABT_bool ABTI_sched_has_to_stop(ABTI_local **pp_local, ABTI_sched *p_sched,
314  ABTI_xstream *p_xstream)
315 {
316  ABT_bool stop = ABT_FALSE;
317  size_t size;
318 
319  /* Check exit request */
320  if (ABTD_atomic_acquire_load_uint32(&p_sched->request) &
321  ABTI_SCHED_REQ_EXIT) {
322  ABTI_spinlock_acquire(&p_xstream->sched_lock);
323  p_sched->state = ABT_SCHED_STATE_TERMINATED;
324  stop = ABT_TRUE;
325  goto fn_exit;
326  }
327 
328  size = ABTI_sched_get_effective_size(*pp_local, p_sched);
329  if (size == 0) {
330  if (ABTD_atomic_acquire_load_uint32(&p_sched->request) &
331  ABTI_SCHED_REQ_FINISH) {
332  /* Check join request */
333  /* We need to lock in case someone wants to migrate to this
334  * scheduler */
335  ABTI_spinlock_acquire(&p_xstream->sched_lock);
336  size = ABTI_sched_get_effective_size(*pp_local, p_sched);
337  if (size == 0) {
338  p_sched->state = ABT_SCHED_STATE_TERMINATED;
339  stop = ABT_TRUE;
340  } else {
341  ABTI_spinlock_release(&p_xstream->sched_lock);
342  }
343  } else if (p_sched->used == ABTI_SCHED_IN_POOL) {
344  /* If the scheduler is a stacked one, we have to escape from the
345  * scheduling function. The scheduler will be stopped if it is a
346  * tasklet type. However, if the scheduler is a ULT type, we
347  * context switch to the parent scheduler. */
348  if (p_sched->type == ABT_SCHED_TYPE_TASK) {
349  p_sched->state = ABT_SCHED_STATE_TERMINATED;
350  stop = ABT_TRUE;
351  } else {
352  ABTI_ASSERT(p_sched->type == ABT_SCHED_TYPE_ULT);
353  ABTI_sched *p_par_sched;
354  p_par_sched = ABTI_xstream_get_parent_sched(p_xstream);
355  ABTI_thread_context_switch_sched_to_sched(pp_local, p_sched,
356  p_par_sched);
357  }
358  }
359  }
360 
361 fn_exit:
362  return stop;
363 }
364 
377 int ABT_sched_set_data(ABT_sched sched, void *data)
378 {
379  int abt_errno = ABT_SUCCESS;
380  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
381  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
382  p_sched->data = data;
383 
384 fn_exit:
385  return abt_errno;
386 
387 fn_fail:
388  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
389  goto fn_exit;
390 }
391 
404 int ABT_sched_get_data(ABT_sched sched, void **data)
405 {
406  int abt_errno = ABT_SUCCESS;
407 
408  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
409  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
410 
411  *data = p_sched->data;
412 
413 fn_exit:
414  return abt_errno;
415 
416 fn_fail:
417  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
418  goto fn_exit;
419 }
420 
432 int ABT_sched_get_size(ABT_sched sched, size_t *size)
433 {
434  int abt_errno = ABT_SUCCESS;
435  size_t pool_size = 0;
436 
437  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
438  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
439 
440  pool_size = ABTI_sched_get_size(p_sched);
441 
442 fn_exit:
443  *size = pool_size;
444  return abt_errno;
445 
446 fn_fail:
447  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
448  goto fn_exit;
449 }
450 
451 size_t ABTI_sched_get_size(ABTI_sched *p_sched)
452 {
453  size_t pool_size = 0;
454  int p;
455 
456  for (p = 0; p < p_sched->num_pools; p++) {
457  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
458  pool_size += ABTI_pool_get_size(p_pool);
459  }
460 
461  return pool_size;
462 }
463 
475 int ABT_sched_get_total_size(ABT_sched sched, size_t *size)
476 {
477  int abt_errno = ABT_SUCCESS;
478  size_t pool_size = 0;
479 
480  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
481  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
482 
483  pool_size = ABTI_sched_get_total_size(p_sched);
484 
485 fn_exit:
486  *size = pool_size;
487  return abt_errno;
488 
489 fn_fail:
490  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
491  goto fn_exit;
492 }
493 
494 size_t ABTI_sched_get_total_size(ABTI_sched *p_sched)
495 {
496  size_t pool_size = 0;
497  int p;
498 
499  for (p = 0; p < p_sched->num_pools; p++) {
500  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
501  pool_size += ABTI_pool_get_total_size(p_pool);
502  }
503 
504  return pool_size;
505 }
506 
507 /* Compared to \c ABTI_sched_get_total_size, ABTI_sched_get_effective_size does
508  * not count the number of blocked ULTs if a pool has more than one consumer or
509  * the caller ES is not the latest consumer. This is necessary when the ES
510  * associated with the target scheduler has to be joined and the pool is shared
511  * between different schedulers associated with different ESs. */
512 size_t ABTI_sched_get_effective_size(ABTI_local *p_local, ABTI_sched *p_sched)
513 {
514  size_t pool_size = 0;
515  int p;
516 
517 #ifndef ABT_CONFIG_DISABLE_POOL_CONSUMER_CHECK
518  ABTI_native_thread_id self_id = ABTI_self_get_native_thread_id(p_local);
519 #endif
520 
521  for (p = 0; p < p_sched->num_pools; p++) {
522  ABT_pool pool = p_sched->pools[p];
523  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
524  pool_size += ABTI_pool_get_size(p_pool);
525  pool_size += ABTD_atomic_acquire_load_int32(&p_pool->num_migrations);
526  switch (p_pool->access) {
528  pool_size +=
529  ABTD_atomic_acquire_load_int32(&p_pool->num_blocked);
530  break;
535 #ifdef ABT_CONFIG_DISABLE_POOL_CONSUMER_CHECK
536  if (ABTD_atomic_acquire_load_int32(&p_pool->num_scheds) == 1) {
537  pool_size +=
538  ABTD_atomic_acquire_load_int32(&p_pool->num_blocked);
539  }
540 #else
541  if (ABTD_atomic_acquire_load_int32(&p_pool->num_scheds) == 1 &&
542  p_pool->consumer_id == self_id) {
543  pool_size +=
544  ABTD_atomic_acquire_load_int32(&p_pool->num_blocked);
545  }
546 #endif
547  break;
548  default:
549  break;
550  }
551  }
552 
553  return pool_size;
554 }
555 
556 /*****************************************************************************/
557 /* Private APIs */
558 /*****************************************************************************/
559 
560 void ABTI_sched_finish(ABTI_sched *p_sched)
561 {
562  ABTI_sched_set_request(p_sched, ABTI_SCHED_REQ_FINISH);
563 }
564 
565 void ABTI_sched_exit(ABTI_sched *p_sched)
566 {
567  ABTI_sched_set_request(p_sched, ABTI_SCHED_REQ_EXIT);
568 }
569 
570 int ABTI_sched_create(ABT_sched_def *def, int num_pools, ABT_pool *pools,
571  ABT_sched_config config, ABT_bool automatic,
572  ABTI_sched **pp_newsched)
573 {
574  int abt_errno = ABT_SUCCESS;
575  ABTI_sched *p_sched;
576  int p;
577 
578  p_sched = (ABTI_sched *)ABTU_malloc(sizeof(ABTI_sched));
579 
580  /* Copy of the contents of pools */
581  ABT_pool *pool_list;
582  pool_list = (ABT_pool *)ABTU_malloc(num_pools * sizeof(ABT_pool));
583  for (p = 0; p < num_pools; p++) {
584  if (pools[p] == ABT_POOL_NULL) {
585  ABTI_pool *p_newpool;
586  abt_errno =
587  ABTI_pool_create_basic(ABT_POOL_FIFO, ABT_POOL_ACCESS_MPSC,
588  ABT_TRUE, &p_newpool);
589  ABTI_CHECK_ERROR(abt_errno);
590  pool_list[p] = ABTI_pool_get_handle(p_newpool);
591  } else {
592  pool_list[p] = pools[p];
593  }
594  }
595 
596  /* Check if the pools are available */
597  for (p = 0; p < num_pools; p++) {
598  ABTI_pool_retain(ABTI_pool_get_ptr(pool_list[p]));
599  }
600 
601  p_sched->used = ABTI_SCHED_NOT_USED;
602  p_sched->automatic = automatic;
603  p_sched->kind = ABTI_sched_get_kind(def);
604  p_sched->state = ABT_SCHED_STATE_READY;
605  ABTD_atomic_relaxed_store_uint32(&p_sched->request, 0);
606  p_sched->pools = pool_list;
607  p_sched->num_pools = num_pools;
608  p_sched->type = def->type;
609  p_sched->p_thread = NULL;
610  p_sched->p_task = NULL;
611  p_sched->p_ctx = NULL;
612 
613  p_sched->init = def->init;
614  p_sched->run = def->run;
615  p_sched->free = def->free;
616  p_sched->get_migr_pool = def->get_migr_pool;
617 
618 #ifdef ABT_CONFIG_USE_DEBUG_LOG
619  p_sched->id = ABTI_sched_get_new_id();
620 #endif
621  LOG_EVENT("[S%" PRIu64 "] created\n", p_sched->id);
622 
623  /* Return value */
624  ABT_sched newsched = ABTI_sched_get_handle(p_sched);
625 
626  /* Specific initialization */
627  p_sched->init(newsched, config);
628  *pp_newsched = p_sched;
629 
630 fn_exit:
631  return abt_errno;
632 
633 fn_fail:
634  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
635  goto fn_exit;
636 }
637 
638 int ABTI_sched_create_basic(ABT_sched_predef predef, int num_pools,
639  ABT_pool *pools, ABT_sched_config config,
640  ABTI_sched **pp_newsched)
641 {
642  int abt_errno = ABT_SUCCESS;
643  ABT_pool_access access;
645  ABT_bool automatic;
646 
647  /* We set the access to the default one */
648  access = ABT_POOL_ACCESS_MPSC;
649  /* TODO: the default value is different from ABT_sched_create().
650  * Make it consistent. */
651  automatic = ABT_TRUE;
652  /* We read the config and set the configured parameters */
653  abt_errno = ABTI_sched_config_read_global(config, &access, &automatic);
654  ABTI_CHECK_ERROR(abt_errno);
655 
656  /* A pool array is provided, predef has to be compatible */
657  if (pools != NULL) {
658  /* Copy of the contents of pools */
659  ABT_pool *pool_list;
660  pool_list = (ABT_pool *)ABTU_malloc(num_pools * sizeof(ABT_pool));
661  int p;
662  for (p = 0; p < num_pools; p++) {
663  if (pools[p] == ABT_POOL_NULL) {
664  ABTI_pool *p_newpool;
665  abt_errno = ABTI_pool_create_basic(ABT_POOL_FIFO, access,
666  ABT_TRUE, &p_newpool);
667  ABTI_CHECK_ERROR(abt_errno);
668  pool_list[p] = ABTI_pool_get_handle(p_newpool);
669  } else {
670  pool_list[p] = pools[p];
671  }
672  }
673 
674  /* Creation of the scheduler */
675  switch (predef) {
676  case ABT_SCHED_DEFAULT:
677  case ABT_SCHED_BASIC:
678  abt_errno =
679  ABTI_sched_create(ABTI_sched_get_basic_def(), num_pools,
680  pool_list, ABT_SCHED_CONFIG_NULL,
681  automatic, pp_newsched);
682  break;
684  abt_errno = ABTI_sched_create(ABTI_sched_get_basic_wait_def(),
685  num_pools, pool_list,
686  ABT_SCHED_CONFIG_NULL, automatic,
687  pp_newsched);
688  break;
689  case ABT_SCHED_PRIO:
690  abt_errno =
691  ABTI_sched_create(ABTI_sched_get_prio_def(), num_pools,
692  pool_list, ABT_SCHED_CONFIG_NULL,
693  automatic, pp_newsched);
694  break;
695  case ABT_SCHED_RANDWS:
696  abt_errno =
697  ABTI_sched_create(ABTI_sched_get_randws_def(), num_pools,
698  pool_list, ABT_SCHED_CONFIG_NULL,
699  automatic, pp_newsched);
700  break;
701  default:
702  abt_errno = ABT_ERR_INV_SCHED_PREDEF;
703  break;
704  }
705  ABTI_CHECK_ERROR(abt_errno);
706  ABTU_free(pool_list);
707  }
708 
709  /* No pool array is provided, predef has to be compatible */
710  else {
711  /* Set the number of pools */
712  switch (predef) {
713  case ABT_SCHED_DEFAULT:
714  case ABT_SCHED_BASIC:
715  num_pools = 1;
716  break;
718  /* FIFO_WAIT is default pool for use with BASIC_WAIT sched */
719  kind = ABT_POOL_FIFO_WAIT;
720  num_pools = 1;
721  break;
722  case ABT_SCHED_PRIO:
723  num_pools = ABTI_SCHED_NUM_PRIO;
724  break;
725  case ABT_SCHED_RANDWS:
726  num_pools = 1;
727  break;
728  default:
729  abt_errno = ABT_ERR_INV_SCHED_PREDEF;
730  ABTI_CHECK_ERROR(abt_errno);
731  break;
732  }
733 
734  /* Creation of the pools */
735  /* To avoid the malloc overhead, we use a stack array. */
736  ABT_pool pool_list[ABTI_SCHED_NUM_PRIO];
737  int p;
738  for (p = 0; p < num_pools; p++) {
739  ABTI_pool *p_newpool;
740  abt_errno =
741  ABTI_pool_create_basic(kind, access, ABT_TRUE, &p_newpool);
742  ABTI_CHECK_ERROR(abt_errno);
743  pool_list[p] = ABTI_pool_get_handle(p_newpool);
744  }
745 
746  /* Creation of the scheduler */
747  switch (predef) {
748  case ABT_SCHED_DEFAULT:
749  case ABT_SCHED_BASIC:
750  abt_errno = ABTI_sched_create(ABTI_sched_get_basic_def(),
751  num_pools, pool_list, config,
752  automatic, pp_newsched);
753  break;
755  abt_errno = ABTI_sched_create(ABTI_sched_get_basic_wait_def(),
756  num_pools, pool_list, config,
757  automatic, pp_newsched);
758  break;
759  case ABT_SCHED_PRIO:
760  abt_errno = ABTI_sched_create(ABTI_sched_get_prio_def(),
761  num_pools, pool_list, config,
762  automatic, pp_newsched);
763  break;
764  case ABT_SCHED_RANDWS:
765  abt_errno = ABTI_sched_create(ABTI_sched_get_randws_def(),
766  num_pools, pool_list, config,
767  automatic, pp_newsched);
768  break;
769  default:
770  abt_errno = ABT_ERR_INV_SCHED_PREDEF;
771  ABTI_CHECK_ERROR(abt_errno);
772  break;
773  }
774  }
775  ABTI_CHECK_ERROR(abt_errno);
776 
777 fn_exit:
778  return abt_errno;
779 
780 fn_fail:
781  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
782  goto fn_exit;
783 }
784 
785 int ABTI_sched_free(ABTI_local *p_local, ABTI_sched *p_sched)
786 {
787  int abt_errno = ABT_SUCCESS;
788  int p;
789 
790  /* If sched is currently used, free is not allowed. */
791  if (p_sched->used != ABTI_SCHED_NOT_USED) {
792  abt_errno = ABT_ERR_SCHED;
793  goto fn_fail;
794  }
795 
796  /* If sched is a default provided one, it should free its pool here.
797  * Otherwise, freeing the pool is the user's responsibility. */
798  for (p = 0; p < p_sched->num_pools; p++) {
799  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
800  int32_t num_scheds = ABTI_pool_release(p_pool);
801  if (p_pool->automatic == ABT_TRUE && num_scheds == 0) {
802  ABTI_CHECK_NULL_POOL_PTR(p_pool);
803  ABTI_pool_free(p_pool);
804  }
805  }
806  ABTU_free(p_sched->pools);
807 
808  /* Free the associated work unit */
809  if (p_sched->type == ABT_SCHED_TYPE_ULT) {
810  if (p_sched->p_thread) {
811  if (p_sched->p_thread->type == ABTI_THREAD_TYPE_MAIN_SCHED) {
812  ABTI_thread_free_main_sched(p_local, p_sched->p_thread);
813  } else {
814  ABTI_thread_free(p_local, p_sched->p_thread);
815  }
816  }
817  } else if (p_sched->type == ABT_SCHED_TYPE_TASK) {
818  if (p_sched->p_task) {
819  ABTI_task_free(p_local, p_sched->p_task);
820  }
821  }
822 
823  LOG_EVENT("[S%" PRIu64 "] freed\n", p_sched->id);
824 
825  p_sched->free(ABTI_sched_get_handle(p_sched));
826  p_sched->data = NULL;
827 
828  ABTU_free(p_sched);
829 
830 fn_exit:
831  return abt_errno;
832 
833 fn_fail:
834  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
835  goto fn_exit;
836 }
837 
838 /* Get the pool suitable for receiving a migrating ULT */
839 int ABTI_sched_get_migration_pool(ABTI_sched *p_sched, ABTI_pool *source_pool,
840  ABTI_pool **pp_pool)
841 {
842  int abt_errno = ABT_SUCCESS;
843  ABT_sched sched = ABTI_sched_get_handle(p_sched);
844  ABTI_pool *p_pool;
845 
846  ABTI_CHECK_TRUE(p_sched->state != ABT_SCHED_STATE_TERMINATED,
848 
849  /* Find a pool */
850  /* If get_migr_pool is not defined, we pick the first pool */
851  if (p_sched->get_migr_pool == NULL) {
852  if (p_sched->num_pools == 0)
853  p_pool = NULL;
854  else
855  p_pool = ABTI_pool_get_ptr(p_sched->pools[0]);
856  } else
857  p_pool = ABTI_pool_get_ptr(p_sched->get_migr_pool(sched));
858 
859  /* Check the pool */
860  if (ABTI_pool_accept_migration(p_pool, source_pool) == ABT_TRUE) {
861  *pp_pool = p_pool;
862  } else {
863  ABTI_CHECK_TRUE(0, ABT_ERR_INV_POOL_ACCESS);
864  }
865 
866 fn_exit:
867  return abt_errno;
868 
869 fn_fail:
870  *pp_pool = NULL;
871  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
872  goto fn_exit;
873 }
874 
875 ABTI_sched_kind ABTI_sched_get_kind(ABT_sched_def *def)
876 {
877  return (ABTI_sched_kind)def;
878 }
879 
880 void ABTI_sched_print(ABTI_sched *p_sched, FILE *p_os, int indent,
881  ABT_bool print_sub)
882 {
883  char *prefix = ABTU_get_indent_str(indent);
884 
885  if (p_sched == NULL) {
886  fprintf(p_os, "%s== NULL SCHED ==\n", prefix);
887  goto fn_exit;
888  }
889 
890  ABTI_sched_kind kind;
891  char *kind_str, *type, *state, *used;
892  char *pools_str;
893  int i;
894  size_t size, pos;
895 
896  kind = p_sched->kind;
897  if (kind == ABTI_sched_get_kind(ABTI_sched_get_basic_def())) {
898  kind_str = "BASIC";
899  } else if (kind == ABTI_sched_get_kind(ABTI_sched_get_basic_wait_def())) {
900  kind_str = "BASIC_WAIT";
901  } else if (kind == ABTI_sched_get_kind(ABTI_sched_get_prio_def())) {
902  kind_str = "PRIO";
903  } else {
904  kind_str = "USER";
905  }
906 
907  switch (p_sched->type) {
908  case ABT_SCHED_TYPE_ULT:
909  type = "ULT";
910  break;
911  case ABT_SCHED_TYPE_TASK:
912  type = "TASKLET";
913  break;
914  default:
915  type = "UNKNOWN";
916  break;
917  }
918  switch (p_sched->state) {
920  state = "READY";
921  break;
923  state = "RUNNING";
924  break;
926  state = "STOPPED";
927  break;
929  state = "TERMINATED";
930  break;
931  default:
932  state = "UNKNOWN";
933  break;
934  }
935  switch (p_sched->used) {
936  case ABTI_SCHED_NOT_USED:
937  used = "NOT_USED";
938  break;
939  case ABTI_SCHED_MAIN:
940  used = "MAIN";
941  break;
942  case ABTI_SCHED_IN_POOL:
943  used = "IN_POOL";
944  break;
945  default:
946  used = "UNKNOWN";
947  break;
948  }
949 
950  size = sizeof(char) * (p_sched->num_pools * 20 + 4);
951  pools_str = (char *)ABTU_calloc(size, 1);
952  pools_str[0] = '[';
953  pools_str[1] = ' ';
954  pos = 2;
955  for (i = 0; i < p_sched->num_pools; i++) {
956  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[i]);
957  sprintf(&pools_str[pos], "%p ", (void *)p_pool);
958  pos = strlen(pools_str);
959  }
960  pools_str[pos] = ']';
961 
962  fprintf(p_os,
963  "%s== SCHED (%p) ==\n"
964 #ifdef ABT_CONFIG_USE_DEBUG_LOG
965  "%sid : %" PRIu64 "\n"
966 #endif
967  "%skind : %" PRIxPTR " (%s)\n"
968  "%stype : %s\n"
969  "%sstate : %s\n"
970  "%sused : %s\n"
971  "%sautomatic: %s\n"
972  "%srequest : 0x%x\n"
973  "%snum_pools: %d\n"
974  "%spools : %s\n"
975  "%ssize : %zu\n"
976  "%stot_size : %zu\n"
977  "%sdata : %p\n",
978  prefix, (void *)p_sched,
979 #ifdef ABT_CONFIG_USE_DEBUG_LOG
980  prefix, p_sched->id,
981 #endif
982  prefix, p_sched->kind, kind_str, prefix, type, prefix, state,
983  prefix, used, prefix,
984  (p_sched->automatic == ABT_TRUE) ? "TRUE" : "FALSE", prefix,
985  ABTD_atomic_acquire_load_uint32(&p_sched->request), prefix,
986  p_sched->num_pools, prefix, pools_str, prefix,
987  ABTI_sched_get_size(p_sched), prefix,
988  ABTI_sched_get_total_size(p_sched), prefix, p_sched->data);
989  ABTU_free(pools_str);
990 
991  if (print_sub == ABT_TRUE) {
992  for (i = 0; i < p_sched->num_pools; i++) {
993  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[i]);
994  ABTI_pool_print(p_pool, p_os, indent + 2);
995  }
996  }
997 
998 fn_exit:
999  fflush(p_os);
1000  ABTU_free(prefix);
1001 }
1002 
1003 static ABTD_atomic_uint64 g_sched_id = ABTD_ATOMIC_UINT64_STATIC_INITIALIZER(0);
1004 void ABTI_sched_reset_id(void)
1005 {
1006  ABTD_atomic_relaxed_store_uint64(&g_sched_id, 0);
1007 }
1008 
1009 /*****************************************************************************/
1010 /* Internal static functions */
1011 /*****************************************************************************/
1012 
1013 #ifdef ABT_CONFIG_USE_DEBUG_LOG
1014 static inline uint64_t ABTI_sched_get_new_id(void)
1015 {
1016  return ABTD_atomic_fetch_add_uint64(&g_sched_id, 1);
1017 }
1018 #endif
ABT_sched_free_fn free
Definition: abt.h:392
int ABT_sched_get_size(ABT_sched sched, size_t *size)
Get the sum of the sizes of the pool of sched.
Definition: sched.c:432
#define ABT_POOL_NULL
Definition: abt.h:341
#define ABT_ERR_INV_POOL_ACCESS
Definition: abt.h:78
ABT_sched_predef
Definition: abt.h:144
struct ABT_sched_opaque * ABT_sched
Definition: abt.h:257
int ABT_sched_finish(ABT_sched sched)
Ask a scheduler to finish.
Definition: sched.c:223
char * ABTU_get_indent_str(int indent)
Definition: util.c:12
ABT_sched_init_fn init
Definition: abt.h:390
static void * ABTU_malloc(size_t size)
Definition: abtu.h:39
int ABT_bool
Definition: abt.h:309
int ABT_sched_create(ABT_sched_def *def, int num_pools, ABT_pool *pools, ABT_sched_config config, ABT_sched *newsched)
Create a new user-defined scheduler and return its handle through newsched.
Definition: sched.c:36
#define ABT_ERR_SCHED
Definition: abt.h:96
struct ABT_pool_opaque * ABT_pool
Definition: abt.h:267
int ABT_sched_exit(ABT_sched sched)
Ask a scheduler to stop as soon as possible.
Definition: sched.c:252
#define ABT_FALSE
Definition: abt.h:224
int ABT_sched_get_num_pools(ABT_sched sched, int *num_pools)
Get the number of pools associated with scheduler.
Definition: sched.c:162
int ABT_sched_get_total_size(ABT_sched sched, size_t *size)
Get the sum of the sizes of the pool of sched.
Definition: sched.c:475
#define HANDLE_ERROR_FUNC_WITH_CODE(n)
Definition: abti_error.h:241
#define ABT_SUCCESS
Definition: abt.h:64
int ABT_sched_free(ABT_sched *sched)
Release the scheduler object associated with sched handle.
Definition: sched.c:127
ABT_pool_access
Definition: abt.h:162
#define LOG_EVENT(fmt,...)
Definition: abti_log.h:60
#define ABT_TRUE
Definition: abt.h:223
#define ABT_SCHED_NULL
Definition: abt.h:339
ABT_sched_type type
Definition: abt.h:387
ABT_pool_kind
Definition: abt.h:157
int ABT_sched_get_data(ABT_sched sched, void **data)
Retrieve the specific data of the target user-defined scheduler.
Definition: sched.c:404
int ABT_sched_get_pools(ABT_sched sched, int max_pools, int idx, ABT_pool *pools)
Get the pools of the scheduler sched.
Definition: sched.c:190
int ABT_sched_create_basic(ABT_sched_predef predef, int num_pools, ABT_pool *pools, ABT_sched_config config, ABT_sched *newsched)
Create a predefined scheduler.
Definition: sched.c:93
static ABTD_atomic_uint64 g_sched_id
Definition: sched.c:1003
struct ABT_sched_config_opaque * ABT_sched_config
Definition: abt.h:259
ABT_sched_get_migr_pool_fn get_migr_pool
Definition: abt.h:393
#define ABT_ERR_INV_SCHED
Definition: abt.h:71
#define ABT_SCHED_CONFIG_NULL
Definition: abt.h:340
#define ABT_ERR_INV_XSTREAM
Definition: abt.h:68
ABT_sched_run_fn run
Definition: abt.h:391
int ABT_sched_set_data(ABT_sched sched, void *data)
Set the specific data of the target user-defined scheduler.
Definition: sched.c:377
static void ABTU_free(void *ptr)
Definition: abtu.h:32
int ABT_sched_has_to_stop(ABT_sched sched, ABT_bool *stop)
Check if the scheduler needs to stop.
Definition: sched.c:285
#define ABT_ERR_INV_SCHED_PREDEF
Definition: abt.h:73
static void * ABTU_calloc(size_t num, size_t size)
Definition: abtu.h:49