Line data Source code
1 : #include "fd_mcache_private.h" 2 : 3 : ulong 4 3 : fd_mcache_align( void ) { 5 3 : return FD_MCACHE_ALIGN; 6 3 : } 7 : 8 : ulong 9 : fd_mcache_footprint( ulong depth, 10 1 : ulong app_sz ) { 11 : 12 1 : if( FD_UNLIKELY( depth<FD_MCACHE_BLOCK ) ) return 0UL; /* too small depth */ 13 1 : if( FD_UNLIKELY( depth>ULONG_MAX/sizeof(fd_frag_meta_t) ) ) return 0UL; /* too large depth */ 14 1 : if( FD_UNLIKELY( !fd_ulong_is_pow2( depth ) ) ) return 0UL; /* non-power-of-two depth */ 15 1 : ulong meta_footprint = depth*sizeof( fd_frag_meta_t ); /* no overflow */ 16 1 : if( FD_UNLIKELY( fd_ulong_align_up( meta_footprint, FD_MCACHE_ALIGN )<meta_footprint ) ) return 0UL; /* too large depth */ 17 1 : meta_footprint = fd_ulong_align_up( meta_footprint, FD_MCACHE_ALIGN ); 18 : 19 1 : ulong app_footprint = fd_ulong_align_up( app_sz, FD_MCACHE_ALIGN ); 20 1 : if( FD_UNLIKELY( app_footprint<app_sz ) ) return 0UL; /* overflow */ 21 : 22 1 : ulong footprint = meta_footprint + app_footprint; /* meta and app */ 23 1 : if( footprint<meta_footprint ) return 0UL; /* overflow */ 24 : 25 1 : footprint += sizeof(fd_mcache_private_hdr_t); /* header and seq */ 26 1 : if( FD_UNLIKELY( footprint<sizeof(fd_mcache_private_hdr_t) ) ) return 0UL; /* overflow */ 27 : 28 1 : return footprint; 29 1 : } 30 : 31 : void * 32 : fd_mcache_new( void * shmem, 33 : ulong depth, 34 : ulong app_sz, 35 1 : ulong seq0 ) { 36 : 37 1 : if( FD_UNLIKELY( !shmem ) ) { 38 0 : FD_LOG_WARNING(( "NULL shmem" )); 39 0 : return NULL; 40 0 : } 41 : 42 1 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_mcache_align() ) ) ) { 43 0 : FD_LOG_WARNING(( "misaligned shmem" )); 44 0 : return NULL; 45 0 : } 46 : 47 1 : ulong footprint = fd_mcache_footprint( depth, app_sz ); 48 1 : if( FD_UNLIKELY( !footprint ) ) { 49 0 : FD_LOG_WARNING(( "bad depth (%lu) or app_sz (%lu)", depth, app_sz )); 50 0 : return NULL; 51 0 : } 52 : 53 1 : fd_memset( shmem, 0, footprint ); 54 : 55 1 : fd_mcache_private_hdr_t * hdr = (fd_mcache_private_hdr_t *)shmem; 56 : 57 1 : hdr->depth = depth; 58 1 : hdr->app_sz = app_sz; 59 1 : hdr->seq0 = seq0; 60 1 : hdr->app_off = sizeof(fd_mcache_private_hdr_t) + fd_ulong_align_up( depth*sizeof(fd_frag_meta_t), FD_MCACHE_ALIGN ); 61 : 62 1 : hdr->seq[0] = seq0; 63 : 64 1 : fd_frag_meta_t * mcache = fd_mcache_private_mcache( hdr ); 65 : 66 1 : ulong seq1 = fd_seq_inc( seq0, depth ); 67 257 : for( ulong seq=seq0; seq!=seq1; seq=fd_seq_inc(seq,1UL) ) { 68 256 : ulong line = fd_mcache_line_idx( seq, depth ); 69 256 : mcache[line].seq = fd_seq_dec( seq, 1UL ); 70 256 : mcache[line].ctl = (ushort)fd_frag_meta_ctl( 0UL /*orig*/, 1 /*som*/, 1 /*eom*/, 1 /*err*/ ); 71 256 : } 72 : 73 1 : FD_COMPILER_MFENCE(); 74 1 : FD_VOLATILE( hdr->magic ) = FD_MCACHE_MAGIC; 75 1 : FD_COMPILER_MFENCE(); 76 : 77 1 : return shmem; 78 1 : } 79 : 80 : fd_frag_meta_t * 81 1 : fd_mcache_join( void * shmcache ) { 82 : 83 1 : if( FD_UNLIKELY( !shmcache ) ) { 84 0 : FD_LOG_WARNING(( "NULL shmcache" )); 85 0 : return NULL; 86 0 : } 87 : 88 1 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmcache, fd_mcache_align() ) ) ) { 89 0 : FD_LOG_WARNING(( "misaligned shmcache" )); 90 0 : return NULL; 91 0 : } 92 : 93 1 : fd_mcache_private_hdr_t * hdr = (fd_mcache_private_hdr_t *)shmcache; 94 1 : if( FD_UNLIKELY( hdr->magic!=FD_MCACHE_MAGIC ) ) { 95 0 : FD_LOG_WARNING(( "bad magic" )); 96 0 : return NULL; 97 0 : } 98 : 99 1 : return fd_mcache_private_mcache( hdr ); 100 1 : } 101 : 102 : void * 103 0 : fd_mcache_leave( fd_frag_meta_t const * mcache ) { 104 : 105 0 : if( FD_UNLIKELY( !mcache ) ) { 106 0 : FD_LOG_WARNING(( "NULL mcache" )); 107 0 : return NULL; 108 0 : } 109 : 110 0 : return (void *)fd_mcache_private_hdr_const( mcache ); /* Kinda ugly const cast */ 111 0 : } 112 : 113 : void * 114 0 : fd_mcache_delete( void * shmcache ) { 115 : 116 0 : if( FD_UNLIKELY( !shmcache ) ) { 117 0 : FD_LOG_WARNING(( "NULL shmcache" )); 118 0 : return NULL; 119 0 : } 120 : 121 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmcache, fd_mcache_align() ) ) ) { 122 0 : FD_LOG_WARNING(( "misaligned shmcache" )); 123 0 : return NULL; 124 0 : } 125 : 126 0 : fd_mcache_private_hdr_t * hdr = (fd_mcache_private_hdr_t *)shmcache; 127 0 : if( FD_UNLIKELY( hdr->magic != FD_MCACHE_MAGIC ) ) { 128 0 : FD_LOG_WARNING(( "bad magic" )); 129 0 : return NULL; 130 0 : } 131 : 132 0 : FD_COMPILER_MFENCE(); 133 0 : FD_VOLATILE( hdr->magic ) = 0UL; 134 0 : FD_COMPILER_MFENCE(); 135 : 136 0 : return shmcache; 137 0 : } 138 : 139 : ulong 140 5 : fd_mcache_depth( fd_frag_meta_t const * mcache ) { 141 5 : return fd_mcache_private_hdr_const( mcache )->depth; 142 5 : } 143 : 144 : ulong 145 0 : fd_mcache_app_sz( fd_frag_meta_t const * mcache ) { 146 0 : return fd_mcache_private_hdr_const( mcache )->app_sz; 147 0 : } 148 : 149 : ulong 150 1 : fd_mcache_seq0( fd_frag_meta_t const * mcache ) { 151 1 : return fd_mcache_private_hdr_const( mcache )->seq0; 152 1 : } 153 : 154 : ulong const * 155 1 : fd_mcache_seq_laddr_const( fd_frag_meta_t const * mcache ) { 156 1 : return fd_mcache_private_hdr_const( mcache )->seq; 157 1 : } 158 : 159 : ulong * 160 1 : fd_mcache_seq_laddr( fd_frag_meta_t * mcache ) { 161 1 : return fd_mcache_private_hdr( mcache )->seq; 162 1 : } 163 : 164 : uchar const * 165 0 : fd_mcache_app_laddr_const( fd_frag_meta_t const * mcache ) { 166 0 : fd_mcache_private_hdr_t const * hdr = fd_mcache_private_hdr_const( mcache ); 167 0 : return (uchar const *)(((ulong)hdr) + hdr->app_off); 168 0 : } 169 : 170 : uchar * 171 0 : fd_mcache_app_laddr( fd_frag_meta_t * mcache ) { 172 0 : fd_mcache_private_hdr_t * hdr = fd_mcache_private_hdr( mcache ); 173 0 : return (uchar *)(((ulong)hdr) + hdr->app_off); 174 0 : } 175 :