Line data Source code
1 : #include "fd_wksp_private.h"
2 : #include "../pod/fd_pod.h"
3 :
4 : /* fd_wksp_private_{join,leave}_func are used to automagically handle
5 : the first join / last leave by the fd_wksp_attach / fd_wksp_detach. */
6 :
7 : static void *
8 : fd_wksp_private_join_func( void * context,
9 0 : fd_shmem_join_info_t const * info ) {
10 0 : (void)context;
11 0 : return fd_wksp_join( info->shmem ); /* logs details */
12 0 : }
13 :
14 : static void *
15 : fd_wksp_private_leave_func( void * context,
16 0 : fd_shmem_join_info_t const * info ) {
17 0 : (void)context;
18 0 : return fd_wksp_leave( info->join ); /* logs details */
19 0 : }
20 :
21 : /* fd_wksp_private_cstr populates cstr with [name]:[gaddr]. Assumes
22 : name is a valid wksp shmem name and that cstr is at least
23 : FD_WKSP_CSTR_MAX bytes. Returns cstr. */
24 :
25 : static char *
26 : fd_wksp_private_cstr( char const * name,
27 : ulong gaddr,
28 0 : char * cstr ) {
29 0 : fd_cstr_fini( fd_cstr_append_ulong_as_text( fd_cstr_append_char( fd_cstr_append_cstr( fd_cstr_init( cstr ),
30 0 : name ), ':' ), ' ', '\0', gaddr, fd_ulong_base10_dig_cnt( gaddr ) ) );
31 0 : return cstr;
32 0 : }
33 :
34 : /* fd_wksp_private_cstr_parse extracts the name and gaddr from a
35 : [name]:[gaddr] cstr. This doesn't actually validate if name is a
36 : compliant fd_shmem_name. That will be handled automatically by the
37 : fd_shmem APIs. */
38 :
39 : static char * /* Returns name on success, NULL on failure (logs details) */
40 : fd_wksp_private_cstr_parse( char const * cstr, /* cstr to parse */
41 : char * name, /* Non-NULL, room for FD_SHMEM_NAME_MAX bytes, holds name on success,
42 : potentially clobbered otherwise */
43 0 : ulong * gaddr ) { /* Non-NULL, holds gaddr on success, untouched otherwise */
44 0 : if( FD_UNLIKELY( !cstr ) ) {
45 0 : FD_LOG_WARNING(( "NULL cstr" ));
46 0 : return NULL;
47 0 : }
48 :
49 0 : ulong len = 0UL;
50 0 : ulong name_len = ULONG_MAX;
51 0 : for(;;) {
52 0 : if( cstr[len]=='\0' ) break;
53 0 : if( cstr[len]==':' ) name_len = len;
54 0 : len++;
55 0 : }
56 0 : ulong gaddr_len = len - name_len - 1UL;
57 :
58 0 : if( FD_UNLIKELY( !name_len ) ) {
59 0 : FD_LOG_WARNING(( "no name found; cstr should be of the form [name]:[gaddr]" ));
60 0 : return NULL;
61 0 : }
62 :
63 0 : if( FD_UNLIKELY( name_len==ULONG_MAX ) ) {
64 0 : FD_LOG_WARNING(( "no ':' found; cstr should be of the form [name]:[gaddr]" ));
65 0 : return NULL;
66 0 : }
67 :
68 0 : if( FD_UNLIKELY( !gaddr_len ) ) {
69 0 : FD_LOG_WARNING(( "no gaddr found; cstr should be of the form [name]:[gaddr]" ));
70 0 : return NULL;
71 0 : }
72 :
73 0 : if( FD_UNLIKELY( name_len>=FD_SHMEM_NAME_MAX ) ) {
74 0 : FD_LOG_WARNING(( "name too long" ));
75 0 : return NULL;
76 0 : }
77 :
78 0 : fd_memcpy( name, cstr, name_len );
79 0 : name[name_len] = '\0';
80 0 : gaddr[0] = fd_cstr_to_ulong( cstr + name_len + 1UL );
81 0 : return name;
82 0 : }
83 :
84 : /* shmem helper APIs **************************************************/
85 :
86 : /* fd_ulong_sum_sat computes sum x[i] for i in [0,cnt), saturating at
87 : ULONG_MAX if the sum would overflow. TODO: MOVE TO SAT LIBRARY */
88 :
89 : FD_FN_PURE static inline ulong
90 : fd_ulong_sum_sat( ulong cnt,
91 0 : ulong const * x ) {
92 0 : ulong sum = 0UL;
93 0 : int ovfl = 0;
94 0 : for( ulong idx=0UL; idx<cnt; idx++ ) {
95 0 : ulong tmp = sum + x[idx];
96 0 : ovfl |= (tmp < sum );
97 0 : sum = tmp;
98 0 : }
99 0 : return fd_ulong_if( ovfl, ULONG_MAX, sum );
100 0 : }
101 :
102 : int
103 : fd_wksp_new_named( char const * name,
104 : ulong page_sz,
105 : ulong sub_cnt,
106 : ulong const * sub_page_cnt,
107 : ulong const * sub_cpu_idx,
108 : ulong mode,
109 : uint seed,
110 0 : ulong part_max ) {
111 :
112 : /* Check input args */
113 :
114 0 : if( FD_UNLIKELY( !fd_shmem_name_len( name ) ) ) { FD_LOG_WARNING(( "bad name" )); return FD_WKSP_ERR_INVAL; }
115 0 : if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "unsupported page_sz" )); return FD_WKSP_ERR_INVAL; }
116 0 : if( FD_UNLIKELY( !sub_cnt ) ) { FD_LOG_WARNING(( "zero sub_cnt" )); return FD_WKSP_ERR_INVAL; }
117 0 : if( FD_UNLIKELY( !sub_page_cnt ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt" )); return FD_WKSP_ERR_INVAL; }
118 0 : if( FD_UNLIKELY( !sub_cpu_idx ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx" )); return FD_WKSP_ERR_INVAL; }
119 :
120 0 : ulong page_cnt = fd_ulong_sum_sat( sub_cnt, sub_page_cnt );
121 :
122 0 : if( FD_UNLIKELY( !page_cnt ) ) { FD_LOG_WARNING(( "zero page_cnt" )); return FD_WKSP_ERR_INVAL; }
123 0 : if( FD_UNLIKELY( page_cnt>=(ULONG_MAX/page_sz) ) ) { FD_LOG_WARNING(( "page_cnt overflow" )); return FD_WKSP_ERR_INVAL; }
124 :
125 : /* Configure the wksp */
126 :
127 0 : ulong footprint = page_cnt*page_sz;
128 :
129 0 : if( !part_max ) {
130 0 : part_max = fd_wksp_part_max_est( footprint, 64UL<<10 ); /* Typical size is fd_alloc top level superblock-ish */
131 0 : if( FD_UNLIKELY( !part_max ) ) { /* should not happen for typical page_sz and non-zero page_cnt */
132 0 : FD_LOG_WARNING(( "fd_wksp_part_max_est(%lu,64KiB) failed", footprint ));
133 0 : return FD_WKSP_ERR_INVAL;
134 0 : }
135 0 : }
136 :
137 0 : ulong data_max = fd_wksp_data_max_est( footprint, part_max );
138 0 : if( FD_UNLIKELY( !data_max ) ) {
139 0 : FD_LOG_WARNING(( "part_max (%lu) too large for footprint (%lu)", part_max, footprint ));
140 0 : return FD_WKSP_ERR_INVAL;
141 0 : }
142 :
143 : /* Create the memory region */
144 :
145 0 : int err = fd_shmem_create_multi( name, page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx, mode ); /* logs details */
146 0 : if( FD_UNLIKELY( err ) ) return FD_WKSP_ERR_FAIL;
147 :
148 : /* Join the memory region */
149 :
150 0 : void * shmem = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, 0, NULL, NULL, NULL ); /* logs details */
151 0 : if( FD_UNLIKELY( !shmem ) ) {
152 0 : fd_shmem_unlink( name, page_sz ); /* logs details */
153 0 : return FD_WKSP_ERR_FAIL;
154 0 : }
155 :
156 : /* Format the region as a workspace */
157 :
158 0 : if( FD_UNLIKELY( !fd_wksp_new( shmem, name, seed, part_max, data_max ) ) ) { /* logs details */
159 0 : fd_shmem_unlink( name, page_sz ); /* logs details */
160 0 : fd_shmem_leave( shmem, NULL, NULL ); /* logs details, after the unlink as per unix file semantics */
161 0 : return FD_WKSP_ERR_FAIL;
162 0 : }
163 :
164 0 : fd_shmem_leave( shmem, NULL, NULL ); /* logs details */
165 :
166 0 : return FD_WKSP_SUCCESS;
167 0 : }
168 :
169 : int
170 0 : fd_wksp_delete_named( char const * name ) {
171 :
172 : /* Join the region and get the page size */
173 :
174 0 : fd_shmem_join_info_t info[1];
175 0 : void * shwksp = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, 0, NULL, NULL, info ); /* logs details */
176 0 : if( FD_UNLIKELY( !shwksp ) ) return FD_WKSP_ERR_FAIL;
177 0 : ulong page_sz = info->page_sz;
178 :
179 : /* Delete the region */
180 :
181 0 : if( FD_UNLIKELY( !fd_wksp_delete( shwksp ) ) ) { /* logs details */
182 0 : fd_shmem_leave( shwksp, NULL, NULL );
183 0 : return FD_WKSP_ERR_FAIL;
184 0 : }
185 :
186 0 : if( FD_UNLIKELY( fd_shmem_unlink( name, page_sz ) ) ) { /* logs details */
187 0 : fd_shmem_leave( shwksp, NULL, NULL );
188 0 : return FD_WKSP_ERR_FAIL;
189 0 : }
190 :
191 0 : fd_shmem_leave( shwksp, NULL, NULL ); /* logs details, after the unlink as per UNIX file semantics */
192 0 : return FD_WKSP_SUCCESS;
193 0 : }
194 :
195 : fd_wksp_t *
196 : fd_wksp_new_anon( char const * name,
197 : ulong page_sz,
198 : ulong sub_cnt,
199 : ulong const * sub_page_cnt,
200 : ulong const * sub_cpu_idx,
201 : uint seed,
202 0 : ulong part_max ) {
203 :
204 : /* Check input args */
205 :
206 0 : if( FD_UNLIKELY( !fd_shmem_name_len( name ) ) ) { FD_LOG_WARNING(( "bad name" )); return NULL; }
207 0 : if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "unsupported page_sz" )); return NULL; }
208 0 : if( FD_UNLIKELY( !sub_cnt ) ) { FD_LOG_WARNING(( "zero sub_cnt" )); return NULL; }
209 0 : if( FD_UNLIKELY( !sub_page_cnt ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt" )); return NULL; }
210 0 : if( FD_UNLIKELY( !sub_cpu_idx ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx" )); return NULL; }
211 :
212 0 : ulong page_cnt = fd_ulong_sum_sat( sub_cnt, sub_page_cnt );
213 :
214 0 : if( FD_UNLIKELY( !page_cnt ) ) { FD_LOG_WARNING(( "zero page_cnt" )); return NULL; }
215 0 : if( FD_UNLIKELY( page_cnt>=(ULONG_MAX/page_sz) ) ) { FD_LOG_WARNING(( "page_cnt overflow" )); return NULL; }
216 :
217 : /* Configure the wksp */
218 :
219 0 : ulong footprint = page_cnt*page_sz;
220 :
221 0 : if( !part_max ) {
222 0 : part_max = fd_wksp_part_max_est( footprint, 64UL<<10 ); /* Typical size is fd_alloc top level superblock-ish */
223 0 : if( FD_UNLIKELY( !part_max ) ) { /* should not happen for typical page_sz and non-zero page_cnt */
224 0 : FD_LOG_WARNING(( "fd_wksp_part_max_est(%lu,64KiB) failed", footprint ));
225 0 : return NULL;
226 0 : }
227 0 : }
228 :
229 0 : ulong data_max = fd_wksp_data_max_est( footprint, part_max );
230 0 : if( FD_UNLIKELY( !data_max ) ) {
231 0 : FD_LOG_WARNING(( "part_max (%lu) too large for footprint (%lu)", part_max, footprint ));
232 0 : return NULL;
233 0 : }
234 :
235 : /* Acquire the pages */
236 :
237 0 : void * shmem = fd_shmem_acquire_multi( page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx ); /* logs details */
238 0 : if( FD_UNLIKELY( !shmem ) ) return NULL;
239 :
240 : /* Format the memory as wksp */
241 :
242 0 : void* shwksp = fd_wksp_new( shmem, name, seed, part_max, data_max ); /* logs details */
243 0 : if( FD_UNLIKELY( !shwksp ) ) {
244 0 : fd_shmem_release( shmem, page_sz, page_cnt ); /* logs details */
245 0 : return NULL;
246 0 : }
247 :
248 : /* Join the wksp */
249 :
250 0 : fd_wksp_t * wksp = fd_wksp_join( shwksp ); /* logs details */
251 0 : if( FD_UNLIKELY( !wksp ) ) {
252 0 : fd_shmem_release( fd_wksp_delete( shwksp ), page_sz, page_cnt ); /* logs details */
253 0 : return NULL;
254 0 : }
255 :
256 : /* Register the join */
257 :
258 0 : if( FD_UNLIKELY( fd_shmem_join_anonymous( name, FD_SHMEM_JOIN_MODE_READ_WRITE, wksp, shmem, page_sz, page_cnt ) ) ) { /* logs */
259 0 : fd_shmem_release( fd_wksp_delete( fd_wksp_leave( wksp ) ), page_sz, page_cnt ); /* logs details */
260 0 : return NULL;
261 0 : }
262 :
263 0 : return wksp;
264 0 : }
265 :
266 : void
267 0 : fd_wksp_delete_anon( fd_wksp_t * wksp ) {
268 0 : fd_shmem_join_info_t info[1];
269 0 : if( FD_UNLIKELY( fd_shmem_leave_anonymous( wksp, info ) ) ) return; /* logs details */
270 0 : fd_shmem_release( fd_wksp_delete( fd_wksp_leave( wksp ) ), info->page_sz, info->page_cnt ); /* logs details */
271 0 : }
272 :
273 : fd_wksp_t *
274 0 : fd_wksp_attach( char const * name ) {
275 0 : return (fd_wksp_t *)
276 0 : fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, 0, fd_wksp_private_join_func, NULL, NULL ); /* logs details */
277 0 : }
278 :
279 : int
280 0 : fd_wksp_detach( fd_wksp_t * wksp ) {
281 0 : if( FD_UNLIKELY( !wksp ) ) {
282 0 : FD_LOG_WARNING(( "NULL wksp" ));
283 0 : return 1;
284 0 : }
285 0 : return fd_shmem_leave( wksp, fd_wksp_private_leave_func, NULL ); /* logs details */
286 0 : }
287 :
288 : fd_wksp_t *
289 221 : fd_wksp_containing( void const * laddr ) {
290 221 : if( FD_UNLIKELY( !laddr ) ) return NULL;
291 :
292 221 : fd_shmem_join_info_t info[1];
293 221 : if( FD_UNLIKELY( fd_shmem_join_query_by_addr( laddr, 1UL, info ) ) ) return NULL;
294 :
295 221 : fd_wksp_t * wksp = (fd_wksp_t *)info->join;
296 221 : if( FD_UNLIKELY( !wksp ) ) return NULL;
297 :
298 221 : if( FD_UNLIKELY( wksp->magic!=FD_WKSP_MAGIC ) ) return NULL;
299 :
300 221 : return wksp;
301 221 : }
302 :
303 : void *
304 : fd_wksp_alloc_laddr( fd_wksp_t * wksp,
305 : ulong align,
306 : ulong sz,
307 137 : ulong tag ) {
308 137 : ulong gaddr = fd_wksp_alloc( wksp, align, sz, tag );
309 137 : if( FD_UNLIKELY( !gaddr ) ) return NULL;
310 137 : return fd_wksp_laddr_fast( wksp, gaddr );
311 137 : }
312 :
313 : void
314 113 : fd_wksp_free_laddr( void * laddr ) {
315 113 : if( FD_UNLIKELY( !laddr ) ) return;
316 :
317 113 : fd_wksp_t * wksp = fd_wksp_containing( laddr );
318 113 : if( FD_UNLIKELY( !wksp ) ) {
319 0 : FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
320 0 : return;
321 0 : }
322 :
323 113 : ulong gaddr = fd_wksp_gaddr_fast( wksp, laddr );
324 113 : if( FD_UNLIKELY( !((wksp->gaddr_lo<=gaddr) & (gaddr<=wksp->gaddr_hi)) ) ) {
325 0 : FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
326 0 : return;
327 0 : }
328 :
329 113 : fd_wksp_free( wksp, gaddr );
330 113 : }
331 :
332 : /* cstr helper APIs ***************************************************/
333 :
334 : char *
335 : fd_wksp_cstr( fd_wksp_t const * wksp,
336 : ulong gaddr,
337 0 : char * cstr ) {
338 0 : if( FD_UNLIKELY( !cstr ) ) { FD_LOG_WARNING(( "NULL cstr" )); return NULL; }
339 0 : if( FD_UNLIKELY( !wksp ) ) { FD_LOG_WARNING(( "NULL wksp" )); return NULL; }
340 :
341 0 : if( FD_UNLIKELY( !( (!gaddr) | ((wksp->gaddr_lo<=gaddr) & (gaddr<=wksp->gaddr_hi)) ) ) ) {
342 0 : FD_LOG_WARNING(( "unmappable gaddr" ));
343 0 : return NULL;
344 0 : }
345 :
346 0 : return fd_wksp_private_cstr( wksp->name, gaddr, cstr );
347 0 : }
348 :
349 : char *
350 : fd_wksp_cstr_laddr( void const * laddr,
351 0 : char * cstr ) {
352 0 : if( FD_UNLIKELY( !cstr ) ) { FD_LOG_WARNING(( "NULL cstr" )); return NULL; }
353 :
354 0 : fd_wksp_t const * wksp = fd_wksp_containing( laddr );
355 0 : if( FD_UNLIKELY( !wksp ) ) {
356 0 : FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
357 0 : return NULL;
358 0 : }
359 :
360 0 : ulong gaddr = fd_wksp_gaddr_fast( wksp, laddr );
361 0 : if( FD_UNLIKELY( !((wksp->gaddr_lo<=gaddr) & (gaddr<=wksp->gaddr_hi)) ) ) {
362 0 : FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
363 0 : return 0UL;
364 0 : }
365 :
366 0 : return fd_wksp_private_cstr( wksp->name, gaddr, cstr );
367 0 : }
368 :
369 : char *
370 : fd_wksp_cstr_alloc( char const * name,
371 : ulong align,
372 : ulong sz,
373 : ulong tag,
374 0 : char * cstr ) {
375 0 : if( FD_UNLIKELY( !cstr ) ) {
376 0 : FD_LOG_WARNING(( "NULL cstr" ));
377 0 : return NULL;
378 0 : }
379 :
380 0 : fd_wksp_t * wksp = fd_wksp_attach( name );
381 0 : if( FD_UNLIKELY( !wksp ) ) return NULL; /* logs details */
382 : /* name must be valid at this point */
383 :
384 0 : ulong gaddr = fd_wksp_alloc( wksp, align, sz, tag );
385 0 : if( FD_UNLIKELY( (!!sz) & (!gaddr) ) ) {
386 0 : fd_wksp_detach( wksp ); /* logs details */
387 0 : return NULL;
388 0 : }
389 :
390 0 : fd_wksp_detach( wksp ); /* logs details */
391 0 : return fd_wksp_private_cstr( name, gaddr, cstr );
392 0 : }
393 :
394 : void
395 0 : fd_wksp_cstr_free( char const * cstr ) {
396 0 : char name[ FD_SHMEM_NAME_MAX ];
397 0 : ulong gaddr;
398 0 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return; /* logs details */
399 :
400 0 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
401 0 : if( FD_UNLIKELY( !wksp ) ) return;
402 :
403 0 : fd_wksp_free( wksp, gaddr ); /* logs details */
404 :
405 0 : fd_wksp_detach( wksp ); /* logs details */
406 0 : }
407 :
408 : ulong
409 0 : fd_wksp_cstr_tag( char const * cstr ) {
410 0 : char name[ FD_SHMEM_NAME_MAX ];
411 0 : ulong gaddr;
412 0 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return 0UL; /* logs details */
413 :
414 0 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
415 0 : if( FD_UNLIKELY( !wksp ) ) return 0UL;
416 :
417 0 : ulong tag = fd_wksp_tag( wksp, gaddr ); /* logs details */
418 :
419 0 : fd_wksp_detach( wksp ); /* logs details */
420 :
421 0 : return tag;
422 0 : }
423 :
424 : void
425 : fd_wksp_cstr_memset( char const * cstr,
426 0 : int c ) {
427 0 : char name[ FD_SHMEM_NAME_MAX ];
428 0 : ulong gaddr;
429 0 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return; /* logs details */
430 :
431 0 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
432 0 : if( FD_UNLIKELY( !wksp ) ) return;
433 :
434 0 : fd_wksp_memset( wksp, gaddr, c ); /* logs details */
435 :
436 0 : fd_wksp_detach( wksp ); /* logs details */
437 0 : }
438 :
439 : void *
440 0 : fd_wksp_map( char const * cstr ) {
441 0 : char name[ FD_SHMEM_NAME_MAX ];
442 0 : ulong gaddr;
443 0 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return NULL; /* logs details */
444 :
445 0 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
446 0 : if( FD_UNLIKELY( !wksp ) ) return NULL;
447 :
448 0 : void * laddr = fd_wksp_laddr( wksp, gaddr ); /* logs details */
449 0 : if( FD_UNLIKELY( !laddr ) ) {
450 : /* We do a detach here regardless of this being an error case or not
451 : (i.e. gaddr was NULL) because unmap will not be able to figure
452 : out which wksp corresponds to the returned NULL */
453 0 : fd_wksp_detach( wksp ); /* logs details */
454 0 : return NULL;
455 0 : }
456 :
457 0 : return laddr;
458 0 : }
459 :
460 : void
461 0 : fd_wksp_unmap( void const * laddr ) {
462 0 : if( FD_UNLIKELY( !laddr ) ) return; /* Silent because NULL might not be an error case (i.e. gaddr passed to map was 0/NULL) */
463 :
464 : /* Technically more efficient given current implementation to do:
465 : shmem_leave_addr( laddr );
466 : but the below is more official from a software maintainability POV */
467 :
468 0 : fd_shmem_join_info_t info[1];
469 0 : if( FD_UNLIKELY( fd_shmem_join_query_by_addr( laddr, 1UL, info ) ) ) {
470 0 : FD_LOG_WARNING(( "laddr does not seem to be from fd_wksp_map" ));
471 0 : return;
472 0 : }
473 :
474 0 : fd_wksp_t * wksp = (fd_wksp_t *)info->join;
475 0 : if( FD_UNLIKELY( !wksp ) ) {
476 0 : FD_LOG_WARNING(( "Called within fd_wksp_join or fd_wksp_leave??" ));
477 0 : return;
478 0 : }
479 :
480 0 : fd_wksp_detach( wksp ); /* logs details */
481 0 : }
482 :
483 : /* pod helper APIs ****************************************************/
484 :
485 : uchar const *
486 0 : fd_wksp_pod_attach( char const * gaddr ) {
487 0 : if( FD_UNLIKELY( !gaddr ) ) FD_LOG_ERR(( "NULL gaddr" ));
488 :
489 0 : void * obj = fd_wksp_map( gaddr );
490 0 : if( FD_UNLIKELY( !obj ) ) FD_LOG_ERR(( "Unable to map pod at gaddr %s into local address space", gaddr ));
491 :
492 0 : uchar const * pod = fd_pod_join( obj );
493 0 : if( FD_UNLIKELY( !pod ) ) FD_LOG_ERR(( "fd_pod_join to pod at gaddr %s failed", gaddr ));
494 :
495 0 : return pod;
496 0 : }
497 :
498 : void
499 0 : fd_wksp_pod_detach( uchar const * pod ) {
500 0 : if( FD_UNLIKELY( !pod ) ) FD_LOG_ERR(( "NULL pod" ));
501 :
502 0 : void * obj = fd_pod_leave( pod );
503 0 : if( FD_UNLIKELY( !obj ) ) FD_LOG_ERR(( "fd_pod_leave failed" ));
504 :
505 0 : fd_wksp_unmap( obj ); /* logs details */
506 0 : }
507 :
508 : void *
509 : fd_wksp_pod_map( uchar const * pod,
510 0 : char const * path ) {
511 0 : if( FD_UNLIKELY( !pod ) ) FD_LOG_ERR(( "NULL pod" ));
512 0 : if( FD_UNLIKELY( !path ) ) FD_LOG_ERR(( "NULL path" ));
513 :
514 0 : char const * gaddr = fd_pod_query_cstr( pod, path, NULL );
515 0 : if( FD_UNLIKELY( !gaddr ) ) FD_LOG_ERR(( "cstr path %s not found in pod", path ));
516 :
517 0 : void * obj = fd_wksp_map( gaddr );
518 0 : if( FD_UNLIKELY( !obj ) ) FD_LOG_ERR(( "Unable to map pod cstr path %s (%s) into local address space", path, gaddr ));
519 :
520 0 : return obj;
521 0 : }
522 :
523 : void
524 0 : fd_wksp_pod_unmap( void * obj ) {
525 0 : if( FD_UNLIKELY( !obj ) ) FD_LOG_ERR(( "NULL obj" ));
526 :
527 0 : fd_wksp_unmap( obj ); /* logs details */
528 0 : }
|