Print this page
11506 smatch resync

@@ -47,10 +47,11 @@
 
 enum return_type {
         ret_any,
         ret_non_zero,
         ret_zero,
+        ret_one,
         ret_negative,
         ret_positive,
 };
 
 #define RETURN_VAL -1

@@ -149,22 +150,22 @@
         {"_spin_lock_bh",              LOCK,   "spin_lock", 0, ret_any},
         {"_spin_unlock_bh",            UNLOCK, "spin_lock", 0, ret_any},
         {"__spin_lock_bh",             LOCK,   "spin_lock", 0, ret_any},
         {"__spin_unlock_bh",           UNLOCK, "spin_lock", 0, ret_any},
 
-        {"spin_trylock",               LOCK,   "spin_lock", 0, ret_non_zero},
-        {"_spin_trylock",              LOCK,   "spin_lock", 0, ret_non_zero},
-        {"__spin_trylock",             LOCK,   "spin_lock", 0, ret_non_zero},
-        {"raw_spin_trylock",           LOCK,   "spin_lock", 0, ret_non_zero},
-        {"_raw_spin_trylock",          LOCK,   "spin_lock", 0, ret_non_zero},
-        {"spin_trylock_irq",           LOCK,   "spin_lock", 0, ret_non_zero},
-        {"spin_trylock_irqsave",       LOCK,   "spin_lock", 0, ret_non_zero},
-        {"spin_trylock_bh",            LOCK,   "spin_lock", 0, ret_non_zero},
-        {"_spin_trylock_bh",           LOCK,   "spin_lock", 0, ret_non_zero},
-        {"__spin_trylock_bh",          LOCK,   "spin_lock", 0, ret_non_zero},
-        {"__raw_spin_trylock",         LOCK,   "spin_lock", 0, ret_non_zero},
-        {"_atomic_dec_and_lock",       LOCK,   "spin_lock", 1, ret_non_zero},
+        {"spin_trylock",               LOCK,   "spin_lock", 0, ret_one},
+        {"_spin_trylock",              LOCK,   "spin_lock", 0, ret_one},
+        {"__spin_trylock",             LOCK,   "spin_lock", 0, ret_one},
+        {"raw_spin_trylock",           LOCK,   "spin_lock", 0, ret_one},
+        {"_raw_spin_trylock",          LOCK,   "spin_lock", 0, ret_one},
+        {"spin_trylock_irq",           LOCK,   "spin_lock", 0, ret_one},
+        {"spin_trylock_irqsave",       LOCK,   "spin_lock", 0, ret_one},
+        {"spin_trylock_bh",            LOCK,   "spin_lock", 0, ret_one},
+        {"_spin_trylock_bh",           LOCK,   "spin_lock", 0, ret_one},
+        {"__spin_trylock_bh",          LOCK,   "spin_lock", 0, ret_one},
+        {"__raw_spin_trylock",         LOCK,   "spin_lock", 0, ret_one},
+        {"_atomic_dec_and_lock",       LOCK,   "spin_lock", 1, ret_one},
 
         {"read_lock",                 LOCK,   "read_lock", 0, ret_any},
         {"read_unlock",               UNLOCK, "read_lock", 0, ret_any},
         {"_read_lock",                LOCK,   "read_lock", 0, ret_any},
         {"_read_unlock",              UNLOCK, "read_lock", 0, ret_any},

@@ -195,17 +196,17 @@
         {"_raw_read_lock_bh",         LOCK,   "read_lock", 0, ret_any},
         {"_raw_read_unlock_bh",       UNLOCK, "read_lock", 0, ret_any},
         {"__raw_read_lock_bh",        LOCK,   "read_lock", 0, ret_any},
         {"__raw_read_unlock_bh",      UNLOCK, "read_lock", 0, ret_any},
 
