Print this page
6138 don't abuse atomic_cas_*

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/i86pc/os/x_call.c
          +++ new/usr/src/uts/i86pc/os/x_call.c
↓ open down ↓ 56 lines elided ↑ open up ↑
  57   57   *
  58   58   * The general idea is that initiating a cross call means putting a message
  59   59   * on a target(s) CPU's work queue. Any synchronization is handled by passing
  60   60   * the message back and forth between initiator and target(s).
  61   61   *
  62   62   * Every CPU has xc_work_cnt, which indicates it has messages to process.
  63   63   * This value is incremented as message traffic is initiated and decremented
  64   64   * with every message that finishes all processing.
  65   65   *
  66   66   * The code needs no mfence or other membar_*() calls. The uses of
  67      - * atomic_cas_ptr(), atomic_cas_32() and atomic_dec_32() for the message
       67 + * atomic_cas_ptr(), atomic_inc_32_nv() and atomic_dec_32() for the message
  68   68   * passing are implemented with LOCK prefix instructions which are
  69   69   * equivalent to mfence.
  70   70   *
  71   71   * One interesting aspect of this implmentation is that it allows 2 or more
  72   72   * CPUs to initiate cross calls to intersecting sets of CPUs at the same time.
  73   73   * The cross call processing by the CPUs will happen in any order with only
  74   74   * a guarantee, for xc_call() and xc_sync(), that an initiator won't return
  75   75   * from cross calls before all slaves have invoked the function.
  76   76   *
  77   77   * The reason for this asynchronous approach is to allow for fast global
↓ open down ↓ 57 lines elided ↑ open up ↑
 135  135  {
 136  136          atomic_dec_32(&mcpu->xc_work_cnt);
 137  137  }
 138  138  
 139  139  /*
 140  140   * Increment a CPU's work count and return the old value
 141  141   */
 142  142  static int
 143  143  xc_increment(struct machcpu *mcpu)
 144  144  {
 145      -        int old;
 146      -        do {
 147      -                old = mcpu->xc_work_cnt;
 148      -        } while (atomic_cas_32(&mcpu->xc_work_cnt, old, old + 1) != old);
 149      -        return (old);
      145 +        return (atomic_inc_32_nv(&mcpu->xc_work_cnt) - 1);
 150  146  }
 151  147  
 152  148  /*
 153  149   * Put a message into a queue. The insertion is atomic no matter
 154  150   * how many different inserts/extracts to the same queue happen.
 155  151   */
 156  152  static void
 157  153  xc_insert(void *queue, xc_msg_t *msg)
 158  154  {
 159  155          xc_msg_t *old_head;
↓ open down ↓ 549 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX