Line data Source code
1 : #include "fd_fctl.h" 2 : 3 : void * 4 : fd_fctl_new( void * shmem, 5 18 : ulong rx_max ) { 6 18 : if( FD_UNLIKELY( !shmem ) ) { 7 3 : FD_LOG_WARNING(( "NULL shmem" )); 8 3 : return NULL; 9 3 : } 10 : 11 15 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_fctl_align() ) ) ) { 12 3 : FD_LOG_WARNING(( "misaligned shmem" )); 13 3 : return NULL; 14 3 : } 15 : 16 12 : if( FD_UNLIKELY( rx_max>FD_FCTL_RX_MAX_MAX ) ) { 17 3 : FD_LOG_WARNING(( "too large rx_max" )); 18 3 : return NULL; 19 3 : } 20 : 21 9 : fd_fctl_t * fctl = (fd_fctl_t *)shmem; 22 : 23 9 : fctl->rx_max = (ushort)rx_max; 24 9 : fctl->rx_cnt = (ushort)0; 25 9 : fctl->in_refill = 0; 26 9 : fctl->cr_burst = 0UL; 27 9 : fctl->cr_max = 0UL; 28 9 : fctl->cr_resume = 0UL; 29 9 : fctl->cr_refill = 0UL; 30 : 31 9 : return shmem; 32 12 : } 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 117 : ulong * slow_laddr ) { 39 117 : if( FD_UNLIKELY( !fctl ) ) { 40 3 : FD_LOG_WARNING(( "NULL fctl" )); 41 3 : return NULL; 42 3 : } 43 : 44 114 : if( FD_UNLIKELY( !cr_max ) ) { 45 3 : FD_LOG_WARNING(( "too small cr_max" )); 46 3 : return NULL; 47 3 : } 48 : 49 111 : if( FD_UNLIKELY( cr_max > (ulong)LONG_MAX ) ) { 50 3 : FD_LOG_WARNING(( "too large cr_max" )); 51 3 : return NULL; 52 3 : } 53 : 54 : /* NULL seq_laddr okay (indicates disabled for time being) */ 55 : 56 108 : if( FD_UNLIKELY( !slow_laddr ) ) { 57 3 : FD_LOG_WARNING(( "NULL slow_laddr" )); 58 3 : return NULL; 59 3 : } 60 : 61 105 : ulong rx_idx = (ulong)fctl->rx_cnt; 62 105 : 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 105 : fd_fctl_private_rx_t * rx = fd_fctl_private_rx( fctl ); 68 105 : rx[ rx_idx ].cr_max = (long)cr_max; 69 105 : rx[ rx_idx ].seq_laddr = seq_laddr; 70 105 : rx[ rx_idx ].slow_laddr = slow_laddr; 71 : 72 105 : fctl->rx_cnt = (ushort)(rx_idx+1UL); 73 105 : return fctl; 74 105 : } 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 12 : ulong cr_refill ) { 82 12 : if( FD_UNLIKELY( !fctl ) ) { 83 3 : FD_LOG_WARNING(( "NULL fctl" )); 84 3 : return NULL; 85 3 : } 86 : 87 9 : fd_fctl_private_rx_t * rx = fd_fctl_private_rx( fctl ); 88 9 : ulong rx_cnt = (ulong)fctl->rx_cnt; 89 : 90 9 : ulong cr_burst_max = (ulong)LONG_MAX; 91 114 : 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 9 : 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 9 : if( !cr_max ) { 102 9 : cr_max = cr_burst_max; 103 114 : 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 9 : } 106 : 107 9 : 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 9 : if( !cr_resume ) cr_resume = cr_burst + ((2UL*(cr_max-cr_burst))/3UL); /* no ovfl possible */ 115 : 116 9 : 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 9 : if( !cr_refill ) cr_refill = cr_burst + ((cr_resume-cr_burst)>>1); /* no ovfl possible */ 124 : 125 9 : 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 9 : fctl->cr_burst = cr_burst; 133 9 : fctl->cr_max = cr_max; 134 9 : fctl->cr_resume = cr_resume; 135 9 : fctl->cr_refill = cr_refill; 136 : 137 9 : return fctl; 138 9 : } 139 :