ARGOBOTS  1227c643f7a7f974f1f1778a9ffebd29d7dafecf
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
global.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 
13 /* Global Data */
14 ABTI_global *gp_ABTI_global = NULL;
15 
16 /* To indicate how many times ABT_init is called. */
17 static uint32_t g_ABTI_num_inits = 0;
18 /* A global lock protecting the initialization/finalization process */
19 static ABTI_spinlock g_ABTI_init_lock = ABTI_SPINLOCK_STATIC_INITIALIZER();
20 /* A flag whether Argobots has been initialized or not */
21 static ABTD_atomic_uint32 g_ABTI_initialized =
22  ABTD_ATOMIC_UINT32_STATIC_INITIALIZER(0);
23 
40 int ABT_init(int argc, char **argv)
41 {
42  ABTI_UNUSED(argc);
43  ABTI_UNUSED(argv);
44  int abt_errno = ABT_SUCCESS;
45 
46  /* First, take a global lock protecting the initialization/finalization
47  * process. Don't go to fn_exit before taking a lock */
48  ABTI_spinlock_acquire(&g_ABTI_init_lock);
49 
50  /* If Argobots has already been initialized, just return */
51  if (g_ABTI_num_inits++ > 0)
52  goto fn_exit;
53 
54  abt_errno = ABTU_malloc(sizeof(ABTI_global), (void **)&gp_ABTI_global);
55  ABTI_CHECK_ERROR(abt_errno);
56 
57  /* Initialize the system environment */
58  ABTD_env_init(gp_ABTI_global);
59 
60  /* Initialize memory pool */
61  ABTI_mem_init(gp_ABTI_global);
62 
63  /* Initialize IDs */
64  ABTI_thread_reset_id();
65  ABTI_sched_reset_id();
66  ABTI_pool_reset_id();
67 
68 #ifndef ABT_CONFIG_DISABLE_TOOL_INTERFACE
69  /* Initialize the tool interface */
70  ABTI_spinlock_clear(&gp_ABTI_global->tool_writer_lock);
71  gp_ABTI_global->tool_thread_cb_f = NULL;
72  gp_ABTI_global->tool_thread_user_arg = NULL;
73  gp_ABTI_global->tool_task_cb_f = NULL;
74  gp_ABTI_global->tool_task_user_arg = NULL;
75  ABTD_atomic_relaxed_store_uint64(&gp_ABTI_global
76  ->tool_thread_event_mask_tagged,
77  0);
78 #endif
79 
80  /* Initialize the ES list */
81  gp_ABTI_global->p_xstream_head = NULL;
82  gp_ABTI_global->num_xstreams = 0;
83 
84  /* Initialize a spinlock */
85  ABTI_spinlock_clear(&gp_ABTI_global->xstream_list_lock);
86 
87  /* Create the primary ES */
88  ABTI_xstream *p_local_xstream;
89  abt_errno = ABTI_xstream_create_primary(&p_local_xstream);
90  ABTI_CHECK_ERROR_MSG(abt_errno, "ABTI_xstream_create_primary");
91 
92  /* Init the ES local data */
93  ABTI_local_set_xstream(p_local_xstream);
94 
95  /* Create the primary ULT, i.e., the main thread */
96  ABTI_ythread *p_main_ythread;
97  abt_errno =
98  ABTI_ythread_create_main(ABTI_xstream_get_local(p_local_xstream),
99  p_local_xstream, &p_main_ythread);
100  /* Set as if p_local_xstream is currently running the main thread. */
101  ABTD_atomic_relaxed_store_int(&p_main_ythread->thread.state,
103  p_main_ythread->thread.p_last_xstream = p_local_xstream;
104  ABTI_CHECK_ERROR_MSG(abt_errno, "ABTI_ythread_create_main");
105  gp_ABTI_global->p_main_ythread = p_main_ythread;
106  p_local_xstream->p_thread = &p_main_ythread->thread;
107 
108  /* Start the primary ES */
109  ABTI_xstream_start_primary(&p_local_xstream, p_local_xstream,
110  p_main_ythread);
111 
112  if (gp_ABTI_global->print_config == ABT_TRUE) {
113  ABTI_info_print_config(stdout);
114  }
115  ABTD_atomic_release_store_uint32(&g_ABTI_initialized, 1);
116 
117 fn_exit:
118  /* Unlock a global lock */
119  ABTI_spinlock_release(&g_ABTI_init_lock);
120  return abt_errno;
121 
122 fn_fail:
123  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
124  goto fn_exit;
125 }
126 
143 int ABT_finalize(void)
144 {
145  int abt_errno = ABT_SUCCESS;
146  ABTI_local *p_local = ABTI_local_get_local();
147 
148  /* First, take a global lock protecting the initialization/finalization
149  * process. Don't go to fn_exit before taking a lock */
150  ABTI_spinlock_acquire(&g_ABTI_init_lock);
151 
152  /* If Argobots is not initialized, just return */
153  if (g_ABTI_num_inits == 0) {
154  abt_errno = ABT_ERR_UNINITIALIZED;
155  goto fn_exit;
156  }
157  /* If Argobots is still referenced by others, just return */
158  if (--g_ABTI_num_inits != 0)
159  goto fn_exit;
160 
161  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
162  /* If called by an external thread, return an error. */
163  ABTI_CHECK_TRUE(!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream,
165 
166  ABTI_CHECK_TRUE_MSG(p_local_xstream->type == ABTI_XSTREAM_TYPE_PRIMARY,
168  "ABT_finalize must be called by the primary ES.");
169 
170  ABTI_thread *p_self = p_local_xstream->p_thread;
171  ABTI_CHECK_TRUE_MSG(p_self->type & ABTI_THREAD_TYPE_MAIN,
173  "ABT_finalize must be called by the primary ULT.");
174  ABTI_ythread *p_ythread;
175  ABTI_CHECK_YIELDABLE(p_self, &p_ythread, ABT_ERR_INV_THREAD);
176 
177 #ifndef ABT_CONFIG_DISABLE_TOOL_INTERFACE
178  /* Turns off the tool interface */
179  ABTI_tool_event_thread_update_callback(NULL, ABT_TOOL_EVENT_THREAD_NONE,
180  NULL);
181  ABTI_tool_event_task_update_callback(NULL, ABT_TOOL_EVENT_TASK_NONE, NULL);
182 #endif
183 
184  /* Set the orphan request for the primary ULT */
185  ABTI_thread_set_request(p_self, ABTI_THREAD_REQ_ORPHAN);
186  /* Finish the main scheduler of this local xstream. */
187  ABTI_sched_finish(p_local_xstream->p_main_sched);
188  /* p_self cannot join the main scheduler since p_self needs to be orphaned.
189  * Let's wait till the main scheduler finishes. This thread will be
190  * scheduled when the main root thread finishes. */
191  ABTI_ythread_yield(&p_local_xstream, p_ythread, ABT_SYNC_EVENT_TYPE_OTHER,
192  NULL);
193  ABTI_ASSERT(p_local_xstream == ABTI_local_get_xstream(p_local));
194  ABTI_ASSERT(p_local_xstream->p_thread == p_self);
195 
196  /* Remove the primary ULT */
197  p_local_xstream->p_thread = NULL;
198  ABTI_ythread_free_main(ABTI_xstream_get_local(p_local_xstream), p_ythread);
199 
200  /* Free the primary ES */
201  ABTI_xstream_free(ABTI_xstream_get_local(p_local_xstream), p_local_xstream,
202  ABT_TRUE);
203 
204  /* Finalize the ES local data */
205  ABTI_local_set_xstream(NULL);
206 
207  /* Free the ES array */
208  ABTI_ASSERT(gp_ABTI_global->p_xstream_head == NULL);
209 
210  /* Finalize the memory pool */
211  ABTI_mem_finalize(gp_ABTI_global);
212 
213  /* Restore the affinity */
214  if (gp_ABTI_global->set_affinity == ABT_TRUE) {
215  ABTD_affinity_finalize();
216  }
217 
218  /* Free the ABTI_global structure */
220  gp_ABTI_global = NULL;
221  ABTD_atomic_release_store_uint32(&g_ABTI_initialized, 0);
222 
223 fn_exit:
224  /* Unlock a global lock */
225  ABTI_spinlock_release(&g_ABTI_init_lock);
226  return abt_errno;
227 
228 fn_fail:
229  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
230  goto fn_exit;
231 }
232 
246 {
247  int abt_errno = ABT_SUCCESS;
248 
249  if (ABTD_atomic_acquire_load_uint32(&g_ABTI_initialized) == 0) {
250  abt_errno = ABT_ERR_UNINITIALIZED;
251  }
252 
253  return abt_errno;
254 }
int ABT_init(int argc, char **argv) ABT_API_PUBLIC
Initialize the Argobots execution environment.
Definition: global.c:40
static ABTD_atomic_uint32 g_ABTI_initialized
Definition: global.c:21
static ABTI_spinlock g_ABTI_init_lock
Definition: global.c:19
#define ABT_ERR_INV_THREAD
Definition: abt.h:80
#define ABT_TOOL_EVENT_THREAD_NONE
Definition: abt.h:260
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:142
#define HANDLE_ERROR_FUNC_WITH_CODE(n)
Definition: abti_error.h:353
static uint32_t g_ABTI_num_inits
Definition: global.c:17
int ABT_finalize(void) ABT_API_PUBLIC
Terminate the Argobots execution environment.
Definition: global.c:143
ABTI_global * gp_ABTI_global
Definition: global.c:14
#define ABT_SUCCESS
Definition: abt.h:64
#define ABT_TRUE
Definition: abt.h:284
#define ABT_ERR_UNINITIALIZED
Definition: abt.h:65
#define ABT_TOOL_EVENT_TASK_NONE
Definition: abt.h:273
#define ABT_ERR_INV_XSTREAM
Definition: abt.h:68
static void ABTU_free(void *ptr)
Definition: abtu.h:135
int ABT_initialized(void) ABT_API_PUBLIC
Check whether ABT_init() has been called.
Definition: global.c:245