Skip to content

Commit

Permalink
locking/static_key: Add support for deferred static branches
Browse files Browse the repository at this point in the history
Add deferred static branches.  We can't unfortunately use the
nice trick of encapsulating the entire structure in true/false
variants, because the inside has to be either struct static_key_true
or struct static_key_false.  Use defines to pass the appropriate
members to the helpers separately.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will.deacon@arm.com>
Cc: alexei.starovoitov@gmail.com
Cc: ard.biesheuvel@linaro.org
Cc: oss-drivers@netronome.com
Cc: yamada.masahiro@socionext.com
Link: https://lkml.kernel.org/r/20190330000854.30142-2-jakub.kicinski@netronome.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Jakub Kicinski authored and Ingo Molnar committed Apr 29, 2019
1 parent 948f837 commit ad282a8
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 10 deletions.
64 changes: 61 additions & 3 deletions include/linux/jump_label_ratelimit.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,79 @@ struct static_key_deferred {
struct delayed_work work;
};

extern void static_key_slow_dec_deferred(struct static_key_deferred *key);
extern void static_key_deferred_flush(struct static_key_deferred *key);
struct static_key_true_deferred {
struct static_key_true key;
unsigned long timeout;
struct delayed_work work;
};

struct static_key_false_deferred {
struct static_key_false key;
unsigned long timeout;
struct delayed_work work;
};

#define static_key_slow_dec_deferred(x) \
__static_key_slow_dec_deferred(&(x)->key, &(x)->work, (x)->timeout)
#define static_branch_slow_dec_deferred(x) \
__static_key_slow_dec_deferred(&(x)->key.key, &(x)->work, (x)->timeout)

#define static_key_deferred_flush(x) \
__static_key_deferred_flush((x), &(x)->work)

extern void
__static_key_slow_dec_deferred(struct static_key *key,
struct delayed_work *work,
unsigned long timeout);
extern void __static_key_deferred_flush(void *key, struct delayed_work *work);
extern void
jump_label_rate_limit(struct static_key_deferred *key, unsigned long rl);

extern void jump_label_update_timeout(struct work_struct *work);

#define DEFINE_STATIC_KEY_DEFERRED_TRUE(name, rl) \
struct static_key_true_deferred name = { \
.key = { STATIC_KEY_INIT_TRUE }, \
.timeout = (rl), \
.work = __DELAYED_WORK_INITIALIZER((name).work, \
jump_label_update_timeout, \
0), \
}

#define DEFINE_STATIC_KEY_DEFERRED_FALSE(name, rl) \
struct static_key_false_deferred name = { \
.key = { STATIC_KEY_INIT_FALSE }, \
.timeout = (rl), \
.work = __DELAYED_WORK_INITIALIZER((name).work, \
jump_label_update_timeout, \
0), \
}

#define static_branch_deferred_inc(x) static_branch_inc(&(x)->key)

#else /* !CONFIG_JUMP_LABEL */
struct static_key_deferred {
struct static_key key;
};
struct static_key_true_deferred {
struct static_key_true key;
};
struct static_key_false_deferred {
struct static_key_false key;
};
#define DEFINE_STATIC_KEY_DEFERRED_TRUE(name, rl) \
struct static_key_true_deferred name = { STATIC_KEY_TRUE_INIT }
#define DEFINE_STATIC_KEY_DEFERRED_FALSE(name, rl) \
struct static_key_false_deferred name = { STATIC_KEY_FALSE_INIT }

#define static_branch_slow_dec_deferred(x) static_branch_dec(&(x)->key)

static inline void static_key_slow_dec_deferred(struct static_key_deferred *key)
{
STATIC_KEY_CHECK_USE(key);
static_key_slow_dec(&key->key);
}
static inline void static_key_deferred_flush(struct static_key_deferred *key)
static inline void static_key_deferred_flush(void *key)
{
STATIC_KEY_CHECK_USE(key);
}
Expand Down
17 changes: 10 additions & 7 deletions kernel/jump_label.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,13 @@ static void __static_key_slow_dec(struct static_key *key,
cpus_read_unlock();
}

static void jump_label_update_timeout(struct work_struct *work)
void jump_label_update_timeout(struct work_struct *work)
{
struct static_key_deferred *key =
container_of(work, struct static_key_deferred, work.work);
__static_key_slow_dec(&key->key, 0, NULL);
}
EXPORT_SYMBOL_GPL(jump_label_update_timeout);

void static_key_slow_dec(struct static_key *key)
{
Expand All @@ -264,19 +265,21 @@ void static_key_slow_dec_cpuslocked(struct static_key *key)
__static_key_slow_dec_cpuslocked(key, 0, NULL);
}

void static_key_slow_dec_deferred(struct static_key_deferred *key)
void __static_key_slow_dec_deferred(struct static_key *key,
struct delayed_work *work,
unsigned long timeout)
{
STATIC_KEY_CHECK_USE(key);
__static_key_slow_dec(&key->key, key->timeout, &key->work);
__static_key_slow_dec(key, timeout, work);
}
EXPORT_SYMBOL_GPL(static_key_slow_dec_deferred);
EXPORT_SYMBOL_GPL(__static_key_slow_dec_deferred);

void static_key_deferred_flush(struct static_key_deferred *key)
void __static_key_deferred_flush(void *key, struct delayed_work *work)
{
STATIC_KEY_CHECK_USE(key);
flush_delayed_work(&key->work);
flush_delayed_work(work);
}
EXPORT_SYMBOL_GPL(static_key_deferred_flush);
EXPORT_SYMBOL_GPL(__static_key_deferred_flush);

void jump_label_rate_limit(struct static_key_deferred *key,
unsigned long rl)
Expand Down

0 comments on commit ad282a8

Please sign in to comment.