locking/static_key: Add support for deferred static branches
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>
This commit is contained in:
		
							parent
							
								
									948f83768a
								
							
						
					
					
						commit
						ad282a8117
					
				| @ -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); | ||||
| } | ||||
|  | ||||
| @ -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) | ||||
| { | ||||
| @ -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) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user