Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 (*
0003  * Copyright (C) 2015 Jade Alglave <j.alglave@ucl.ac.uk>,
0004  * Copyright (C) 2016 Luc Maranget <luc.maranget@inria.fr> for Inria
0005  * Copyright (C) 2017 Alan Stern <stern@rowland.harvard.edu>,
0006  *                    Andrea Parri <parri.andrea@gmail.com>
0007  *
0008  * An earlier version of this file appeared in the companion webpage for
0009  * "Frightening small children and disconcerting grown-ups: Concurrency
0010  * in the Linux kernel" by Alglave, Maranget, McKenney, Parri, and Stern,
0011  * which appeared in ASPLOS 2018.
0012  *)
0013 
0014 "Linux-kernel memory consistency model"
0015 
0016 enum Accesses = 'once (*READ_ONCE,WRITE_ONCE*) ||
0017                 'release (*smp_store_release*) ||
0018                 'acquire (*smp_load_acquire*) ||
0019                 'noreturn (* R of non-return RMW *)
0020 instructions R[{'once,'acquire,'noreturn}]
0021 instructions W[{'once,'release}]
0022 instructions RMW[{'once,'acquire,'release}]
0023 
0024 enum Barriers = 'wmb (*smp_wmb*) ||
0025                 'rmb (*smp_rmb*) ||
0026                 'mb (*smp_mb*) ||
0027                 'barrier (*barrier*) ||
0028                 'rcu-lock (*rcu_read_lock*)  ||
0029                 'rcu-unlock (*rcu_read_unlock*) ||
0030                 'sync-rcu (*synchronize_rcu*) ||
0031                 'before-atomic (*smp_mb__before_atomic*) ||
0032                 'after-atomic (*smp_mb__after_atomic*) ||
0033                 'after-spinlock (*smp_mb__after_spinlock*) ||
0034                 'after-unlock-lock (*smp_mb__after_unlock_lock*)
0035 instructions F[Barriers]
0036 
0037 (* SRCU *)
0038 enum SRCU = 'srcu-lock || 'srcu-unlock || 'sync-srcu
0039 instructions SRCU[SRCU]
0040 (* All srcu events *)
0041 let Srcu = Srcu-lock | Srcu-unlock | Sync-srcu
0042 
0043 (* Compute matching pairs of nested Rcu-lock and Rcu-unlock *)
0044 let rcu-rscs = let rec
0045             unmatched-locks = Rcu-lock \ domain(matched)
0046         and unmatched-unlocks = Rcu-unlock \ range(matched)
0047         and unmatched = unmatched-locks | unmatched-unlocks
0048         and unmatched-po = [unmatched] ; po ; [unmatched]
0049         and unmatched-locks-to-unlocks =
0050                 [unmatched-locks] ; po ; [unmatched-unlocks]
0051         and matched = matched | (unmatched-locks-to-unlocks \
0052                 (unmatched-po ; unmatched-po))
0053         in matched
0054 
0055 (* Validate nesting *)
0056 flag ~empty Rcu-lock \ domain(rcu-rscs) as unbalanced-rcu-locking
0057 flag ~empty Rcu-unlock \ range(rcu-rscs) as unbalanced-rcu-locking
0058 
0059 (* Compute matching pairs of nested Srcu-lock and Srcu-unlock *)
0060 let srcu-rscs = let rec
0061             unmatched-locks = Srcu-lock \ domain(matched)
0062         and unmatched-unlocks = Srcu-unlock \ range(matched)
0063         and unmatched = unmatched-locks | unmatched-unlocks
0064         and unmatched-po = ([unmatched] ; po ; [unmatched]) & loc
0065         and unmatched-locks-to-unlocks =
0066                 ([unmatched-locks] ; po ; [unmatched-unlocks]) & loc
0067         and matched = matched | (unmatched-locks-to-unlocks \
0068                 (unmatched-po ; unmatched-po))
0069         in matched
0070 
0071 (* Validate nesting *)
0072 flag ~empty Srcu-lock \ domain(srcu-rscs) as unbalanced-srcu-locking
0073 flag ~empty Srcu-unlock \ range(srcu-rscs) as unbalanced-srcu-locking
0074 
0075 (* Check for use of synchronize_srcu() inside an RCU critical section *)
0076 flag ~empty rcu-rscs & (po ; [Sync-srcu] ; po) as invalid-sleep
0077 
0078 (* Validate SRCU dynamic match *)
0079 flag ~empty different-values(srcu-rscs) as srcu-bad-nesting
0080 
0081 (* Compute marked and plain memory accesses *)
0082 let Marked = (~M) | IW | Once | Release | Acquire | domain(rmw) | range(rmw) |
0083                 LKR | LKW | UL | LF | RL | RU
0084 let Plain = M \ Marked