aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/lockdep.c154
1 files changed, 61 insertions, 93 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 22ced8d4912f..42dfc28d12cc 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -1268,68 +1268,84 @@ check_usage(struct task_struct *curr, struct held_lock *prev,
1268 bit_backwards, bit_forwards, irqclass); 1268 bit_backwards, bit_forwards, irqclass);
1269} 1269}
1270 1270
1271static int 1271static const char *state_names[] = {
1272check_prev_add_irq(struct task_struct *curr, struct held_lock *prev, 1272#define LOCKDEP_STATE(__STATE) \
1273 struct held_lock *next) 1273 STR(__STATE),
1274#include "lockdep_states.h"
1275#undef LOCKDEP_STATE
1276};
1277
1278static const char *state_rnames[] = {
1279#define LOCKDEP_STATE(__STATE) \
1280 STR(__STATE)"-READ",
1281#include "lockdep_states.h"
1282#undef LOCKDEP_STATE
1283};
1284
1285static inline const char *state_name(enum lock_usage_bit bit)
1274{ 1286{
1275 /* 1287 return (bit & 1) ? state_rnames[bit >> 2] : state_names[bit >> 2];
1276 * Prove that the new dependency does not connect a hardirq-safe 1288}
1277 * lock with a hardirq-unsafe lock - to achieve this we search
1278 * the backwards-subgraph starting at <prev>, and the
1279 * forwards-subgraph starting at <next>:
1280 */
1281 if (!check_usage(curr, prev, next, LOCK_USED_IN_HARDIRQ,
1282 LOCK_ENABLED_HARDIRQ, "hard"))
1283 return 0;
1284 1289
1290static int exclusive_bit(int new_bit)
1291{
1285 /* 1292 /*
1286 * Prove that the new dependency does not connect a hardirq-safe-read 1293 * USED_IN
1287 * lock with a hardirq-unsafe lock - to achieve this we search 1294 * USED_IN_READ
1288 * the backwards-subgraph starting at <prev>, and the 1295 * ENABLED
1289 * forwards-subgraph starting at <next>: 1296 * ENABLED_READ
1297 *
1298 * bit 0 - write/read
1299 * bit 1 - used_in/enabled
1300 * bit 2+ state
1290 */ 1301 */
1291 if (!check_usage(curr, prev, next, LOCK_USED_IN_HARDIRQ_READ, 1302
1292 LOCK_ENABLED_HARDIRQ, "hard-read")) 1303 int state = new_bit & ~3;
1293 return 0; 1304 int dir = new_bit & 2;
1294 1305
1295 /* 1306 /*
1296 * Prove that the new dependency does not connect a softirq-safe 1307 * keep state, bit flip the direction and strip read.
1297 * lock with a softirq-unsafe lock - to achieve this we search
1298 * the backwards-subgraph starting at <prev>, and the
1299 * forwards-subgraph starting at <next>:
1300 */ 1308 */
1301 if (!check_usage(curr, prev, next, LOCK_USED_IN_SOFTIRQ, 1309 return state | (dir ^ 2);
1302 LOCK_ENABLED_SOFTIRQ, "soft")) 1310}
1303 return 0; 1311
1312static int check_irq_usage(struct task_struct *curr, struct held_lock *prev,
1313 struct held_lock *next, enum lock_usage_bit bit)
1314{
1304 /* 1315 /*
1305 * Prove that the new dependency does not connect a softirq-safe-read 1316 * Prove that the new dependency does not connect a hardirq-safe
1306 * lock with a softirq-unsafe lock - to achieve this we search 1317 * lock with a hardirq-unsafe lock - to achieve this we search
1307 * the backwards-subgraph starting at <prev>, and the 1318 * the backwards-subgraph starting at <prev>, and the
1308 * forwards-subgraph starting at <next>: 1319 * forwards-subgraph starting at <next>:
1309 */ 1320 */
1310 if (!check_usage(curr, prev, next, LOCK_USED_IN_SOFTIRQ_READ, 1321 if (!check_usage(curr, prev, next, bit,
1311 LOCK_ENABLED_SOFTIRQ, "soft")) 1322 exclusive_bit(bit), state_name(bit)))
1312 return 0; 1323 return 0;
1313 1324
1325 bit++; /* _READ */
1326
1314 /* 1327 /*
1315 * Prove that the new dependency does not connect a reclaim-fs-safe 1328 * Prove that the new dependency does not connect a hardirq-safe-read
1316 * lock with a reclaim-fs-unsafe lock - to achieve this we search 1329 * lock with a hardirq-unsafe lock - to achieve this we search
1317 * the backwards-subgraph starting at <prev>, and the 1330 * the backwards-subgraph starting at <prev>, and the
1318 * forwards-subgraph starting at <next>: 1331 * forwards-subgraph starting at <next>:
1319 */ 1332 */
1320 if (!check_usage(curr, prev, next, LOCK_USED_IN_RECLAIM_FS, 1333 if (!check_usage(curr, prev, next, bit,
1321 LOCK_ENABLED_RECLAIM_FS, "reclaim-fs")) 1334 exclusive_bit(bit), state_name(bit)))
1322 return 0; 1335 return 0;
1323 1336
1324 /* 1337 return 1;
1325 * Prove that the new dependency does not connect a reclaim-fs-safe-read 1338}
1326 * lock with a reclaim-fs-unsafe lock - to achieve this we search 1339
1327 * the backwards-subgraph starting at <prev>, and the 1340static int
1328 * forwards-subgraph starting at <next>: 1341check_prev_add_irq(struct task_struct *curr, struct held_lock *prev,
1329 */ 1342 struct held_lock *next)
1330 if (!check_usage(curr, prev, next, LOCK_USED_IN_RECLAIM_FS_READ, 1343{
1331 LOCK_ENABLED_RECLAIM_FS, "reclaim-fs-read")) 1344#define LOCKDEP_STATE(__STATE) \
1345 if (!check_irq_usage(curr, prev, next, LOCK_USED_IN_##__STATE)) \
1332 return 0; 1346 return 0;
1347#include "lockdep_states.h"
1348#undef LOCKDEP_STATE
1333 1349
1334 return 1; 1350 return 1;
1335} 1351}
@@ -1984,30 +2000,6 @@ static int RECLAIM_FS_verbose(struct lock_class *class)
1984 2000
1985#define STRICT_READ_CHECKS 1 2001#define STRICT_READ_CHECKS 1
1986 2002
1987static const char *state_names[] = {
1988#define LOCKDEP_STATE(__STATE) \
1989 STR(__STATE),
1990#include "lockdep_states.h"
1991#undef LOCKDEP_STATE
1992};
1993
1994static inline const char *state_name(enum lock_usage_bit bit)
1995{
1996 return state_names[bit >> 2];
1997}
1998
1999static const char *state_rnames[] = {
2000#define LOCKDEP_STATE(__STATE) \
2001 STR(__STATE)"-READ",
2002#include "lockdep_states.h"
2003#undef LOCKDEP_STATE
2004};
2005
2006static inline const char *state_rname(enum lock_usage_bit bit)
2007{
2008 return state_rnames[bit >> 2];
2009}
2010
2011static int (*state_verbose_f[])(struct lock_class *class) = { 2003static int (*state_verbose_f[])(struct lock_class *class) = {
2012#define LOCKDEP_STATE(__STATE) \ 2004#define LOCKDEP_STATE(__STATE) \
2013 __STATE##_verbose, 2005 __STATE##_verbose,
@@ -2021,37 +2013,12 @@ static inline int state_verbose(enum lock_usage_bit bit,
2021 return state_verbose_f[bit >> 2](class); 2013 return state_verbose_f[bit >> 2](class);
2022} 2014}
2023 2015
2024static int exclusive_bit(int new_bit)
2025{
2026 /*
2027 * USED_IN
2028 * USED_IN_READ
2029 * ENABLED
2030 * ENABLED_READ
2031 *
2032 * bit 0 - write/read
2033 * bit 1 - used_in/enabled
2034 * bit 2+ state
2035 */
2036
2037 int state = new_bit & ~3;
2038 int dir = new_bit & 2;
2039
2040 /*
2041 * keep state, bit flip the direction and strip read.
2042 */
2043 return state | (dir ^ 2);
2044}
2045
2046typedef int (*check_usage_f)(struct task_struct *, struct held_lock *, 2016typedef int (*check_usage_f)(struct task_struct *, struct held_lock *,
2047 enum lock_usage_bit bit, const char *name); 2017 enum lock_usage_bit bit, const char *name);
2048 2018
2049static int 2019static int
2050mark_lock_irq(struct task_struct *curr, struct held_lock *this, int new_bit) 2020mark_lock_irq(struct task_struct *curr, struct held_lock *this, int new_bit)
2051{ 2021{
2052 const char *name = state_name(new_bit);
2053 const char *rname = state_rname(new_bit);
2054
2055 int excl_bit = exclusive_bit(new_bit); 2022 int excl_bit = exclusive_bit(new_bit);
2056 int read = new_bit & 1; 2023 int read = new_bit & 1;
2057 int dir = new_bit & 2; 2024 int dir = new_bit & 2;
@@ -2078,7 +2045,7 @@ mark_lock_irq(struct task_struct *curr, struct held_lock *this, int new_bit)
2078 * states. 2045 * states.
2079 */ 2046 */
2080 if ((!read || !dir || STRICT_READ_CHECKS) && 2047 if ((!read || !dir || STRICT_READ_CHECKS) &&
2081 !usage(curr, this, excl_bit, name)) 2048 !usage(curr, this, excl_bit, state_name(new_bit)))
2082 return 0; 2049 return 0;
2083 2050
2084 /* 2051 /*
@@ -2089,7 +2056,8 @@ mark_lock_irq(struct task_struct *curr, struct held_lock *this, int new_bit)
2089 return 0; 2056 return 0;
2090 2057
2091 if (STRICT_READ_CHECKS && 2058 if (STRICT_READ_CHECKS &&
2092 !usage(curr, this, excl_bit + 1, rname)) 2059 !usage(curr, this, excl_bit + 1,
2060 state_name(new_bit + 1)))
2093 return 0; 2061 return 0;
2094 } 2062 }
2095 2063