Process context: Pode fazer: current copy_to_user copy_from_user GFP_KERNEL Onde: contexto de processo (chamada de sistema) workqueue NOTA: work da wq executa em uma kthread e pode fazer copy_to_user e copy_from_user, segundo esse comentário em kernel/kmod.c: /* * Normally it is bogus to call wait4() from in-kernel because * wait4() wants to write the exit code to a userspace address. * But wait_for_helper() always runs as keventd, and put_user() * to a kernel address works OK for kernel threads, due to their * having an mm_segment_t which spans the entire address space. * * Thus the __user pointer cast is valid here. */ Atomic context: Pode fazer: GFP_ATOMIC Não pode fazer: copy_{to,from}_user GFP_KERNEL "dormir" schedule mutex wait Onde: interrupção spinlock timers tasklet NOTES: scalable SMP: that's what's important (for most people, anyway) BKL: not scalable Bottom Half: after handling interrupts, Linux executes the bottom half (TODO: Check this) Bottom Halves were "single-threaded": only one bottom half could execute at a time (only one or only one NET_BH?). UPDATE: only one. tasklets allow a single tasklet to run on only one CPU at a time. But other tasklets may run on other CPUs. Bottom Half now is softirq and tasklet (which is a softirq itself). spin_lock_irqsave Disables interrupts in the local CPU Why? Explanation: CPU 1 grabs spinlock, CPU 1 is interrupted and handler grabs same spinlock: spins forever (code will not migrate? TODO). Second scenario: CPU 2 is interrupted and grabs the same lock, CPU 1 has the chance to release the lock and CPU 2 will go on. spin_lock_bh If used only in process context and BHs local_irq_disable() or local_irq_save(flags) It's enough when data is per-CPU. That is, there will not be concurrency between CPUs, but only between interrupt handler and process code. CPU affinity: softirq runs on the same CPU it was raised on. -- CONFIG_DEBUG_PREEMPT Preemption. preempt_disable - disable preemption in current CPU TODO: check "current" preempt_enable - enable preemption in current CPU -- SMP Trabalhando com CPUs. smp_processor_id() retorna ID do processador corrente: só pode ser utilizado se a tarefa estiver amarrada a um processador ou em um contexto não preemptível (preempt off) get_cpu - desabilita preempção e retorna ID da CPU put_cpu - reabilita preempção Referências: "I'll Do It Later: Softirqs, Tasklets, Bottom Halves, Task Queues, Work Queues and Timers" by Matthew Wilcox TODO: Zoombie Defunct Uninterruptible Unkillable