This diff reduces IPI traffic for a case when process A is sending a lot of signals to process B running on a different CPU. userret() delivers all process signals at once, so there is no need to send an interrupt for every signal.
The problem was noticed by rtorrent 0.9.2 users, which does exactly this, which led to process/system hangs and slowness. Tested and known to help on amd64 by me and dcoppa@. Index: amd64/amd64/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/machdep.c,v retrieving revision 1.155 diff -u -r1.155 machdep.c --- amd64/amd64/machdep.c 4 Jun 2012 15:19:47 -0000 1.155 +++ amd64/amd64/machdep.c 23 Jul 2012 13:49:40 -0000 @@ -690,8 +690,10 @@ void signotify(struct proc *p) { - aston(p); - cpu_unidle(p->p_cpu); + if (!isastset(p)) { + aston(p); + cpu_unidle(p->p_cpu); + } } #ifdef MULTIPROCESSOR Index: amd64/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/amd64/include/cpu.h,v retrieving revision 1.73 diff -u -r1.73 cpu.h --- amd64/include/cpu.h 17 Apr 2012 16:02:33 -0000 1.73 +++ amd64/include/cpu.h 23 Jul 2012 13:49:40 -0000 @@ -213,6 +213,7 @@ #endif #define aston(p) ((p)->p_md.md_astpending = 1) +#define isastset(p) ((p)->p_md.md_astpending == 1) #define curpcb curcpu()->ci_curpcb Index: hppa/hppa/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/hppa/hppa/machdep.c,v retrieving revision 1.206 diff -u -r1.206 machdep.c --- hppa/hppa/machdep.c 21 Jun 2012 00:56:59 -0000 1.206 +++ hppa/hppa/machdep.c 23 Jul 2012 13:49:40 -0000 @@ -1399,8 +1399,10 @@ void signotify(struct proc *p) { - setsoftast(p); - cpu_unidle(p->p_cpu); + if (!isastset(p)) { + setsoftast(p); + cpu_unidle(p->p_cpu); + } } /* Index: hppa/include/intr.h =================================================================== RCS file: /cvs/src/sys/arch/hppa/include/intr.h,v retrieving revision 1.37 diff -u -r1.37 intr.h --- hppa/include/intr.h 14 Jan 2011 13:20:06 -0000 1.37 +++ hppa/include/intr.h 23 Jul 2012 13:49:40 -0000 @@ -157,7 +157,8 @@ int hppa_ipi_broadcast(u_long); #endif -#define setsoftast(p) (p->p_md.md_astpending = 1) +#define setsoftast(p) ((p)->p_md.md_astpending = 1) +#define isastset(p) ((p)->p_md.md_astpending == 1) void *softintr_establish(int, void (*)(void *), void *); void softintr_disestablish(void *); Index: i386/i386/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/i386/i386/machdep.c,v retrieving revision 1.510 diff -u -r1.510 machdep.c --- i386/i386/machdep.c 23 May 2012 08:23:43 -0000 1.510 +++ i386/i386/machdep.c 23 Jul 2012 13:49:40 -0000 @@ -2420,8 +2420,10 @@ void signotify(struct proc *p) { - aston(p); - cpu_unidle(p->p_cpu); + if (!isastset(p)) { + aston(p); + cpu_unidle(p->p_cpu); + } } #ifdef MULTIPROCESSOR Index: i386/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/i386/include/cpu.h,v retrieving revision 1.122 diff -u -r1.122 cpu.h --- i386/include/cpu.h 27 Mar 2012 06:44:01 -0000 1.122 +++ i386/include/cpu.h 23 Jul 2012 13:49:41 -0000 @@ -226,6 +226,7 @@ #endif #define aston(p) ((p)->p_md.md_astpending = 1) +#define isastset(p) ((p)->p_md.md_astpending == 1) #define curpcb curcpu()->ci_curpcb Index: m88k/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/m88k/include/cpu.h,v retrieving revision 1.54 diff -u -r1.54 cpu.h --- m88k/include/cpu.h 25 Oct 2011 18:38:06 -0000 1.54 +++ m88k/include/cpu.h 23 Jul 2012 13:49:41 -0000 @@ -256,6 +256,7 @@ (((struct cpu_info *)(framep)->tf.tf_cpu)->ci_intrdepth > 1) #define aston(p) ((p)->p_md.md_astpending = 1) +#define isastset(p) ((p)->p_md.md_astpending == 1) /* * This is used during profiling to integrate system time. Index: m88k/m88k/m88k_machdep.c =================================================================== RCS file: /cvs/src/sys/arch/m88k/m88k/m88k_machdep.c,v retrieving revision 1.52 diff -u -r1.52 m88k_machdep.c --- m88k/m88k/m88k_machdep.c 23 Mar 2012 15:51:26 -0000 1.52 +++ m88k/m88k/m88k_machdep.c 23 Jul 2012 13:49:41 -0000 @@ -314,8 +314,10 @@ void signotify(struct proc *p) { - aston(p); - cpu_unidle(p->p_cpu); + if (!isastset(p)) { + aston(p); + cpu_unidle(p->p_cpu); + } } #ifdef MULTIPROCESSOR Index: macppc/macppc/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/macppc/macppc/machdep.c,v retrieving revision 1.131 diff -u -r1.131 machdep.c --- macppc/macppc/machdep.c 29 Aug 2011 20:21:44 -0000 1.131 +++ macppc/macppc/machdep.c 23 Jul 2012 13:49:41 -0000 @@ -935,8 +935,10 @@ void signotify(struct proc *p) { - aston(p); - cpu_unidle(p->p_cpu); + if (!isastset(p)) { + aston(p); + cpu_unidle(p->p_cpu); + } } #ifdef MULTIPROCESSOR Index: mips64/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/mips64/include/cpu.h,v retrieving revision 1.83 diff -u -r1.83 cpu.h --- mips64/include/cpu.h 14 Jul 2012 19:50:11 -0000 1.83 +++ mips64/include/cpu.h 23 Jul 2012 13:49:41 -0000 @@ -511,12 +511,20 @@ * process as soon as possible. */ #ifdef MULTIPROCESSOR -#define signotify(p) (aston(p), cpu_unidle(p->p_cpu)) +static __inline void +signotify(struct proc *p) +{ + if (!isastset(p)) { + aston(p); + cpu_unidle(p->p_cpu); + } +} #else #define signotify(p) aston(p) #endif -#define aston(p) p->p_md.md_astpending = 1 +#define aston(p) ((p)->p_md.md_astpending = 1) +#define isastset(p) ((p)->p_md.md_astpending == 1) #endif /* _KERNEL && !_LOCORE */ Index: powerpc/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/powerpc/include/cpu.h,v retrieving revision 1.46 diff -u -r1.46 cpu.h --- powerpc/include/cpu.h 28 Sep 2010 20:27:55 -0000 1.46 +++ powerpc/include/cpu.h 23 Jul 2012 13:49:41 -0000 @@ -155,6 +155,7 @@ #define DELAY(n) delay(n) #define aston(p) ((p)->p_md.md_astpending = 1) +#define isastset(p) ((p)->p_md.md_astpending == 1) /* * Preempt the current process if in interrupt from user mode, Index: sparc64/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/sparc64/include/cpu.h,v retrieving revision 1.78 diff -u -r1.78 cpu.h --- sparc64/include/cpu.h 6 Jul 2011 22:26:44 -0000 1.78 +++ sparc64/include/cpu.h 23 Jul 2012 13:49:41 -0000 @@ -226,7 +226,7 @@ extern void (*cpu_start_clock)(void); #define aston(p) ((p)->p_md.md_astpending = 1) - +#define isastset(p) ((p)->p_md.md_astpending == 1) /* * Preempt the current process if in interrupt from user mode, * or after the current trap/syscall if in system mode. Index: sparc64/sparc64/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/sparc64/sparc64/machdep.c,v retrieving revision 1.138 diff -u -r1.138 machdep.c --- sparc64/sparc64/machdep.c 9 May 2012 18:34:21 -0000 1.138 +++ sparc64/sparc64/machdep.c 23 Jul 2012 13:49:42 -0000 @@ -613,8 +613,10 @@ void signotify(struct proc *p) { - aston(p); - cpu_unidle(p->p_cpu); + if (!isastset(p)) { + aston(p); + cpu_unidle(p->p_cpu); + } } int waittime = -1;