Messages in this thread | | | From | David Woodhouse <> | Subject | Re: recalc_sigpending() / recalc_sigpending_tsk() ? | Date | Fri, 01 Mar 2002 17:05:06 +0000 |
| |
torvalds@transmeta.com said: > So the basic rule should be: drivers etc should not ever have to > touch "sigmask_lock", because they simply should never even _know_ > about things like that. Agreed?
Absolutely.
> So I would suggest solving this problem by just adding something like > /* Block all signals except for mask */ > void sigallow(unsigned long mask) > { > spin_lock_irq(¤t->sigmask_lock); > siginitsetinv(current->blocked, mask); > recalc_sigpending(); > spin_unlock_irq(¤t->sigmask_lock); > }
Now that I like. Especially if coupled with the equivalent for dequeuing a signal with implicit locking too, so I really can drop all references to current->sigmask_lock -- the JFFS2 garbage collection thread dequeues signals and deals as you might expect with SIGSTOP/SIGKILL:
for (;;) { spin_lock_irq(¤t->sigmask_lock); siginitsetinv (¤t->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock);
if (!thread_should_wake(c)) { set_current_state (TASK_INTERRUPTIBLE); D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); /* Yes, there's a race here; we checked thread_should_wake() before setting current->state to TASK_INTERRUPTIBLE. But it doesn't matter - We don't care if we miss a wakeup, because the GC thread is only an optimisation anyway. */ schedule(); } cond_resched();
/* Put_super will send a SIGKILL and then wait on the sem. */ while (signal_pending(current)) { siginfo_t info; unsigned long signr;
spin_lock_irq(¤t->sigmask_lock); signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock);
switch(signr) { case SIGSTOP: D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGSTOP received.\n")); set_current_state(TASK_STOPPED); schedule(); break;
case SIGKILL: D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGKILL received.\n")); spin_lock_bh(&c->erase_completion_lock); c->gc_task = NULL; spin_unlock_bh(&c->erase_completion_lock); complete_and_exit(&c->gc_thread_exit, 0);
case SIGHUP: D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGHUP received.\n")); break; default: D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): signal %ld received\n", signr));
} } /* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */ spin_lock_irq(¤t->sigmask_lock); siginitsetinv (¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock);
D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): pass\n")); jffs2_garbage_collect_pass(c); }
-- dwmw2
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |