lkml.org 
[lkml]   [2022]   [Mar]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v4 03/24] dept: Embed Dept data in Lockdep
    Date
    Dept should work independently from Lockdep. However, there's no choise
    but to rely on Lockdep code and its instances for now.

    Signed-off-by: Byungchul Park <byungchul.park@lge.com>
    ---
    include/linux/lockdep.h | 71 ++++++++++++++++++++++++++++++++++++++++---
    include/linux/lockdep_types.h | 3 ++
    kernel/locking/lockdep.c | 12 ++++----
    3 files changed, 76 insertions(+), 10 deletions(-)

    diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
    index 467b942..c56f6b6 100644
    --- a/include/linux/lockdep.h
    +++ b/include/linux/lockdep.h
    @@ -20,6 +20,33 @@
    extern int prove_locking;
    extern int lock_stat;

    +#ifdef CONFIG_DEPT
    +static inline void dept_after_copy_map(struct dept_map *to,
    + struct dept_map *from)
    +{
    + int i;
    +
    + if (from->keys == &from->keys_local)
    + to->keys = &to->keys_local;
    +
    + if (!to->keys)
    + return;
    +
    + /*
    + * Since the class cache can be modified concurrently we could observe
    + * half pointers (64bit arch using 32bit copy insns). Therefore clear
    + * the caches and take the performance hit.
    + *
    + * XXX it doesn't work well with lockdep_set_class_and_subclass(), since
    + * that relies on cache abuse.
    + */
    + for (i = 0; i < DEPT_MAX_SUBCLASSES_CACHE; i++)
    + to->keys->classes[i] = NULL;
    +}
    +#else
    +#define dept_after_copy_map(t, f) do { } while (0)
    +#endif
    +
    #ifdef CONFIG_LOCKDEP

    #include <linux/linkage.h>
    @@ -43,6 +70,8 @@ static inline void lockdep_copy_map(struct lockdep_map *to,
    */
    for (i = 0; i < NR_LOCKDEP_CACHING_CLASSES; i++)
    to->class_cache[i] = NULL;
    +
    + dept_after_copy_map(&to->dmap, &from->dmap);
    }

    /*
    @@ -176,8 +205,19 @@ struct held_lock {
    current->lockdep_recursion -= LOCKDEP_OFF; \
    } while (0)

    -extern void lockdep_register_key(struct lock_class_key *key);
    -extern void lockdep_unregister_key(struct lock_class_key *key);
    +extern void __lockdep_register_key(struct lock_class_key *key);
    +extern void __lockdep_unregister_key(struct lock_class_key *key);
    +
    +#define lockdep_register_key(k) \
    +do { \
    + __lockdep_register_key(k); \
    + dept_key_init(&(k)->dkey); \
    +} while (0)
    +#define lockdep_unregister_key(k) \
    +do { \
    + __lockdep_unregister_key(k); \
    + dept_key_destroy(&(k)->dkey); \
    +} while (0)

    /*
    * These methods are used by specific locking variants (spinlocks,
    @@ -185,9 +225,18 @@ struct held_lock {
    * to lockdep:
    */

    -extern void lockdep_init_map_type(struct lockdep_map *lock, const char *name,
    +extern void __lockdep_init_map_type(struct lockdep_map *lock, const char *name,
    struct lock_class_key *key, int subclass, u8 inner, u8 outer, u8 lock_type);

    +#define lockdep_init_map_type(l, n, k, s, i, o, t) \
    +do { \
    + __lockdep_init_map_type(l, n, k, s, i, o, t); \
    + if ((k) == &__lockdep_no_validate__) \
    + dept_map_nocheck(&(l)->dmap); \
    + else \
    + dept_map_init(&(l)->dmap, &(k)->dkey, s, n); \
    +} while (0)
    +
    static inline void
    lockdep_init_map_waits(struct lockdep_map *lock, const char *name,
    struct lock_class_key *key, int subclass, u8 inner, u8 outer)
    @@ -431,13 +480,27 @@ enum xhlock_context_t {
    XHLOCK_CTX_NR,
    };

    +#ifdef CONFIG_DEPT
    +/*
    + * TODO: I found the case to use an address of other than a real key as
    + * _key, for instance, in workqueue. So for now, we cannot use the
    + * assignment like '.dmap.keys = &(_key)->dkey' unless it's fixed.
    + */
    +#define STATIC_DEPT_MAP_INIT(_name, _key) .dmap = { \
    + .name = (_name), \
    + .keys = NULL },
    +#else
    +#define STATIC_DEPT_MAP_INIT(_name, _key)
    +#endif
    +
    #define lockdep_init_map_crosslock(m, n, k, s) do {} while (0)
    /*
    * To initialize a lockdep_map statically use this macro.
    * Note that _name must not be NULL.
    */
    #define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
    - { .name = (_name), .key = (void *)(_key), }
    + { .name = (_name), .key = (void *)(_key), \
    + STATIC_DEPT_MAP_INIT(_name, _key) }

    static inline void lockdep_invariant_state(bool force) {}
    static inline void lockdep_free_task(struct task_struct *task) {}
    diff --git a/include/linux/lockdep_types.h b/include/linux/lockdep_types.h
    index d224308..50c8879 100644
    --- a/include/linux/lockdep_types.h
    +++ b/include/linux/lockdep_types.h
    @@ -11,6 +11,7 @@
    #define __LINUX_LOCKDEP_TYPES_H

    #include <linux/types.h>
    +#include <linux/dept.h>

    #define MAX_LOCKDEP_SUBCLASSES 8UL

    @@ -76,6 +77,7 @@ struct lock_class_key {
    struct hlist_node hash_entry;
    struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES];
    };
    + struct dept_key dkey;
    };

    extern struct lock_class_key __lockdep_no_validate__;
    @@ -185,6 +187,7 @@ struct lockdep_map {
    int cpu;
    unsigned long ip;
    #endif
    + struct dept_map dmap;
    };

    struct pin_cookie { unsigned int val; };
    diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
    index 4a882f8..a85468d 100644
    --- a/kernel/locking/lockdep.c
    +++ b/kernel/locking/lockdep.c
    @@ -1184,7 +1184,7 @@ static inline struct hlist_head *keyhashentry(const struct lock_class_key *key)
    }

    /* Register a dynamically allocated key. */
    -void lockdep_register_key(struct lock_class_key *key)
    +void __lockdep_register_key(struct lock_class_key *key)
    {
    struct hlist_head *hash_head;
    struct lock_class_key *k;
    @@ -1207,7 +1207,7 @@ void lockdep_register_key(struct lock_class_key *key)
    restore_irqs:
    raw_local_irq_restore(flags);
    }
    -EXPORT_SYMBOL_GPL(lockdep_register_key);
    +EXPORT_SYMBOL_GPL(__lockdep_register_key);

    /* Check whether a key has been registered as a dynamic key. */
    static bool is_dynamic_key(const struct lock_class_key *key)
    @@ -4771,7 +4771,7 @@ static inline int check_wait_context(struct task_struct *curr,
    /*
    * Initialize a lock instance's lock-class mapping info:
    */
    -void lockdep_init_map_type(struct lockdep_map *lock, const char *name,
    +void __lockdep_init_map_type(struct lockdep_map *lock, const char *name,
    struct lock_class_key *key, int subclass,
    u8 inner, u8 outer, u8 lock_type)
    {
    @@ -4831,7 +4831,7 @@ void lockdep_init_map_type(struct lockdep_map *lock, const char *name,
    raw_local_irq_restore(flags);
    }
    }
    -EXPORT_SYMBOL_GPL(lockdep_init_map_type);
    +EXPORT_SYMBOL_GPL(__lockdep_init_map_type);

    struct lock_class_key __lockdep_no_validate__;
    EXPORT_SYMBOL_GPL(__lockdep_no_validate__);
    @@ -6291,7 +6291,7 @@ void lockdep_reset_lock(struct lockdep_map *lock)
    }

    /* Unregister a dynamically allocated key. */
    -void lockdep_unregister_key(struct lock_class_key *key)
    +void __lockdep_unregister_key(struct lock_class_key *key)
    {
    struct hlist_head *hash_head = keyhashentry(key);
    struct lock_class_key *k;
    @@ -6326,7 +6326,7 @@ void lockdep_unregister_key(struct lock_class_key *key)
    /* Wait until is_dynamic_key() has finished accessing k->hash_entry. */
    synchronize_rcu();
    }
    -EXPORT_SYMBOL_GPL(lockdep_unregister_key);
    +EXPORT_SYMBOL_GPL(__lockdep_unregister_key);

    void __init lockdep_init(void)
    {
    --
    1.9.1
    \
     
     \ /
      Last update: 2022-03-04 08:09    [W:2.595 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site