ARGOBOTS  4dc37e16e1b227a480715ab67dae1dcfb4d2d4e0
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,
10  ABTI_sched_config *p_config,
11  ABT_bool def_automatic,
12  ABTI_sched **pp_newsched);
13 static inline ABTI_sched_kind sched_get_kind(ABT_sched_def *def);
14 #ifdef ABT_CONFIG_USE_DEBUG_LOG
15 static inline uint64_t sched_get_new_id(void);
16 #endif
17 
91 int ABT_sched_create(ABT_sched_def *def, int num_pools, ABT_pool *pools,
92  ABT_sched_config config, ABT_sched *newsched)
93 {
94  ABTI_UB_ASSERT(ABTI_initialized());
95  ABTI_UB_ASSERT(def);
96  ABTI_UB_ASSERT(def->run);
97  ABTI_UB_ASSERT(pools || num_pools == 0);
98 
99  ABTI_sched *p_sched;
100 #ifndef ABT_CONFIG_ENABLE_VER_20_API
101  *newsched = ABT_SCHED_NULL;
102  ABTI_CHECK_TRUE(newsched != NULL, ABT_ERR_SCHED);
103 #else
104  ABTI_UB_ASSERT(newsched);
105 #endif
106  ABTI_CHECK_TRUE(num_pools >= 0, ABT_ERR_INV_ARG);
107 
108  /* The default automatic is different from ABT_sched_create_basic(). */
109  const ABT_bool def_automatic = ABT_FALSE;
110  ABTI_sched_config *p_config = ABTI_sched_config_get_ptr(config);
111  int abt_errno =
112  sched_create(def, num_pools, pools, p_config, def_automatic, &p_sched);
113  ABTI_CHECK_ERROR(abt_errno);
114 
115  /* Return value */
116  *newsched = ABTI_sched_get_handle(p_sched);
117  return ABT_SUCCESS;
118 }
119 
181 int ABT_sched_create_basic(ABT_sched_predef predef, int num_pools,
182  ABT_pool *pools, ABT_sched_config config,
183  ABT_sched *newsched)
184 {
185  ABTI_UB_ASSERT(ABTI_initialized());
186 
187 #ifndef ABT_CONFIG_ENABLE_VER_20_API
188  *newsched = ABT_SCHED_NULL;
189  ABTI_CHECK_TRUE(newsched != NULL, ABT_ERR_SCHED);
190 #else
191  ABTI_UB_ASSERT(newsched);
192 #endif
193  ABTI_CHECK_TRUE(num_pools >= 0, ABT_ERR_INV_ARG);
194 
195  ABTI_sched *p_newsched;
196  ABTI_sched_config *p_config = ABTI_sched_config_get_ptr(config);
197  int abt_errno = ABTI_sched_create_basic(predef, num_pools, pools, p_config,
198  &p_newsched);
199  ABTI_CHECK_ERROR(abt_errno);
200  *newsched = ABTI_sched_get_handle(p_newsched);
201  return ABT_SUCCESS;
202 }
203 
246 {
247  ABTI_UB_ASSERT(ABTI_initialized());
248  ABTI_UB_ASSERT(sched);
249 
250  ABTI_global *p_global;
251  ABTI_SETUP_GLOBAL(&p_global);
252  ABTI_local *p_local = ABTI_local_get_local();
253  ABTI_sched *p_sched = ABTI_sched_get_ptr(*sched);
254  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
255 #ifndef ABT_CONFIG_ENABLE_VER_20_API
256  ABTI_CHECK_TRUE(p_sched->used == ABTI_SCHED_NOT_USED, ABT_ERR_SCHED);
257 #else
258  ABTI_UB_ASSERT(p_sched->used == ABTI_SCHED_NOT_USED);
259 #endif
260 
261  /* Free the scheduler */
262  ABTI_sched_free(p_global, p_local, p_sched, ABT_FALSE);
263 
264  /* Return value */
265  *sched = ABT_SCHED_NULL;
266  return ABT_SUCCESS;
267 }
268 
291 int ABT_sched_get_num_pools(ABT_sched sched, int *num_pools)
292 {
293  ABTI_UB_ASSERT(ABTI_initialized());
294  ABTI_UB_ASSERT(num_pools);
295 
296  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
297  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
298 
299  *num_pools = p_sched->num_pools;
300  return ABT_SUCCESS;
301 }
302 
339 int ABT_sched_get_pools(ABT_sched sched, int max_pools, int idx,
340  ABT_pool *pools)
341 {
342  ABTI_UB_ASSERT(ABTI_initialized());
343  ABTI_UB_ASSERT(pools || max_pools > 0);
344 
345  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
346  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
347  ABTI_CHECK_TRUE(max_pools >= 0, ABT_ERR_INV_ARG);
348  ABTI_CHECK_TRUE(idx >= 0, ABT_ERR_INV_ARG);
349 #ifndef ABT_CONFIG_ENABLE_VER_20_API
350  ABTI_CHECK_TRUE((size_t)(idx + max_pools) <= p_sched->num_pools,
351  ABT_ERR_SCHED);
352 #endif
353 
354  size_t p;
355  for (p = idx; p < (size_t)idx + max_pools; p++) {
356  if (p >= p_sched->num_pools) {
357  /* Out of range. */
358  break;
359  }
360  pools[p - idx] = p_sched->pools[p];
361  }
362  return ABT_SUCCESS;
363 }
364 
396 {
397  ABTI_UB_ASSERT(ABTI_initialized());
398 
399  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
400  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
401 
402  ABTI_sched_finish(p_sched);
403  return ABT_SUCCESS;
404 }
405 
435 {
436  ABTI_UB_ASSERT(ABTI_initialized());
437 
438  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
439  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
440 
441  ABTI_sched_exit(p_sched);
442  return ABT_SUCCESS;
443 }
444 
483 {
484  ABTI_UB_ASSERT(ABTI_initialized());
485  ABTI_UB_ASSERT(stop);
486 
487 #ifndef ABT_CONFIG_ENABLE_VER_20_API
488  *stop = ABT_FALSE;
489 #endif
490  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
491  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
492 #ifndef ABT_CONFIG_ENABLE_VER_20_API
493  ABTI_CHECK_TRUE(ABTI_local_get_local(), ABT_ERR_INV_XSTREAM);
494 #endif
495 
496  *stop = ABTI_sched_has_to_stop(p_sched);
497  return ABT_SUCCESS;
498 }
499 
522 int ABT_sched_set_data(ABT_sched sched, void *data)
523 {
524  ABTI_UB_ASSERT(ABTI_initialized());
525 
526  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
527  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
528 
529  p_sched->data = data;
530  return ABT_SUCCESS;
531 }
532 
556 int ABT_sched_get_data(ABT_sched sched, void **data)
557 {
558  ABTI_UB_ASSERT(ABTI_initialized());
559  ABTI_UB_ASSERT(data);
560 
561  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
562  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
563 
564  *data = p_sched->data;
565  return ABT_SUCCESS;
566 }
603 int ABT_sched_get_size(ABT_sched sched, size_t *size)
604 {
605  ABTI_UB_ASSERT(ABTI_initialized());
606  ABTI_UB_ASSERT(size);
607 
608 #ifndef ABT_CONFIG_ENABLE_VER_20_API
609  *size = 0;
610 #endif
611 
612  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
613  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
614  /* Check availability of p_get_size() */
615  size_t p;
616  for (p = 0; p < p_sched->num_pools; p++) {
617  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
618  ABTI_CHECK_TRUE(p_pool->optional_def.p_get_size, ABT_ERR_POOL);
619  }
620 
621  /* Sum up all the sizes */
622  size_t pool_size = 0;
623  for (p = 0; p < p_sched->num_pools; p++) {
624  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
625  pool_size += ABTI_pool_get_size(p_pool);
626  }
627  *size = pool_size;
628  return ABT_SUCCESS;
629 }
630 
668 int ABT_sched_get_total_size(ABT_sched sched, size_t *size)
669 {
670  ABTI_UB_ASSERT(ABTI_initialized());
671  ABTI_UB_ASSERT(size);
672 
673 #ifndef ABT_CONFIG_ENABLE_VER_20_API
674  *size = 0;
675 #endif
676 
677  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
678  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
679  /* Check availability of p_get_size() */
680  size_t p;
681  for (p = 0; p < p_sched->num_pools; p++) {
682  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
683  ABTI_CHECK_TRUE(p_pool->optional_def.p_get_size, ABT_ERR_POOL);
684  }
685 
686  /* Sum up all the sizes */
687  size_t pool_size = 0;
688  for (p = 0; p < p_sched->num_pools; p++) {
689  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
690  pool_size += ABTI_pool_get_total_size(p_pool);
691  }
692  *size = pool_size;
693  return ABT_SUCCESS;
694 }
695 
696 /*****************************************************************************/
697 /* Private APIs */
698 /*****************************************************************************/
699 
700 void ABTI_sched_finish(ABTI_sched *p_sched)
701 {
702  ABTI_sched_set_request(p_sched, ABTI_SCHED_REQ_FINISH);
703 }
704 
705 void ABTI_sched_exit(ABTI_sched *p_sched)
706 {
707  ABTI_sched_set_request(p_sched, ABTI_SCHED_REQ_EXIT);
708 }
709 
710 ABTU_ret_err int ABTI_sched_create_basic(ABT_sched_predef predef, int num_pools,
711  ABT_pool *pools,
712  ABTI_sched_config *p_config,
713  ABTI_sched **pp_newsched)
714 {
715  int abt_errno;
717  /* The default value is different from ABT_sched_create. */
718  const ABT_bool def_automatic = ABT_TRUE;
719  /* Always use MPMC pools */
720  const ABT_pool_access def_access = ABT_POOL_ACCESS_MPMC;
721 
722  /* A pool array is provided, predef has to be compatible */
723  if (pools != NULL) {
724  /* Copy of the contents of pools */
725  ABT_pool *pool_list;
726  if (num_pools > 0) {
727  abt_errno =
728  ABTU_malloc(num_pools * sizeof(ABT_pool), (void **)&pool_list);
729  ABTI_CHECK_ERROR(abt_errno);
730 
731  int p;
732  for (p = 0; p < num_pools; p++) {
733  if (pools[p] == ABT_POOL_NULL) {
734  ABTI_pool *p_newpool;
735  abt_errno =
736  ABTI_pool_create_basic(ABT_POOL_FIFO, def_access,
737  ABT_TRUE, &p_newpool);
738  if (ABTI_IS_ERROR_CHECK_ENABLED &&
739  abt_errno != ABT_SUCCESS) {
740  /* Remove pools that are already created. */
741  int i;
742  for (i = 0; i < p; i++) {
743  if (pools[i] != ABT_POOL_NULL)
744  continue; /* User given pool. */
745  /* Free a pool created in this function. */
746  ABTI_pool_free(ABTI_pool_get_ptr(pool_list[i]));
747  }
748  ABTU_free(pool_list);
749  ABTI_HANDLE_ERROR(abt_errno);
750  }
751  pool_list[p] = ABTI_pool_get_handle(p_newpool);
752  } else {
753  pool_list[p] = pools[p];
754  }
755  }
756  } else {
757  /* TODO: Check if it works. */
758  pool_list = NULL;
759  }
760 
761  /* Creation of the scheduler */
762  switch (predef) {
763  case ABT_SCHED_DEFAULT:
764  case ABT_SCHED_BASIC:
765  abt_errno = sched_create(ABTI_sched_get_basic_def(), num_pools,
766  pool_list, p_config, def_automatic,
767  pp_newsched);
768  break;
770  abt_errno = sched_create(ABTI_sched_get_basic_wait_def(),
771  num_pools, pool_list, p_config,
772  def_automatic, pp_newsched);
773  break;
774  case ABT_SCHED_PRIO:
775  abt_errno = sched_create(ABTI_sched_get_prio_def(), num_pools,
776  pool_list, p_config, def_automatic,
777  pp_newsched);
778  break;
779  case ABT_SCHED_RANDWS:
780  abt_errno = sched_create(ABTI_sched_get_randws_def(), num_pools,
781  pool_list, p_config, def_automatic,
782  pp_newsched);
783  break;
784  default:
785  abt_errno = ABT_ERR_INV_SCHED_PREDEF;
786  break;
787  }
788  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
789  /* Remove pools that are already created. */
790  int i;
791  for (i = 0; i < num_pools; i++) {
792  if (pools[i] != ABT_POOL_NULL)
793  continue; /* User given pool. */
794  /* Free a pool created in this function. */
795  ABTI_pool_free(ABTI_pool_get_ptr(pool_list[i]));
796  }
797  ABTU_free(pool_list);
798  ABTI_HANDLE_ERROR(abt_errno);
799  }
800  ABTU_free(pool_list);
801  } else { /* No pool array is provided, predef has to be compatible */
802  /* Set the number of pools */
803  switch (predef) {
804  case ABT_SCHED_DEFAULT:
805  case ABT_SCHED_BASIC:
806  num_pools = 1;
807  break;
809  /* FIFO_WAIT is default pool for use with BASIC_WAIT sched */
810  kind = ABT_POOL_FIFO_WAIT;
811  num_pools = 1;
812  break;
813  case ABT_SCHED_PRIO:
814  num_pools = ABTI_SCHED_NUM_PRIO;
815  break;
816  case ABT_SCHED_RANDWS:
817  num_pools = 1;
818  break;
819  default:
820  abt_errno = ABT_ERR_INV_SCHED_PREDEF;
821  ABTI_CHECK_ERROR(abt_errno);
822  break;
823  }
824 
825  /* Creation of the pools */
826  /* To avoid the malloc overhead, we use a stack array. */
827  ABT_pool pool_list[ABTI_SCHED_NUM_PRIO];
828  int p;
829  /* ICC 19 warns an unused variable in the following error path. To
830  * suppress the warning, let's initialize the array member here. */
831  for (p = 0; p < num_pools; p++)
832  pool_list[p] = ABT_POOL_NULL;
833  for (p = 0; p < num_pools; p++) {
834  ABTI_pool *p_newpool;
835  abt_errno =
836  ABTI_pool_create_basic(kind, def_access, ABT_TRUE, &p_newpool);
837  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
838  /* Remove pools that are already created. */
839  int i;
840  for (i = 0; i < p; i++) {
841  /* Free a pool created in this function. */
842  ABTI_pool_free(ABTI_pool_get_ptr(pool_list[i]));
843  }
844  ABTI_HANDLE_ERROR(abt_errno);
845  }
846  pool_list[p] = ABTI_pool_get_handle(p_newpool);
847  }
848 
849  /* Creation of the scheduler */
850  switch (predef) {
851  case ABT_SCHED_DEFAULT:
852  case ABT_SCHED_BASIC:
853  abt_errno = sched_create(ABTI_sched_get_basic_def(), num_pools,
854  pool_list, p_config, def_automatic,
855  pp_newsched);
856  break;
858  abt_errno = sched_create(ABTI_sched_get_basic_wait_def(),
859  num_pools, pool_list, p_config,
860  def_automatic, pp_newsched);
861  break;
862  case ABT_SCHED_PRIO:
863  abt_errno = sched_create(ABTI_sched_get_prio_def(), num_pools,
864  pool_list, p_config, def_automatic,
865  pp_newsched);
866  break;
867  case ABT_SCHED_RANDWS:
868  abt_errno = sched_create(ABTI_sched_get_randws_def(), num_pools,
869  pool_list, p_config, def_automatic,
870  pp_newsched);
871  break;
872  default:
873  abt_errno = ABT_ERR_INV_SCHED_PREDEF;
874  break;
875  }
876  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
877  /* Remove pools that are already created. */
878  int i;
879  for (i = 0; i < num_pools; i++) {
880  /* Free a pool created in this function. */
881  ABTI_pool_free(ABTI_pool_get_ptr(pool_list[i]));
882  }
883  ABTI_HANDLE_ERROR(abt_errno);
884  }
885  }
886  return ABT_SUCCESS;
887 }
888 
889 void ABTI_sched_free(ABTI_global *p_global, ABTI_local *p_local,
890  ABTI_sched *p_sched, ABT_bool force_free)
891 {
892  ABTI_ASSERT(p_sched->used == ABTI_SCHED_NOT_USED);
893  /* Free the scheduler first. */
894  if (p_sched->free) {
895  p_sched->free(ABTI_sched_get_handle(p_sched));
896  }
897  /* If sched is a default provided one, it should free its pool here.
898  * Otherwise, freeing the pool is the user's responsibility. */
899  size_t p;
900  for (p = 0; p < p_sched->num_pools; p++) {
901  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]);
902  if (!p_pool) {
903  /* p_pool can be set to NULL when that p_pool must be preserved,
904  * for example, when this function is called because
905  * ABT_xstream_create_basic() fails. */
906  continue;
907  }
908  int32_t num_scheds = ABTI_pool_release(p_pool);
909  if ((p_pool->automatic == ABT_TRUE && num_scheds == 0) || force_free) {
910  ABTI_pool_free(p_pool);
911  }
912  }
913  ABTU_free(p_sched->pools);
914 
915  /* Free the associated work unit */
916  if (p_sched->p_ythread) {
917  ABTI_thread_free(p_global, p_local, &p_sched->p_ythread->thread);
918  }
919 
920  p_sched->data = NULL;
921 
922  ABTU_free(p_sched);
923 }
924 
925 ABT_bool ABTI_sched_has_to_stop(ABTI_sched *p_sched)
926 {
927  /* Check exit request */
928  if (ABTD_atomic_acquire_load_uint32(&p_sched->request) &
929  ABTI_SCHED_REQ_EXIT) {
930  return ABT_TRUE;
931  }
932 
933  if (!ABTI_sched_has_unit(p_sched)) {
934  if (ABTD_atomic_acquire_load_uint32(&p_sched->request) &
935  (ABTI_SCHED_REQ_FINISH | ABTI_SCHED_REQ_REPLACE)) {
936  /* Check join request */
937  if (!ABTI_sched_has_unit(p_sched))
938  return ABT_TRUE;
939  } else if (p_sched->used == ABTI_SCHED_IN_POOL) {
940  /* Let's finish it anyway.
941  * TODO: think about the condition. */
942  return ABT_TRUE;
943  }
944  }
945  return ABT_FALSE;
946 }
947 
948 ABT_bool ABTI_sched_has_unit(ABTI_sched *p_sched)
949 {
950  /* ABTI_sched_has_unit() does not count the number of blocked ULTs if a pool
951  * has more than one consumer or the caller ES is not the latest consumer.
952  * This is necessary when the ES associated with the target scheduler has to
953  * be joined and the pool is shared between different schedulers associated
954  * with different ESs. */
955  size_t p, num_pools = p_sched->num_pools;
956  for (p = 0; p < num_pools; p++) {
957  ABT_pool pool = p_sched->pools[p];
958  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
959  if (!ABTI_pool_is_empty(p_pool))
960  return ABT_TRUE;
961  switch (p_pool->access) {
963  if (ABTD_atomic_acquire_load_int32(&p_pool->num_blocked))
964  return ABT_TRUE;
965  break;
970  if (ABTD_atomic_acquire_load_int32(&p_pool->num_scheds) == 1) {
971  if (ABTD_atomic_acquire_load_int32(&p_pool->num_blocked))
972  return ABT_TRUE;
973  }
974  break;
975  default:
976  break;
977  }
978  }
979  return ABT_FALSE;
980 }
981 
982 /* Get the pool suitable for receiving a migrating thread */
983 ABTU_ret_err int ABTI_sched_get_migration_pool(ABTI_sched *p_sched,
984  ABTI_pool *source_pool,
985  ABTI_pool **pp_pool)
986 {
987  /* Find a pool. If get_migr_pool is not defined, we pick the first pool */
988  if (p_sched->get_migr_pool == NULL) {
989  ABTI_CHECK_TRUE(p_sched->num_pools > 0, ABT_ERR_MIGRATION_TARGET);
990  *pp_pool = ABTI_pool_get_ptr(p_sched->pools[0]);
991  } else {
992  ABT_sched sched = ABTI_sched_get_handle(p_sched);
993  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->get_migr_pool(sched));
994  ABTI_CHECK_TRUE(p_pool, ABT_ERR_MIGRATION_TARGET);
995  *pp_pool = p_pool;
996  }
997  return ABT_SUCCESS;
998 }
999 
1000 void ABTI_sched_print(ABTI_sched *p_sched, FILE *p_os, int indent,
1001  ABT_bool print_sub)
1002 {
1003  if (p_sched == NULL) {
1004  fprintf(p_os, "%*s== NULL SCHED ==\n", indent, "");
1005  } else {
1006  ABTI_sched_kind kind;
1007  const char *kind_str, *used;
1008 
1009  kind = p_sched->kind;
1010  if (kind == sched_get_kind(ABTI_sched_get_basic_def())) {
1011  kind_str = "BASIC";
1012  } else if (kind == sched_get_kind(ABTI_sched_get_basic_wait_def())) {
1013  kind_str = "BASIC_WAIT";
1014  } else if (kind == sched_get_kind(ABTI_sched_get_prio_def())) {
1015  kind_str = "PRIO";
1016  } else if (kind == sched_get_kind(ABTI_sched_get_randws_def())) {
1017  kind_str = "RANDWS";
1018  } else {
1019  kind_str = "USER";
1020  }
1021 
1022  switch (p_sched->used) {
1023  case ABTI_SCHED_NOT_USED:
1024  used = "NOT_USED";
1025  break;
1026  case ABTI_SCHED_MAIN:
1027  used = "MAIN";
1028  break;
1029  case ABTI_SCHED_IN_POOL:
1030  used = "IN_POOL";
1031  break;
1032  default:
1033  used = "UNKNOWN";
1034  break;
1035  }
1036 
1037  fprintf(p_os,
1038  "%*s== SCHED (%p) ==\n"
1039 #ifdef ABT_CONFIG_USE_DEBUG_LOG
1040  "%*sid : %" PRIu64 "\n"
1041 #endif
1042  "%*skind : %" PRIxPTR " (%s)\n"
1043  "%*sused : %s\n"
1044  "%*sautomatic: %s\n"
1045  "%*srequest : 0x%x\n"
1046  "%*snum_pools: %zu\n"
1047  "%*shas_unit : %s\n"
1048  "%*sthread : %p\n"
1049  "%*sdata : %p\n",
1050  indent, "", (void *)p_sched,
1051 #ifdef ABT_CONFIG_USE_DEBUG_LOG
1052  indent, "", p_sched->id,
1053 #endif
1054  indent, "", p_sched->kind, kind_str, indent, "", used, indent,
1055  "", (p_sched->automatic == ABT_TRUE) ? "TRUE" : "FALSE", indent,
1056  "", ABTD_atomic_acquire_load_uint32(&p_sched->request), indent,
1057  "", p_sched->num_pools, indent, "",
1058  (ABTI_sched_has_unit(p_sched) ? "TRUE" : "FALSE"), indent, "",
1059  (void *)p_sched->p_ythread, indent, "", p_sched->data);
1060  if (print_sub == ABT_TRUE) {
1061  size_t i;
1062  for (i = 0; i < p_sched->num_pools; i++) {
1063  ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[i]);
1064  ABTI_pool_print(p_pool, p_os, indent + 2);
1065  }
1066  }
1067  }
1068  fflush(p_os);
1069 }
1070 
1071 static ABTD_atomic_uint64 g_sched_id = ABTD_ATOMIC_UINT64_STATIC_INITIALIZER(0);
1072 void ABTI_sched_reset_id(void)
1073 {
1074  ABTD_atomic_relaxed_store_uint64(&g_sched_id, 0);
1075 }
1076 
1077 /*****************************************************************************/
1078 /* Internal static functions */
1079 /*****************************************************************************/
1080 
1081 static inline ABTI_sched_kind sched_get_kind(ABT_sched_def *def)
1082 {
1083  return (ABTI_sched_kind)def;
1084 }
1085 
1086 ABTU_ret_err static int sched_create(ABT_sched_def *def, int num_pools,
1087  ABT_pool *pools,
1088  ABTI_sched_config *p_config,
1089  ABT_bool def_automatic,
1090  ABTI_sched **pp_newsched)
1091 {
1092  ABTI_sched *p_sched;
1093  int p, abt_errno;
1094 
1095  abt_errno = ABTU_malloc(sizeof(ABTI_sched), (void **)&p_sched);
1096  ABTI_CHECK_ERROR(abt_errno);
1097 
1098  /* We read the config and set the configured parameters */
1099  ABT_bool automatic = def_automatic;
1100  if (p_config) {
1101  int automatic_val = 0;
1102  abt_errno =
1103  ABTI_sched_config_read(p_config, ABT_sched_config_automatic.idx,
1104  &automatic_val);
1105  if (abt_errno == ABT_SUCCESS) {
1106  automatic = (automatic_val == 0) ? ABT_FALSE : ABT_TRUE;
1107  }
1108  }
1109 
1110  /* Copy of the contents of pools */
1111  ABT_pool *pool_list;
1112  abt_errno = ABTU_malloc(num_pools * sizeof(ABT_pool), (void **)&pool_list);
1113  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
1114  ABTU_free(p_sched);
1115  return abt_errno;
1116  }
1117  for (p = 0; p < num_pools; p++) {
1118  if (pools[p] == ABT_POOL_NULL) {
1119  ABTI_pool *p_newpool;
1120  abt_errno =
1121  ABTI_pool_create_basic(ABT_POOL_FIFO, ABT_POOL_ACCESS_MPSC,
1122  ABT_TRUE, &p_newpool);
1123  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
1124  int i;
1125  for (i = 0; i < p; i++) {
1126  if (pools[i] == ABT_POOL_NULL)
1127  ABTI_pool_free(ABTI_pool_get_ptr(pool_list[i]));
1128  }
1129  ABTU_free(pool_list);
1130  ABTU_free(p_sched);
1131  return abt_errno;
1132  }
1133  pool_list[p] = ABTI_pool_get_handle(p_newpool);
1134  } else {
1135  pool_list[p] = pools[p];
1136  }
1137  }
1138  /* Check if the pools are available */
1139  for (p = 0; p < num_pools; p++) {
1140  ABTI_pool_retain(ABTI_pool_get_ptr(pool_list[p]));
1141  }
1142 
1143  p_sched->used = ABTI_SCHED_NOT_USED;
1144  p_sched->automatic = automatic;
1145  p_sched->kind = sched_get_kind(def);
1146  p_sched->p_replace_sched = NULL;
1147  p_sched->p_replace_waiter = NULL;
1148  ABTD_atomic_relaxed_store_uint32(&p_sched->request, 0);
1149  p_sched->pools = pool_list;
1150  p_sched->num_pools = num_pools;
1151  p_sched->type = def->type;
1152  p_sched->p_ythread = NULL;
1153  p_sched->data = NULL;
1154 
1155  p_sched->init = def->init;
1156  p_sched->run = def->run;
1157  p_sched->free = def->free;
1158  p_sched->get_migr_pool = def->get_migr_pool;
1159 
1160 #ifdef ABT_CONFIG_USE_DEBUG_LOG
1161  p_sched->id = sched_get_new_id();
1162 #endif
1163 
1164  /* Return value */
1165  ABT_sched newsched = ABTI_sched_get_handle(p_sched);
1166 
1167  /* Specific initialization */
1168  if (p_sched->init) {
1169  ABT_sched_config config = ABTI_sched_config_get_handle(p_config);
1170  abt_errno = p_sched->init(newsched, config);
1171  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
1172  for (p = 0; p < num_pools; p++) {
1173  if (pools[p] == ABT_POOL_NULL) {
1174  ABTI_pool_free(ABTI_pool_get_ptr(pool_list[p]));
1175  } else {
1176  ABTI_pool_release(ABTI_pool_get_ptr(pool_list[p]));
1177  }
1178  }
1179  ABTU_free(pool_list);
1180  ABTU_free(p_sched);
1181  return abt_errno;
1182  }
1183  }
1184 
1185  *pp_newsched = p_sched;
1186 
1187  return ABT_SUCCESS;
1188 }
1189 
1190 #ifdef ABT_CONFIG_USE_DEBUG_LOG
1191 static inline uint64_t sched_get_new_id(void)
1192 {
1193  return ABTD_atomic_fetch_add_uint64(&g_sched_id, 1);
1194 }
1195 #endif
ABT_sched_predef
ABT_sched_predef
Predefined scheduler type.
Definition: abt.h:475
ABT_sched_create_basic
int ABT_sched_create_basic(ABT_sched_predef predef, int num_pools, ABT_pool *pools, ABT_sched_config config, ABT_sched *newsched)
Create a new scheduler with a predefined scheduler type.
Definition: sched.c:181
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1043
ABT_sched_def::type
ABT_sched_type type
Unused value.
Definition: abt.h:1418
ABT_ERR_INV_XSTREAM
#define ABT_ERR_INV_XSTREAM
Error code: invalid execution stream.
Definition: abt.h:114
ABT_ERR_INV_SCHED_PREDEF
#define ABT_ERR_INV_SCHED_PREDEF
Error code: invalid predefined scheduler type.
Definition: abt.h:139
ABT_ERR_POOL
#define ABT_ERR_POOL
Error code: error related to a pool.
Definition: abt.h:292
ABT_sched_exit
int ABT_sched_exit(ABT_sched sched)
Request a scheduler to finish.
Definition: sched.c:434
ABT_POOL_ACCESS_MPMC
@ ABT_POOL_ACCESS_MPMC
Definition: abt.h:575
ABT_sched_def::run
ABT_sched_run_fn run
Function that defines a kernel of a scheduler.
Definition: abt.h:1476
ABT_sched_config
struct ABT_sched_config_opaque * ABT_sched_config
Scheduler configuration handle type.
Definition: abt.h:852
ABT_SCHED_DEFAULT
@ ABT_SCHED_DEFAULT
Definition: abt.h:477
g_sched_id
static ABTD_atomic_uint64 g_sched_id
Definition: sched.c:1071
ABT_pool
struct ABT_pool_opaque * ABT_pool
Pool handle type.
Definition: abt.h:878
ABT_sched_config_automatic
ABT_sched_config_var ABT_sched_config_automatic
Predefined ABT_sched_config_var to configure whether the scheduler is freed automatically or not.
Definition: sched_config.c:47
ABT_POOL_ACCESS_MPSC
@ ABT_POOL_ACCESS_MPSC
Definition: abt.h:569
ABT_sched_finish
int ABT_sched_finish(ABT_sched sched)
Request a scheduler to finish after its pools get empty.
Definition: sched.c:395
ABT_POOL_ACCESS_PRIV
@ ABT_POOL_ACCESS_PRIV
Definition: abt.h:560
ABT_sched
struct ABT_sched_opaque * ABT_sched
Scheduler handle type.
Definition: abt.h:845
ABT_POOL_NULL
#define ABT_POOL_NULL
Definition: abt.h:1102
abti.h
sched_get_kind
static ABTI_sched_kind sched_get_kind(ABT_sched_def *def)
Definition: sched.c:1081
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:235
ABT_ERR_SCHED
#define ABT_ERR_SCHED
Error code: error related to a scheduler.
Definition: abt.h:282
sched_create
static ABTU_ret_err int sched_create(ABT_sched_def *def, int num_pools, ABT_pool *pools, ABTI_sched_config *p_config, ABT_bool def_automatic, ABTI_sched **pp_newsched)
Definition: sched.c:1086
ABT_POOL_FIFO
@ ABT_POOL_FIFO
Definition: abt.h:516
ABT_POOL_FIFO_WAIT
@ ABT_POOL_FIFO_WAIT
Definition: abt.h:525
ABT_sched_get_total_size
int ABT_sched_get_total_size(ABT_sched sched, size_t *size)
Obtain the sum of the total sizes of pools associated with a scheduler.
Definition: sched.c:668
ABT_ERR_MIGRATION_TARGET
#define ABT_ERR_MIGRATION_TARGET
Error code: error related to a migration target.
Definition: abt.h:370
ABT_SCHED_BASIC
@ ABT_SCHED_BASIC
Definition: abt.h:479
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABT_sched_def::get_migr_pool
ABT_sched_get_migr_pool_fn get_migr_pool
Function that returns a pool for migration.
Definition: abt.h:1509
ABTU_ret_err
#define ABTU_ret_err
Definition: abtu.h:155
ABT_sched_get_num_pools
int ABT_sched_get_num_pools(ABT_sched sched, int *num_pools)
Obtain the number of pools associated with a scheduler.
Definition: sched.c:291
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:784
ABT_SCHED_NULL
#define ABT_SCHED_NULL
Definition: abt.h:1100
ABT_POOL_ACCESS_SPMC
@ ABT_POOL_ACCESS_SPMC
Definition: abt.h:573
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:786
ABT_sched_def::free
ABT_sched_free_fn free
Function that frees a scheduler.
Definition: abt.h:1492
ABT_sched_set_data
int ABT_sched_set_data(ABT_sched sched, void *data)
Associate a user value with a scheduler.
Definition: sched.c:522
ABT_ERR_INV_ARG
#define ABT_ERR_INV_ARG
Error code: invalid user argument.
Definition: abt.h:260
ABT_POOL_ACCESS_SPSC
@ ABT_POOL_ACCESS_SPSC
Definition: abt.h:565
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:228
ABT_sched_def
A struct that defines a scheduler.
Definition: abt.h:1411
ABT_SCHED_BASIC_WAIT
@ ABT_SCHED_BASIC_WAIT
Definition: abt.h:489
ABT_SCHED_RANDWS
@ ABT_SCHED_RANDWS
Definition: abt.h:487
ABT_sched_has_to_stop
int ABT_sched_has_to_stop(ABT_sched sched, ABT_bool *stop)
Check if a scheduler needs to stop.
Definition: sched.c:482
ABT_sched_def::init
ABT_sched_init_fn init
Function that initializes a scheduler.
Definition: abt.h:1436
ABT_sched_free
int ABT_sched_free(ABT_sched *sched)
Free a scheduler.
Definition: sched.c:245
ABT_sched_get_pools
int ABT_sched_get_pools(ABT_sched sched, int max_pools, int idx, ABT_pool *pools)
Retrieve pools associated with a scheduler.
Definition: sched.c:339
ABT_pool_kind
ABT_pool_kind
Predefined pool type.
Definition: abt.h:514
ABT_sched_get_data
int ABT_sched_get_data(ABT_sched sched, void **data)
Retrieve a user value associated with a scheduler.
Definition: sched.c:556
ABT_sched_create
int ABT_sched_create(ABT_sched_def *def, int num_pools, ABT_pool *pools, ABT_sched_config config, ABT_sched *newsched)
Create a new scheduler with a scheduler definition.
Definition: sched.c:91
ABT_sched_config_var::idx
int idx
Definition: abt.h:1351
ABT_sched_get_size
int ABT_sched_get_size(ABT_sched sched, size_t *size)
Obtain the sum of sizes of pools associated with a scheduler.
Definition: sched.c:603
ABT_SCHED_PRIO
@ ABT_SCHED_PRIO
Definition: abt.h:483
ABT_pool_access
ABT_pool_access
Pool access type.
Definition: abt.h:556