Line data Source code
1 : #include "fd_fctl.h"
2 :
3 : void *
4 : fd_fctl_new( void * shmem,
5 0 : ulong rx_max ) {
6 0 : if( FD_UNLIKELY( !shmem ) ) {
7 0 : FD_LOG_WARNING(( "NULL shmem" ));
8 0 : return NULL;
9 0 : }
10 :
11 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_fctl_align() ) ) ) {
12 0 : FD_LOG_WARNING(( "misaligned shmem" ));
13 0 : return NULL;
14 0 : }
15 :
16 0 : if( FD_UNLIKELY( rx_max>FD_FCTL_RX_MAX_MAX ) ) {
17 0 : FD_LOG_WARNING(( "too large rx_max" ));
18 0 : return NULL;
19 0 : }
20 :
21 0 : fd_fctl_t * fctl = (fd_fctl_t *)shmem;
22 :
23 0 : fctl->rx_max = (ushort)rx_max;
24 0 : fctl->rx_cnt = (ushort)0;
25 0 : fctl->in_refill = 0;
26 0 : fctl->cr_burst = 0UL;
27 0 : fctl->cr_max = 0UL;
28 0 : fctl->cr_resume = 0UL;
29 0 : fctl->cr_refill = 0UL;
30 :
31 0 : return shmem;
32 0 : }
33 :
34 : fd_fctl_t *
35 : fd_fctl_cfg_rx_add( fd_fctl_t * fctl,
36 : ulong cr_max,
37 : ulong const * seq_laddr,
38 0 : ulong * slow_laddr ) {
39 0 : if( FD_UNLIKELY( !fctl ) ) {
40 0 : FD_LOG_WARNING(( "NULL fctl" ));
41 0 : return NULL;
42 0 : }
43 :
44 0 : if( FD_UNLIKELY( !cr_max ) ) {
45 0 : FD_LOG_WARNING(( "too small cr_max" ));
46 0 : return NULL;
47 0 : }
48 :
49 0 : if( FD_UNLIKELY( cr_max > (ulong)LONG_MAX ) ) {
50 0 : FD_LOG_WARNING(( "too large cr_max" ));
51 0 : return NULL;
52 0 : }
53 :
54 : /* NULL seq_laddr okay (indicates disabled for time being) */
55 :
56 0 : if( FD_UNLIKELY( !slow_laddr ) ) {
57 0 : FD_LOG_WARNING(( "NULL slow_laddr" ));
58 0 : return NULL;
59 0 : }
60 :
61 0 : ulong rx_idx = (ulong)fctl->rx_cnt;
62 0 : if( FD_UNLIKELY( rx_idx>=(ulong)fctl->rx_max ) ) {
63 0 : FD_LOG_WARNING(( "too many rx in this fctl" ));
64 0 : return NULL;
65 0 : }
66 :
67 0 : fd_fctl_private_rx_t * rx = fd_fctl_private_rx( fctl );
68 0 : rx[ rx_idx ].cr_max = (long)cr_max;
69 0 : rx[ rx_idx ].seq_laddr = seq_laddr;
70 0 : rx[ rx_idx ].slow_laddr = slow_laddr;
71 :
72 0 : fctl->rx_cnt = (ushort)(rx_idx+1UL);
73 0 : return fctl;
74 0 : }
75 :
76 : fd_fctl_t *
77 : fd_fctl_cfg_done( fd_fctl_t * fctl,
78 : ulong cr_burst,
79 : ulong cr_max,
80 : ulong cr_resume,
81 0 : ulong cr_refill ) {
82 0 : if( FD_UNLIKELY( !fctl ) ) {
83 0 : FD_LOG_WARNING(( "NULL fctl" ));
84 0 : return NULL;
85 0 : }
86 :
87 0 : fd_fctl_private_rx_t * rx = fd_fctl_private_rx( fctl );
88 0 : ulong rx_cnt = (ulong)fctl->rx_cnt;
89 :
90 0 : ulong cr_burst_max = (ulong)LONG_MAX;
91 0 : for( ulong rx_idx=0UL; rx_idx<rx_cnt; rx_idx++ ) cr_burst_max = fd_ulong_min( cr_burst_max, (ulong)rx[rx_idx].cr_max );
92 : /* cr_burst_max is min( LONG_MAX, rx[:].cr_max ), which is in [1,LONG_MAX] as rx[:].cr_max is positive */
93 :
94 0 : if( FD_UNLIKELY( !((1UL<=cr_burst) & (cr_burst<=cr_burst_max)) ) ) {
95 0 : FD_LOG_WARNING(( "cr_burst (%lu) must be in [%lu,%lu] for receiver config", cr_burst, 1UL, cr_burst_max ));
96 0 : return NULL;
97 0 : }
98 :
99 : /* At this point, cr_burst is in [1,cr_burst_max], which is in [1,LONG_MAX] */
100 :
101 0 : if( !cr_max ) {
102 0 : cr_max = cr_burst_max;
103 0 : for( ulong rx_idx=0UL; rx_idx<rx_cnt; rx_idx++ ) cr_max = fd_ulong_max( cr_max, (ulong)rx[rx_idx].cr_max );
104 : /* cr_max is in [cr_burst,LONG_MAX] as rx[:].cr_max is positive */
105 0 : }
106 :
107 0 : if( FD_UNLIKELY( !((cr_burst<=cr_max) & (cr_max<=((ulong)LONG_MAX))) ) ) {
108 0 : FD_LOG_WARNING(( "cr_max (%lu) must be in [%lu,%lu] for receiver config", cr_max, cr_burst, (ulong)LONG_MAX ));
109 0 : return NULL;
110 0 : }
111 :
112 : /* cr_max is in [cr_burst,LONG_MAX] at this point */
113 :
114 0 : if( !cr_resume ) cr_resume = cr_burst + ((2UL*(cr_max-cr_burst))/3UL); /* no ovfl possible */
115 :
116 0 : if( FD_UNLIKELY( !((cr_burst<=cr_resume) & (cr_resume<=cr_max)) ) ) {
117 0 : FD_LOG_WARNING(( "cr_resume (%lu) must be in [%lu,%lu] for receiver config", cr_resume, cr_burst, cr_max ));
118 0 : return NULL;
119 0 : }
120 :
121 : /* cr_resume is in [cr_burst,cr_max] at this point */
122 :
123 0 : if( !cr_refill ) cr_refill = cr_burst + ((cr_resume-cr_burst)>>1); /* no ovfl possible */
124 :
125 0 : if( FD_UNLIKELY( !((cr_burst<=cr_refill) & (cr_refill<=cr_resume)) ) ) {
126 0 : FD_LOG_WARNING(( "cr_refill (%lu) must be in [%lu,%lu] for receiver config", cr_refill, cr_burst, cr_resume ));
127 0 : return NULL;
128 0 : }
129 :
130 : /* cr_refill is in [cr_burst,cr_resume] at this point */
131 :
132 0 : fctl->cr_burst = cr_burst;
133 0 : fctl->cr_max = cr_max;
134 0 : fctl->cr_resume = cr_resume;
135 0 : fctl->cr_refill = cr_refill;
136 :
137 0 : return fctl;
138 0 : }
139 :
|