LCOV - code coverage report
Current view: top level - vinyl/rq - fd_vinyl_rq.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 50 71 70.4 %
Date: 2025-12-07 04:58:33 Functions: 14 350 4.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_vinyl_rq_fd_vinyl_rq_h
       2             : #define HEADER_fd_src_vinyl_rq_fd_vinyl_rq_h
       3             : 
       4             : /* A fd_vinyl_req_t describes a batch request to a vinyl tile.  Batch
       5             :    requests from a client are processed in order from that client.  The
       6             :    individual items in a batch request can be processed in _any_ order
       7             :    (including concurrently).  Thus ...
       8             : 
       9             :    IMPORTANT SAFETY TIP!  The client promises that all items in a
      10             :    request are logically independent such that they can be safely
      11             :    processed in an arbitrary order / in parallel.
      12             : 
      13             :    The simplest way to ensure this is to keep all keys in a request
      14             :    unique.  That being said, repeated keys in a request will generally
      15             :    "do the right thing" in the sense that the result can be interpreted
      16             :    as though each item in the request executed in some order (with some
      17             :    technical caveats for the advanced optimization of processing batch
      18             :    items before receiving a completion).  Batch requests from different
      19             :    clients can be arbitrarily interleaved at batch request granularity.
      20             : 
      21             :    As such, a batch request executes _atomically_ relative to other
      22             :    requests.
      23             : 
      24             :    Note though that concurrent meta readers see individual batch items
      25             :    complete as they happen.  Specifically, except for "move", individual
      26             :    items in a batch complete atomically in whatever order they were
      27             :    processed.  (During the move of an individual item for the current
      28             :    implementation, there is a brief momment where a concurrent meta
      29             :    reader could observe both key_src and key_dst as not present.)
      30             :    Similarly clients doing speculative processing will see individual
      31             :    batch items complete atomically (including move) in whatever order
      32             :    they are being processed (which is the point of speculative
      33             :    processing). */
      34             : 
      35             : #include "../fd_vinyl_base.h"
      36             : 
      37             : /* FD_VINYL_REQ_{ALIGN,FOOTPRINT} give the byte alignment and footprint
      38             :    of a fd_vinyl_req_t.  ALIGN is a reasonable power-of-2.  FOOTPRINT is
      39             :    a multiple of ALIGN. */
      40             : 
      41             : #define FD_VINYL_REQ_ALIGN     (64UL)
      42             : #define FD_VINYL_REQ_FOOTPRINT (64UL)
      43             : 
      44             : /* FD_VINYL_REQ_TYPE_* give supported request types.  Note that
      45             :    requests like JOIN are handled out of band because the client doesn't
      46             :    have a rq to send the request until it is joined.  (LEAVE could be
      47             :    handled in band though but is handle via the same mechanism as JOIN
      48             :    for symmetry.  SYNC and PART requests are also handled out of band as
      49             :    they don't pertain to individual clients.) */
      50             : 
      51           0 : #define FD_VINYL_REQ_TYPE_ACQUIRE (0) /* Acquire the requested pairs */
      52           0 : #define FD_VINYL_REQ_TYPE_RELEASE (1) /* Release the requested pairs */
      53           0 : #define FD_VINYL_REQ_TYPE_ERASE   (2) /* Erase   the requested pairs */
      54           0 : #define FD_VINYL_REQ_TYPE_MOVE    (3) /* Move    the requested pairs (replace if dst exists, rename if not) */
      55           0 : #define FD_VINYL_REQ_TYPE_FETCH   (4) /* Fetch   the requested pairs into cache (does not generate a completion) */
      56           0 : #define FD_VINYL_REQ_TYPE_FLUSH   (5) /* Flush   the requested pairs from cache (does not generate a completion) */
      57           0 : #define FD_VINYL_REQ_TYPE_TRY     (6) /* Start to speculatively read (non-blocking) the requested pairs */
      58           0 : #define FD_VINYL_REQ_TYPE_TEST    (7) /* Test for speculation success */
      59             : 
      60             : /* FD_VINL_REQ_FLAG_* give flags that specify options for the above
      61             :    request types. */
      62             : 
      63     3000000 : #define FD_VINYL_REQ_FLAG_MODIFY (1UL<<0) /* (Acquire) The client intends to modify the given pairs (info and/or val)
      64             :                                              (Release) The client modified          the given pairs (info and/or val) */
      65     3000000 : #define FD_VINYL_REQ_FLAG_IGNORE (1UL<<1) /* (Acquire) Ignore the existing pair val               (ignored if not MODIFY),
      66             :                                              (Release) Cached pair val and/or info were clobbered (ignored if MODIFY or an acquire-for-read FIXME: have acquire-for-read with ignore set flush?) */
      67     3000000 : #define FD_VINYL_REQ_FLAG_CREATE (1UL<<2) /* (Acquire) Create any pairs that do not already exist (ignored if not MODIFY) */
      68     3000000 : #define FD_VINYL_REQ_FLAG_EXCL   (1UL<<3) /* (Acquire) Do not modify any pairs that already exist (ignored if not MODIFY) */
      69     3000000 : #define FD_VINYL_REQ_FLAG_ERASE  (1UL<<4) /* (Release) Erase given pairs                          (ignored if not MODIFY) */
      70     3000000 : #define FD_VINYL_REQ_FLAG_BY_KEY (1UL<<5) /* (Release) Use keys instead of cache val gaddrs to specify pairs to release */
      71             : #define FD_VINYL_REQ_FLAG_MRU    (0UL<<6) /* Make given pairs MRU (note: arb order from MRU->LRU for individual items in batch) */
      72             : #define FD_VINYL_REQ_FLAG_LRU    (1UL<<6) /* Make given pairs LRU (note: arb order from LRU->MRU for individual items in batch) */
      73             : #define FD_VINYL_REQ_FLAG_UNC    (2UL<<6) /* Do not change eviction priorities for the given pairs */
      74             : 
      75             : /* A fd_vinyl_req_t gives the layout of a request */
      76             : 
      77             : struct __attribute__((aligned(FD_VINYL_REQ_ALIGN))) fd_vinyl_req {
      78             : 
      79             :   ulong  seq;       /* Message sequence number */
      80             :   ulong  req_id;    /* Request id (identifies the request for the completion recipients) */
      81             :   ulong  link_id;   /* Link id (identifies client -> vinyl tile for request and completion recipients) */
      82             :   schar  type;      /* == FD_VINYL_REQ_TYPE_* */
      83             :   uchar  flags;     /* Bit-or of FD_VINYL_REQ_FLAG flags */
      84             :   ushort batch_cnt; /* Num key-val pairs in request */
      85             :   uint   val_max;   /* (acquire with modify) Max byte size pair val, in [0,FD_VINYL_VAL_MAX] */
      86             : 
      87             :   /* key_gaddr is typically the shared client request global address of
      88             :      a:
      89             : 
      90             :        fd_vinyl_key_t key[ batch_cnt ]
      91             : 
      92             :      array that contains the set of keys for this batch request.  The
      93             :      vinyl tile will typically have a read interest in this region until
      94             :      the request is completed.  In particular:
      95             : 
      96             :        ACQUIRE - keys to acquire
      97             :        RELEASE - (BY_KEY) keys to release, (~BY_KEY) ignored (release ~BY_KEY faster)
      98             :        ERASE   - keys to erase
      99             :        FETCH   - keys to fetch
     100             :        FLUSH   - keys to flush
     101             :        MOVE    - src keys to move
     102             :        TRY     - keys to speculatively read
     103             :        TEST    - ignored
     104             : 
     105             :      If there are redundant keys in a batch request, from the caller's
     106             :      perspective, the items will appear to executed in some serial
     107             :      order.  E.g. in an acquire for modify, the first batch item
     108             :      processed for a key will result in either success or a failure and
     109             :      the remaining batch items for key will result in either AGAIN
     110             :      (because the first item acquired) or failure (because it couldn't
     111             :      acquire key for the same reason as first item).
     112             : 
     113             :      IMPORTANT SAFETY TIP!  When doing the advanced optimization of
     114             :      processing batch items before receiving a completion in a batch
     115             :      acquire-for-read or a try, the remaining batch items for key can
     116             :      report success before the first batch item for key has finished
     117             :      reading, validating and decoding the pair.  See case_acquire for
     118             :      more details.
     119             : 
     120             :      Note that, for FETCH, evict prio flags are ignored.  The keys will
     121             :      always be fetched at MRU priority. */
     122             : 
     123             :   ulong key_gaddr;
     124             : 
     125             :   /* val_gaddr_gaddr is typically the shared client request global
     126             :      address of a:
     127             : 
     128             :        ulong val_gaddr[ batch_cnt ]
     129             : 
     130             :      array where shared data cache global addresses for pair vals should
     131             :      be stored on completion.  The current pair info is also available
     132             :      to the client at this location for read / modification.  The vinyl
     133             :      tile will have a write interest in this region until the request is
     134             :      complete.  On receipt of a successful completion, batch items that
     135             :      were successfully processed will have valid entries and batch items
     136             :      that failed will have unchanged entries.  On receipt of a failed
     137             :      completion, this array will be unchanged.  In particular:
     138             : 
     139             :        ACQUIRE - pair val (and pair info) data cache global address
     140             :        RELEASE - (BY_KEY) ignored, (~BY_KEY) data cache global addresses
     141             :                  of pairs to release (i.e. echo back the array returned
     142             :                  by acquire), (release ~BY_KEY faster)
     143             :        ERASE   - ignored
     144             :        MOVE    - this field is repurposed to point to the batch_cnt dst
     145             :                  keys for the move (vinyl tile will have a read interest
     146             :                  in this region until the request is complete)
     147             :                  (FIXME: consider having key_gaddr be 2*batch_cnt for
     148             :                  move, store all the keys there, and ignore this
     149             :                  entirely ...  would make sense if it is easier for
     150             :                  store move src/dst keys interleaved)
     151             :        FETCH   - ignored
     152             :        FLUSH   - ignored
     153             :        TRY     - pair val (and pair info) data cache global addresses
     154             :                  must be a 2*batch_cnt array for try (the second half is
     155             :                  for internal use).  Note that the info region
     156             :                  (including the val_sz for the try) might be corrupt.
     157             :                  The pointer returned though is guaranteed to be
     158             :                  readable out to FD_VINYL_VAL_MAX regardless val_sz.
     159             :        TEST    - echo back the same array (with an untouched second
     160             :                  half) from the corresponding try */
     161             : 
     162             :   ulong val_gaddr_gaddr;
     163             : 
     164             :   /* err_gaddr is typically the shared client request global address of
     165             :      a:
     166             : 
     167             :        schar err[ batch_cnt ]
     168             : 
     169             :      array where the results of individual batch item executions will be
     170             :      stored by the vinyl tile.  The vinyl tile will have a write
     171             :      interest in this region until the request is completed.  On receipt
     172             :      of a successful completion, the individual entries will be valid.
     173             :      Entries will be FD_VINYL_SUCCESS (zero) or a FD_VINYL_ERR code
     174             :      (negative).  On receipt of a failed completion, this array is
     175             :      unchanged.  In particular:
     176             : 
     177             :        ACQUIRE (for read)
     178             : 
     179             :          SUCCESS - acquired the corresponding pair key.  The pair val
     180             :                    and pair info can be found via the corresponding
     181             :                    val_gaddr in the shared data cache.  This location
     182             :                    will be stable until the pair is released.  info will
     183             :                    have the current pair metadata (including the val
     184             :                    byte size), val will have the current pair val.
     185             : 
     186             :          AGAIN   - there was a conflicting acquire on pair key, try
     187             :                    again after the conflicting acquire has been
     188             :                    released.  That is, pair key is currently
     189             :                    acquired-for-modify (this includes pair key in the
     190             :                    process of being created).
     191             : 
     192             :          KEY     - pair key did not exist at bstream seq_present and
     193             :                    is not in the process of being created.
     194             : 
     195             :        ACQUIRE (for modify)
     196             : 
     197             :          SUCCESS - acquired the corresponding pair key.  The pair val
     198             :                    and pair info can be found via the corresponding
     199             :                    val_gaddr in the shared data cache.  This location
     200             :                    will be stable until the pair is released.
     201             : 
     202             :                    If pair key exists and ignore was _not_ set, info
     203             :                    will contain the current pair metadata (including the
     204             :                    val byte size), val contain the current pair val and
     205             :                    the val region will be sized to the greater of the
     206             :                    current val byte size and the requested max val byte
     207             :                    size.
     208             : 
     209             :                    If pair key exists and ignore _was_ set, info will
     210             :                    contain the _current_ pair metadata (_but_ with a val
     211             :                    byte size of 0), val will be empty and the region
     212             :                    will be sized to the requested max val byte size.
     213             : 
     214             :                    If pair key did not exist, the pair info will be all
     215             :                    zeros, val will be empty and the val region will be
     216             :                    sized to the requested max val byte size.
     217             : 
     218             :          INVAL   - pair key existed and exclusive was set
     219             : 
     220             :          KEY     - pair key did not exist and create was not set
     221             : 
     222             :          AGAIN   - there was a conflicting acquire on pair, try again
     223             :                    after conflicting acquire(s) have been released.
     224             :                    That is, pair key is currently acquired-for-read one
     225             :                    or more times or acquired-for-modify.
     226             : 
     227             :        RELEASE
     228             : 
     229             :          SUCCESS - released the corresponding pair key.  The key-val
     230             :                    store was updated appropriately.  In particular:
     231             : 
     232             :                    When releasing an acquire-for-modify _with_ modify
     233             :                    set, the modification "happened" (i.e. is now part of
     234             :                    the bstream's past).  This includes creating or
     235             :                    erasing a pair.  The cached pair info gave the
     236             :                    modified pair info (including the updated pair val
     237             :                    byte size).
     238             : 
     239             :                    When releasing an acquire-for-modify _without_ modify
     240             :                    set, the modification was cancelled.  If the ignore
     241             :                    flag _was_set, the vinyl tile assumed the cached info
     242             :                    and/or val were clobbered by the client during the
     243             :                    acquire.  If the ignore flag was _not_ set, the vinyl
     244             :                    tile assumed the client did not alter any pair value
     245             :                    or pair info _at_ _any_ _time_ _during_ _the_
     246             :                    _acquire_ (such that the cached values and any
     247             :                    speculations on those cached values during the
     248             :                    acquire were valid).  Note that when releasing an
     249             :                    acquire-for-modify-with-ignore, the implicily
     250             :                    clobbered the cached pair info val byte size and
     251             :                    cached pair val for pairs that had a non-zero val
     252             :                    size immediately before the acquire.  Since the
     253             :                    client probably didn't know if the val size was zero
     254             :                    beforehand, it is strongly recommended that
     255             :                    acquire-for-modify-with-ignore only be canceled via a
     256             :                    release-with-ignore.
     257             : 
     258             :                    TL;DR If client never wrote to the cached pair info
     259             :                    or cached pair val on an
     260             :                    acquire-for-modify-without-ignore, the modification
     261             :                    can be cancelled fast with a release-without-modify.
     262             :                    In all other cases, a modification should be
     263             :                    cancelled via a release-without-modify-with-ignore.
     264             : 
     265             :                    Note that release-with-modify of an acquire-for-read
     266             :                    is considered a catastrophe (the client modified data
     267             :                    it promised not to change and may have corrupted
     268             :                    state of themselves, other clients and the store
     269             :                    itself).  Overrunning pair cache storage (the client
     270             :                    set the pair info val_sz to something larger than the
     271             :                    acquire-with-modify val_max) is also treated as a
     272             :                    catastrophe for similar reasons.
     273             : 
     274             :          INVAL   - the corresponding key (BY_KEY) / val (~BY_KEY) did
     275             :                    not appear to be to an acquired pair
     276             : 
     277             :        ERASE
     278             : 
     279             :          SUCCESS - the corresponding key was erased
     280             : 
     281             :          KEY     - the corresponding key did not exist
     282             : 
     283             :          AGAIN   - corresponding key is currently acquired for something
     284             :                    (including read, modify or create), try again after
     285             :                    conflicting acquires have been released
     286             : 
     287             :        MOVE
     288             : 
     289             :          SUCCESS - the corresponding src_key was renamed to the
     290             :                    corresponding dst_key.  If dst_key existed before the
     291             :                    move, it was atomically erased before renaming pair
     292             :                    src_key.  The new pair dst_key has the pair info and
     293             :                    pair val of the old pair src_key.
     294             : 
     295             :                    Note that a move from src_key to src_key is treated
     296             :                    as a no-op that immediately succeeds (with no
     297             :                    checking, for example, whether or not src_key even
     298             :                    exists).
     299             : 
     300             :          KEY     - the corresponding src_key did not exist
     301             : 
     302             :          AGAIN   - there was at least one conflicting acquire on src_key
     303             :                    and/or dst_key.  Try again after the conflicting
     304             :                    acquires have been released.
     305             : 
     306             :        FETCH - ignored
     307             : 
     308             :        FLUSH - ignored
     309             : 
     310             :        TRY
     311             : 
     312             :          SUCCESS - the client is clear to try a speculative
     313             :                    (non-blocking) read of the corresponding key.  The
     314             :                    key was located in the data cache region at the given
     315             :                    val_gaddr at the start of the try.
     316             : 
     317             :          KEY     - the corresponding key did not exist to try
     318             : 
     319             :          AGAIN   - the corresponding key was acquired-for-modify
     320             :                    (includes create), try again after conflicting
     321             :                    acquires have been released
     322             : 
     323             :        TEST
     324             : 
     325             :          SUCCESS - the speculative read was successful
     326             : 
     327             :          INVAL   - the corresponding try never started (i.e. try failed
     328             :                    with KEY or AGAIN)
     329             : 
     330             :          CORRUPT - the corresponding try failed (i.e. the pair was
     331             :                    potentially changed during the speculation)
     332             : 
     333             :      If these are set to a positive number before sending the request,
     334             :      the caller can detect individual items as they finish processing
     335             :      (and then access the pair val and pair info via the corresponding
     336             :      val_gaddr on success) before receiving the completion (with some
     337             :      caveats for requests with redundant keys described in
     338             :      case_acquire). */
     339             : 
     340             :   ulong err_gaddr;
     341             : 
     342             :   /* comp_gaddr gives the shared client request gaddr of a:
     343             : 
     344             :        fd_vinyl_comp_t comp[ 1 ]
     345             : 
     346             :      or zero.
     347             : 
     348             :      If non-zero, the completion information will be written into comp
     349             :      (with comp->seq set to 1 last).  If not, the completion will be
     350             :      sent to the completion queue registered to the client for this
     351             :      vinyl tile (and if no completion queue was registered, no
     352             :      completion will be sent ... which is not a recommended mode of
     353             :      operations).
     354             : 
     355             :      If a completion was successful, err will be FD_VINYL_SUCCESS (0),
     356             :      batch_cnt will match the request batch_cnt, fail_cnt will give the
     357             :      number of individual items in the batch that failed (in
     358             :      [0,batch_cnt]), and quota_rem will give the remaining client
     359             :      acquire quota (each successful acquire/release
     360             :      decrements/increments the client's remaining quota by 1 all other
     361             :      operations do not impact the client's quota).
     362             : 
     363             :      If a completion has an error, err will be a FD_VINYL_ERR code
     364             :      (negative).  No processing of any items in the batch was done,
     365             :      batch_cnt will match the request batch_cnt, fail_cnt will be zero
     366             :      and quota_rem will give the remaining client acquire quota
     367             :      (unchanged).  Reasons for a completion error are:
     368             : 
     369             :        INVAL - one or more input arrays were unmappable (i.e. not a
     370             :                valid global address in the shared client request memory
     371             :                region) or this was a modify request with a requested val
     372             :                byte size larger than FD_VINYL_VAL_MAX.
     373             : 
     374             :        FULL  - client acquire quota remaining is too low to process this
     375             :                request fully (ACQUIRE only)
     376             : 
     377             :      FETCH and FLUSH requests do not produce completions. */
     378             : 
     379             :   ulong  comp_gaddr;
     380             : };
     381             : 
     382             : typedef struct fd_vinyl_req fd_vinyl_req_t;
     383             : 
     384             : /* A fd_vinyl_rq_t is an interprocess shared persistent SPMC queue
     385             :    used to communicate fd_vinyl_req_t requests from a client to vinyl
     386             :    tiles.  It is virtually identically to fd_vinyl_cq_t but holds
     387             :    fd_vinyl_req_t instead of fd_vinyl_comp_t.  See fd_vinyl_cq_t for
     388             :    concurrency and flow control details. */
     389             : 
     390           3 : #define FD_VINYL_RQ_MAGIC (0xfd3a7352d703a6c0UL) /* fd warm snd rq magc version 0 */
     391             : 
     392             : struct __attribute__((aligned(128))) fd_vinyl_rq_private {
     393             : 
     394             :   ulong magic;    /* ==FD_VINYL_RQ_MAGIC */
     395             :   ulong req_cnt;  /* Number of requests that can be in flight on this cq at any given time, power of 2 of least 4 */
     396             :   uchar _[ 112 ]; /* Padding to put seq on a separate cache line pair */
     397             :   ulong seq;      /* Request sequence number to publish next */
     398             : 
     399             :   /* padding to 128 alignment */
     400             : 
     401             :   /* fd_vinyl_req_t req[ req_cnt ] here, seq number at idx = seq & (req_cnt-1UL) when available */
     402             : 
     403             :   /* padding to 128 alignment */
     404             : 
     405             : };
     406             : 
     407             : typedef struct fd_vinyl_rq_private fd_vinyl_rq_t;
     408             : 
     409             : FD_PROTOTYPES_BEGIN
     410             : 
     411             : /* fd_vinyl_req_{flag_*,evict_prio} extract the {given flag,eviction
     412             :    priority} from a fd_vinyl_req_t flags field. */
     413             : 
     414     3000000 : FD_FN_CONST static inline int fd_vinyl_req_flag_modify( ulong flags ) { return !!(flags & FD_VINYL_REQ_FLAG_MODIFY); }
     415     3000000 : FD_FN_CONST static inline int fd_vinyl_req_flag_ignore( ulong flags ) { return !!(flags & FD_VINYL_REQ_FLAG_IGNORE); }
     416     3000000 : FD_FN_CONST static inline int fd_vinyl_req_flag_create( ulong flags ) { return !!(flags & FD_VINYL_REQ_FLAG_CREATE); }
     417     3000000 : FD_FN_CONST static inline int fd_vinyl_req_flag_excl  ( ulong flags ) { return !!(flags & FD_VINYL_REQ_FLAG_EXCL  ); }
     418     3000000 : FD_FN_CONST static inline int fd_vinyl_req_flag_erase ( ulong flags ) { return !!(flags & FD_VINYL_REQ_FLAG_ERASE);  }
     419     3000000 : FD_FN_CONST static inline int fd_vinyl_req_flag_by_key( ulong flags ) { return !!(flags & FD_VINYL_REQ_FLAG_BY_KEY); }
     420     3000000 : FD_FN_CONST static inline int fd_vinyl_req_evict_prio ( ulong flags ) { return (int)((flags >> 6) & 3UL);            }
     421             : 
     422             : /* fd_vinyl_rq_{align,footprint,new,join,leave_delete} have the usual
     423             :    interprocess shared persistent object semantics.  req_cnt is a
     424             :    power-of-2 of at least 4 that gives the number requests that can be
     425             :    in flight on this rq. */
     426             : 
     427             : FD_FN_CONST ulong fd_vinyl_rq_align    ( void );
     428             : FD_FN_CONST ulong fd_vinyl_rq_footprint( ulong req_cnt );
     429             : void *            fd_vinyl_rq_new      ( void * shmem, ulong req_cnt );
     430             : fd_vinyl_rq_t *   fd_vinyl_rq_join     ( void * shrq );
     431             : void *            fd_vinyl_rq_leave    ( fd_vinyl_rq_t * rq );
     432             : void *            fd_vinyl_rq_delete   ( void * shrq );
     433             : 
     434             : /* fd_vinyl_rq_req returns the location in the caller's address space of
     435             :    the rq's request array.  fd_vinyl_rq_req_const is a const correct
     436             :    version.  fd_vinyl_rq_req_cnt is the size of this array.  The
     437             :    lifetime of the returned array is the lifetime of the local join.
     438             :    These assume rq is a current local join.
     439             : 
     440             :    fd_vinyl_rq_req_idx gives the array index that will cache request seq
     441             :    in a rq request array with req_cnt elements. */
     442             : 
     443             : FD_FN_CONST static inline fd_vinyl_req_t *
     444    73850719 : fd_vinyl_rq_req( fd_vinyl_rq_t * rq ) {
     445    73850719 :   return (fd_vinyl_req_t *)(rq+1);
     446    73850719 : }
     447             : 
     448             : FD_FN_CONST static inline fd_vinyl_req_t const *
     449           3 : fd_vinyl_rq_req_const( fd_vinyl_rq_t const * rq ) {
     450           3 :   return (fd_vinyl_req_t const *)(rq+1);
     451           3 : }
     452             : 
     453           3 : FD_FN_PURE static inline ulong fd_vinyl_rq_req_cnt( fd_vinyl_rq_t const * rq ) { return rq->req_cnt; }
     454             : 
     455    73880713 : FD_FN_CONST static inline ulong fd_vinyl_rq_req_idx( ulong seq, ulong req_cnt ) { return seq & (req_cnt-1UL); }
     456             : 
     457             : /* fd_vinyl_rq_seq returns the position of the request producer's
     458             :    sequence number cursor.  Specifically, at some point during the call,
     459             :    requests [0,seq) were published, requests (seq,ULONG_MAX] were not
     460             :    published, and request seq was either published, being published or
     461             :    not published.  This is used for initial synchronization between
     462             :    producer and consumers.  This is a compiler fence. */
     463             : 
     464             : static inline ulong
     465           3 : fd_vinyl_rq_seq( fd_vinyl_rq_t const * rq ) {
     466           3 :   FD_COMPILER_MFENCE();
     467           3 :   ulong seq = rq->seq;
     468           3 :   FD_COMPILER_MFENCE();
     469           3 :   return seq;
     470           3 : }
     471             : 
     472             : /* fd_vinyl_rq_send enqueues the given request into the given rq.
     473             :    Assumes rq is a current local join.  This is a compiler fence. */
     474             : 
     475             : /* FIXME: consider SIMD accelerating */
     476             : 
     477             : static inline void
     478             : fd_vinyl_rq_send( fd_vinyl_rq_t * rq,
     479             :                   ulong           req_id,
     480             :                   ulong           link_id,
     481             :                   int             type,            /* In [-2^7,2^7) */
     482             :                   ulong           flags,           /* In [0,2^8)  */
     483             :                   ulong           batch_cnt,       /* In [0,2^16) */
     484             :                   ulong           val_max,
     485             :                   ulong           key_gaddr,
     486             :                   ulong           val_gaddr_gaddr,
     487             :                   ulong           err_gaddr,
     488    73850713 :                   ulong           comp_gaddr ) {
     489    73850713 :   ulong            seq = rq->seq;
     490    73850713 :   fd_vinyl_req_t * req = fd_vinyl_rq_req( rq ) + fd_vinyl_rq_req_idx( seq, rq->req_cnt );
     491    73850713 :   FD_COMPILER_MFENCE();
     492    73850713 :   req->seq             = seq - 1UL; /* Mark request seq being written */
     493    73850713 :   FD_COMPILER_MFENCE();
     494    73850713 :   req->req_id          = req_id;
     495    73850713 :   req->link_id         = link_id;
     496    73850713 :   req->type            = (schar)type;
     497    73850713 :   req->flags           = (uchar)flags;
     498    73850713 :   req->batch_cnt       = (ushort)batch_cnt;
     499    73850713 :   req->val_max         = (uint)val_max;
     500    73850713 :   req->key_gaddr       = key_gaddr;
     501    73850713 :   req->val_gaddr_gaddr = val_gaddr_gaddr;
     502    73850713 :   req->err_gaddr       = err_gaddr;
     503    73850713 :   req->comp_gaddr      = comp_gaddr;
     504    73850713 :   FD_COMPILER_MFENCE();
     505    73850713 :   req->seq             = seq; /* Mark request seq as written */
     506    73850713 :   FD_COMPILER_MFENCE();
     507    73850713 :   rq->seq              = seq + 1UL; /* Record that requests [0,seq) are published */
     508    73850713 :   FD_COMPILER_MFENCE();
     509    73850713 : }
     510             : 
     511             : /* fd_vinyl_rq_recv receives request seq from the given rq.  Returns 0
     512             :    on success, positive if request seq has not been published yet and
     513             :    negative if the consumer has been overrun by the producer.  On
     514             :    return, *dst will contain the desired request on success and was
     515             :    clobbered otherwise.  Assumes rq is a current local join and dst is
     516             :    valid.  This is a compiler fence. */
     517             : 
     518             : /* FIXME: consider SIMD accelerating */
     519             : 
     520             : static inline long
     521             : fd_vinyl_rq_recv( fd_vinyl_rq_t const * rq,
     522             :                   ulong                 seq,
     523           0 :                   fd_vinyl_req_t *      dst ) {
     524           0 :   fd_vinyl_req_t const * src = fd_vinyl_rq_req_const( rq ) + fd_vinyl_rq_req_idx( seq, rq->req_cnt );
     525             : 
     526           0 :   FD_COMPILER_MFENCE();
     527           0 :   ulong seq0 = src->seq;
     528           0 :   FD_COMPILER_MFENCE();
     529           0 :   *dst = *src;
     530           0 :   FD_COMPILER_MFENCE();
     531           0 :   ulong seq1 = src->seq;
     532           0 :   FD_COMPILER_MFENCE();
     533             : 
     534           0 :   long diff0 = (long)(seq-seq0);
     535           0 :   long diff1 = (long)(seq-seq1);
     536           0 :   return fd_long_if( !diff0, diff1, diff0 );
     537           0 : }
     538             : 
     539             : FD_PROTOTYPES_END
     540             : 
     541             : #endif /* HEADER_fd_src_vinyl_rq_fd_vinyl_rq_h */

Generated by: LCOV version 1.14