13
13
* All rights reserved.
14
14
* Copyright (c) 2009-2012 Cisco Systems, Inc. All rights reserved.
15
15
* Copyright (c) 2011 Oak Ridge National Labs. All rights reserved.
16
- * Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
16
+ * Copyright (c) 2013-2019 Intel, Inc. All rights reserved.
17
17
* Copyright (c) 2015 Mellanox Technologies, Inc. All rights reserved.
18
18
* $COPYRIGHT$
19
19
*
30
30
#include <time.h>
31
31
32
32
#include <pmix.h>
33
-
34
- /* define a structure for collecting returned
35
- * info from an allocation request */
36
- typedef struct {
37
- volatile bool active ;
38
- pmix_info_t * info ;
39
- size_t ninfo ;
40
- } mydata_t ;
41
-
42
- static volatile bool waiting_for_allocation = true;
33
+ #include "examples.h"
43
34
44
35
/* this is a callback function for the PMIx_Query and
45
36
* PMIx_Allocate APIs. The query will callback with a status indicating
@@ -59,7 +50,7 @@ static void infocbfunc(pmix_status_t status,
59
50
pmix_release_cbfunc_t release_fn ,
60
51
void * release_cbdata )
61
52
{
62
- mydata_t * mq = (mydata_t * )cbdata ;
53
+ myquery_data_t * mq = (myquery_data_t * )cbdata ;
63
54
size_t n ;
64
55
65
56
fprintf (stderr , "Allocation request returned %s" , PMIx_Error_string (status ));
@@ -75,6 +66,9 @@ static void infocbfunc(pmix_status_t status,
75
66
PMIX_INFO_XFER (& mq -> info [n ], & info [n ]);
76
67
}
77
68
}
69
+ /* the status returned here indicates whether the requested
70
+ * information was found or not - preserve it */
71
+ mq -> lock .status = status ;
78
72
79
73
/* let the library release the data and cleanup from
80
74
* the operation */
@@ -83,7 +77,7 @@ static void infocbfunc(pmix_status_t status,
83
77
}
84
78
85
79
/* release the block */
86
- mq -> active = false ;
80
+ DEBUG_WAKEUP_THREAD ( & mq -> lock ) ;
87
81
}
88
82
89
83
/* this is an event notification function that we explicitly request
@@ -100,12 +94,37 @@ static void release_fn(size_t evhdlr_registration_id,
100
94
pmix_event_notification_cbfunc_fn_t cbfunc ,
101
95
void * cbdata )
102
96
{
97
+ myrel_t * lock ;
98
+ size_t n ;
99
+
100
+ /* find the return object */
101
+ lock = NULL ;
102
+ for (n = 0 ; n < ninfo ; n ++ ) {
103
+ if (0 == strncmp (info [n ].key , PMIX_EVENT_RETURN_OBJECT , PMIX_MAX_KEYLEN )) {
104
+ lock = (myrel_t * )info [n ].value .data .ptr ;
105
+ break ;
106
+ }
107
+ }
108
+ /* if the object wasn't returned, then that is an error */
109
+ if (NULL == lock ) {
110
+ fprintf (stderr , "LOCK WASN'T RETURNED IN RELEASE CALLBACK\n" );
111
+ /* let the event handler progress */
112
+ if (NULL != cbfunc ) {
113
+ cbfunc (PMIX_SUCCESS , NULL , 0 , NULL , NULL , cbdata );
114
+ }
115
+ return ;
116
+ }
117
+
103
118
/* tell the event handler state machine that we are the last step */
104
119
if (NULL != cbfunc ) {
105
120
cbfunc (PMIX_EVENT_ACTION_COMPLETE , NULL , 0 , NULL , NULL , cbdata );
106
121
}
107
- /* flag that the allocation is complete so we can exit */
108
- waiting_for_allocation = false;
122
+ /* the status will be PMIX_ERR_ALLOC_COMPLETE since that is the code
123
+ * we registered to receive. The result of the allocation request is
124
+ * in the info array - for now, just assume success */
125
+ lock -> lock .status = PMIX_SUCCESS ;
126
+ /* release the lock */
127
+ DEBUG_WAKEUP_THREAD (& lock -> lock );
109
128
}
110
129
111
130
/* event handler registration is done asynchronously because it
@@ -114,18 +133,20 @@ static void release_fn(size_t evhdlr_registration_id,
114
133
* the status of the request (success or an error), plus a numerical index
115
134
* to the registered event. The index is used later on to deregister
116
135
* an event handler - if we don't explicitly deregister it, then the
117
- * PMIx server will do so when it see us exit */
136
+ * PMIx server will do so when it sees us exit */
118
137
static void evhandler_reg_callbk (pmix_status_t status ,
119
138
size_t evhandler_ref ,
120
139
void * cbdata )
121
140
{
122
- volatile int * active = (volatile int * )cbdata ;
141
+ mylock_t * lock = (mylock_t * )cbdata ;
123
142
124
143
if (PMIX_SUCCESS != status ) {
125
144
fprintf (stderr , "EVENT HANDLER REGISTRATION FAILED WITH STATUS %d, ref=%lu\n" ,
126
145
status , (unsigned long )evhandler_ref );
127
146
}
128
- * active = status ;
147
+ lock -> status = status ;
148
+ lock -> evhandler_ref = evhandler_ref ;
149
+ DEBUG_WAKEUP_THREAD (lock );
129
150
}
130
151
131
152
int main (int argc , char * * argv )
@@ -138,11 +159,12 @@ int main(int argc, char **argv)
138
159
uint32_t nprocs ;
139
160
pmix_info_t * info ;
140
161
uint64_t nnodes = 12 ;
141
- mydata_t mydata ;
162
+ myquery_data_t mydata ;
142
163
pmix_query_t * query ;
143
164
char * myallocation = "MYALLOCATION" ;
144
- volatile int active ;
145
- pmix_status_t code = PMIX_NOTIFY_ALLOC_COMPLETE ;
165
+ mylock_t mylock ;
166
+ pmix_status_t code ;
167
+ myrel_t myrel ;
146
168
147
169
/* init us */
148
170
if (PMIX_SUCCESS != (rc = PMIx_Init (& myproc , NULL , 0 ))) {
@@ -163,63 +185,64 @@ int main(int argc, char **argv)
163
185
PMIX_VALUE_RELEASE (val );
164
186
fprintf (stderr , "Client %s:%d universe size %d\n" , myproc .nspace , myproc .rank , nprocs );
165
187
166
- /* initialize the return info struct */
167
- mydata .info = NULL ;
168
- mydata .ninfo = 0 ;
169
-
170
188
if (0 == myproc .rank ) {
171
189
/* try to get an allocation */
172
- mydata . active = true ;
190
+ DEBUG_CONSTRUCT_MYQUERY ( & mydata ) ;
173
191
PMIX_INFO_CREATE (info , 2 );
174
192
PMIX_INFO_LOAD (& info [0 ], PMIX_ALLOC_NUM_NODES , & nnodes , PMIX_UINT64 );
175
193
PMIX_INFO_LOAD (& info [0 ], PMIX_ALLOC_ID , myallocation , PMIX_STRING );
176
- if (PMIX_SUCCESS != (rc = PMIx_Allocation_request_nb (PMIX_ALLOC_NEW , info , 2 , infocbfunc , NULL ))) {
194
+ if (PMIX_SUCCESS != (rc = PMIx_Allocation_request_nb (PMIX_ALLOC_NEW , info , 2 , infocbfunc , & mydata ))) {
177
195
fprintf (stderr , "Client ns %s rank %d: PMIx_Allocation_request_nb failed: %d\n" , myproc .nspace , myproc .rank , rc );
178
196
goto done ;
179
197
}
180
- while (mydata .active ) {
181
- usleep (10 );
182
- }
198
+ DEBUG_WAIT_THREAD (& mydata .lock );
183
199
PMIX_INFO_FREE (info , 2 );
184
- if (NULL != mydata .info ) {
185
- PMIX_INFO_FREE (mydata .info , mydata .ninfo );
186
- }
200
+ fprintf (stderr , "Client ns %s rank %d: Allocation returned status: %s\n" ,
201
+ myproc .nspace , myproc .rank , PMIx_Error_string (mydata .lock .status ));
202
+ DEBUG_DESTRUCT_MYQUERY (& mydata );
203
+
187
204
} else if (1 == myproc .rank ) {
188
- /* register a handler specifically for when the allocation
189
- * operation completes */
190
- PMIX_INFO_CREATE (info , 1 );
205
+ /* demonstrate a notification based approach - register a handler
206
+ * specifically for when the allocation operation completes */
207
+ DEBUG_CONSTRUCT_MYREL (& myrel );
208
+ PMIX_INFO_CREATE (info , 2 );
191
209
PMIX_INFO_LOAD (& info [0 ], PMIX_ALLOC_ID , myallocation , PMIX_STRING );
192
- active = -1 ;
193
- PMIx_Register_event_handler ( & code , 1 , info , 1 ,
194
- release_fn , evhandler_reg_callbk , ( void * ) & active ) ;
195
- while ( -1 == active ) {
196
- usleep ( 10 );
197
- }
198
- if ( 0 != active ) {
199
- exit ( active ) ;
200
- }
201
- PMIX_INFO_FREE ( info , 1 );
210
+ PMIX_INFO_LOAD ( & info [ 1 ], PMIX_EVENT_RETURN_OBJECT , & myrel , PMIX_POINTER ) ;
211
+ DEBUG_CONSTRUCT_LOCK ( & mylock );
212
+ code = PMIX_NOTIFY_ALLOC_COMPLETE ;
213
+ PMIx_Register_event_handler ( & code , 1 , info , 2 ,
214
+ release_fn , evhandler_reg_callbk , ( void * ) & mylock );
215
+ DEBUG_WAIT_THREAD ( & mylock );
216
+ PMIX_INFO_FREE ( info , 2 );
217
+ rc = mylock . status ;
218
+ DEBUG_DESTRUCT_LOCK ( & mylock );
219
+
202
220
/* now wait to hear that the request is complete */
203
- while (waiting_for_allocation ) {
204
- usleep (10 );
205
- }
221
+ DEBUG_WAIT_THREAD (& myrel .lock );
222
+ fprintf (stderr , "[%s:%d] Allocation returned status: %s\n" ,
223
+ myproc .nspace , myproc .rank , PMIx_Error_string (myrel .lock .status ));
224
+ DEBUG_DESTRUCT_MYREL (& myrel );
225
+
206
226
} else {
207
- /* I am not the root rank, so let me wait a little while and then
208
- * query the status of the allocation request */
227
+ /* demonstrate a query-based approach - wait a little while and ask to
228
+ * see if it was done */
209
229
usleep (10 );
230
+ DEBUG_CONSTRUCT_MYQUERY (& mydata );
231
+
210
232
PMIX_QUERY_CREATE (query , 1 );
211
233
PMIX_ARGV_APPEND (rc , query [0 ].keys , PMIX_QUERY_ALLOC_STATUS );
212
234
PMIX_INFO_CREATE (query [0 ].qualifiers , 1 );
213
235
PMIX_INFO_LOAD (& query [0 ].qualifiers [0 ], PMIX_ALLOC_ID , myallocation , PMIX_STRING );
214
- mydata . active = true;
236
+
215
237
if (PMIX_SUCCESS != (rc = PMIx_Query_info_nb (query , 1 , infocbfunc , (void * )& mydata ))) {
216
238
fprintf (stderr , "PMIx_Query_info failed: %d\n" , rc );
217
239
goto done ;
218
240
}
219
- while (mydata .active ) {
220
- usleep (10 );
221
- }
241
+ DEBUG_WAIT_THREAD (& mydata .lock );
222
242
PMIX_QUERY_FREE (query , 1 );
243
+ fprintf (stderr , "[%s:%d] Allocation returned status: %s\n" ,
244
+ myproc .nspace , myproc .rank , PMIx_Error_string (mydata .lock .status ));
245
+ DEBUG_DESTRUCT_MYQUERY (& mydata );
223
246
}
224
247
225
248
done :
0 commit comments