Line data Source code
1 : #ifndef HEADER_fd_src_tango_fseq_fd_fseq_h 2 : #define HEADER_fd_src_tango_fseq_fd_fseq_h 3 : 4 : /* fseq provides APIs for wrapping up a sequence number as a persistent 5 : shared memory object (primarily for use in rx->tx flow control 6 : communications but potentially could be used for other cases of 7 : making sequence numbers visible to other processes at run-time). */ 8 : 9 : #include "../fd_tango_base.h" 10 : 11 : /* FD_FSEQ_{ALIGN,FOOTPRINT} specify the alignment and footprint needed 12 : for a fseq. ALIGN is a positive integer power of 2. FOOTPRINT is a 13 : multiple of ALIGN. ALIGN is recommended to be at least double cache 14 : line to mitigate various kinds of false sharing. These are provided 15 : to facilitate compile time declarations. */ 16 : 17 156 : #define FD_FSEQ_ALIGN (128UL) 18 210 : #define FD_FSEQ_FOOTPRINT (128UL) 19 : 20 : /* FD_FSEQ_APP_{ALIGN,FOOTPRINT} specify the alignment and footprint of 21 : a fseq's application region. ALIGN is a positive integer power of 2. 22 : FOOTPRINT is a multiple of ALIGN. */ 23 : 24 : #define FD_FSEQ_APP_ALIGN (32UL) 25 297 : #define FD_FSEQ_APP_FOOTPRINT (96UL) 26 : 27 : FD_PROTOTYPES_BEGIN 28 : 29 : /* fd_fseq_{align,footprint} return the required alignment and footprint 30 : of a memory region suitable for use as a fseq. fd_fseq_align returns 31 : FD_FSEQ_ALIGN. fd_fseq_footprint returns FD_FSEQ_FOOTPRINT. */ 32 : 33 : FD_FN_CONST ulong 34 : fd_fseq_align( void ); 35 : 36 : FD_FN_CONST ulong 37 : fd_fseq_footprint( void ); 38 : 39 : /* fd_fseq_new formats an unused memory region for use as a fseq. Assumes 40 : shmem is a non-NULL pointer to this region in the local address space 41 : with the required footprint and alignment. The fseq will be 42 : initialized to seq0 and the application region will be cleared to 0. 43 : Returns shmem (and the memory region it points to will be formatted 44 : as a fseq, caller is not joined) and NULL on failure (logs details). 45 : Reasons for failure include an obviously bad memory region. */ 46 : 47 : void * 48 : fd_fseq_new( void * shmem, 49 : ulong seq0 ); 50 : 51 : /* fd_fseq_join joins the caller to the fseq. shfseq points to the first 52 : byte of the memory region backing the fseq in the caller's address 53 : space. Returns a pointer in the local address space to the fseq on 54 : success (IMPORTANT! THIS SHOULD NOT BE ASSUMED TO BE JUST A CAST OF 55 : SHFSEQ) or NULL on failure (logs details). Reasons for failure 56 : include the shfseq is obviously not a local pointer to a memory 57 : region holding a fseq. Every successful join should have a matching 58 : leave. The lifetime of the join is until the matching leave or 59 : caller's thread group is terminated. */ 60 : 61 : ulong * 62 : fd_fseq_join( void * shfseq ); 63 : 64 : /* fd_fseq_leave leaves a current local join. Returns a pointer to the 65 : underlying shared memory region on success (IMPORTANT! THIS SHOULD 66 : NOT BE ASSUMED TO BE JUST A CAST OF FSEQ) and NULL on failure (logs 67 : details). Reasons for failure include fseq is NULL. */ 68 : 69 : void * 70 : fd_fseq_leave( ulong const * fseq ); 71 : 72 : /* fd_fseq_delete unformats a memory region used as a fseq. Assumes 73 : nobody is joined to the region. Returns a pointer to the underlying 74 : shared memory region or NULL if used obviously in error (e.g. shfseq 75 : obviously does not point to a fseq ... logs details). The ownership 76 : of the memory region is transferred to the caller on success. */ 77 : 78 : void * 79 : fd_fseq_delete( void * shfseq ); 80 : 81 : /* fd_fctl_app_laddr returns local address of the fctl's application 82 : region. This will have FD_FCTL_APP_ALIGN alignment and room for at 83 : least FD_FCTL_APP_FOOTPRINT bytes. Assumes fseq is a current local 84 : join. fd_cnc_app_laddr_const is for const correctness. The return 85 : values are valid for the lifetime of the local join. */ 86 : 87 195 : FD_FN_CONST static inline void * fd_fseq_app_laddr ( ulong * fseq ) { return (void *)&fseq[2]; } 88 6 : FD_FN_CONST static inline void const * fd_fseq_app_laddr_const( ulong const * fseq ) { return (void const *)&fseq[2]; } 89 : 90 : /* fd_fseq_seq0 returns the sequencer number used when the fseq was 91 : created. Assumes fseq is a current local join. */ 92 : 93 3000006 : FD_FN_PURE static inline ulong fd_fseq_seq0( ulong const * fseq ) { return fseq[-1]; } 94 : 95 : /* fd_fseq_query reads the current sequence number stored the fseq. The 96 : value is observed at some point between when the call started and the 97 : call returned. This acts as an implicit compiler fence. Assumes 98 : fseq is a current local join. */ 99 : 100 : static inline ulong 101 3000009 : fd_fseq_query( ulong const * fseq ) { 102 3000009 : FD_COMPILER_MFENCE(); 103 3000009 : ulong seq = FD_VOLATILE_CONST( fseq[0] ); 104 3000009 : FD_COMPILER_MFENCE(); 105 3000009 : return seq; 106 3000009 : } 107 : 108 : /* fd_fseq_update updates the sequence number stored in the fseq to seq. 109 : The value is updated at some point between when the call started and 110 : the call returned. This acts as an implicit compiler fence. Assumes 111 : fseq is a current local join. */ 112 : 113 : static inline void 114 : fd_fseq_update( ulong * fseq, 115 3000000 : ulong seq ) { 116 3000000 : FD_COMPILER_MFENCE(); 117 3000000 : FD_VOLATILE( fseq[0] ) = seq; 118 3000000 : FD_COMPILER_MFENCE(); 119 3000000 : } 120 : 121 : FD_PROTOTYPES_END 122 : 123 : #endif /* HEADER_fd_src_tango_fseq_fd_fseq_h */