Line data Source code
1 : #ifndef HEADER_fd_src_util_tile_fd_tile_h 2 : #define HEADER_fd_src_util_tile_fd_tile_h 3 : 4 : /* Note: fd must be booted to use the APIs in this module */ 5 : 6 : /* fd_tile is used for fast dispatching of task within a thread group. */ 7 : 8 : #include "../shmem/fd_shmem.h" 9 : 10 : /* FD_TILE_MAX gives a compile tile constant that is the upper bound 11 : of the number of tiles that could exist within a thread group. */ 12 : 13 4807302 : #define FD_TILE_MAX (1024UL) 14 : 15 : /* A fd_tile_task_t is a function pointer with the function signature 16 : for tasks that can be dispatched to a tile. */ 17 : 18 : typedef int (*fd_tile_task_t)( int argc, char ** argv ); 19 : 20 : /* A fd_tile_exec_t is an opaque handle of a tile execution */ 21 : 22 : struct fd_tile_exec_private; 23 : typedef struct fd_tile_exec_private fd_tile_exec_t; 24 : 25 : /* TODO: Allow this to be run-time configured (e.g. match ulimit -s)? */ 26 180 : #define FD_TILE_PRIVATE_STACK_SZ (8UL<<20) /* Should be a multiple of HUGE (and NORMAL) page sizes */ 27 : 28 : FD_PROTOTYPES_BEGIN 29 : 30 : /* fd_tile_{id0,id1,id,idx,cnt} return various information about the 31 : calling tile. Will be constant while tile services are booted. */ 32 : 33 : FD_FN_PURE ulong fd_tile_id0( void ); /* Application threads [fd_tile_id0(),fd_tile_id1()) are the caller's thread group */ 34 : FD_FN_PURE ulong fd_tile_id1( void ); 35 : FD_FN_PURE ulong fd_tile_id ( void ); /* == fd_log_thread_id(), in [fd_tile_id0(),fd_tile_id1()) */ 36 : FD_FN_PURE ulong fd_tile_idx( void ); /* == fd_tile_id ()-fd_tile_id0(), in [0,fd_tile_cnt()) */ 37 : FD_FN_PURE ulong fd_tile_cnt( void ); /* == fd_tile_id1()-fd_tile_id0() > 0 */ 38 : 39 : /* fd_tile_cpu_id returns the physical cpu_idx used by tile_idx. This 40 : matches the --tile-cpus / FD_TILE_CPUS configuration extracted from 41 : the command line / environment when tile services were booted. Will 42 : be constant while tile services are booted. Returns ULONG_MAX if 43 : tile_idx is not in [0,td_tile_cnt()) and ULONG_MAX-1 if tile_idx was 44 : configured to float. */ 45 : 46 : FD_FN_PURE ulong fd_tile_cpu_id( ulong tile_idx ); 47 : 48 : /* Tile stack diagnostics. These are meant to help with instrumenting 49 : and debugging stack issues but usually should not be used in final 50 : production code. For reference, tile 0's stack size is usually set 51 : at thread group start with the size in KiB given by "ulimit -s". 52 : This is typically 8 MiB and dynamically backed by normal 4 KiB pages. 53 : Other tiles usually have a size of a not-so-coincidentally 8 MiB but 54 : are backed by preallocated NUMA and TLB optimized huge 2 MiB pages. 55 : Additionally, tile stacks are usually bookended by guard regions that 56 : are 4 KiB in size to protect against common stack overflow / 57 : underflow risks. The below assumes the stack grows from higher 58 : addresses (i.e. stack1) toward lower addresses (i.e. stack0). 59 : 60 : [fd_tile_stack0(),fd_tile_stack1()) gives the location in caller's 61 : local address space the caller's stack. The size of this region is 62 : fd_tile_stack_sz(). fd_tile_stack_est_used() and 63 : fd_tile_stack_est_free() are estimates of the number of bytes in the 64 : stack currently used and currently free. 65 : 66 : If the tile stack parameters could not be determined at tile startup, 67 : details will be logged and stack0/stack1/stack_sz/est_used/est_free 68 : will be NULL/NULL/0/0/0. */ 69 : 70 : extern FD_TL ulong fd_tile_private_stack0; 71 : extern FD_TL ulong fd_tile_private_stack1; 72 : 73 18 : static inline void const * fd_tile_stack0 ( void ) { return (void const *)fd_tile_private_stack0; } 74 18 : static inline void const * fd_tile_stack1 ( void ) { return (void const *)fd_tile_private_stack1; } 75 18 : static inline ulong fd_tile_stack_sz( void ) { return fd_tile_private_stack1 - fd_tile_private_stack0; } 76 : 77 : static inline ulong 78 18 : fd_tile_stack_est_used( void ) { 79 18 : uchar stack_mem[1]; 80 18 : FD_VOLATILE( stack_mem[0] ) = (uchar)1; /* Paranoia to guarantee stack_mem is on the stack and backed by memory */ 81 18 : return fd_ulong_if( !fd_tile_private_stack1, 0UL, fd_tile_private_stack1 - (ulong)stack_mem ); 82 18 : } 83 : 84 : static inline ulong 85 6531 : fd_tile_stack_est_free( void ) { 86 6531 : uchar stack_mem[1]; 87 6531 : FD_VOLATILE( stack_mem[0] ) = (uchar)1; /* Paranoia to guarantee stack_mem is on the stack and backed by memory */ 88 6531 : return fd_ulong_if( !fd_tile_private_stack0, 0UL, (ulong)stack_mem - fd_tile_private_stack0 ); 89 6531 : } 90 : 91 : /* fd_tile_exec_new starts parallel execution of task( argc, argv ) on 92 : tile idx (in [0,fd_tile_cnt()). Returns a handle for this exec on 93 : success (tile idx was signaled to start execution of task) or NULL on 94 : failure (e.g. tried to dispatch to self or tried dispatch to tile 0, 95 : another exec is currently running on that tile id, tried to dispatch 96 : to a thread in a different thread group, etc). 97 : 98 : task, argc, argv and argv[0:argc] are intended to be in this thread 99 : group's address space and argc and argv are intended (but not 100 : required) to be POSIX-like command line interface such that argc>0, 101 : argv[0] is the task name, argv[argc]==NULL and argv[0:argc-1] are all 102 : non-NULL cstrs. On success, the returned exec has ownership of argv 103 : and all cstrs pointed to by it. On failure, ownership is unchanged. 104 : 105 : Typically, a tile can't dispatch to itself or to tile 0. */ 106 : 107 : fd_tile_exec_t * 108 : fd_tile_exec_new( ulong idx, /* In [0,fd_tile_cnt()) */ 109 : fd_tile_task_t task, /* Non-NULL */ 110 : int argc, 111 : char ** argv ); 112 : 113 : /* fd_tile_exec_by_id_new same as the above but tile to run is specified 114 : by the application thread index. */ 115 : 116 : static inline fd_tile_exec_t * 117 : fd_tile_exec_by_id_new( ulong id, /* In [fd_tile_id0(),fd_tile_id1()) */ 118 : fd_tile_task_t task, /* Non-NULL */ 119 : int argc, 120 0 : char ** argv ) { 121 0 : return fd_tile_exec_new( id-fd_tile_id0(), task, argc, argv ); 122 0 : } 123 : 124 : /* fd_tile_exec_delete deletes the given exec, blocking the caller if 125 : necessary (will be non-blocking if the exec is done). Returns NULL 126 : if the exec terminated normally (if opt_ret is non-NULL and *opt_ret 127 : will be the value returned by the tile task) or an infinite lifetime 128 : cstr if the exec terminated abnormally (e.g. had an uncaught 129 : exception, called exit ... yes, currently tile tasks must return for 130 : normal termination, called abort, etc ... opt_ret will be 131 : non-touched). */ 132 : 133 : char const * 134 : fd_tile_exec_delete( fd_tile_exec_t * exec, 135 : int * opt_ret ); 136 : 137 : /* fd_tile_exec returns the fd_tile_exec_t * running on tile tile_idx. 138 : fd_tile_exec_by_id_new same but tile to specified by the application 139 : thread index. Undefined if tile_idx is not in [0,fd_tile_cnt()) (or 140 : tile_id is not in [fd_tile_id0(),fd_tile_id1()) or called outside a 141 : fd_tile_exec*_new / fd_tile_exec_delete pair. */ 142 : 143 : FD_FN_PURE fd_tile_exec_t * fd_tile_exec( ulong tile_idx ); 144 : 145 12 : static inline fd_tile_exec_t * fd_tile_exec_by_id( ulong tile_id ) { return fd_tile_exec( tile_id-fd_tile_id0() ); } 146 : 147 : /* fd_tile_exec_{id,idx,task,argc,argv} access details exec pointed to 148 : by exec. These assume exec points to a current exec. */ 149 : 150 : FD_FN_PURE ulong fd_tile_exec_id ( fd_tile_exec_t const * exec ); 151 : FD_FN_PURE ulong fd_tile_exec_idx ( fd_tile_exec_t const * exec ); 152 : FD_FN_PURE fd_tile_task_t fd_tile_exec_task( fd_tile_exec_t const * exec ); 153 : FD_FN_PURE int fd_tile_exec_argc( fd_tile_exec_t const * exec ); 154 : FD_FN_PURE char ** fd_tile_exec_argv( fd_tile_exec_t const * exec ); 155 : 156 : /* fd_tile_exec_done returns 0 if the given exec is still running or 1 157 : if it has stopped. Assumes exec points to a current exec. */ 158 : 159 : int fd_tile_exec_done( fd_tile_exec_t const * exec ); 160 : 161 : /* These functions are for fd_util internal use only. */ 162 : 163 : void 164 : fd_tile_private_boot( int * pargc, 165 : char *** pargv ); 166 : 167 : void 168 : fd_tile_private_map_boot( ushort * tile_to_cpu, 169 : ulong tile_cnt ); 170 : 171 : void 172 : fd_tile_private_halt( void ); 173 : 174 : FD_PROTOTYPES_END 175 : 176 : #endif /* HEADER_fd_src_util_tile_fd_tile_h */