WL#6363: InnoDB: implement SX-lock for rw_lock

Status: Complete

InnoDB internally uses rw-lock implementation to keep consistency of internal
resources. Basically the rw-lock has 2 types S-lock (shared) and X-lock (exluded).
The fix adds the new type SX-lock (shared excluded) for room to optimize
concurrency and improve scalability more.

At least, S-lock and X-lock behave same, and compatible for current code. So,
nothing changed by only this fix as it is. (no functional/performance changes
for users)

The new state SX-lock will be used by the future work. (e.g. WL#6326: InnoDB:
fix index->lock contention)
(1) new state of rw_lock: SX-lock
      | S|SX| X|
    --+--+--+--+
     S| o| o| x|
    --+--+--+--+
    SX| o| x| x|
    --+--+--+--+
     X| x| x| x|
    --+--+--+--+

  Though it can be equivalent to 2 rw-locks (S=S1 SX=S1+X2 X=X1),
 the increasing atomic instructions should make more expensive, so chosen
SX-lock for now.

  The recursive obtaining of the SX-lock is allowed when has only X or SX or
both of them.
  *Obtaining X-lock on SX-lock is allowed, but it treated as new lock and should
 obey to latching order.

  The operation to relax the X-lock to SX-lock should be supported.
  (not need special function if implemented "sx-lock;x-unlock" as 1 atomic
operation)



***inaam: Can you add more details about recursive locking? It is not very clear 
as it stands right now.
Also can you please add some low level details about the core parts like changes 
to lock_word, dealing with recursion and how is integrity maintained of other 
flags in the rw-lock.

***yasufumi: Currently no limitation about recursive locking about X (not
changed) and SX (also). But we should careful about X lock on SX lock. It should
be check as new lock because upgrading.
- X_LOCK_HALF_DECR defined as X_LOCK_DECR/2

- (volatile lint)(lock->sx_recursive) added to count sx-locks

- lock->writer_thread is used also for sx-locks, because exclusive each other
among x and sx.

- lock->lock_word represents state as followings
------------------------------------------------------------------------------
lock_word == X_LOCK_DECR                        Unlocked

X_LOCK_HALF_DECR < lock_word < X_LOCK_DECR      S locked.
                                                No waiting writers.
                                                (X_LOCK_DECR - lock_word) is the
number of readers that hold the lock.

lock_word == X_LOCK_HALF_DECR                   SX locked
                                                Waiting writers not allowed

0 < lock_word < X_LOCK_HALF_DECR                SX locked AND S locked
                                                (X_LOCK_HALF_DECR - lock_word)
is the number of readers i.e.: S locks
                                                No waiting writers allowed

lock_word == 0                                  X locked
                                                No waiting writers allowed

-X_LOCK_HALF_DECR < lock_word < 0               S locked with a waiting writer
                                                -lock_word is the number of
readers i.e.: S locks

lock_word == -X_LOCK_HALF_DECR                  X lock + recursive SX lock
                                                No waiting writers allowed

-X_LOCK_DECR < lock_word < -X_LOCK_HALF_DECR    S locked with a waiting writer
which has SX-lock
                                                -(lock_word + X_LOCK_HALF_DECR)
is the number of readers i.e.: S locks

lock_word == -X_LOCK_DECR                       X lock + recursive X lock i.e.:
2X locks

-(X_LOCK_DECR + X_LOCK_HALF_DECR) < lock_word < -X_LOCK_DECR
                                                (2 - (lock_word + X_LOCK_DECR))X
locks

lock_word == -(X_LOCK_DECR + X_LOCK_HALF_DECR)  2X locks + SX lock

lock_word < -(X_LOCK_DECR + X_LOCK_HALF_DECR)   (2 - (lock_word + X_LOCK_DECR +
X_LOCK_HALF_DECR))X locks
                                                + SX lock
------------------------------------------------------------------------------