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