ARGOBOTS  1227c643f7a7f974f1f1778a9ffebd29d7dafecf
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
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 ABTU_ret_err static int sched_create(ABT_sched_def *def, int num_pools,
9  ABT_pool *pools, ABT_sched_config config,
10  ABT_bool automatic,
11  ABTI_sched **pp_newsched);
12 static inline ABTI_sched_kind sched_get_kind(ABT_sched_def *def);
13 #ifdef ABT_CONFIG_USE_DEBUG_LOG
14 static inline uint64_t sched_get_new_id(void);
15 #endif
16 
41 int ABT_sched_create(ABT_sched_def *def, int num_pools, ABT_pool *pools,
42  ABT_sched_config config, ABT_sched *newsched)
43 {
44  int abt_errno = ABT_SUCCESS;
45  ABTI_sched *p_sched;
46 
47  ABTI_CHECK_TRUE(newsched != NULL, ABT_ERR_SCHED);
48  /* TODO: the default value of automatic is different from
49  * ABT_sched_create_basic(). Make it consistent. */
50  const ABT_bool def_automatic = ABT_FALSE;
51  abt_errno =
52  sched_create(def, num_pools, pools, config, def_automatic, &p_sched);
53  ABTI_CHECK_ERROR(abt_errno);
54 
55  /* Return value */
56  *newsched = ABTI_sched_get_handle(p_sched);
57 
58 fn_exit:
59  return abt_errno;
60 
61 fn_fail:
62  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
63  goto fn_exit;
64 }
65 
97 int ABT_sched_create_basic(ABT_sched_predef predef, int num_pools,
98  ABT_pool *pools, ABT_sched_config config,
99  ABT_sched *newsched)
100 {
101  int abt_errno = ABT_SUCCESS;
102  ABTI_sched *p_newsched;
103  abt_errno =
104  ABTI_sched_create_basic(predef, num_pools, pools, config, &p_newsched);
105  ABTI_CHECK_ERROR(abt_errno);
106  *newsched = ABTI_sched_get_handle(p_newsched);
107 
108 fn_exit:
109  return abt_errno;
110 
111 fn_fail:
112  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
113  goto fn_exit;
114 }
115 
131 {
132  int abt_errno = ABT_SUCCESS;
133  ABTI_local *p_local = ABTI_local_get_local();
134  ABTI_sched *p_sched = ABTI_sched_get_ptr(*sched);
135  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
136  ABTI_CHECK_TRUE_RET(p_sched->used == ABTI_SCHED_NOT_USED, ABT_ERR_SCHED);
137 
138  /* Free the scheduler */
139  ABTI_sched_free(p_local, p_sched, ABT_FALSE);
140 
141  /* Return value */
142  *sched = ABT_SCHED_NULL;
143 
144 fn_exit:
145  return abt_errno;
146 
147 fn_fail:
148  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
149  goto fn_exit;
150 }
151 
165 int ABT_sched_get_num_pools(ABT_sched sched, int *num_pools)
166 {
167  int abt_errno = ABT_SUCCESS;
168 
169  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
170  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
171 
172  *num_pools = p_sched->num_pools;
173 
174 fn_exit:
175  return abt_errno;
176 
177 fn_fail:
178  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
179  goto fn_exit;
180 }
181 
193 int ABT_sched_get_pools(ABT_sched sched, int max_pools, int idx,
194  ABT_pool *pools)
195 {
196  int abt_errno = ABT_SUCCESS;
197 
198  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
199  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
200 
201  ABTI_CHECK_TRUE(idx + max_pools <= p_sched->num_pools, ABT_ERR_SCHED);
202 
203  int p;
204  for (p = idx; p < idx + max_pools; p++) {
205  pools[p - idx] = p_sched->pools[p];
206  }
207 
208 fn_exit:
209  return abt_errno;
210 
211 fn_fail:
212  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
213  goto fn_exit;
214 }
215 
227 {
228  int abt_errno = ABT_SUCCESS;
229 
230  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
231  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
232 
233  ABTI_sched_finish(p_sched);
234 
235 fn_exit:
236  return abt_errno;
237 
238 fn_fail:
239  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
240  goto fn_exit;
241 }
242 
256 {
257  int abt_errno = ABT_SUCCESS;
258  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
259  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
260 
261  ABTI_sched_exit(p_sched);
262 
263 fn_exit:
264  return abt_errno;
265 
266 fn_fail:
267  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
268  goto fn_exit;
269 }
270 
289 {
290  int abt_errno = ABT_SUCCESS;
291  ABTI_local *p_local = ABTI_local_get_local();
292  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
293  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
294 
295  *stop = ABTI_sched_has_to_stop(&p_local, p_sched);
296 
297 fn_exit:
298  return abt_errno;
299 
300 fn_fail:
301  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
302  goto fn_exit;
303 }
304 
317 int ABT_sched_set_data(ABT_sched sched, void *data)
318 {
319  int abt_errno = ABT_SUCCESS;
320  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
321  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
322  p_sched->data = data;
323 
324 fn_exit:
325  return abt_errno;
326 
327 fn_fail:
328  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
329  goto fn_exit;
330 }
331 
344 int ABT_sched_get_data(ABT_sched sched, void **data)
345 {
346  int abt_errno = ABT_SUCCESS;
347 
348  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
349  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
350 
351  *data = p_sched->data;
352 
353 fn_exit:
354  return abt_errno;
355 
356 fn_fail:
357  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
358  goto fn_exit;
359 }
360 
372 int ABT_sched_get_size(ABT_sched sched, size_t *size)
373 {
374  int abt_errno = ABT_SUCCESS;
375 
376  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
377  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
378 
379  *size = ABTI_sched_get_size(p_sched);
380 
381 fn_exit:
382  return abt_errno;
383 
384 fn_fail:
385  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
386  goto fn_exit;
387 }
388 
389 size_t ABTI_sched_get_size(ABTI_sched *p_sched)
390 {
391  size_t pool_size = 0;
392  int p;
393 
394  for (p = 0; p < p_sched->num_pools; p++) {
395  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
396  pool_size += ABTI_pool_get_size(p_pool);
397  }
398 
399  return pool_size;
400 }
401 
413 int ABT_sched_get_total_size(ABT_sched sched, size_t *size)
414 {
415  int abt_errno = ABT_SUCCESS;
416 
417  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
418  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
419 
420  *size = ABTI_sched_get_total_size(p_sched);
421 
422 fn_exit:
423  return abt_errno;
424 
425 fn_fail:
426  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
427  goto fn_exit;
428 }
429 
430 /*****************************************************************************/
431 /* Private APIs */
432 /*****************************************************************************/
433 
434 void ABTI_sched_finish(ABTI_sched *p_sched)
435 {
436  ABTI_sched_set_request(p_sched, ABTI_SCHED_REQ_FINISH);
437 }
438 
439 void ABTI_sched_exit(ABTI_sched *p_sched)
440 {
441  ABTI_sched_set_request(p_sched, ABTI_SCHED_REQ_EXIT);
442 }
443 
444 ABTU_ret_err int ABTI_sched_create_basic(ABT_sched_predef predef, int num_pools,
445  ABT_pool *pools,
446  ABT_sched_config config,
447  ABTI_sched **pp_newsched)
448 {
449  int abt_errno;
450  ABT_pool_access access;
452  ABT_bool automatic;
453 
454  ABTI_CHECK_TRUE_RET(!pools || num_pools > 0, ABT_ERR_SCHED);
455 
456  /* We set the access to the default one */
457  access = ABT_POOL_ACCESS_MPSC;
458  /* TODO: the default value is different from ABT_sched_create().
459  * Make it consistent. */
460  automatic = ABT_TRUE;
461  /* We read the config and set the configured parameters */
462  abt_errno = ABTI_sched_config_read_global(config, &access, &automatic);
463  ABTI_CHECK_ERROR_RET(abt_errno);
464 
465  /* A pool array is provided, predef has to be compatible */
466  if (pools != NULL) {
467  /* Copy of the contents of pools */
468  ABT_pool *pool_list;
469  abt_errno =
470  ABTU_malloc(num_pools * sizeof(ABT_pool), (void **)&pool_list);
471  ABTI_CHECK_ERROR_RET(abt_errno);
472 
473  int p;
474  for (p = 0; p < num_pools; p++) {
475  if (pools[p] == ABT_POOL_NULL) {
476  ABTI_pool *p_newpool;
477  abt_errno = ABTI_pool_create_basic(ABT_POOL_FIFO, access,
478  ABT_TRUE, &p_newpool);
479  ABTI_CHECK_ERROR_RET(abt_errno);
480  pool_list[p] = ABTI_pool_get_handle(p_newpool);
481  } else {
482  pool_list[p] = pools[p];
483  }
484  }
485 
486  /* Creation of the scheduler */
487  switch (predef) {
488  case ABT_SCHED_DEFAULT:
489  case ABT_SCHED_BASIC:
490  abt_errno = sched_create(ABTI_sched_get_basic_def(), num_pools,
491  pool_list, ABT_SCHED_CONFIG_NULL,
492  automatic, pp_newsched);
493  break;
495  abt_errno =
496  sched_create(ABTI_sched_get_basic_wait_def(), num_pools,
497  pool_list, ABT_SCHED_CONFIG_NULL, automatic,
498  pp_newsched);
499  break;
500  case ABT_SCHED_PRIO:
501  abt_errno = sched_create(ABTI_sched_get_prio_def(), num_pools,
502  pool_list, ABT_SCHED_CONFIG_NULL,
503  automatic, pp_newsched);
504  break;
505  case ABT_SCHED_RANDWS:
506  abt_errno = sched_create(ABTI_sched_get_randws_def(), num_pools,
507  pool_list, ABT_SCHED_CONFIG_NULL,
508  automatic, pp_newsched);
509  break;
510  default:
511  abt_errno = ABT_ERR_INV_SCHED_PREDEF;
512  break;
513  }
514  ABTI_CHECK_ERROR_RET(abt_errno);
515  ABTU_free(pool_list);
516  }
517 
518  /* No pool array is provided, predef has to be compatible */
519  else {
520  /* Set the number of pools */
521  switch (predef) {
522  case ABT_SCHED_DEFAULT:
523  case ABT_SCHED_BASIC:
524  num_pools = 1;
525  break;
527  /* FIFO_WAIT is default pool for use with BASIC_WAIT sched */
528  kind = ABT_POOL_FIFO_WAIT;
529  num_pools = 1;
530  break;
531  case ABT_SCHED_PRIO:
532  num_pools = ABTI_SCHED_NUM_PRIO;
533  break;
534  case ABT_SCHED_RANDWS:
535  num_pools = 1;
536  break;
537  default:
538  abt_errno = ABT_ERR_INV_SCHED_PREDEF;
539  ABTI_CHECK_ERROR_RET(abt_errno);
540  break;
541  }
542 
543  /* Creation of the pools */
544  /* To avoid the malloc overhead, we use a stack array. */
545  ABT_pool pool_list[ABTI_SCHED_NUM_PRIO];
546  int p;
547  for (p = 0; p < num_pools; p++) {
548  ABTI_pool *p_newpool;
549  abt_errno =
550  ABTI_pool_create_basic(kind, access, ABT_TRUE, &p_newpool);
551  ABTI_CHECK_ERROR_RET(abt_errno);
552  pool_list[p] = ABTI_pool_get_handle(p_newpool);
553  }
554 
555  /* Creation of the scheduler */
556  switch (predef) {
557  case ABT_SCHED_DEFAULT:
558  case ABT_SCHED_BASIC:
559  abt_errno =
560  sched_create(ABTI_sched_get_basic_def(), num_pools,
561  pool_list, config, automatic, pp_newsched);
562  break;
564  abt_errno =
565  sched_create(ABTI_sched_get_basic_wait_def(), num_pools,
566  pool_list, config, automatic, pp_newsched);
567  break;
568  case ABT_SCHED_PRIO:
569  abt_errno =
570  sched_create(ABTI_sched_get_prio_def(), num_pools,
571  pool_list, config, automatic, pp_newsched);
572  break;
573  case ABT_SCHED_RANDWS:
574  abt_errno =
575  sched_create(ABTI_sched_get_randws_def(), num_pools,
576  pool_list, config, automatic, pp_newsched);
577  break;
578  default:
579  abt_errno = ABT_ERR_INV_SCHED_PREDEF;
580  break;
581  }
582  ABTI_CHECK_ERROR_RET(abt_errno);
583  }
584  return ABT_SUCCESS;
585 }
586 
587 void ABTI_sched_free(ABTI_local *p_local, ABTI_sched *p_sched,
588  ABT_bool force_free)
589 {
590  ABTI_ASSERT(p_sched->used == ABTI_SCHED_NOT_USED);
591  /* If sched is a default provided one, it should free its pool here.
592  * Otherwise, freeing the pool is the user's responsibility. */
593  int p;
594  for (p = 0; p < p_sched->num_pools; p++) {
595  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
596  int32_t num_scheds = ABTI_pool_release(p_pool);
597  if ((p_pool->automatic == ABT_TRUE && num_scheds == 0) || force_free) {
598  ABTI_pool_free(p_pool);
599  }
600  }
601  ABTU_free(p_sched->pools);
602 
603  /* Free the associated work unit */
604  if (p_sched->p_ythread) {
605  ABTI_thread_free(p_local, &p_sched->p_ythread->thread);
606  }
607 
608  LOG_DEBUG("[S%" PRIu64 "] freed\n", p_sched->id);
609 
610  p_sched->free(ABTI_sched_get_handle(p_sched));
611  p_sched->data = NULL;
612 
613  ABTU_free(p_sched);
614 }
615 
616 ABT_bool ABTI_sched_has_to_stop(ABTI_local **pp_local, ABTI_sched *p_sched)
617 {
618  /* Check exit request */
619  if (ABTD_atomic_acquire_load_uint32(&p_sched->request) &
620  ABTI_SCHED_REQ_EXIT) {
621  return ABT_TRUE;
622  }
623 
624  if (ABTI_sched_get_effective_size(*pp_local, p_sched) == 0) {
625  if (ABTD_atomic_acquire_load_uint32(&p_sched->request) &
626  ABTI_SCHED_REQ_FINISH) {
627  /* Check join request */
628  if (ABTI_sched_get_effective_size(*pp_local, p_sched) == 0)
629  return ABT_TRUE;
630  } else if (p_sched->used == ABTI_SCHED_IN_POOL) {
631  /* If the scheduler is a stacked one, we have to escape from the
632  * scheduling function. The scheduler will be stopped if it is a
633  * tasklet type. However, if the scheduler is a ULT type, we
634  * context switch to the parent scheduler. */
635  if (p_sched->type == ABT_SCHED_TYPE_TASK)
636  return ABT_TRUE;
637  /* If the current caller cannot yield, let's finish it */
638  ABTI_xstream *p_local_xstream =
639  ABTI_local_get_xstream_or_null(*pp_local);
640  if (ABTI_IS_EXT_THREAD_ENABLED && p_local_xstream == NULL)
641  return ABT_TRUE;
642  /* If the current caller is not the scheduler, let's finish. */
643  if (&p_sched->p_ythread->thread != p_local_xstream->p_thread)
644  return ABT_TRUE;
645  /* Yield this scheduler. */
646  ABTI_ythread_context_switch_to_parent(&p_local_xstream,
647  p_sched->p_ythread,
649  NULL);
650  *pp_local = ABTI_xstream_get_local(p_local_xstream);
651  }
652  }
653  return ABT_FALSE;
654 }
655 
656 /* Get the pool suitable for receiving a migrating ULT */
657 ABTU_ret_err int ABTI_sched_get_migration_pool(ABTI_sched *p_sched,
658  ABTI_pool *source_pool,
659  ABTI_pool **pp_pool)
660 {
661  ABT_sched sched = ABTI_sched_get_handle(p_sched);
662 
663  /* Find a pool. If get_migr_pool is not defined, we pick the first pool */
664  if (p_sched->get_migr_pool == NULL) {
665  *pp_pool = ABTI_pool_get_ptr(p_sched->pools[0]);
666  } else {
667  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->get_migr_pool(sched));
668  if (ABTI_IS_ERROR_CHECK_ENABLED && p_pool == NULL) {
669  return ABT_ERR_SCHED;
670  }
671  *pp_pool = p_pool;
672  }
673  return ABT_SUCCESS;
674 }
675 
676 size_t ABTI_sched_get_total_size(ABTI_sched *p_sched)
677 {
678  size_t pool_size = 0;
679  int p;
680 
681  for (p = 0; p < p_sched->num_pools; p++) {
682  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
683  pool_size += ABTI_pool_get_total_size(p_pool);
684  }
685 
686  return pool_size;
687 }
688 
689 /* Compared to \c ABTI_sched_get_total_size, ABTI_sched_get_effective_size does
690  * not count the number of blocked ULTs if a pool has more than one consumer or
691  * the caller ES is not the latest consumer. This is necessary when the ES
692  * associated with the target scheduler has to be joined and the pool is shared
693  * between different schedulers associated with different ESs. */
694 size_t ABTI_sched_get_effective_size(ABTI_local *p_local, ABTI_sched *p_sched)
695 {
696  size_t pool_size = 0;
697  int p;
698 
699  for (p = 0; p < p_sched->num_pools; p++) {
700  ABT_pool pool = p_sched->pools[p];
701  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
702  pool_size += ABTI_pool_get_size(p_pool);
703  pool_size += ABTD_atomic_acquire_load_int32(&p_pool->num_migrations);
704  switch (p_pool->access) {
706  pool_size +=
707  ABTD_atomic_acquire_load_int32(&p_pool->num_blocked);
708  break;
713  if (ABTD_atomic_acquire_load_int32(&p_pool->num_scheds) == 1) {
714  pool_size +=
715  ABTD_atomic_acquire_load_int32(&p_pool->num_blocked);
716  }
717  break;
718  default:
719  break;
720  }
721  }
722 
723  return pool_size;
724 }
725 
726 void ABTI_sched_print(ABTI_sched *p_sched, FILE *p_os, int indent,
727  ABT_bool print_sub)
728 {
729  if (p_sched == NULL) {
730  fprintf(p_os, "%*s== NULL SCHED ==\n", indent, "");
731  } else {
732  ABTI_sched_kind kind;
733  char *kind_str, *type, *used;
734 
735  kind = p_sched->kind;
736  if (kind == sched_get_kind(ABTI_sched_get_basic_def())) {
737  kind_str = "BASIC";
738  } else if (kind == sched_get_kind(ABTI_sched_get_basic_wait_def())) {
739  kind_str = "BASIC_WAIT";
740  } else if (kind == sched_get_kind(ABTI_sched_get_prio_def())) {
741  kind_str = "PRIO";
742  } else {
743  kind_str = "USER";
744  }
745 
746  switch (p_sched->type) {
747  case ABT_SCHED_TYPE_ULT:
748  type = "ULT";
749  break;
750  case ABT_SCHED_TYPE_TASK:
751  type = "TASKLET";
752  break;
753  default:
754  type = "UNKNOWN";
755  break;
756  }
757  switch (p_sched->used) {
758  case ABTI_SCHED_NOT_USED:
759  used = "NOT_USED";
760  break;
761  case ABTI_SCHED_MAIN:
762  used = "MAIN";
763  break;
764  case ABTI_SCHED_IN_POOL:
765  used = "IN_POOL";
766  break;
767  default:
768  used = "UNKNOWN";
769  break;
770  }
771 
772  fprintf(p_os,
773  "%*s== SCHED (%p) ==\n"
774 #ifdef ABT_CONFIG_USE_DEBUG_LOG
775  "%*sid : %" PRIu64 "\n"
776 #endif
777  "%*skind : %" PRIxPTR " (%s)\n"
778  "%*stype : %s\n"
779  "%*sused : %s\n"
780  "%*sautomatic: %s\n"
781  "%*srequest : 0x%x\n"
782  "%*snum_pools: %d\n"
783  "%*ssize : %zu\n"
784  "%*stot_size : %zu\n"
785  "%*sdata : %p\n",
786  indent, "", (void *)p_sched,
787 #ifdef ABT_CONFIG_USE_DEBUG_LOG
788  indent, "", p_sched->id,
789 #endif
790  indent, "", p_sched->kind, kind_str, indent, "", type, indent,
791  "", used, indent, "",
792  (p_sched->automatic == ABT_TRUE) ? "TRUE" : "FALSE", indent, "",
793  ABTD_atomic_acquire_load_uint32(&p_sched->request), indent, "",
794  p_sched->num_pools, indent, "", ABTI_sched_get_size(p_sched),
795  indent, "", ABTI_sched_get_total_size(p_sched), indent, "",
796  p_sched->data);
797  if (print_sub == ABT_TRUE) {
798  int i;
799  for (i = 0; i < p_sched->num_pools; i++) {
800  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[i]);
801  ABTI_pool_print(p_pool, p_os, indent + 2);
802  }
803  }
804  }
805  fflush(p_os);
806 }
807 
808 static ABTD_atomic_uint64 g_sched_id = ABTD_ATOMIC_UINT64_STATIC_INITIALIZER(0);
809 void ABTI_sched_reset_id(void)
810 {
811  ABTD_atomic_relaxed_store_uint64(&g_sched_id, 0);
812 }
813 
814 /*****************************************************************************/
815 /* Internal static functions */
816 /*****************************************************************************/
817 
818 static inline ABTI_sched_kind sched_get_kind(ABT_sched_def *def)
819 {
820  return (ABTI_sched_kind)def;
821 }
822 
823 ABTU_ret_err static int sched_create(ABT_sched_def *def, int num_pools,
824  ABT_pool *pools, ABT_sched_config config,
825  ABT_bool automatic,
826  ABTI_sched **pp_newsched)
827 {
828  ABTI_sched *p_sched;
829  int p, abt_errno;
830 
831  abt_errno = ABTU_malloc(sizeof(ABTI_sched), (void **)&p_sched);
832  ABTI_CHECK_ERROR_RET(abt_errno);
833 
834  /* Copy of the contents of pools */
835  ABT_pool *pool_list;
836  abt_errno = ABTU_malloc(num_pools * sizeof(ABT_pool), (void **)&pool_list);
837  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
838  ABTU_free(p_sched);
839  return abt_errno;
840  }
841  for (p = 0; p < num_pools; p++) {
842  if (pools[p] == ABT_POOL_NULL) {
843  ABTI_pool *p_newpool;
844  abt_errno =
845  ABTI_pool_create_basic(ABT_POOL_FIFO, ABT_POOL_ACCESS_MPSC,
846  ABT_TRUE, &p_newpool);
847  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
848  int i;
849  for (i = 0; i < p; i++) {
850  if (pools[i] == ABT_POOL_NULL)
851  ABTI_pool_free(ABTI_pool_get_ptr(pool_list[i]));
852  }
853  ABTU_free(pool_list);
854  ABTU_free(p_sched);
855  return abt_errno;
856  }
857  pool_list[p] = ABTI_pool_get_handle(p_newpool);
858  } else {
859  pool_list[p] = pools[p];
860  }
861  }
862  /* Check if the pools are available */
863  for (p = 0; p < num_pools; p++) {
864  ABTI_pool_retain(ABTI_pool_get_ptr(pool_list[p]));
865  }
866 
867  p_sched->used = ABTI_SCHED_NOT_USED;
868  p_sched->automatic = automatic;
869  p_sched->kind = sched_get_kind(def);
870  ABTD_atomic_relaxed_store_uint32(&p_sched->request, 0);
871  p_sched->pools = pool_list;
872  p_sched->num_pools = num_pools;
873  p_sched->type = def->type;
874  p_sched->p_ythread = NULL;
875 
876  p_sched->init = def->init;
877  p_sched->run = def->run;
878  p_sched->free = def->free;
879  p_sched->get_migr_pool = def->get_migr_pool;
880 
881 #ifdef ABT_CONFIG_USE_DEBUG_LOG
882  p_sched->id = sched_get_new_id();
883 #endif
884  LOG_DEBUG("[S%" PRIu64 "] created\n", p_sched->id);
885 
886  /* Return value */
887  ABT_sched newsched = ABTI_sched_get_handle(p_sched);
888 
889  /* Specific initialization */
890  abt_errno = p_sched->init(newsched, config);
891  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
892  for (p = 0; p < num_pools; p++) {
893  if (pools[p] == ABT_POOL_NULL) {
894  ABTI_pool_free(ABTI_pool_get_ptr(pool_list[p]));
895  } else {
896  ABTI_pool_release(ABTI_pool_get_ptr(pool_list[p]));
897  }
898  }
899  ABTU_free(pool_list);
900  ABTU_free(p_sched);
901  return abt_errno;
902  }
903 
904  *pp_newsched = p_sched;
905 
906  return ABT_SUCCESS;
907 }
908 
909 #ifdef ABT_CONFIG_USE_DEBUG_LOG
910 static inline uint64_t sched_get_new_id(void)
911 {
912  return ABTD_atomic_fetch_add_uint64(&g_sched_id, 1);
913 }
914 #endif
ABT_sched_free_fn free
Definition: abt.h:465
int ABT_sched_get_size(ABT_sched sched, size_t *size) ABT_API_PUBLIC
Get the sum of the sizes of the pool of sched.
Definition: sched.c:372
#define ABT_POOL_NULL
Definition: abt.h:413
ABT_sched_predef
Definition: abt.h:143
struct ABT_sched_opaque * ABT_sched
Definition: abt.h:319
int ABT_sched_finish(ABT_sched sched) ABT_API_PUBLIC
Ask a scheduler to finish.
Definition: sched.c:226
static ABTU_ret_err int sched_create(ABT_sched_def *def, int num_pools, ABT_pool *pools, ABT_sched_config config, ABT_bool automatic, ABTI_sched **pp_newsched)
Definition: sched.c:823
ABT_sched_init_fn init
Definition: abt.h:463
int ABT_bool
Definition: abt.h:373
int ABT_sched_create(ABT_sched_def *def, int num_pools, ABT_pool *pools, ABT_sched_config config, ABT_sched *newsched) ABT_API_PUBLIC
Create a new user-defined scheduler and return its handle through newsched.
Definition: sched.c:41
static ABTI_sched_kind sched_get_kind(ABT_sched_def *def)
Definition: sched.c:818
#define ABT_ERR_SCHED
Definition: abt.h:97
struct ABT_pool_opaque * ABT_pool
Definition: abt.h:329
int ABT_sched_exit(ABT_sched sched) ABT_API_PUBLIC
Ask a scheduler to stop as soon as possible.
Definition: sched.c:255
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:142
#define ABT_FALSE
Definition: abt.h:285
int ABT_sched_get_num_pools(ABT_sched sched, int *num_pools) ABT_API_PUBLIC
Get the number of pools associated with scheduler.
Definition: sched.c:165
int ABT_sched_get_total_size(ABT_sched sched, size_t *size) ABT_API_PUBLIC
Get the sum of the sizes of the pool of sched.
Definition: sched.c:413
#define HANDLE_ERROR_FUNC_WITH_CODE(n)
Definition: abti_error.h:353
#define ABT_SUCCESS
Definition: abt.h:64
int ABT_sched_free(ABT_sched *sched) ABT_API_PUBLIC
Release the scheduler object associated with sched handle.
Definition: sched.c:130
ABT_pool_access
Definition: abt.h:161
#define ABT_TRUE
Definition: abt.h:284
#define ABT_SCHED_NULL
Definition: abt.h:411
ABT_sched_type type
Definition: abt.h:460
ABT_pool_kind
Definition: abt.h:156
int ABT_sched_get_data(ABT_sched sched, void **data) ABT_API_PUBLIC
Retrieve the specific data of the target user-defined scheduler.
Definition: sched.c:344
int ABT_sched_get_pools(ABT_sched sched, int max_pools, int idx, ABT_pool *pools) ABT_API_PUBLIC
Get the pools of the scheduler sched.
Definition: sched.c:193
int ABT_sched_create_basic(ABT_sched_predef predef, int num_pools, ABT_pool *pools, ABT_sched_config config, ABT_sched *newsched) ABT_API_PUBLIC
Create a predefined scheduler.
Definition: sched.c:97
static ABTD_atomic_uint64 g_sched_id
Definition: sched.c:808
#define LOG_DEBUG(fmt,...)
Definition: abti_log.h:26
struct ABT_sched_config_opaque * ABT_sched_config
Definition: abt.h:321
ABT_sched_get_migr_pool_fn get_migr_pool
Definition: abt.h:466
#define ABT_SCHED_CONFIG_NULL
Definition: abt.h:412
ABT_sched_run_fn run
Definition: abt.h:464
int ABT_sched_set_data(ABT_sched sched, void *data) ABT_API_PUBLIC
Set the specific data of the target user-defined scheduler.
Definition: sched.c:317
static void ABTU_free(void *ptr)
Definition: abtu.h:135
int ABT_sched_has_to_stop(ABT_sched sched, ABT_bool *stop) ABT_API_PUBLIC
Check if the scheduler needs to stop.
Definition: sched.c:288
#define ABTU_ret_err
Definition: abtu.h:49
#define ABT_ERR_INV_SCHED_PREDEF
Definition: abt.h:73