aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/kprobes.c
diff options
context:
space:
mode:
authorAnanth N Mavinakayanahalli <ananth@in.ibm.com>2005-11-07 04:00:07 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 10:53:45 -0500
commit66ff2d0691e00e1e7bfdf398a970310c9a0fe671 (patch)
treef53bcd846be8fbaee5a5ee65f9bacc5b34392090 /arch/ia64/kernel/kprobes.c
parentb385676b355549afc9a7507ce09c7df47f166521 (diff)
[PATCH] Kprobes: rearrange preempt_disable/enable() calls
The following set of patches are aimed at improving kprobes scalability. We currently serialize kprobe registration, unregistration and handler execution using a single spinlock - kprobe_lock. With these changes, kprobe handlers can run without any locks held. It also allows for simultaneous kprobe handler executions on different processors as we now track kprobe execution on a per processor basis. It is now necessary that the handlers be re-entrant since handlers can run concurrently on multiple processors. All changes have been tested on i386, ia64, ppc64 and x86_64, while sparc64 has been compile tested only. The patches can be viewed as 3 logical chunks: patch 1: Reorder preempt_(dis/en)able calls patches 2-7: Introduce per_cpu data areas to track kprobe execution patches 8-9: Use RCU to synchronize kprobe (un)registration and handler execution. Thanks to Maneesh Soni, James Keniston and Anil Keshavamurthy for their review and suggestions. Thanks again to Anil, Hien Nguyen and Kevin Stafford for testing the patches. This patch: Reorder preempt_disable/enable() calls in arch kprobes files in preparation to introduce locking changes. No functional changes introduced by this patch. Signed-off-by: Ananth N Mavinakayahanalli <ananth@in.ibm.com> Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ia64/kernel/kprobes.c')
-rw-r--r--arch/ia64/kernel/kprobes.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 471086b808a4..1e80ec80dd21 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -395,7 +395,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
395 /* 395 /*
396 * By returning a non-zero value, we are telling 396 * By returning a non-zero value, we are telling
397 * kprobe_handler() that we have handled unlocking 397 * kprobe_handler() that we have handled unlocking
398 * and re-enabling preemption. 398 * and re-enabling preemption
399 */ 399 */
400 return 1; 400 return 1;
401} 401}
@@ -607,8 +607,6 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
607 struct pt_regs *regs = args->regs; 607 struct pt_regs *regs = args->regs;
608 kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); 608 kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
609 609
610 preempt_disable();
611
612 /* Handle recursion cases */ 610 /* Handle recursion cases */
613 if (kprobe_running()) { 611 if (kprobe_running()) {
614 p = get_kprobe(addr); 612 p = get_kprobe(addr);
@@ -665,6 +663,11 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
665 goto no_kprobe; 663 goto no_kprobe;
666 } 664 }
667 665
666 /*
667 * This preempt_disable() matches the preempt_enable_no_resched()
668 * in post_kprobes_handler()
669 */
670 preempt_disable();
668 kprobe_status = KPROBE_HIT_ACTIVE; 671 kprobe_status = KPROBE_HIT_ACTIVE;
669 set_current_kprobe(p); 672 set_current_kprobe(p);
670 673
@@ -682,7 +685,6 @@ ss_probe:
682 return 1; 685 return 1;
683 686
684no_kprobe: 687no_kprobe:
685 preempt_enable_no_resched();
686 return ret; 688 return ret;
687} 689}
688 690
@@ -733,22 +735,26 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
733 unsigned long val, void *data) 735 unsigned long val, void *data)
734{ 736{
735 struct die_args *args = (struct die_args *)data; 737 struct die_args *args = (struct die_args *)data;
738 int ret = NOTIFY_DONE;
739
740 preempt_disable();
736 switch(val) { 741 switch(val) {
737 case DIE_BREAK: 742 case DIE_BREAK:
738 if (pre_kprobes_handler(args)) 743 if (pre_kprobes_handler(args))
739 return NOTIFY_STOP; 744 ret = NOTIFY_STOP;
740 break; 745 break;
741 case DIE_SS: 746 case DIE_SS:
742 if (post_kprobes_handler(args->regs)) 747 if (post_kprobes_handler(args->regs))
743 return NOTIFY_STOP; 748 ret = NOTIFY_STOP;
744 break; 749 break;
745 case DIE_PAGE_FAULT: 750 case DIE_PAGE_FAULT:
746 if (kprobes_fault_handler(args->regs, args->trapnr)) 751 if (kprobes_fault_handler(args->regs, args->trapnr))
747 return NOTIFY_STOP; 752 ret = NOTIFY_STOP;
748 default: 753 default:
749 break; 754 break;
750 } 755 }
751 return NOTIFY_DONE; 756 preempt_enable();
757 return ret;
752} 758}
753 759
754int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) 760int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)