From 7777d006d3c38a0bbb254e35d96cf8f2b9f925a2 Mon Sep 17 00:00:00 2001 From: John Levon Date: Fri, 4 Apr 2003 04:12:09 -0800 Subject: [PATCH] bk - fix oprofile for pm driver register OK, so I screwed up - didn't notice the late_initcall() that was introduced, which was obviously bogus. This one should build OK for the module case. I've tested insmod/rmmod alongside a mounted sysfs. I think the built-in case is OK: oprofile/ is after kernel/ in the link order. I tested that too. --- include/linux/oprofile.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h index 5d906c21103f..6dba9058bca0 100644 --- a/include/linux/oprofile.h +++ b/include/linux/oprofile.h @@ -45,6 +45,11 @@ struct oprofile_operations { */ int oprofile_arch_init(struct oprofile_operations ** ops); +/** + * One-time exit/cleanup for the arch. + */ +void oprofile_arch_exit(void); + /** * Add a sample. This may be called from any context. Pass * smp_processor_id() as cpu. -- cgit v1.2.3 From da334d91ff7001d234863fc7692de1ff90bed57a Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 4 Apr 2003 04:12:17 -0800 Subject: [PATCH] linux-2.5.66-signal-cleanup.patch Here is the cleanup patch I promised back in February. Sorry it took a while. The effects should be purely cosmetic in 2.5.66. However, the new interface for the proper way to send thread-specific of process-global signals from inside the kernel is needed for correct implementation of some fixes to timer stuff that Ulrich told me about. This cleans up some obsolete comments and macros in kernel/signal.c, restores send_sig_info to its original behavior, and adds a global entry point send_group_sig_info. I checked all the uses of send_sig and send_sig_info and changed a few to send_group_sig_info. I think it would be cleanest if the whole mess of *_sig* entry points were reduced to two or three, but I did the change that minimized the number of callers I had to fix up. There should be no discernible difference, since the 2.5.66 send_sig_info function did group semantics for those signals by number already. The only exception to that is pdeath_signal, which I guess can be any signal number but I deemed ought to be process-wide. I did not change any of the calls using SIGKILL, though that does have process-wide semantics. There is no need to change it since SIGKILL always kills the whole group, though the code path for send_sig(SIGKILL,...) calls in multithreaded processes will be different now. --- drivers/char/tty_io.c | 4 +- drivers/isdn/i4l/isdn_tty.c | 2 +- fs/fcntl.c | 4 +- include/linux/sched.h | 6 ++ kernel/exit.c | 2 +- kernel/itimer.c | 2 +- kernel/signal.c | 171 ++++++++++++++++++++++++-------------------- 7 files changed, 106 insertions(+), 85 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f3c2f35381ac..c57b097ac389 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -506,8 +506,8 @@ void do_tty_hangup(void *data) p->tty = NULL; if (!p->leader) continue; - send_sig(SIGHUP, p, 1); - send_sig(SIGCONT, p, 1); + send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p); + send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p); if (tty->pgrp > 0) p->tty_old_pgrp = tty->pgrp; } diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index dd58066f7386..0053c471fb16 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -2036,7 +2036,7 @@ modem_write_profile(atemu * m) memcpy(m->pmsn, m->msn, ISDN_MSNLEN); memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN); if (dev->profd) - send_sig(SIGIO, dev->profd, 1); + group_send_sig_info(SIGIO, SEND_SIG_PRIV, dev->profd); } int diff --git a/fs/fcntl.c b/fs/fcntl.c index fae2022ada19..f1bf41ec99a5 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -465,7 +465,7 @@ static void send_sigio_to_task(struct task_struct *p, break; /* fall-through: fall back on the old plain SIGIO signal */ case 0: - send_sig(SIGIO, p, 1); + send_group_sig_info(SIGIO, SEND_SIG_PRIV, p); } } @@ -501,7 +501,7 @@ static void send_sigurg_to_task(struct task_struct *p, struct fown_struct *fown) { if (sigio_perm(p, fown)) - send_sig(SIGURG, p, 1); + send_group_sig_info(SIGURG, SEND_SIG_PRIV, p); } int send_sigurg(struct fown_struct *fown) diff --git a/include/linux/sched.h b/include/linux/sched.h index d001088e58b3..f3b4c5891898 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -541,6 +541,7 @@ extern void block_all_signals(int (*notifier)(void *priv), void *priv, extern void unblock_all_signals(void); extern void release_task(struct task_struct * p); extern int send_sig_info(int, struct siginfo *, struct task_struct *); +extern int send_group_sig_info(int, struct siginfo *, struct task_struct *); extern int force_sig_info(int, struct siginfo *, struct task_struct *); extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp); extern int kill_pg_info(int, struct siginfo *, pid_t); @@ -558,6 +559,11 @@ extern int kill_proc(pid_t, int, int); extern int do_sigaction(int, const struct k_sigaction *, struct k_sigaction *); extern int do_sigaltstack(const stack_t *, stack_t *, unsigned long); +/* These can be the second arg to send_sig_info/send_group_sig_info. */ +#define SEND_SIG_NOINFO ((struct siginfo *) 0) +#define SEND_SIG_PRIV ((struct siginfo *) 1) +#define SEND_SIG_FORCED ((struct siginfo *) 2) + /* True if we are on the alternate signal stack. */ static inline int on_sig_stack(unsigned long sp) diff --git a/kernel/exit.c b/kernel/exit.c index ffc0973ab074..b393a46247c4 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -488,7 +488,7 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) p->self_exec_id++; if (p->pdeath_signal) - send_sig(p->pdeath_signal, p, 0); + send_group_sig_info(p->pdeath_signal, 0, p); /* Move the child from its dying parent to the new one. */ if (unlikely(traced)) { diff --git a/kernel/itimer.c b/kernel/itimer.c index 4fc29f3de5e8..4db3b24ec41e 100644 --- a/kernel/itimer.c +++ b/kernel/itimer.c @@ -67,7 +67,7 @@ void it_real_fn(unsigned long __data) struct task_struct * p = (struct task_struct *) __data; unsigned long interval; - send_sig(SIGALRM, p, 1); + send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p); interval = p->it_real_incr; if (interval) { if (interval > (unsigned long) LONG_MAX) diff --git a/kernel/signal.c b/kernel/signal.c index 488134eec0e2..096d58ad5237 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -33,64 +33,79 @@ static kmem_cache_t *sigqueue_cachep; atomic_t nr_queued_signals; int max_queued_signals = 1024; -/********************************************************* - - POSIX thread group signal behavior: - ----------------------------------------------------------- -| | userspace | kernel | ----------------------------------------------------------- -| SIGHUP | load-balance | kill-all | -| SIGINT | load-balance | kill-all | -| SIGQUIT | load-balance | kill-all+core | -| SIGILL | specific | kill-all+core | -| SIGTRAP | specific | kill-all+core | -| SIGABRT/SIGIOT | specific | kill-all+core | -| SIGBUS | specific | kill-all+core | -| SIGFPE | specific | kill-all+core | -| SIGKILL | n/a | kill-all | -| SIGUSR1 | load-balance | kill-all | -| SIGSEGV | specific | kill-all+core | -| SIGUSR2 | load-balance | kill-all | -| SIGPIPE | specific | kill-all | -| SIGALRM | load-balance | kill-all | -| SIGTERM | load-balance | kill-all | -| SIGCHLD | load-balance | ignore | -| SIGCONT | load-balance | ignore | -| SIGSTOP | n/a | stop-all | -| SIGTSTP | load-balance | stop-all | -| SIGTTIN | load-balance | stop-all | -| SIGTTOU | load-balance | stop-all | -| SIGURG | load-balance | ignore | -| SIGXCPU | specific | kill-all+core | -| SIGXFSZ | specific | kill-all+core | -| SIGVTALRM | load-balance | kill-all | -| SIGPROF | specific | kill-all | -| SIGPOLL/SIGIO | load-balance | kill-all | -| SIGSYS/SIGUNUSED | specific | kill-all+core | -| SIGSTKFLT | specific | kill-all | -| SIGWINCH | load-balance | ignore | -| SIGPWR | load-balance | kill-all | -| SIGRTMIN-SIGRTMAX | load-balance | kill-all | ----------------------------------------------------------- - - non-POSIX signal thread group behavior: - ----------------------------------------------------------- -| | userspace | kernel | ----------------------------------------------------------- -| SIGEMT | specific | kill-all+core | ----------------------------------------------------------- -*/ - -/* Some systems do not have a SIGSTKFLT and the kernel never - * generates such signals anyways. +/* + * In POSIX a signal is sent either to a specific thread (Linux task) + * or to the process as a whole (Linux thread group). How the signal + * is sent determines whether it's to one thread or the whole group, + * which determines which signal mask(s) are involved in blocking it + * from being delivered until later. When the signal is delivered, + * either it's caught or ignored by a user handler or it has a default + * effect that applies to the whole thread group (POSIX process). + * + * The possible effects an unblocked signal set to SIG_DFL can have are: + * ignore - Nothing Happens + * terminate - kill the process, i.e. all threads in the group, + * similar to exit_group. The group leader (only) reports + * WIFSIGNALED status to its parent. + * coredump - write a core dump file describing all threads using + * the same mm and then kill all those threads + * stop - stop all the threads in the group, i.e. TASK_STOPPED state + * + * SIGKILL and SIGSTOP cannot be caught, blocked, or ignored. + * Other signals when not blocked and set to SIG_DFL behaves as follows. + * The job control signals also have other special effects. + * + * +--------------------+------------------+ + * | POSIX signal | default action | + * +--------------------+------------------+ + * | SIGHUP | terminate | + * | SIGINT | terminate | + * | SIGQUIT | coredump | + * | SIGILL | coredump | + * | SIGTRAP | coredump | + * | SIGABRT/SIGIOT | coredump | + * | SIGBUS | coredump | + * | SIGFPE | coredump | + * | SIGKILL | terminate(+) | + * | SIGUSR1 | terminate | + * | SIGSEGV | coredump | + * | SIGUSR2 | terminate | + * | SIGPIPE | terminate | + * | SIGALRM | terminate | + * | SIGTERM | terminate | + * | SIGCHLD | ignore | + * | SIGCONT | ignore(*) | + * | SIGSTOP | stop(*)(+) | + * | SIGTSTP | stop(*) | + * | SIGTTIN | stop(*) | + * | SIGTTOU | stop(*) | + * | SIGURG | ignore | + * | SIGXCPU | coredump | + * | SIGXFSZ | coredump | + * | SIGVTALRM | terminate | + * | SIGPROF | terminate | + * | SIGPOLL/SIGIO | terminate | + * | SIGSYS/SIGUNUSED | coredump | + * | SIGSTKFLT | terminate | + * | SIGWINCH | ignore | + * | SIGPWR | terminate | + * | SIGRTMIN-SIGRTMAX | terminate | + * +--------------------+------------------+ + * | non-POSIX signal | default action | + * +--------------------+------------------+ + * | SIGEMT | coredump | + * +--------------------+------------------+ + * + * (+) For SIGKILL and SIGSTOP the action is "always", not just "default". + * (*) Special job control effects: + * When SIGCONT is sent, it resumes the process (all threads in the group) + * from TASK_STOPPED state and also clears any pending/queued stop signals + * (any of those marked with "stop(*)"). This happens regardless of blocking, + * catching, or ignoring SIGCONT. When any stop signal is sent, it clears + * any pending/queued SIGCONT signals; this happens regardless of blocking, + * catching, or ignored the stop signal, though (except for SIGSTOP) the + * default action of stopping the process may happen later or never. */ -#ifdef SIGSTKFLT -#define M_SIGSTKFLT M(SIGSTKFLT) -#else -#define M_SIGSTKFLT 0 -#endif #ifdef SIGEMT #define M_SIGEMT M(SIGEMT) @@ -105,16 +120,6 @@ int max_queued_signals = 1024; #endif #define T(sig, mask) (M(sig) & (mask)) -#define SIG_KERNEL_BROADCAST_MASK (\ - M(SIGHUP) | M(SIGINT) | M(SIGQUIT) | M(SIGILL) | \ - M(SIGTRAP) | M(SIGABRT) | M(SIGBUS) | M(SIGFPE) | \ - M(SIGKILL) | M(SIGUSR1) | M(SIGSEGV) | M(SIGUSR2) | \ - M(SIGPIPE) | M(SIGALRM) | M(SIGTERM) | M(SIGXCPU) | \ - M(SIGXFSZ) | M(SIGVTALRM) | M(SIGPROF) | M(SIGPOLL) | \ - M(SIGSYS) | M_SIGSTKFLT | M(SIGPWR) | M(SIGCONT) | \ - M(SIGSTOP) | M(SIGTSTP) | M(SIGTTIN) | M(SIGTTOU) | \ - M_SIGEMT ) - #define SIG_KERNEL_ONLY_MASK (\ M(SIGKILL) | M(SIGSTOP) ) @@ -599,7 +604,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent); /* - * Handle magic process-wide effects of stop/continue signals, and SIGKILL. + * Handle magic process-wide effects of stop/continue signals. * Unlike the signal actions, these happen immediately at signal-generation * time regardless of blocking, ignoring, or handling. This does the * actual continuing for SIGCONT, but not the actual stopping for stop @@ -1134,9 +1139,8 @@ static int kill_something_info(int sig, struct siginfo *info, int pid) */ /* - * XXX should probably nix these interfaces and update the kernel - * to specify explicitly whether the signal is a group signal or - * specific to a thread. + * These two are the most common entry points. They send a signal + * just to the specific thread. */ int send_sig_info(int sig, struct siginfo *info, struct task_struct *p) @@ -1150,13 +1154,9 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p) * going away or changing from under us. */ read_lock(&tasklist_lock); - if (T(sig, SIG_KERNEL_BROADCAST_MASK)) { - ret = group_send_sig_info(sig, info, p); - } else { - spin_lock_irq(&p->sighand->siglock); - ret = specific_send_sig_info(sig, info, p); - spin_unlock_irq(&p->sighand->siglock); - } + spin_lock_irq(&p->sighand->siglock); + ret = specific_send_sig_info(sig, info, p); + spin_unlock_irq(&p->sighand->siglock); read_unlock(&tasklist_lock); return ret; } @@ -1167,6 +1167,20 @@ send_sig(int sig, struct task_struct *p, int priv) return send_sig_info(sig, (void*)(long)(priv != 0), p); } +/* + * This is the entry point for "process-wide" signals. + * They will go to an appropriate thread in the thread group. + */ +int +send_group_sig_info(int sig, struct siginfo *info, struct task_struct *p) +{ + int ret; + read_lock(&tasklist_lock); + ret = group_send_sig_info(sig, info, p); + read_unlock(&tasklist_lock); + return ret; +} + void force_sig(int sig, struct task_struct *p) { @@ -1642,6 +1656,7 @@ EXPORT_SYMBOL(kill_sl_info); EXPORT_SYMBOL(notify_parent); EXPORT_SYMBOL(send_sig); EXPORT_SYMBOL(send_sig_info); +EXPORT_SYMBOL(send_group_sig_info); EXPORT_SYMBOL(sigprocmask); EXPORT_SYMBOL(block_all_signals); EXPORT_SYMBOL(unblock_all_signals); -- cgit v1.2.3