Line data Source code
1 : #include "fd_tcache.h" 2 : 3 : ulong 4 0 : fd_tcache_align( void ) { 5 0 : return FD_TCACHE_ALIGN; 6 0 : } 7 : 8 : ulong 9 : fd_tcache_footprint( ulong depth, 10 0 : ulong map_cnt ) { 11 0 : if( !map_cnt ) map_cnt = fd_tcache_map_cnt_default( depth ); /* use default */ 12 : 13 0 : if( FD_UNLIKELY( (!depth) | (map_cnt<(depth+2UL)) | (!fd_ulong_is_pow2( map_cnt )) ) ) return 0UL; /* Invalid depth / max_cnt */ 14 : 15 0 : ulong cnt = 4UL+depth; if( FD_UNLIKELY( cnt<depth ) ) return 0UL; /* overflow */ 16 0 : cnt += map_cnt; if( FD_UNLIKELY( cnt<map_cnt ) ) return 0UL; /* overflow */ 17 0 : if( FD_UNLIKELY( cnt>(ULONG_MAX/sizeof(ulong)) ) ) return 0UL; /* overflow */ 18 0 : cnt *= sizeof(ulong); /* no overflow */ 19 0 : ulong footprint = fd_ulong_align_up( cnt, FD_TCACHE_ALIGN ); if( FD_UNLIKELY( footprint<cnt ) ) return 0UL; /* overflow */ 20 0 : return footprint; 21 0 : } 22 : 23 : void * 24 : fd_tcache_new( void * shmem, 25 : ulong depth, 26 0 : ulong map_cnt ) { 27 0 : if( !map_cnt ) map_cnt = fd_tcache_map_cnt_default( depth ); /* use default */ 28 : 29 0 : if( FD_UNLIKELY( !shmem ) ) { 30 0 : FD_LOG_WARNING(( "NULL shmem" )); 31 0 : return NULL; 32 0 : } 33 : 34 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_tcache_align() ) ) ) { 35 0 : FD_LOG_WARNING(( "misaligned shmem" )); 36 0 : return NULL; 37 0 : } 38 : 39 0 : ulong footprint = fd_tcache_footprint( depth, map_cnt ); 40 0 : if( FD_UNLIKELY( !footprint ) ) { 41 0 : FD_LOG_WARNING(( "bad depth (%lu) and/or map_cnt (%lu)", depth, map_cnt )); 42 0 : return NULL; 43 0 : } 44 : 45 0 : fd_memset( shmem, 0, footprint ); 46 : 47 0 : fd_tcache_t * tcache = (fd_tcache_t *)shmem; 48 : 49 0 : tcache->depth = depth; 50 0 : tcache->map_cnt = map_cnt; 51 0 : tcache->oldest = fd_tcache_reset( fd_tcache_ring_laddr( tcache ), depth, fd_tcache_map_laddr( tcache ), map_cnt ); 52 : 53 0 : FD_COMPILER_MFENCE(); 54 0 : FD_VOLATILE( tcache->magic ) = FD_TCACHE_MAGIC; 55 0 : FD_COMPILER_MFENCE(); 56 : 57 0 : return shmem; 58 0 : } 59 : 60 : fd_tcache_t * 61 0 : fd_tcache_join( void * _tcache ) { 62 : 63 0 : if( FD_UNLIKELY( !_tcache ) ) { 64 0 : FD_LOG_WARNING(( "NULL _tcache" )); 65 0 : return NULL; 66 0 : } 67 : 68 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)_tcache, fd_tcache_align() ) ) ) { 69 0 : FD_LOG_WARNING(( "misaligned _tcache" )); 70 0 : return NULL; 71 0 : } 72 : 73 0 : fd_tcache_t * tcache = (fd_tcache_t *)_tcache; 74 0 : if( FD_UNLIKELY( tcache->magic!=FD_TCACHE_MAGIC ) ) { 75 0 : FD_LOG_WARNING(( "bad magic" )); 76 0 : return NULL; 77 0 : } 78 : 79 0 : return tcache; 80 0 : } 81 : 82 : void * 83 0 : fd_tcache_leave( fd_tcache_t * tcache ) { 84 : 85 0 : if( FD_UNLIKELY( !tcache ) ) { 86 0 : FD_LOG_WARNING(( "NULL tcache" )); 87 0 : return NULL; 88 0 : } 89 : 90 0 : return (void *)tcache; 91 0 : } 92 : 93 : void * 94 0 : fd_tcache_delete( void * _tcache ) { 95 : 96 0 : if( FD_UNLIKELY( !_tcache ) ) { 97 0 : FD_LOG_WARNING(( "NULL _tcache" )); 98 0 : return NULL; 99 0 : } 100 : 101 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)_tcache, fd_tcache_align() ) ) ) { 102 0 : FD_LOG_WARNING(( "misaligned _tcache" )); 103 0 : return NULL; 104 0 : } 105 : 106 0 : fd_tcache_t * tcache = (fd_tcache_t *)_tcache; 107 0 : if( FD_UNLIKELY( tcache->magic != FD_TCACHE_MAGIC ) ) { 108 0 : FD_LOG_WARNING(( "bad magic" )); 109 0 : return NULL; 110 0 : } 111 : 112 0 : FD_COMPILER_MFENCE(); 113 0 : FD_VOLATILE( tcache->magic ) = 0UL; 114 0 : FD_COMPILER_MFENCE(); 115 : 116 0 : return _tcache; 117 0 : } 118 :