diff options
author | Christoph Lameter <cl@linux-foundation.org> | 2010-01-05 01:34:50 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-01-05 01:34:50 -0500 |
commit | e1783a240f491fb233f04edc042e16b18a7a79ba (patch) | |
tree | b523bf2db00fff96f1ab488168fc16ab56c372aa /include/linux/module.h | |
parent | 38b7827fcdd660f591d645bd3ae6644456a4773c (diff) |
module: Use this_cpu_xx to dynamically allocate counters
Use cpu ops to deal with the per cpu data instead of a local_t. Reduces memory
requirements, cache footprint and decreases cycle counts.
The this_cpu_xx operations are also used for !SMP mode. Otherwise we could
not drop the use of __module_ref_addr() which would make per cpu data handling
complicated. this_cpu_xx operations have their own fallback for !SMP.
V8-V9:
- Leave include asm/module.h since ringbuffer.c depends on it. Nothing else
does though. Another patch will deal with that.
- Remove spurious free.
Signed-off-by: Christoph Lameter <cl@linux-foundation.org>
Acked-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'include/linux/module.h')
-rw-r--r-- | include/linux/module.h | 36 |
1 files changed, 14 insertions, 22 deletions
diff --git a/include/linux/module.h b/include/linux/module.h index 6cb1a3cab5d3..2302f09ea2d9 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/tracepoint.h> | 18 | #include <linux/tracepoint.h> |
19 | 19 | ||
20 | #include <asm/local.h> | 20 | #include <asm/local.h> |
21 | #include <linux/percpu.h> | ||
21 | #include <asm/module.h> | 22 | #include <asm/module.h> |
22 | 23 | ||
23 | #include <trace/events/module.h> | 24 | #include <trace/events/module.h> |
@@ -363,11 +364,9 @@ struct module | |||
363 | /* Destruction function. */ | 364 | /* Destruction function. */ |
364 | void (*exit)(void); | 365 | void (*exit)(void); |
365 | 366 | ||
366 | #ifdef CONFIG_SMP | 367 | struct module_ref { |
367 | char *refptr; | 368 | int count; |
368 | #else | 369 | } *refptr; |
369 | local_t ref; | ||
370 | #endif | ||
371 | #endif | 370 | #endif |
372 | 371 | ||
373 | #ifdef CONFIG_CONSTRUCTORS | 372 | #ifdef CONFIG_CONSTRUCTORS |
@@ -454,25 +453,16 @@ void __symbol_put(const char *symbol); | |||
454 | #define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x) | 453 | #define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x) |
455 | void symbol_put_addr(void *addr); | 454 | void symbol_put_addr(void *addr); |
456 | 455 | ||
457 | static inline local_t *__module_ref_addr(struct module *mod, int cpu) | ||
458 | { | ||
459 | #ifdef CONFIG_SMP | ||
460 | return (local_t *) (mod->refptr + per_cpu_offset(cpu)); | ||
461 | #else | ||
462 | return &mod->ref; | ||
463 | #endif | ||
464 | } | ||
465 | |||
466 | /* Sometimes we know we already have a refcount, and it's easier not | 456 | /* Sometimes we know we already have a refcount, and it's easier not |
467 | to handle the error case (which only happens with rmmod --wait). */ | 457 | to handle the error case (which only happens with rmmod --wait). */ |
468 | static inline void __module_get(struct module *module) | 458 | static inline void __module_get(struct module *module) |
469 | { | 459 | { |
470 | if (module) { | 460 | if (module) { |
471 | unsigned int cpu = get_cpu(); | 461 | preempt_disable(); |
472 | local_inc(__module_ref_addr(module, cpu)); | 462 | __this_cpu_inc(module->refptr->count); |
473 | trace_module_get(module, _THIS_IP_, | 463 | trace_module_get(module, _THIS_IP_, |
474 | local_read(__module_ref_addr(module, cpu))); | 464 | __this_cpu_read(module->refptr->count)); |
475 | put_cpu(); | 465 | preempt_enable(); |
476 | } | 466 | } |
477 | } | 467 | } |
478 | 468 | ||
@@ -481,15 +471,17 @@ static inline int try_module_get(struct module *module) | |||
481 | int ret = 1; | 471 | int ret = 1; |
482 | 472 | ||
483 | if (module) { | 473 | if (module) { |
484 | unsigned int cpu = get_cpu(); | 474 | preempt_disable(); |
475 | |||
485 | if (likely(module_is_live(module))) { | 476 | if (likely(module_is_live(module))) { |
486 | local_inc(__module_ref_addr(module, cpu)); | 477 | __this_cpu_inc(module->refptr->count); |
487 | trace_module_get(module, _THIS_IP_, | 478 | trace_module_get(module, _THIS_IP_, |
488 | local_read(__module_ref_addr(module, cpu))); | 479 | __this_cpu_read(module->refptr->count)); |
489 | } | 480 | } |
490 | else | 481 | else |
491 | ret = 0; | 482 | ret = 0; |
492 | put_cpu(); | 483 | |
484 | preempt_enable(); | ||
493 | } | 485 | } |
494 | return ret; | 486 | return ret; |
495 | } | 487 | } |