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 1020 : fd_shmem_join_info_t const * info ) {
9 1020 : (void)context;
10 1020 : return fd_wksp_join( info->shmem ); /* logs details */
11 1020 : }
12 :
13 : static void *
14 : fd_wksp_private_leave_func( void * context,
15 1320 : fd_shmem_join_info_t const * info ) {
16 1320 : (void)context;
17 1320 : return fd_wksp_leave( info->join ); /* logs details */
18 1320 : }
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 213 : char * cstr ) {
28 213 : fd_cstr_fini( fd_cstr_append_ulong_as_text( fd_cstr_append_char( fd_cstr_append_cstr( fd_cstr_init( cstr ),
29 213 : name ), ':' ), ' ', '\0', gaddr, fd_ulong_base10_dig_cnt( gaddr ) ) );
30 213 : return cstr;
31 213 : }
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 1128 : ulong * gaddr ) { /* Non-NULL, holds gaddr on success, untouched otherwise */
43 1128 : if( FD_UNLIKELY( !cstr ) ) {
44 30 : FD_LOG_WARNING(( "NULL cstr" ));
45 30 : return NULL;
46 30 : }
47 :
48 1098 : ulong len = 0UL;
49 1098 : ulong name_len = ULONG_MAX;
50 24531 : for(;;) {
51 24531 : if( cstr[len]=='\0' ) break;
52 23433 : if( cstr[len]==':' ) name_len = len;
53 23433 : len++;
54 23433 : }
55 1098 : ulong gaddr_len = len - name_len - 1UL;
56 :
57 1098 : 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 1098 : if( FD_UNLIKELY( name_len==ULONG_MAX ) ) {
63 48 : FD_LOG_WARNING(( "no ':' found; cstr should be of the form [name]:[gaddr]" ));
64 48 : return NULL;
65 48 : }
66 :
67 1050 : 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 1050 : 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 1050 : fd_memcpy( name, cstr, name_len );
78 1050 : name[name_len] = '\0';
79 1050 : gaddr[0] = fd_cstr_to_ulong( cstr + name_len + 1UL );
80 1050 : return name;
81 1050 : }
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 537 : ulong const * x ) {
91 537 : ulong sum = 0UL;
92 537 : int ovfl = 0;
93 1074 : for( ulong idx=0UL; idx<cnt; idx++ ) {
94 537 : ulong tmp = sum + x[idx];
95 537 : ovfl |= (tmp < sum );
96 537 : sum = tmp;
97 537 : }
98 537 : return fd_ulong_if( ovfl, ULONG_MAX, sum );
99 537 : }
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 51 : ulong part_max ) {
110 :
111 : /* Check input args */
112 :
113 51 : if( FD_UNLIKELY( !fd_shmem_name_len( name ) ) ) { FD_LOG_WARNING(( "bad name" )); return FD_WKSP_ERR_INVAL; }
114 48 : if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "unsupported page_sz" )); return FD_WKSP_ERR_INVAL; }
115 45 : if( FD_UNLIKELY( !sub_cnt ) ) { FD_LOG_WARNING(( "zero sub_cnt" )); return FD_WKSP_ERR_INVAL; }
116 42 : if( FD_UNLIKELY( !sub_page_cnt ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt" )); return FD_WKSP_ERR_INVAL; }
117 39 : if( FD_UNLIKELY( !sub_cpu_idx ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx" )); return FD_WKSP_ERR_INVAL; }
118 :
119 36 : ulong page_cnt = fd_ulong_sum_sat( sub_cnt, sub_page_cnt );
120 :
121 36 : if( FD_UNLIKELY( !page_cnt ) ) { FD_LOG_WARNING(( "zero page_cnt" )); return FD_WKSP_ERR_INVAL; }
122 33 : 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 30 : ulong footprint = page_cnt*page_sz;
127 :
128 30 : if( !part_max ) {
129 27 : part_max = fd_wksp_part_max_est( footprint, 64UL<<10 ); /* Typical size is fd_alloc top level superblock-ish */
130 27 : 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 27 : }
135 :
136 30 : ulong data_max = fd_wksp_data_max_est( footprint, part_max );
137 30 : 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 27 : int err = fd_shmem_create_multi( name, page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx, mode ); /* logs details */
145 27 : if( FD_UNLIKELY( err ) ) return FD_WKSP_ERR_FAIL;
146 :
147 : /* Join the memory region */
148 :
149 21 : void * shmem = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, NULL, NULL, NULL ); /* logs details */
150 21 : 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 21 : 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 21 : fd_shmem_leave( shmem, NULL, NULL ); /* logs details */
164 :
165 21 : return FD_WKSP_SUCCESS;
166 21 : }
167 :
168 : int
169 27 : fd_wksp_delete_named( char const * name ) {
170 :
171 : /* Join the region and get the page size */
172 :
173 27 : fd_shmem_join_info_t info[1];
174 27 : void * shwksp = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, NULL, NULL, info ); /* logs details */
175 27 : if( FD_UNLIKELY( !shwksp ) ) return FD_WKSP_ERR_FAIL;
176 21 : ulong page_sz = info->page_sz;
177 :
178 : /* Delete the region */
179 :
180 21 : 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 21 : 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 21 : fd_shmem_leave( shwksp, NULL, NULL ); /* logs details, after the unlink as per UNIX file semantics */
191 21 : return FD_WKSP_SUCCESS;
192 21 : }
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 516 : ulong part_max ) {
202 :
203 : /* Check input args */
204 :
205 516 : if( FD_UNLIKELY( !fd_shmem_name_len( name ) ) ) { FD_LOG_WARNING(( "bad name" )); return NULL; }
206 513 : if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "unsupported page_sz" )); return NULL; }
207 510 : if( FD_UNLIKELY( !sub_cnt ) ) { FD_LOG_WARNING(( "zero sub_cnt" )); return NULL; }
208 507 : if( FD_UNLIKELY( !sub_page_cnt ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt" )); return NULL; }
209 504 : if( FD_UNLIKELY( !sub_cpu_idx ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx" )); return NULL; }
210 :
211 501 : ulong page_cnt = fd_ulong_sum_sat( sub_cnt, sub_page_cnt );
212 :
213 501 : if( FD_UNLIKELY( !page_cnt ) ) { FD_LOG_WARNING(( "zero page_cnt" )); return NULL; }
214 498 : if( FD_UNLIKELY( page_cnt>=(ULONG_MAX/page_sz) ) ) { FD_LOG_WARNING(( "page_cnt overflow" )); return NULL; }
215 :
216 : /* Configure the wksp */
217 :
218 495 : ulong footprint = page_cnt*page_sz;
219 :
220 495 : if( !part_max ) {
221 492 : part_max = fd_wksp_part_max_est( footprint, 64UL<<10 ); /* Typical size is fd_alloc top level superblock-ish */
222 492 : 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 492 : }
227 :
228 495 : ulong data_max = fd_wksp_data_max_est( footprint, part_max );
229 495 : 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 492 : void * shmem = fd_shmem_acquire_multi( page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx ); /* logs details */
237 492 : if( FD_UNLIKELY( !shmem ) ) return NULL;
238 :
239 : /* Format the memory as wksp */
240 :
241 489 : void* shwksp = fd_wksp_new( shmem, name, seed, part_max, data_max ); /* logs details */
242 489 : 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 489 : fd_wksp_t * wksp = fd_wksp_join( shwksp ); /* logs details */
250 489 : 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 489 : 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 489 : return wksp;
263 489 : }
264 :
265 : void
266 186 : fd_wksp_delete_anon( fd_wksp_t * wksp ) {
267 186 : fd_shmem_join_info_t info[1];
268 186 : if( FD_UNLIKELY( fd_shmem_leave_anonymous( wksp, info ) ) ) return; /* logs details */
269 180 : fd_shmem_release( fd_wksp_delete( fd_wksp_leave( wksp ) ), info->page_sz, info->page_cnt ); /* logs details */
270 180 : }
271 :
272 : fd_wksp_t *
273 110256 : fd_wksp_attach( char const * name ) {
274 110256 : return (fd_wksp_t *)
275 110256 : fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, fd_wksp_private_join_func, NULL, NULL ); /* logs details */
276 110256 : }
277 :
278 : int
279 110538 : fd_wksp_detach( fd_wksp_t * wksp ) {
280 110538 : if( FD_UNLIKELY( !wksp ) ) {
281 3 : FD_LOG_WARNING(( "NULL wksp" ));
282 3 : return 1;
283 3 : }
284 110535 : return fd_shmem_leave( wksp, fd_wksp_private_leave_func, NULL ); /* logs details */
285 110538 : }
286 :
287 : fd_wksp_t *
288 1100976 : fd_wksp_containing( void const * laddr ) {
289 1100976 : if( FD_UNLIKELY( !laddr ) ) return NULL;
290 :
291 1100964 : fd_shmem_join_info_t info[1];
292 1100964 : if( FD_UNLIKELY( fd_shmem_join_query_by_addr( laddr, 1UL, info ) ) ) return NULL;
293 :
294 1100922 : fd_wksp_t * wksp = (fd_wksp_t *)info->join;
295 1100922 : if( FD_UNLIKELY( !wksp ) ) return NULL;
296 :
297 1100922 : if( FD_UNLIKELY( wksp->magic!=FD_WKSP_MAGIC ) ) return NULL;
298 :
299 1100922 : return wksp;
300 1100922 : }
301 :
302 : void *
303 : fd_wksp_alloc_laddr( fd_wksp_t * wksp,
304 : ulong align,
305 : ulong sz,
306 551334 : ulong tag ) {
307 551334 : ulong gaddr = fd_wksp_alloc( wksp, align, sz, tag );
308 551334 : if( FD_UNLIKELY( !gaddr ) ) return NULL;
309 551304 : return fd_wksp_laddr_fast( wksp, gaddr );
310 551334 : }
311 :
312 : void
313 550074 : fd_wksp_free_laddr( void * laddr ) {
314 550074 : if( FD_UNLIKELY( !laddr ) ) return;
315 :
316 550068 : fd_wksp_t * wksp = fd_wksp_containing( laddr );
317 550068 : 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 550056 : ulong gaddr = fd_wksp_gaddr_fast( wksp, laddr );
323 550056 : 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 550056 : fd_wksp_free( wksp, gaddr );
329 550056 : }
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 63 : char * cstr ) {
374 63 : if( FD_UNLIKELY( !cstr ) ) {
375 0 : FD_LOG_WARNING(( "NULL cstr" ));
376 0 : return NULL;
377 0 : }
378 :
379 63 : fd_wksp_t * wksp = fd_wksp_attach( name );
380 63 : if( FD_UNLIKELY( !wksp ) ) return NULL; /* logs details */
381 : /* name must be valid at this point */
382 :
383 57 : ulong gaddr = fd_wksp_alloc( wksp, align, sz, tag );
384 57 : if( FD_UNLIKELY( (!!sz) & (!gaddr) ) ) {
385 18 : fd_wksp_detach( wksp ); /* logs details */
386 18 : return NULL;
387 18 : }
388 :
389 39 : fd_wksp_detach( wksp ); /* logs details */
390 39 : return fd_wksp_private_cstr( name, gaddr, cstr );
391 57 : }
392 :
393 : void
394 48 : fd_wksp_cstr_free( char const * cstr ) {
395 48 : char name[ FD_SHMEM_NAME_MAX ];
396 48 : ulong gaddr;
397 48 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return; /* logs details */
398 :
399 39 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
400 39 : if( FD_UNLIKELY( !wksp ) ) return;
401 :
402 39 : fd_wksp_free( wksp, gaddr ); /* logs details */
403 :
404 39 : fd_wksp_detach( wksp ); /* logs details */
405 39 : }
406 :
407 : ulong
408 33 : fd_wksp_cstr_tag( char const * cstr ) {
409 33 : char name[ FD_SHMEM_NAME_MAX ];
410 33 : ulong gaddr;
411 33 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return 0UL; /* logs details */
412 :
413 24 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
414 24 : if( FD_UNLIKELY( !wksp ) ) return 0UL;
415 :
416 24 : ulong tag = fd_wksp_tag( wksp, gaddr ); /* logs details */
417 :
418 24 : fd_wksp_detach( wksp ); /* logs details */
419 :
420 24 : return tag;
421 24 : }
422 :
423 : void
424 : fd_wksp_cstr_memset( char const * cstr,
425 24 : int c ) {
426 24 : char name[ FD_SHMEM_NAME_MAX ];
427 24 : ulong gaddr;
428 24 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return; /* logs details */
429 :
430 9 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
431 9 : if( FD_UNLIKELY( !wksp ) ) return;
432 :
433 9 : fd_wksp_memset( wksp, gaddr, c ); /* logs details */
434 :
435 9 : fd_wksp_detach( wksp ); /* logs details */
436 9 : }
437 :
438 : void *
439 1023 : fd_wksp_map( char const * cstr ) {
440 1023 : char name[ FD_SHMEM_NAME_MAX ];
441 1023 : ulong gaddr;
442 1023 : if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return NULL; /* logs details */
443 :
444 978 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
445 978 : if( FD_UNLIKELY( !wksp ) ) return NULL;
446 :
447 978 : void * laddr = fd_wksp_laddr( wksp, gaddr ); /* logs details */
448 978 : 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 975 : return laddr;
457 978 : }
458 :
459 : void
460 981 : fd_wksp_unmap( void const * laddr ) {
461 981 : 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 975 : fd_shmem_join_info_t info[1];
468 975 : 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 975 : fd_wksp_t * wksp = (fd_wksp_t *)info->join;
474 975 : 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 975 : fd_wksp_detach( wksp ); /* logs details */
480 975 : }
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 : }
528 :
|