ARGOBOTS  4dc37e16e1b227a480715ab67dae1dcfb4d2d4e0
basic_wait.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 static int sched_init(ABT_sched sched, ABT_sched_config config);
9 static void sched_run(ABT_sched sched);
10 static int sched_free(ABT_sched);
11 static void sched_sort_pools(int num_pools, ABT_pool *pools);
12 
15  .init = sched_init,
16  .run = sched_run,
17  .free = sched_free,
18  .get_migr_pool = NULL,
19 };
20 
21 typedef struct {
22  uint32_t event_freq;
23  int num_pools;
24  ABT_pool *pools;
25 } sched_data;
26 
27 ABT_sched_def *ABTI_sched_get_basic_wait_def(void)
28 {
29  return &sched_basic_wait_def;
30 }
31 
32 static inline sched_data *sched_data_get_ptr(void *data)
33 {
34  return (sched_data *)data;
35 }
36 
37 static int sched_init(ABT_sched sched, ABT_sched_config config)
38 {
39  int abt_errno;
40  int num_pools;
41  ABTI_global *p_global = ABTI_global_get_global();
42 
43  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
44  ABTI_CHECK_NULL_SCHED_PTR(p_sched);
45  ABTI_sched_config *p_config = ABTI_sched_config_get_ptr(config);
46 
47  /* Default settings */
48  sched_data *p_data;
49  abt_errno = ABTU_malloc(sizeof(sched_data), (void **)&p_data);
50  ABTI_CHECK_ERROR(abt_errno);
51 
52  /* Set the default value by default. */
53  p_data->event_freq = p_global->sched_event_freq;
54  if (p_config) {
55  int event_freq;
56  /* Set the variables from config */
57  abt_errno = ABTI_sched_config_read(p_config, ABT_sched_basic_freq.idx,
58  &event_freq);
59  if (abt_errno == ABT_SUCCESS) {
60  p_data->event_freq = event_freq;
61  }
62  }
63 
64  /* Save the list of pools */
65  num_pools = p_sched->num_pools;
66  p_data->num_pools = num_pools;
67  abt_errno =
68  ABTU_malloc(num_pools * sizeof(ABT_pool), (void **)&p_data->pools);
69  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
70  ABTU_free(p_data);
71  ABTI_CHECK_ERROR(abt_errno);
72  }
73  memcpy(p_data->pools, p_sched->pools, sizeof(ABT_pool) * num_pools);
74 
75  /* Sort pools according to their access mode so the scheduler can execute
76  work units from the private pools. */
77  if (num_pools > 1) {
78  sched_sort_pools(num_pools, p_data->pools);
79  }
80 
81  p_sched->data = p_data;
82  return ABT_SUCCESS;
83 }
84 
85 static void sched_run(ABT_sched sched)
86 {
87  ABTI_global *p_global = ABTI_global_get_global();
88  ABTI_xstream *p_local_xstream =
89  ABTI_local_get_xstream(ABTI_local_get_local());
90  uint32_t work_count = 0;
91  sched_data *p_data;
92  uint32_t event_freq;
93  int num_pools;
94  ABT_pool *pools;
95  int i;
96  int run_cnt_nowait;
97 
98  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
99  ABTI_ASSERT(p_sched);
100 
101  p_data = sched_data_get_ptr(p_sched->data);
102  event_freq = p_data->event_freq;
103  num_pools = p_data->num_pools;
104  pools = p_data->pools;
105 
106  while (1) {
107  run_cnt_nowait = 0;
108 
109  /* Execute one work unit from the scheduler's pool */
110  for (i = 0; i < num_pools; i++) {
111  ABT_pool pool = pools[i];
112  ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
113  /* Pop one work unit */
114  ABT_thread thread =
115  ABTI_pool_pop(p_pool, ABT_POOL_CONTEXT_OP_POOL_OTHER);
116  if (thread != ABT_THREAD_NULL) {
117  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
118  ABTI_ythread_schedule(p_global, &p_local_xstream, p_thread);
119  run_cnt_nowait++;
120  break;
121  }
122  }
123 
124  /* Block briefly on pop_wait() if we didn't find work to do in main loop
125  * above. */
126  if (!run_cnt_nowait) {
127  ABTI_pool *p_pool = ABTI_pool_get_ptr(pools[0]);
128  ABT_thread thread;
129  if (p_pool->optional_def.p_pop_wait) {
130  thread = ABTI_pool_pop_wait(p_pool, 0.1,
132  } else if (p_pool->deprecated_def.p_pop_timedwait) {
133  thread =
134  ABTI_pool_pop_timedwait(p_pool, ABTI_get_wtime() + 0.1);
135  } else {
136  /* No "wait" pop, so let's use a normal one. */
137  thread = ABTI_pool_pop(p_pool, ABT_POOL_CONTEXT_OP_POOL_OTHER);
138  }
139  if (thread != ABT_THREAD_NULL) {
140  ABTI_thread *p_thread = ABTI_thread_get_ptr(thread);
141  ABTI_ythread_schedule(p_global, &p_local_xstream, p_thread);
142  break;
143  }
144  }
145 
146  /* If run_cnt_nowait is zero, that means that no units were found in
147  * first pass through pools and we must have called pop_wait above. We
148  * should check events regardless of work_count in that case for them to
149  * be processed in a timely manner. */
150  if (!run_cnt_nowait || (++work_count >= event_freq)) {
151  ABTI_xstream_check_events(p_local_xstream, p_sched);
152  if (ABTI_sched_has_to_stop(p_sched) == ABT_TRUE)
153  break;
154  work_count = 0;
155  }
156  }
157 }
158 
159 static int sched_free(ABT_sched sched)
160 {
161  ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
162  ABTI_ASSERT(p_sched);
163 
164  sched_data *p_data = sched_data_get_ptr(p_sched->data);
165  ABTU_free(p_data->pools);
166  ABTU_free(p_data);
167  return ABT_SUCCESS;
168 }
169 
170 static int pool_get_access_num(ABT_pool *p_pool)
171 {
172  ABT_pool_access access;
173  int num = 0;
174 
175  access = ABTI_pool_get_ptr(*p_pool)->access;
176  switch (access) {
178  num = 0;
179  break;
182  num = 1;
183  break;
186  num = 2;
187  break;
188  default:
189  ABTI_ASSERT(0);
191  }
192 
193  return num;
194 }
195 
196 static int sched_cmp_pools(const void *p1, const void *p2)
197 {
198  int p1_access, p2_access;
199 
200  p1_access = pool_get_access_num((ABT_pool *)p1);
201  p2_access = pool_get_access_num((ABT_pool *)p2);
202 
203  if (p1_access > p2_access) {
204  return 1;
205  } else if (p1_access < p2_access) {
206  return -1;
207  } else {
208  return 0;
209  }
210 }
211 
212 static void sched_sort_pools(int num_pools, ABT_pool *pools)
213 {
214  qsort(pools, num_pools, sizeof(ABT_pool), sched_cmp_pools);
215 }
ABT_sched_def::type
ABT_sched_type type
Unused value.
Definition: abt.h:1418
ABT_thread
struct ABT_thread_opaque * ABT_thread
Work unit handle type.
Definition: abt.h:932
ABT_POOL_CONTEXT_OP_POOL_OTHER
#define ABT_POOL_CONTEXT_OP_POOL_OTHER
A flag that hints an unspecified pool operation.
Definition: abt.h:1660
sched_run
static void sched_run(ABT_sched sched)
Definition: basic_wait.c:85
sched_init
static int sched_init(ABT_sched sched, ABT_sched_config config)
Definition: basic_wait.c:37
ABT_POOL_ACCESS_MPMC
@ ABT_POOL_ACCESS_MPMC
Definition: abt.h:575
ABT_sched_config
struct ABT_sched_config_opaque * ABT_sched_config
Scheduler configuration handle type.
Definition: abt.h:852
sched_data_get_ptr
static sched_data * sched_data_get_ptr(void *data)
Definition: basic_wait.c:32
pool_get_access_num
static int pool_get_access_num(ABT_pool *p_pool)
Definition: basic_wait.c:170
ABT_THREAD_NULL
#define ABT_THREAD_NULL
Definition: abt.h:1105
ABT_pool
struct ABT_pool_opaque * ABT_pool
Pool handle type.
Definition: abt.h:878
ABT_POOL_ACCESS_MPSC
@ ABT_POOL_ACCESS_MPSC
Definition: abt.h:569
ABTU_unreachable
#define ABTU_unreachable()
Definition: abtu.h:133
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_SCHED_TYPE_ULT
@ ABT_SCHED_TYPE_ULT
Definition: abt.h:502
abti.h
sched_free
static int sched_free(ABT_sched)
Definition: basic_wait.c:159
sched_basic_wait_def
static ABT_sched_def sched_basic_wait_def
Definition: basic_wait.c:13
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:235
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:784
ABT_POOL_ACCESS_SPMC
@ ABT_POOL_ACCESS_SPMC
Definition: abt.h:573
sched_cmp_pools
static int sched_cmp_pools(const void *p1, const void *p2)
Definition: basic_wait.c:196
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_freq
ABT_sched_config_var ABT_sched_basic_freq
Predefined ABT_sched_config_var to configure the frequency for checking events of the basic scheduler...
Definition: sched_config.c:51
sched_sort_pools
static void sched_sort_pools(int num_pools, ABT_pool *pools)
Definition: basic_wait.c:212
ABT_sched_config_var::idx
int idx
Definition: abt.h:1351
ABT_pool_access
ABT_pool_access
Pool access type.
Definition: abt.h:556