-        {"generic__raw_read_trylock", LOCK,   "read_lock", 0, ret_non_zero},
-        {"read_trylock",              LOCK,   "read_lock", 0, ret_non_zero},
-        {"_read_trylock",             LOCK,   "read_lock", 0, ret_non_zero},
-        {"raw_read_trylock",          LOCK,   "read_lock", 0, ret_non_zero},
-        {"_raw_read_trylock",         LOCK,   "read_lock", 0, ret_non_zero},
-        {"__raw_read_trylock",        LOCK,   "read_lock", 0, ret_non_zero},
-        {"__read_trylock",            LOCK,   "read_lock", 0, ret_non_zero},
+        {"generic__raw_read_trylock", LOCK,   "read_lock", 0, ret_one},
+        {"read_trylock",              LOCK,   "read_lock", 0, ret_one},
+        {"_read_trylock",             LOCK,   "read_lock", 0, ret_one},
+        {"raw_read_trylock",          LOCK,   "read_lock", 0, ret_one},
+        {"_raw_read_trylock",         LOCK,   "read_lock", 0, ret_one},
+        {"__raw_read_trylock",        LOCK,   "read_lock", 0, ret_one},
+        {"__read_trylock",            LOCK,   "read_lock", 0, ret_one},
 
         {"write_lock",                LOCK,   "write_lock", 0, ret_any},
         {"write_unlock",              UNLOCK, "write_lock", 0, ret_any},
         {"_write_lock",               LOCK,   "write_lock", 0, ret_any},
         {"_write_unlock",             UNLOCK, "write_lock", 0, ret_any},

@@ -232,33 +233,47 @@
         {"_raw_write_lock",           LOCK,   "write_lock", 0, ret_any},
         {"__raw_write_lock",          LOCK,   "write_lock", 0, ret_any},
         {"_raw_write_unlock",         UNLOCK, "write_lock", 0, ret_any},
         {"__raw_write_unlock",        UNLOCK, "write_lock", 0, ret_any},
 
-        {"write_trylock",             LOCK,   "write_lock", 0, ret_non_zero},
-        {"_write_trylock",            LOCK,   "write_lock", 0, ret_non_zero},
-        {"raw_write_trylock",         LOCK,   "write_lock", 0, ret_non_zero},
-        {"_raw_write_trylock",        LOCK,   "write_lock", 0, ret_non_zero},
-        {"__write_trylock",           LOCK,   "write_lock", 0, ret_non_zero},
-        {"__raw_write_trylock",       LOCK,   "write_lock", 0, ret_non_zero},
+        {"write_trylock",             LOCK,   "write_lock", 0, ret_one},
+        {"_write_trylock",            LOCK,   "write_lock", 0, ret_one},
+        {"raw_write_trylock",         LOCK,   "write_lock", 0, ret_one},
+        {"_raw_write_trylock",        LOCK,   "write_lock", 0, ret_one},
+        {"__write_trylock",           LOCK,   "write_lock", 0, ret_one},
+        {"__raw_write_trylock",       LOCK,   "write_lock", 0, ret_one},
 
         {"down",               LOCK,   "sem", 0, ret_any},
         {"up",                 UNLOCK, "sem", 0, ret_any},
         {"down_trylock",       LOCK,   "sem", 0, ret_zero},
         {"down_timeout",       LOCK,   "sem", 0, ret_zero},
         {"down_interruptible", LOCK,   "sem", 0, ret_zero},
 
+
+        {"down_write",          LOCK,   "rw_sem", 0, ret_any},
+        {"downgrade_write",     UNLOCK, "rw_sem", 0, ret_any},
+        {"downgrade_write",     LOCK,   "read_sem", 0, ret_any},
+        {"up_write",            UNLOCK, "rw_sem", 0, ret_any},
+        {"down_write_trylock",  LOCK,   "rw_sem", 0, ret_one},
+        {"down_write_killable", LOCK,   "rw_sem", 0, ret_zero},
+        {"down_read",           LOCK,   "read_sem", 0, ret_any},
+        {"down_read_trylock",   LOCK,   "read_sem", 0, ret_one},
+        {"down_read_killable",  LOCK,   "read_sem", 0, ret_zero},
+        {"up_read",             UNLOCK, "read_sem", 0, ret_any},
+
         {"mutex_lock",                      LOCK,   "mutex", 0, ret_any},
