Before we conclude this section, there's one more interesting point to take into consideration: the kernel provides an IRQ allocation API that, based on certain circumstances, will either set up your interrupt handler as a traditional hardirq handler or as a threaded handler. This API is called request_any_context_irq(); note that it's exported as GPL-only though. Its signature is as follows:
int __must_check
request_any_context_irq(unsigned int irq, irq_handler_t handler,
unsigned long flags, const char *name, void *dev_id);
The parameters are identical to that of request_irq(). When invoked, this routine will decide whether the interrupt handler function – the  handler parameter – will run in an atomic hardirq context or in a sleep-capable process context, that of a kernel thread – in other words, as a threaded handler. How will you know which context handler() will run...