LCOV - code coverage report
Current view: top level - tango/dcache - fd_dcache.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 145 163 89.0 %
Date: 2024-11-13 11:58:15 Functions: 12 12 100.0 %

          Line data    Source code
       1             : #include "fd_dcache_private.h"
       2             : 
       3             : ulong
       4             : fd_dcache_req_data_sz( ulong mtu,
       5             :                        ulong depth,
       6             :                        ulong burst,
       7     3000087 :                        int   compact ) {
       8             : 
       9     3000087 :   if( FD_UNLIKELY( !mtu   ) ) return 0UL; /* zero mtu (technically unnecessary) */
      10     2953977 :   if( FD_UNLIKELY( !depth ) ) return 0UL; /* zero depth */
      11     2908773 :   if( FD_UNLIKELY( !burst ) ) return 0UL; /* zero burst */
      12             : 
      13     2863176 :   ulong slot_footprint = FD_DCACHE_SLOT_FOOTPRINT( mtu );
      14     2863176 :   if( FD_UNLIKELY( !slot_footprint ) ) return 0UL; /* overflow */
      15             : 
      16     2863176 :   ulong slot_cnt = depth + burst;  
      17     2863176 :   if( FD_UNLIKELY( slot_cnt<depth ) ) return 0UL; /* overflow */
      18     2863176 :   slot_cnt += (ulong)!!compact;
      19     2863176 :   if( FD_UNLIKELY( !slot_cnt ) ) return 0UL; /* overflow (technically unnecessary) */
      20     2863176 :   if( FD_UNLIKELY( slot_cnt>(ULONG_MAX/slot_footprint) ) ) return 0UL; /* overflow */
      21             : 
      22     2863176 :   return slot_footprint*slot_cnt;
      23     2863176 : }
      24             : 
      25             : ulong
      26          93 : fd_dcache_align( void ) {
      27          93 :   return FD_DCACHE_ALIGN;
      28          93 : }
      29             : 
      30             : ulong
      31             : fd_dcache_footprint( ulong data_sz,
      32     3000114 :                      ulong app_sz ) {
      33             : 
      34     3000114 :   ulong data_footprint = fd_ulong_align_up( data_sz, FD_DCACHE_ALIGN );
      35     3000114 :   if( FD_UNLIKELY( data_footprint<data_sz ) ) return 0UL; /* overflow */
      36             : 
      37     3000111 :   ulong app_footprint  = fd_ulong_align_up( app_sz,  FD_DCACHE_ALIGN );
      38     3000111 :   if( FD_UNLIKELY( app_footprint<app_sz ) ) return 0UL; /* overflow */
      39             : 
      40     3000108 :   ulong footprint = data_footprint + app_footprint; /* data and app */
      41     3000108 :   if( FD_UNLIKELY( footprint<data_footprint ) ) return 0UL; /* overflow */
      42             : 
      43     3000108 :   footprint += sizeof(fd_dcache_private_hdr_t); /* header and guard */
      44     3000108 :   if( FD_UNLIKELY( footprint<sizeof(fd_dcache_private_hdr_t) ) ) return 0UL; /* overflow */
      45             : 
      46     3000108 :   return footprint;
      47     3000108 : }
      48             : 
      49             : void *
      50             : fd_dcache_new( void * shmem,
      51             :                ulong  data_sz,
      52          30 :                ulong  app_sz ) {
      53             : 
      54          30 :   if( FD_UNLIKELY( !shmem ) ) {
      55           3 :     FD_LOG_WARNING(( "NULL shmem" ));
      56           3 :     return NULL;
      57           3 :   }
      58             : 
      59          27 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_dcache_align() ) ) ) {
      60           3 :     FD_LOG_WARNING(( "misaligned shmem" ));
      61           3 :     return NULL;
      62           3 :   }
      63             : 
      64          24 :   ulong footprint = fd_dcache_footprint( data_sz, app_sz );
      65          24 :   if( FD_UNLIKELY( !footprint ) ) {
      66           6 :     FD_LOG_WARNING(( "bad data_sz (%lu) or app_sz (%lu)", data_sz, app_sz ));
      67           6 :     return NULL;
      68           6 :   }
      69             : 
      70          18 :   fd_memset( shmem, 0, sizeof(fd_dcache_private_hdr_t ) );
      71             : 
      72          18 :   fd_dcache_private_hdr_t * hdr = (fd_dcache_private_hdr_t *)shmem;
      73             : 
      74          18 :   hdr->data_sz = data_sz;
      75          18 :   hdr->app_sz  = app_sz;
      76          18 :   hdr->app_off = sizeof(fd_dcache_private_hdr_t) + fd_ulong_align_up( data_sz, FD_DCACHE_ALIGN );
      77             : 
      78          18 :   fd_memset( (uchar*)shmem+hdr->app_off, 0, app_sz );
      79             : 
      80          18 :   FD_COMPILER_MFENCE();
      81          18 :   FD_VOLATILE( hdr->magic ) = FD_DCACHE_MAGIC;
      82          18 :   FD_COMPILER_MFENCE();
      83             : 
      84          18 :   return shmem;
      85          24 : }
      86             : 
      87             : uchar *
      88          81 : fd_dcache_join( void * shdcache ) {
      89             : 
      90          81 :   if( FD_UNLIKELY( !shdcache ) ) {
      91           3 :     FD_LOG_WARNING(( "NULL shdcache" ));
      92           3 :     return NULL;
      93           3 :   }
      94             : 
      95          78 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shdcache, fd_dcache_align() ) ) ) {
      96           3 :     FD_LOG_WARNING(( "misaligned shdcache" ));
      97           3 :     return NULL;
      98           3 :   }
      99             : 
     100          75 :   fd_dcache_private_hdr_t * hdr = (fd_dcache_private_hdr_t *)shdcache;
     101          75 :   if( FD_UNLIKELY( hdr->magic!=FD_DCACHE_MAGIC ) ) {
     102           0 :     FD_LOG_WARNING(( "bad magic" ));
     103           0 :     return NULL;
     104           0 :   }
     105             : 
     106          75 :   return fd_dcache_private_dcache( hdr );
     107          75 : }
     108             : 
     109             : void *
     110          78 : fd_dcache_leave( uchar const * dcache ) {
     111             : 
     112          78 :   if( FD_UNLIKELY( !dcache ) ) {
     113           3 :     FD_LOG_WARNING(( "NULL dcache" ));
     114           3 :     return NULL;
     115           3 :   }
     116             : 
     117          75 :   return (void *)fd_dcache_private_hdr_const( dcache ); /* Kinda ugly const cast */
     118          78 : }
     119             : 
     120             : void *
     121          21 : fd_dcache_delete( void * shdcache ) {
     122             : 
     123          21 :   if( FD_UNLIKELY( !shdcache ) ) {
     124           3 :     FD_LOG_WARNING(( "NULL shdcache" ));
     125           3 :     return NULL;
     126           3 :   }
     127             : 
     128          18 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shdcache, fd_dcache_align() ) ) ) {
     129           3 :     FD_LOG_WARNING(( "misaligned shdcache" ));
     130           3 :     return NULL;
     131           3 :   }
     132             : 
     133          15 :   fd_dcache_private_hdr_t * hdr = (fd_dcache_private_hdr_t *)shdcache;
     134          15 :   if( FD_UNLIKELY( hdr->magic != FD_DCACHE_MAGIC ) ) {
     135           0 :     FD_LOG_WARNING(( "bad magic" ));
     136           0 :     return NULL;
     137           0 :   }
     138             : 
     139          15 :   FD_COMPILER_MFENCE();
     140          15 :   FD_VOLATILE( hdr->magic ) = 0UL;
     141          15 :   FD_COMPILER_MFENCE();
     142             : 
     143          15 :   return shdcache;
     144          15 : }
     145             : 
     146             : ulong
     147     1206853 : fd_dcache_data_sz( uchar const * dcache ) {
     148     1206853 :   return fd_dcache_private_hdr_const( dcache )->data_sz;
     149     1206853 : }
     150             : 
     151             : ulong
     152           6 : fd_dcache_app_sz( uchar const * dcache ) {
     153           6 :   return fd_dcache_private_hdr_const( dcache )->app_sz;
     154           6 : }
     155             : 
     156             : uchar const *
     157          15 : fd_dcache_app_laddr_const( uchar const * dcache ) {
     158          15 :   fd_dcache_private_hdr_t const * hdr = fd_dcache_private_hdr_const( dcache );
     159          15 :   return (uchar const *)(((ulong)hdr) + hdr->app_off);
     160          15 : }
     161             : 
     162             : uchar *
     163           6 : fd_dcache_app_laddr( uchar * dcache ) {
     164           6 :   fd_dcache_private_hdr_t * hdr = fd_dcache_private_hdr( dcache );
     165           6 :   return (uchar *)(((ulong)hdr) + hdr->app_off);
     166           6 : }
     167             : 
     168             : int
     169             : fd_dcache_compact_is_safe( void const * base,
     170             :                            void const * dcache,
     171             :                            ulong        mtu,
     172          33 :                            ulong        depth ) {
     173             : 
     174             :   /* Validate base */
     175             : 
     176          33 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)base, 2UL*FD_CHUNK_SZ ) ) ) {
     177           3 :     FD_LOG_WARNING(( "base is not double chunk aligned" ));
     178           3 :     return 0;
     179           3 :   }
     180             : 
     181          30 :   if( FD_UNLIKELY( (ulong)dcache < (ulong)base ) ) {
     182           3 :     FD_LOG_WARNING(( "dcache before base" ));
     183           3 :     return 0;
     184           3 :   }
     185             : 
     186             :   /* Validate dcache */
     187             : 
     188          27 :   if( FD_UNLIKELY( !dcache ) ) {
     189           3 :     FD_LOG_WARNING(( "NULL dcache" ));
     190           3 :     return 0;
     191           3 :   }
     192             : 
     193          24 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)dcache, 2UL*FD_CHUNK_SZ ) ) ) { /* Should be impossible if valid join */
     194           3 :     FD_LOG_WARNING(( "bad dcache (alignment)" ));
     195           3 :     return 0;
     196           3 :   }
     197             : 
     198          21 :   ulong data_sz = fd_dcache_data_sz( (uchar const *)dcache );
     199          21 :   if( FD_UNLIKELY( ((ulong)dcache + (ulong)data_sz) < (ulong)dcache ) ) { /* Should be impossible if valid join */
     200           0 :     FD_LOG_WARNING(( "bad dcache (data_sz)" ));
     201           0 :     return 0;
     202           0 :   }
     203             : 
     204          21 :   ulong chunk0 = ((ulong)dcache - (ulong)base) >> FD_CHUNK_LG_SZ; /* No overflow */
     205          21 :   ulong chunk1 = ((ulong)dcache + data_sz - (ulong)base) >> FD_CHUNK_LG_SZ; /* No overflow */
     206             : 
     207          21 :   if( FD_UNLIKELY( chunk1>(ulong)UINT_MAX ) ) {
     208           0 :     FD_LOG_WARNING(( "base to dcache address space span too large" ));
     209           0 :     return 0;
     210           0 :   }
     211             : 
     212             :   /* At this point, complete chunks in dcache cover [chunk0,chunk1)
     213             :      relative to the base address and any range of chunks in the dcache
     214             :      can be losslessly compressed into two 32-bit values. */
     215             : 
     216             :   /* Validate mtu */
     217             : 
     218          21 :   if( FD_UNLIKELY( !mtu ) ) {
     219           3 :     FD_LOG_WARNING(( "zero mtu" ));
     220           3 :     return 0;
     221           3 :   }
     222             : 
     223          18 :   ulong mtu_up = mtu + (2UL*FD_CHUNK_SZ-1UL);
     224             : 
     225          18 :   if( FD_UNLIKELY( mtu_up < mtu ) ) {
     226           3 :     FD_LOG_WARNING(( "too large mtu" ));
     227           3 :     return 0;
     228           3 :   }
     229             : 
     230          15 :   ulong chunk_mtu = (mtu_up >> (1+FD_CHUNK_LG_SZ)) << 1; /* >0 */
     231             : 
     232             :   /* At this point, mtu is non-zero, chunk_mtu is non-zero and a
     233             :      sufficient number of chunks to cover an mtu frag.  Further, the
     234             :      fd_dcache_chunk_next calculation is guaranteed overflow safe for
     235             :      any size in [0,mtu]. */
     236             : 
     237             :   /* Validate depth */
     238             : 
     239          15 :   if( FD_UNLIKELY( !depth ) ) {
     240           3 :     FD_LOG_WARNING(( "zero depth" ));
     241           3 :     return 0;
     242           3 :   }
     243             : 
     244          12 :   ulong overhead  = 2UL*chunk_mtu-1UL; /* no overflow chunk_sz >> 1, chunk_mtu << ULONG_MAX/2 */
     245          12 :   ulong depth_max = (ULONG_MAX-overhead) / chunk_mtu; /* no overflow as overhead < ULONG_MAX */
     246             : 
     247          12 :   if( FD_UNLIKELY( depth > depth_max ) ) {
     248           0 :     FD_LOG_WARNING(( "too large depth" ));
     249           0 :     return 0;
     250           0 :   }
     251             : 
     252          12 :   ulong chunk_req = depth*chunk_mtu + overhead; /* (depth+2)*chunk_mtu-1, no overflow */
     253             : 
     254          12 :   if( FD_UNLIKELY( (chunk1-chunk0) < chunk_req ) ) {
     255           0 :     FD_LOG_WARNING(( "too small dcache" ));
     256           0 :     return 0;
     257           0 :   }
     258             : 
     259          12 :   return 1;
     260          12 : }
     261             : 

Generated by: LCOV version 1.14