+        {"mutex_lock_io",                   LOCK,   "mutex", 0, ret_any},
         {"mutex_unlock",                    UNLOCK, "mutex", 0, ret_any},
         {"mutex_lock_nested",               LOCK,   "mutex", 0, ret_any},
+        {"mutex_lock_io_nested",            LOCK,   "mutex", 0, ret_any},
 
         {"mutex_lock_interruptible",        LOCK,   "mutex", 0, ret_zero},
         {"mutex_lock_interruptible_nested", LOCK,   "mutex", 0, ret_zero},
         {"mutex_lock_killable",             LOCK,   "mutex", 0, ret_zero},
         {"mutex_lock_killable_nested",      LOCK,   "mutex", 0, ret_zero},
 
-        {"mutex_trylock",                   LOCK,   "mutex", 0, ret_non_zero},
+        {"mutex_trylock",                   LOCK,   "mutex", 0, ret_one},
 
         {"raw_local_irq_disable", LOCK,   "irq", NO_ARG, ret_any},
         {"raw_local_irq_enable",  UNLOCK, "irq", NO_ARG, ret_any},
         {"spin_lock_irq",         LOCK,   "irq", NO_ARG, ret_any},
         {"spin_unlock_irq",       UNLOCK, "irq", NO_ARG, ret_any},

@@ -267,11 +282,11 @@
         {"__spin_lock_irq",       LOCK,   "irq", NO_ARG, ret_any},
         {"__spin_unlock_irq",     UNLOCK, "irq", NO_ARG, ret_any},
         {"_raw_spin_lock_irq",    LOCK,   "irq", NO_ARG, ret_any},
         {"_raw_spin_unlock_irq",  UNLOCK, "irq", NO_ARG, ret_any},
         {"__raw_spin_unlock_irq", UNLOCK, "irq", NO_ARG, ret_any},
-        {"spin_trylock_irq",      LOCK,   "irq", NO_ARG, ret_non_zero},
+        {"spin_trylock_irq",      LOCK,   "irq", NO_ARG, ret_one},
         {"read_lock_irq",         LOCK,   "irq", NO_ARG, ret_any},
         {"read_unlock_irq",       UNLOCK, "irq", NO_ARG, ret_any},
         {"_read_lock_irq",        LOCK,   "irq", NO_ARG, ret_any},
         {"_read_unlock_irq",      UNLOCK, "irq", NO_ARG, ret_any},
         {"__read_lock_irq",       LOCK,   "irq", NO_ARG, ret_any},

@@ -302,11 +317,11 @@
         {"_raw_spin_lock_irqsave",     LOCK,   "irqsave", 1, ret_any},
         {"_raw_spin_unlock_irqrestore",UNLOCK, "irqsave", 1, ret_any},
         {"__raw_spin_lock_irqsave",    LOCK,   "irqsave", RETURN_VAL, ret_any},
         {"__raw_spin_unlock_irqrestore",UNLOCK, "irqsave", 1, ret_any},
         {"_raw_spin_lock_irqsave_nested", LOCK, "irqsave", RETURN_VAL, ret_any},
-        {"spin_trylock_irqsave",       LOCK,   "irqsave", 1, ret_non_zero},
+        {"spin_trylock_irqsave",       LOCK,   "irqsave", 1, ret_one},
         {"read_lock_irqsave",          LOCK,   "irqsave", RETURN_VAL, ret_any},
         {"read_lock_irqsave",          LOCK,   "irqsave", 1, ret_any},
         {"read_unlock_irqrestore",     UNLOCK, "irqsave", 1, ret_any},
         {"_read_lock_irqsave",         LOCK,   "irqsave", RETURN_VAL, ret_any},
         {"_read_lock_irqsave",         LOCK,   "irqsave", 1, ret_any},

@@ -346,13 +361,13 @@
         {"write_unlock_bh",     UNLOCK, "bottom_half", NO_ARG, ret_any},
         {"_write_lock_bh",      LOCK,   "bottom_half", NO_ARG, ret_any},
         {"_write_unlock_bh",    UNLOCK, "bottom_half", NO_ARG, ret_any},
         {"__write_lock_bh",     LOCK,   "bottom_half", NO_ARG, ret_any},
         {"__write_unlock_bh",   UNLOCK, "bottom_half", NO_ARG, ret_any},
