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 1836 : fd_shmem_join_info_t const * info ) {
10 1836 : (void)context;
11 1836 : return fd_wksp_join( info->shmem ); /* logs details */
12 1836 : }
13 :
14 : static void *
15 : fd_wksp_private_leave_func( void * context,
16 1746 : fd_shmem_join_info_t const * info ) {
17 1746 : (void)context;
18 1746 : return fd_wksp_leave( info->join ); /* logs details */
19 1746 : }
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 258 : char * cstr ) {
29 258 : fd_cstr_fini( fd_cstr_append_ulong_as_text( fd_cstr_append_char( fd_cstr_append_cstr( fd_cstr_init( cstr ),
30 258 : name ), ':' ), ' ', '\0', gaddr, fd_ulong_base10_dig_cnt( gaddr ) ) );
31 258 : return cstr;
32 258 : }
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 1353 : ulong * gaddr ) { /* Non-NULL, holds gaddr on success, untouched otherwise */
44 1353 : if( FD_UNLIKELY( !cstr ) ) {
45 30 : FD_LOG_WARNING(( "NULL cstr" ));
46 30 : return NULL;
47 30 : }
48 :
49 1323 : ulong len = 0UL;
50 1323 : ulong name_len = ULONG_MAX;
51 29046 : for(;;) {
52 29046 : if( cstr[len]=='\0' ) break;
53 27723 : if( cstr[len]==':' ) name_len = len;
54 27723 : len++;
55 27723 : }
56 1323 : ulong gaddr_len = len - name_len - 1UL;
57 :
58 1323 : 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 1323 : if( FD_UNLIKELY( name_len==ULONG_MAX ) ) {
64 141 : FD_LOG_WARNING(( "no ':' found; cstr should be of the form [name]:[gaddr]" ));
65 141 : return NULL;
66 141 : }
67 :
68 1182 : 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 1182 : 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 1182 : fd_memcpy( name, cstr, name_len );
79 1182 : name[name_len] = '\0';
80 1182 : gaddr[0] = fd_cstr_to_ulong( cstr + name_len + 1UL );
81 1182 : return name;
82 1182 : }
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 147 : ulong const * x ) {
92 147 : ulong sum = 0UL;
93 147 : int ovfl = 0;
94 294 : for( ulong idx=0UL; idx<cnt; idx++ ) {
95 147 : ulong tmp = sum + x[idx];
96 147 : ovfl |= (tmp < sum );
97 147 : sum = tmp;
98 147 : }
99 147 : return fd_ulong_if( ovfl, ULONG_MAX, sum );
100 147 : }
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 78 : ulong part_max ) {
111 :
112 : /* Check input args */
113 :
114 78 : if( FD_UNLIKELY( !fd_shmem_name_len( name ) ) ) { FD_LOG_WARNING(( "bad name" )); return FD_WKSP_ERR_INVAL; }
115 72 : if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "unsupported page_sz" )); return FD_WKSP_ERR_INVAL; }
116 66 : if( FD_UNLIKELY( !sub_cnt ) ) { FD_LOG_WARNING(( "zero sub_cnt" )); return FD_WKSP_ERR_INVAL; }
117 63 : if( FD_UNLIKELY( !sub_page_cnt ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt" )); return FD_WKSP_ERR_INVAL; }
118 60 : if( FD_UNLIKELY( !sub_cpu_idx ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx" )); return FD_WKSP_ERR_INVAL; }
119 :
120 57 : ulong page_cnt = fd_ulong_sum_sat( sub_cnt, sub_page_cnt );
121 :
122 57 : if( FD_UNLIKELY( !page_cnt ) ) { FD_LOG_WARNING(( "zero page_cnt" )); return FD_WKSP_ERR_INVAL; }
123 51 : 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 48 : ulong footprint = page_cnt*page_sz;
128 :
129 48 : if( !part_max ) {
130 45 : part_max = fd_wksp_part_max_est( footprint, 64UL<<10 ); /* Typical size is fd_alloc top level superblock-ish */
131 45 : 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 45 : }
136 :
137 48 : ulong data_max = fd_wksp_data_max_est( footprint, part_max );
138 48 : if( FD_UNLIKELY( !data_max ) ) {
139 3 : FD_LOG_WARNING(( "part_max (%lu) too large for footprint (%lu)", part_max, footprint ));
140 3 : return FD_WKSP_ERR_INVAL;
141 3 : }
142 :
143 : /* Create the memory region */
144 :
145 45 : int err = fd_shmem_create_multi( name, page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx, mode ); /* logs details */
146 45 : if( FD_UNLIKELY( err ) ) return FD_WKSP_ERR_FAIL;
147 :
148 : /* Join the memory region */
149 :
150 30 : void * shmem = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, NULL, NULL, NULL ); /* logs details */
151 30 : 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 30 : 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 30 : fd_shmem_leave( shmem, NULL, NULL ); /* logs details */
165 :
166 30 : return FD_WKSP_SUCCESS;
167 30 : }
168 :
169 : int
170 54 : fd_wksp_delete_named( char const * name ) {
171 :
172 : /* Join the region and get the page size */
173 :
174 54 : fd_shmem_join_info_t info[1];
175 54 : void * shwksp = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, NULL, NULL, info ); /* logs details */
176 54 : if( FD_UNLIKELY( !shwksp ) ) return FD_WKSP_ERR_FAIL;
177 30 : ulong page_sz = info->page_sz;
178 :
179 : /* Delete the region */
180 :
181 30 : 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 30 : 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 30 : fd_shmem_leave( shwksp, NULL, NULL ); /* logs details, after the unlink as per UNIX file semantics */
192 30 : return FD_WKSP_SUCCESS;
193 30 : }
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 105 : ulong part_max ) {
203 :
204 : /* Check input args */
205 :
206 105 : if( FD_UNLIKELY( !fd_shmem_name_len( name ) ) ) { FD_LOG_WARNING(( "bad name" )); return NULL; }
207 102 : if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "unsupported page_sz" )); return NULL; }
208 99 : if( FD_UNLIKELY( !sub_cnt ) ) { FD_LOG_WARNING(( "zero sub_cnt" )); return NULL; }
209 96 : if( FD_UNLIKELY( !sub_page_cnt ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt" )); return NULL; }
210 93 : if( FD_UNLIKELY( !sub_cpu_idx ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx" )); return NULL; }
211 :
212 90 : ulong page_cnt = fd_ulong_sum_sat( sub_cnt, sub_page_cnt );
213 :
214 90 : if( FD_UNLIKELY( !page_cnt ) ) { FD_LOG_WARNING(( "zero page_cnt" )); return NULL; }
215 87 : if( FD_UNLIKELY( page_cnt>=(ULONG_MAX/page_sz) ) ) { FD_LOG_WARNING(( "page_cnt overflow" )); return NULL; }
216 :
217 : /* Configure the wksp */
218 :
219 84 : ulong footprint = page_cnt*page_sz;
220 :
221 84 : if( !part_max ) {
222 81 : part_max = fd_wksp_part_max_est( footprint, 64UL<<10 ); /* Typical size is fd_alloc top level superblock-ish */
223 81 : 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 81 : }
228 :
229 84 : ulong data_max = fd_wksp_data_max_est( footprint, part_max );
230 84 : if( FD_UNLIKELY( !data_max ) ) {
231 3 : FD_LOG_WARNING(( "part_max (%lu) too large for footprint (%lu)", part_max, footprint ));
232 3 : return NULL;
233 3 : }
234 :
235 : /* Acquire the pages */
236 :
237 81 : void * shmem = fd_shmem_acquire_multi( page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx ); /* logs details */
238 81 : if( FD_UNLIKELY( !shmem ) ) return NULL;
239 :
240 : /* Format the memory as wksp */
241 :
242 78 : void* shwksp = fd_wksp_new( shmem, name, seed, part_max, data_max ); /* logs details */
243 78 : 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 78 : fd_wksp_t * wksp = fd_wksp_join( shwksp ); /* logs details */
251 78 : 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 78 : 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 78 : return wksp;
264 78 : }
265 :
266 : void
267 66 : fd_wksp_delete_anon( fd_wksp_t * wksp ) {
268 66 : fd_shmem_join_info_t info[1];
269 66 : if( FD_UNLIKELY( fd_shmem_leave_anonymous( wksp, info ) ) ) return; /* logs details */
270 60 : fd_shmem_release( fd_wksp_delete( fd_wksp_leave( wksp ) ), info->page_sz, info->page_cnt ); /* logs details */
271 60 : }
272 :
273 : fd_wksp_t *
274 2412 : fd_wksp_attach( char const * name ) {
275 2412 : return (fd_wksp_t *)
276 2412 : fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, fd_wksp_private_join_func, NULL, NULL ); /* logs details */
277 2412 : }
278 :
279 : int
280 2178 : fd_wksp_detach( fd_wksp_t * wksp ) {
281 2178 : if( FD_UNLIKELY( !wksp ) ) {
282 3 : FD_LOG_WARNING(( "NULL wksp" ));
283 3 : return 1;
284 3 : }
285 2175 : return fd_shmem_leave( wksp, fd_wksp_private_leave_func, NULL ); /* logs details */
286 2178 : }
287 :
288 : fd_wksp_t *
289 441 : fd_wksp_containing( void const * laddr ) {
290 441 : if( FD_UNLIKELY( !laddr ) ) return NULL;
291 :
292 426 : fd_shmem_join_info_t info[1];
293 426 : if( FD_UNLIKELY( fd_shmem_join_query_by_addr( laddr, 1UL, info ) ) ) return NULL;
294 :
295 381 : fd_wksp_t * wksp = (fd_wksp_t *)info->join;
296 381 : if( FD_UNLIKELY( !wksp ) ) return NULL;
297 :
298 381 : if( FD_UNLIKELY( wksp->magic!=FD_WKSP_MAGIC ) ) return NULL;
299 :
300 381 : return wksp;
301 381 : }
302 :
303 : void *
304 : fd_wksp_alloc_laddr( fd_wksp_t * wksp,
305 : ulong align,
306 : ulong sz,
307 213 : ulong tag ) {
308 213 : ulong gaddr = fd_wksp_alloc( wksp, align, sz, tag );
309 213 : if( FD_UNLIKELY( !gaddr ) ) return NULL;
310 189 : return fd_wksp_laddr_fast( wksp, gaddr );
311 213 : }
312 :
313 : void
314 165 : fd_wksp_free_laddr( void * laddr ) {
315 165 : if( FD_UNLIKELY( !laddr ) ) return;
316 :
317 159 : fd_wksp_t * wksp = fd_wksp_containing( laddr );
318 159 : if( FD_UNLIKELY( !wksp ) ) {
319 12 : FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
320 12 : return;
321 12 : }
322 :
323 147 : ulong gaddr = fd_wksp_gaddr_fast( wksp, laddr );
324 147 : 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 147 : fd_wksp_free( wksp, gaddr );
330 147 : }
331 :
332 : /* cstr helper APIs ***************************************************/
333 :
334 : char *
335 : fd_wksp_cstr( fd_wksp_t const * wksp,
336 : ulong gaddr,
337 177 : char * cstr ) {
338 177 : if( FD_UNLIKELY( !cstr ) ) { FD_LOG_WARNING(( "NULL cstr" )); return NULL; }
339 171 : if( FD_UNLIKELY( !wksp ) ) { FD_LOG_WARNING(( "NULL wksp" )); return NULL; }
340 :
341 165 : if( FD_UNLIKELY( !( (!gaddr) | ((wksp->gaddr_lo<=gaddr) & (gaddr<=wksp->gaddr_hi)) ) ) ) {
342 6 : FD_LOG_WARNING(( "unmappable gaddr" ));
343 6 : return NULL;
344 6 : }
345 :
346 159 : return fd_wksp_private_cstr( wksp->name, gaddr, cstr );
347 165 : }
348 :
349 : char *
350 : fd_wksp_cstr_laddr( void const * laddr,
351 33 : char * cstr ) {
352 33 : if( FD_UNLIKELY( !cstr ) ) { FD_LOG_WARNING(( "NULL cstr" )); return NULL; }
353 :
354 27 : fd_wksp_t const * wksp = fd_wksp_containing( laddr );
355 27 : if( FD_UNLIKELY( !wksp ) ) {
356 12 : FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
357 12 : return NULL;
358 12 : }
359 :
360 15 : ulong gaddr = fd_wksp_gaddr_fast( wksp, laddr );
361 15 : 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 15 : return fd_wksp_private_cstr( wksp->name, gaddr, cstr );
367 15 : }
368 :
369 : char *
370 : fd_wksp_cstr_alloc( char const * name,
371 : ulong align,
372 : ulong sz,
373 : ulong tag,
374 117 : char * cstr ) {
375 117 : if( FD_UNLIKELY( !cstr ) ) {
376 0 : FD_LOG_WARNING(( "NULL cstr" ));
377 0 : return NULL;
378 0 : }
379 :
380 117 : fd_wksp_t * wksp = fd_wksp_attach( name );
381 117 : if( FD_UNLIKELY( !wksp ) ) return NULL; /* logs details */
382 : /* name must be valid at this point */
383 :
384 108 : ulong gaddr = fd_wksp_alloc( wksp, align, sz, tag );
385 108 : if( FD_UNLIKELY( (!!sz) & (!gaddr) ) ) {
386 24 : fd_wksp_detach( wksp ); /* logs details */
387 24 : return NULL;
388 24 : }
389 :
390 84 : fd_wksp_detach( wksp ); /* logs details */
391 84 : return fd_wksp_private_cstr( name, gaddr, cstr );
392 108 : }
393 :
394 : void
395 75 : fd_wksp_cstr_free( char const * cstr ) {
396 75 : char name[ FD_SHMEM_NAME_MAX ];
397 75 : ulong gaddr;
398 75 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return; /* logs details */
399 :
400 57 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
401 57 : if( FD_UNLIKELY( !wksp ) ) return;
402 :
403 57 : fd_wksp_free( wksp, gaddr ); /* logs details */
404 :
405 57 : fd_wksp_detach( wksp ); /* logs details */
406 57 : }
407 :
408 : ulong
409 78 : fd_wksp_cstr_tag( char const * cstr ) {
410 78 : char name[ FD_SHMEM_NAME_MAX ];
411 78 : ulong gaddr;
412 78 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return 0UL; /* logs details */
413 :
414 60 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
415 60 : if( FD_UNLIKELY( !wksp ) ) return 0UL;
416 :
417 60 : ulong tag = fd_wksp_tag( wksp, gaddr ); /* logs details */
418 :
419 60 : fd_wksp_detach( wksp ); /* logs details */
420 :
421 60 : return tag;
422 60 : }
423 :
424 : void
425 : fd_wksp_cstr_memset( char const * cstr,
426 42 : int c ) {
427 42 : char name[ FD_SHMEM_NAME_MAX ];
428 42 : ulong gaddr;
429 42 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return; /* logs details */
430 :
431 18 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
432 18 : if( FD_UNLIKELY( !wksp ) ) return;
433 :
434 18 : fd_wksp_memset( wksp, gaddr, c ); /* logs details */
435 :
436 18 : fd_wksp_detach( wksp ); /* logs details */
437 18 : }
438 :
439 : void *
440 1158 : fd_wksp_map( char const * cstr ) {
441 1158 : char name[ FD_SHMEM_NAME_MAX ];
442 1158 : ulong gaddr;
443 1158 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return NULL; /* logs details */
444 :
445 1047 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
446 1047 : if( FD_UNLIKELY( !wksp ) ) return NULL;
447 :
448 1047 : void * laddr = fd_wksp_laddr( wksp, gaddr ); /* logs details */
449 1047 : 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 3 : fd_wksp_detach( wksp ); /* logs details */
454 3 : return NULL;
455 3 : }
456 :
457 1044 : return laddr;
458 1047 : }
459 :
460 : void
461 999 : fd_wksp_unmap( void const * laddr ) {
462 999 : 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 993 : fd_shmem_join_info_t info[1];
469 993 : 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 993 : fd_wksp_t * wksp = (fd_wksp_t *)info->join;
475 993 : 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 993 : fd_wksp_detach( wksp ); /* logs details */
481 993 : }
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 : }
|