I'm a bit confused as to what constitutes an interrupt in the Linux kernel. From what I understand, spin_lock_irqsave() / spin_lock_irqrestore() ensure that my critical section won't be preempted by an interrupt handler. Fair enough.
But I'm a bit confused by what constitutes an interrupt handler. First, I'm not 100% sure that I'm also protected from preemption from softirqs. Is this the case?
What about exceptions? From what I understand, they're the same thing as interrupts, but not really. Am I protected from preemption by a page fault handler when I use spin_lock_irqsave() for instance? What precisely happens when a page fault occurs, is the mechanism used to handle them the exact same thing as interrupts?
What about signal handlers? I don't get how those are implemented. What if I send a signal a SIGTERM, SIGINT, or SIGKILL signal? Is this implemented with a soft IRQ? something else? Can such a signal preempt my critical section when I use spin_lock_irqsave()? Or not at all because those signals are handled exclusively in user space?
What about calls to schedule()? Can those preempt me at any time, even in my critical sections when I use spin_lock_irqsave()?
I guess what I'd really like to know is what exactly can preempt me when I use spin_lock_irqsave(). Nobody who uses the same lock as me, and no interrupt handlers, for sure. What about all these other things? What about softirqs/tasklets/work queues?
Finally, is spin_lock_irqsave() stronger than spin_lock_bh()? I.e., does spin_lock_irqsave() prevent preemption from bottom halves (i.e., softirqs, tasklets, and work queues)?
I've been Googling all of this quite a bit, but I find it hard to find clear answers.