-        {"spin_trylock_bh",     LOCK,   "bottom_half", NO_ARG, ret_non_zero},
-        {"_spin_trylock_bh",    LOCK,   "bottom_half", NO_ARG, ret_non_zero},
-        {"__spin_trylock_bh",   LOCK,   "bottom_half", NO_ARG, ret_non_zero},
+        {"spin_trylock_bh",     LOCK,   "bottom_half", NO_ARG, ret_one},
+        {"_spin_trylock_bh",    LOCK,   "bottom_half", NO_ARG, ret_one},
+        {"__spin_trylock_bh",   LOCK,   "bottom_half", NO_ARG, ret_one},
 
         {"ffs_mutex_lock",        LOCK,   "mutex", 0, ret_zero},
 };
 
 static struct lock_info *lock_table;

@@ -445,10 +460,19 @@
 {
         if (is_impossible_path())
                 set_state(my_id, sm->name, sm->sym, &impossible);
 }
 
+static bool nestable(const char *name)
+{
+        if (strstr(name, "read_sem:"))
+                return true;
+        if (strcmp(name, "bottom_half:") == 0)
+                return true;
+        return false;
+}
+
 static void do_lock(const char *name)
 {
         struct sm_state *sm;
 
         if (__inline_fn)

@@ -455,12 +479,11 @@
                 return;
 
         sm = get_sm_state(my_id, name, NULL);
         if (!sm)
                 add_tracker(&starts_unlocked, my_id, name, NULL);
-        if (sm && slist_has_state(sm->possible, &locked) &&
-                        strcmp(name, "bottom_half:") != 0)
+        if (sm && slist_has_state(sm->possible, &locked) && !nestable(name))
                 sm_error("double lock '%s'", name);
         if (sm)
                 func_has_transition = TRUE;
         set_state(my_id, name, NULL, &locked);
 }

@@ -742,16 +765,19 @@
 }
 
 static int matches_return_type(struct range_list *rl, enum return_type type)
 {
         sval_t zero_sval = ll_to_sval(0);
+        sval_t one_sval = ll_to_sval(1);
 
         /* All these double negatives are super ugly!  */
 
         switch (type) {
         case ret_zero:
                 return !possibly_true_rl(rl, SPECIAL_NOTEQUAL, alloc_rl(zero_sval, zero_sval));
+        case ret_one:
+                return !possibly_true_rl(rl, SPECIAL_NOTEQUAL, alloc_rl(one_sval, one_sval));
         case ret_non_zero:
                 return !possibly_true_rl(rl, SPECIAL_EQUAL, alloc_rl(zero_sval, zero_sval));
         case ret_negative:
                 return !possibly_true_rl(rl, SPECIAL_GTE, alloc_rl(zero_sval, zero_sval));
         case ret_positive:

@@ -904,19 +930,22 @@
 {
         struct lock_info *lock = &lock_table[index];
         void *idx = INT_PTR(index);
 
         if (lock->return_type == ret_non_zero) {
-                return_implies_state(lock->function, valid_ptr_min, valid_ptr_max, &match_lock_held, idx);
+                return_implies_state(lock->function, 1, INT_MAX, &match_lock_held, idx);
                 return_implies_state(lock->function, 0, 0, &match_lock_failed, idx);
         } else if (lock->return_type == ret_any && lock->arg == RETURN_VAL) {
                 add_function_assign_hook(lock->function, &match_returns_locked, idx);
         } else if (lock->return_type == ret_any) {
                 add_function_hook(lock->function, &match_lock_unlock, idx);
         } else if (lock->return_type == ret_zero) {
                 return_implies_state(lock->function, 0, 0, &match_lock_held, idx);
                 return_implies_state(lock->function, -4095, -1, &match_lock_failed, idx);
+        } else if (lock->return_type == ret_one) {
+                return_implies_state(lock->function, 1, 1, &match_lock_held, idx);
+                return_implies_state(lock->function, 0, 0, &match_lock_failed, idx);
         }
 }
 
 static void load_table(struct lock_info *_lock_table, int size)
 {