Line data Source code
1 : #include "fd_vinyl_req_pool.h"
2 :
3 : #define SET_NAME used
4 : #include "../../util/tmpl/fd_set_dynamic.c"
5 :
6 : FD_STATIC_ASSERT( alignof(fd_vinyl_req_pool_t)<=FD_VINYL_REQ_POOL_ALIGN, align );
7 : FD_STATIC_ASSERT( alignof(ulong) <=FD_VINYL_REQ_POOL_ALIGN, align );
8 : FD_STATIC_ASSERT( alignof(fd_vinyl_key_t) <=FD_VINYL_REQ_POOL_ALIGN, align );
9 : FD_STATIC_ASSERT( alignof(fd_vinyl_comp_t) <=FD_VINYL_REQ_POOL_ALIGN, align );
10 :
11 : ulong
12 0 : fd_vinyl_req_pool_align( void ) {
13 0 : return FD_VINYL_REQ_POOL_ALIGN;
14 0 : }
15 :
16 : ulong
17 : fd_vinyl_req_pool_footprint( ulong batch_max,
18 0 : ulong batch_key_max ) {
19 : /* No point in creating empty pools */
20 0 : if( FD_UNLIKELY( !batch_max || !batch_key_max ) ) return 0UL;
21 :
22 : /* Check for integer overflow / oversized params */
23 0 : ulong req_max;
24 0 : if( FD_UNLIKELY( __builtin_umull_overflow( batch_max, batch_key_max, &req_max ) ) ) return 0UL;
25 0 : ulong ignored_;
26 0 : if( FD_UNLIKELY( __builtin_umull_overflow( req_max, 1024UL, &ignored_ ) ) ) return 0UL;
27 :
28 0 : ulong l = FD_LAYOUT_INIT;
29 0 : l = FD_LAYOUT_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, sizeof(fd_vinyl_req_pool_t) );
30 0 : l = FD_LAYOUT_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, batch_max*sizeof(ulong) );
31 0 : l = FD_LAYOUT_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, used_footprint( batch_max ) );
32 0 : l = FD_LAYOUT_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, req_max*sizeof(fd_vinyl_key_t) );
33 0 : l = FD_LAYOUT_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, req_max*sizeof(ulong) );
34 0 : l = FD_LAYOUT_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, req_max*sizeof(schar) );
35 0 : l = FD_LAYOUT_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, req_max*sizeof(fd_vinyl_comp_t) );
36 0 : return FD_LAYOUT_FINI( l, FD_VINYL_REQ_POOL_ALIGN );
37 0 : }
38 :
39 : void *
40 : fd_vinyl_req_pool_new( void * shmem,
41 : ulong batch_max,
42 0 : ulong batch_key_max ) {
43 0 : if( FD_UNLIKELY( !fd_vinyl_req_pool_footprint( batch_max, batch_key_max ) ) ) {
44 0 : FD_LOG_WARNING(( "invalid req_pool params: batch_max=%lu batch_key_max=%lu",
45 0 : batch_max, batch_key_max ));
46 0 : return NULL;
47 0 : }
48 :
49 0 : if( FD_UNLIKELY( !shmem ) ) {
50 0 : FD_LOG_WARNING(( "NULL shmem" ));
51 0 : return NULL;
52 0 : }
53 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, FD_VINYL_REQ_POOL_ALIGN ) ) ) {
54 0 : FD_LOG_WARNING(( "misaligned shmem" ));
55 0 : return NULL;
56 0 : }
57 0 : fd_wksp_t * wksp = fd_wksp_containing( shmem );
58 0 : if( FD_UNLIKELY( !shmem ) ) {
59 0 : FD_LOG_WARNING(( "shmem was not allocated from a wksp" ));
60 0 : return NULL;
61 0 : }
62 0 : if( FD_UNLIKELY( !used_footprint( batch_max ) ) ) {
63 0 : FD_LOG_WARNING(( "invalid batch_max parameter" ));
64 0 : return NULL;
65 0 : }
66 :
67 0 : ulong req_max = batch_max*batch_key_max;
68 :
69 0 : FD_SCRATCH_ALLOC_INIT( l, shmem );
70 0 : fd_vinyl_req_pool_t * pool = FD_SCRATCH_ALLOC_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, sizeof(fd_vinyl_req_pool_t) );
71 0 : ulong * free = FD_SCRATCH_ALLOC_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, batch_max*sizeof(ulong) );
72 0 : void * used_mem = FD_SCRATCH_ALLOC_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, used_footprint( batch_max ) );
73 0 : fd_vinyl_key_t * key0 = FD_SCRATCH_ALLOC_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, req_max*sizeof(fd_vinyl_key_t) );
74 0 : ulong * val_gaddr0 = FD_SCRATCH_ALLOC_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, req_max*sizeof(ulong) );
75 0 : schar * err0 = FD_SCRATCH_ALLOC_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, req_max*sizeof(schar) );
76 0 : fd_vinyl_comp_t * comp0 = FD_SCRATCH_ALLOC_APPEND( l, FD_VINYL_REQ_POOL_ALIGN, req_max*sizeof(fd_vinyl_comp_t) );
77 0 : ulong obj1 = FD_SCRATCH_ALLOC_FINI( l, FD_VINYL_REQ_POOL_ALIGN );
78 0 : FD_TEST( obj1-(ulong)shmem == fd_vinyl_req_pool_footprint( batch_max, batch_key_max ) );
79 :
80 0 : for( ulong i=0UL; i<batch_max; i++ ) free[i] = i;
81 0 : *pool = (fd_vinyl_req_pool_t){
82 0 : .wksp = wksp,
83 0 : .batch_max = batch_max,
84 0 : .batch_key_max = batch_key_max,
85 0 : .free = free,
86 0 : .free_cnt = batch_max,
87 0 : .used = used_join( used_new( used_mem, batch_max ) ),
88 :
89 0 : .key_off = (ulong)key0 - (ulong)pool,
90 0 : .val_gaddr_off = (ulong)val_gaddr0 - (ulong)pool,
91 0 : .err_off = (ulong)err0 - (ulong)pool,
92 0 : .comp_off = (ulong)comp0 - (ulong)pool
93 0 : };
94 0 : if( FD_UNLIKELY( !pool->used ) ) FD_LOG_CRIT(( "set_dynamic_new failed" ));
95 :
96 0 : FD_COMPILER_MFENCE();
97 0 : pool->magic = FD_VINYL_REQ_POOL_MAGIC;
98 0 : FD_COMPILER_MFENCE();
99 :
100 0 : return pool;
101 0 : }
102 :
103 : fd_vinyl_req_pool_t *
104 0 : fd_vinyl_req_pool_join( void * shmem ) {
105 :
106 0 : if( FD_UNLIKELY( !shmem || !fd_ulong_is_aligned( (ulong)shmem, FD_VINYL_REQ_POOL_ALIGN ) ) ) {
107 0 : FD_LOG_WARNING(( "invalid shmem" ));
108 0 : return NULL;
109 0 : }
110 :
111 0 : fd_vinyl_req_pool_t * pool = (fd_vinyl_req_pool_t *)shmem;
112 0 : if( FD_UNLIKELY( pool->magic!=FD_VINYL_REQ_POOL_MAGIC ) ) {
113 0 : FD_LOG_WARNING(( "bad magic" ));
114 0 : return NULL;
115 0 : }
116 :
117 0 : return pool;
118 0 : }
119 :
120 : void *
121 0 : fd_vinyl_req_pool_leave( fd_vinyl_req_pool_t * pool ) {
122 0 : return (void *)pool;
123 0 : }
124 :
125 : void *
126 0 : fd_vinyl_req_pool_delete( void * shmem ) {
127 :
128 0 : if( FD_UNLIKELY( !shmem || !fd_ulong_is_aligned( (ulong)shmem, FD_VINYL_REQ_POOL_ALIGN ) ) ) {
129 0 : FD_LOG_WARNING(( "invalid shmem" ));
130 0 : return NULL;
131 0 : }
132 :
133 0 : fd_vinyl_req_pool_t * pool = (fd_vinyl_req_pool_t *)shmem;
134 0 : pool->magic = 0UL;
135 :
136 0 : return shmem;
137 0 : }
138 :
139 : ulong
140 0 : fd_vinyl_req_pool_acquire( fd_vinyl_req_pool_t * pool ) {
141 :
142 0 : if( FD_UNLIKELY( !pool->free_cnt ) ) {
143 0 : FD_LOG_CRIT(( "Cannot acquire request batch: batch_max %lu exceeded",
144 0 : pool->batch_max ));
145 0 : }
146 :
147 0 : ulong idx = pool->free[ --pool->free_cnt ];
148 0 : if( FD_UNLIKELY( used_test( pool->used, idx ) ) ) {
149 0 : FD_LOG_CRIT(( "use after free detected" ));
150 0 : }
151 0 : used_insert( pool->used, idx );
152 :
153 0 : return idx;
154 0 : }
155 :
156 : void
157 : fd_vinyl_req_pool_release( fd_vinyl_req_pool_t * pool,
158 0 : ulong idx ) {
159 :
160 0 : if( FD_UNLIKELY( idx >= pool->batch_max ) ) {
161 0 : FD_LOG_CRIT(( "invalid batch_idx %lu (batch_max %lu)",
162 0 : idx, pool->batch_max ));
163 0 : }
164 0 : if( FD_UNLIKELY( pool->free_cnt>=pool->batch_max ) ) {
165 0 : FD_LOG_CRIT(( "double free detected" ));
166 0 : }
167 0 : if( FD_UNLIKELY( !used_test( pool->used, idx ) ) ) {
168 0 : FD_LOG_CRIT(( "double free detected" ));
169 0 : }
170 :
171 0 : used_remove( pool->used, idx );
172 0 : pool->free[ pool->free_cnt++ ] = idx;
173 0 : }
|