Sunday 22 February 2009

spin lock variations...

spin_lock_irqsave(spinlock_t *lock, unsigned long flags);

Disables interrupts on the local processor and stores the current interrupt state in flags. Note that all of the spinlock primitives are defined as macros, and that the flags argument is passed directly, not as a pointer.

spin_lock_irq(spinlock_t *lock);

Acts like spin_lock_irqsave, except that it does not save the current interrupt state. This version is slightly more efficient than spin_lock_irqsave, but it should only be used in situations in which you know that interrupts will not have already been disabled.

spin_lock_bh(spinlock_t *lock);

Obtains the given lock and prevents the execution of bottom halves.

spin_unlock(spinlock_t *lock);
spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
spin_unlock_irq(spinlock_t *lock);
spin_unlock_bh(spinlock_t *lock);

These functions are the counterparts of the various locking primitives described previously. spin_unlock unlocks the given lock and nothing else. spin_unlock_irqrestore possibly enables interrupts, depending on the flags value (which should have come from spin_lock_irqsave). spin_unlock_irq enables interrupts unconditionally, and spin_unlock_bh reenables bottom-half processing. In each case, your function should be in possession of the lock before calling one of the unlocking primitives, or serious disorder will result.

spin_is_locked(spinlock_t *lock);
spin_trylock(spinlock_t *lock)
spin_unlock_wait(spinlock_t *lock);

spin_is_locked queries the state of a spinlock without changing it. It returns nonzero if the lock is currently busy. To attempt to acquire a lock without waiting, use spin_trylock, which returns nonzero if the operation failed (the lock was busy). spin_unlock_wait waits until the lock becomes free, but does not take possession of it.


A table for locking among different contexts:
http://www.kernel.org/pub/linux/kernel/people/rusty/kernel-locking/c214.html

Thursday 19 February 2009

tcp_sock.ucopy always clean in BLCR checkpoint

extremely fortunate: while BLCR's checkpoint signal handler is executed tcp_sock's fasthpath is surely not in action and the ucopy field is clear. tcp_recvmsg() breaks the main loop (with -ERESTARTSYS) in case of signal_pending(), but ucopy is cleaned up first. As a consqeuence, during cr_restart we can simply reinject packages by calling ip_rcv_finish() on each, tcp_recvmsg() will be reexecuted and it will process the queues properly.

on netfilter's NF_QUEUE verdict..

Installing a netfilter hook that returns NF_QUEUE on certain packets will cause the kernel to find a nf_queue_handler and call it with the given packet. If no handler is installed tha packet is discarded. A handler can be registered with the nf_register_queue_handler(). (ip_queue module uses this for expose the packets to userspace.) After your queue handler is done, you are supposed to insert it back to the network stack by calling nf_reinject().