1 /*
2 * Copyright (c) 2013 Mellanox Technologies, Inc.
3 * All rights reserved.
4 * Copyright (c) 2019 Research Organization for Information Science
5 * and Technology (RIST). All rights reserved.
6 * $COPYRIGHT$
7 *
8 * Additional copyrights may follow
9 *
10 * $HEADER$
11 */
12
13 /**
14 * @file
15 *
16 * Interface into the SHMEM portion of the Open SHMEM Run Time Environment
17 */
18
19 #ifndef OSHMEM_SHMEM_RUNTIME_H
20 #define OSHMEM_SHMEM_RUNTIME_H
21
22 #include "oshmem_config.h"
23 #include "shmem.h"
24
25 #include "opal/class/opal_list.h"
26 #include "opal/class/opal_hash_table.h"
27
28 #include "ompi/include/mpi.h"
29 #include <pthread.h>
30
31 BEGIN_C_DECLS
32
33 /* Global variables and symbols for the SHMEM layer */
34
35 /** Is oshmem initialized? */
36 OSHMEM_DECLSPEC extern bool oshmem_shmem_initialized;
37 /** Has oshmem been aborted **/
38 OSHMEM_DECLSPEC extern bool oshmem_shmem_aborted;
39
40 /** Do we have multiple threads? */
41 OSHMEM_DECLSPEC extern bool oshmem_mpi_thread_multiple;
42 /** Thread level requested to \c MPI_Init_thread() */
43 OSHMEM_DECLSPEC extern int oshmem_mpi_thread_requested;
44 /** Thread level provided by Open MPI */
45 OSHMEM_DECLSPEC extern int oshmem_mpi_thread_provided;
46 /** Identifier of the main thread */
47 OSHMEM_DECLSPEC extern struct opal_thread_t *oshmem_mpi_main_thread;
48
49 OSHMEM_DECLSPEC extern MPI_Comm oshmem_comm_world;
50
51 typedef pthread_mutex_t shmem_internal_mutex_t;
52 OSHMEM_DECLSPEC extern shmem_internal_mutex_t shmem_internal_mutex_alloc;
53
54 OSHMEM_DECLSPEC extern shmem_ctx_t oshmem_ctx_default;
55
56 # define SHMEM_MUTEX_INIT(_mutex) \
57 do { \
58 if (oshmem_mpi_thread_provided == SHMEM_THREAD_MULTIPLE) \
59 pthread_mutex_init(&_mutex, NULL); \
60 } while (0)
61 # define SHMEM_MUTEX_DESTROY(_mutex) \
62 do { \
63 if (oshmem_mpi_thread_provided == SHMEM_THREAD_MULTIPLE) \
64 pthread_mutex_destroy(&_mutex); \
65 } while (0)
66 # define SHMEM_MUTEX_LOCK(_mutex) \
67 do { \
68 if (oshmem_mpi_thread_provided == SHMEM_THREAD_MULTIPLE) \
69 pthread_mutex_lock(&_mutex); \
70 } while (0)
71 # define SHMEM_MUTEX_UNLOCK(_mutex) \
72 do { \
73 if (oshmem_mpi_thread_provided == SHMEM_THREAD_MULTIPLE) \
74 pthread_mutex_unlock(&_mutex); \
75 } while (0)
76
77
78 /** Bitflags to be used for the modex exchange for the various thread
79 * levels. Required to support heterogeneous environments */
80 #define OSHMEM_THREADLEVEL_SINGLE_BF 0x00000001
81 #define OSHMEM_THREADLEVEL_FUNNELED_BF 0x00000002
82 #define OSHMEM_THREADLEVEL_SERIALIZED_BF 0x00000004
83 #define OSHMEM_THREADLEVEL_MULTIPLE_BF 0x00000008
84
85 /** In ompi_mpi_init: the lists of Fortran 90 mathing datatypes.
86 * We need these lists and hashtables in order to satisfy the new
87 * requirements introduced in MPI 2-1 Sect. 10.2.5,
88 * MPI_TYPE_CREATE_F90_xxxx, page 295, line 47.
89 */
90 extern opal_hash_table_t ompi_mpi_f90_integer_hashtable;
91 extern opal_hash_table_t ompi_mpi_f90_real_hashtable;
92 extern opal_hash_table_t ompi_mpi_f90_complex_hashtable;
93
94 /** version string of ompi */
95 OSHMEM_DECLSPEC extern const char oshmem_version_string[];
96
97 /**
98 * Initialize the Open SHMEM environment
99 *
100 * @param argc argc, typically from main() (IN)
101 * @param argv argv, typically from main() (IN)
102 * @param requested Thread support that is requested (IN)
103 * @param provided Thread support that is provided (OUT)
104 *
105 * @returns OSHMEM_SUCCESS if successful
106 * @returns Error code if unsuccessful
107 *
108 * Intialize all support code needed for SHMEM applications. This
109 * function should only be called by SHMEM applications (including
110 * singletons). If this function is called, ompi_init() and
111 * ompi_rte_init() should *not* be called.
112 *
113 * It is permissable to pass in (0, NULL) for (argc, argv).
114 */
115 int oshmem_shmem_init(int argc, char **argv, int requested, int *provided);
116
117 /**
118 * Finalize the Open SHMEM environment
119 *
120 * @returns OSHMEM_SUCCESS if successful
121 * @returns Error code if unsuccessful
122 *
123 */
124 int oshmem_shmem_finalize(void);
125
126 /**
127 * Abort SHMEM processes
128 */
129 OSHMEM_DECLSPEC int oshmem_shmem_abort(int errcode);
130
131 /**
132 * Allgather between all PEs
133 */
134 OSHMEM_DECLSPEC int oshmem_shmem_allgather(void *send_buf, void *rcv_buf, int elem_size);
135
136 /**
137 * Allgatherv between all PEs
138 */
139 OSHMEM_DECLSPEC int oshmem_shmem_allgatherv(void *send_buf, void* rcv_buf, int send_count,
140 int *rcv_size, int* displs);
141
142 /**
143 * Barrier between all PEs
144 */
145 OSHMEM_DECLSPEC void oshmem_shmem_barrier(void);
146
147 /**
148 * Register OSHMEM specific runtime parameters
149 */
150 OSHMEM_DECLSPEC int oshmem_shmem_register_params(void);
151
152 #if OSHMEM_PARAM_CHECK == 1
153
154 #define RUNTIME_CHECK_ERROR(...) \
155 do { \
156 fprintf(stderr, "[%s]%s[%s:%d:%s] ", \
157 ompi_process_info.nodename, \
158 OMPI_NAME_PRINT(OMPI_PROC_MY_NAME), \
159 __FILE__, __LINE__, __func__); \
160 fprintf(stderr, __VA_ARGS__); \
161 } while(0);
162
163 /**
164 * Check if SHMEM API generates internal error return code
165 * Note: most API does not return error code
166 */
167 #define RUNTIME_CHECK_RC(x) \
168 if (OPAL_UNLIKELY(OSHMEM_SUCCESS != (x))) \
169 { \
170 RUNTIME_CHECK_ERROR("Internal error is appeared rc = %d\n", (x)); \
171 }
172
173 /**
174 * Check if we called start_pes() and passed initialization phase
175 */
176 #define RUNTIME_CHECK_INIT() \
177 if (OPAL_UNLIKELY(!oshmem_shmem_initialized)) \
178 { \
179 RUNTIME_CHECK_ERROR("SHMEM is not initialized\n"); \
180 oshmem_shmem_abort(-1); \
181 }
182
183 /**
184 * Check if we target PE is valid
185 */
186 #define RUNTIME_CHECK_PE(x) \
187 if (OPAL_UNLIKELY(((x) < 0) || \
188 ((int)(x) > (int)(ompi_process_info.num_procs - 1)))) \
189 { \
190 RUNTIME_CHECK_ERROR("Target PE #%d is not in valid range\n", (x)); \
191 oshmem_shmem_abort(-1); \
192 }
193
194 /**
195 * Check if required address is in symmetric address space
196 */
197 #include "oshmem/mca/memheap/memheap.h"
198 #define RUNTIME_CHECK_ADDR(x) \
199 if (OPAL_UNLIKELY(!MCA_MEMHEAP_CALL(is_symmetric_addr((x))))) \
200 { \
201 RUNTIME_CHECK_ERROR("Required address %p is not in symmetric space\n", ((void*)x)); \
202 oshmem_shmem_abort(-1); \
203 }
204 /* Check if address is in symmetric space or size is zero */
205 #define RUNTIME_CHECK_ADDR_SIZE(x,s) \
206 if (OPAL_UNLIKELY((s) && !MCA_MEMHEAP_CALL(is_symmetric_addr((x))))) \
207 { \
208 RUNTIME_CHECK_ERROR("Required address %p is not in symmetric space\n", ((void*)x)); \
209 oshmem_shmem_abort(-1); \
210 }
211 #define RUNTIME_CHECK_WITH_MEMHEAP_SIZE(x) \
212 if (OPAL_UNLIKELY((long)(x) > MCA_MEMHEAP_CALL(size))) \
213 { \
214 RUNTIME_CHECK_ERROR("Requested (%ld)bytes and it exceeds symmetric space size (%ld)bytes\n", (long)(x), MCA_MEMHEAP_CALL(size)); \
215 }
216
217 #else
218
219 #define RUNTIME_CHECK_RC(x) (x = x)
220 #define RUNTIME_CHECK_INIT()
221 #define RUNTIME_CHECK_PE(x)
222 #define RUNTIME_CHECK_ADDR(x)
223 #define RUNTIME_CHECK_ADDR_SIZE(x,s)
224 #define RUNTIME_CHECK_WITH_MEMHEAP_SIZE(x)
225
226 #endif /* OSHMEM_PARAM_CHECK */
227
228 END_C_DECLS
229
230 #endif /* OSHMEM_SHMEM_RUNTIME_H */