分类: LINUX
2008-09-27 09:54:29
Multiprocessor systems require ensuring serialized execution of critical sections of code that manipulate shared data structures. Various mechanisms for mutual exclusion have been used in traditional Unix kernels including spin locks, semaphores, reader-writer spin locks etc. Even uniprocessor systems require controlled concurrency when critical section code can be executed from both process as well interrupt context. While short-term mutual exclusions like spin locks are simple to use, with the advent of faster cpus and memory interconnect speeds not keeping up with it, cost of acquiring spinning locks is increasing with each generation of architecture. The wider this gap is, more the number of cycles a cpu has to waste spin-waiting for some slow memory interconnect to respond. Therefore, it has become increasingly necessary to look for alternatives to conventional spin-waiting locking models.
Read-Copy Update is one such mutual exclusion method where readers (threads trying to access, but not modify the data) can access the shared data without acquiring any conventional lock. The writers (threads that update the data) however, have to use a special callback scheme to update the data. They update all the global references to the updated data with a new copy and use the callback scheme to free the old copy after all the CPUs have lost local references to it by going through a quiescent state (like a context switch). Because the write-side is significantly expensive compared to the read side, Read-Copy Update mechanism is more suited for scenerios where the data to be protected is read more often than written. For uniprocessor systems, Read-Copy Update mechanism eliminates the need to mask interrupts for mutual exclusion. Read-Copy Update mechanism is thus suitable for mutual exclusion in network routing tables, device state tables, deferred deletion of data structures, multi-path I/O device maintenance etc.
Read-Copy Update was originally designed for DYNIX/ptx, a UNIX operating system from Sequent Computer Systems Inc., now a part of IBM. Similar methods were also used for and OS projects at University of Toronto and IBM Research.
/*
* Structure to queue requests for invoking a callback at after
* all CPUs have gone through a "quiescent" state
*/
struct rcu_head {
struct rcu_head *next;
void (*func)(void *obj);
void *obj;
};
/* Invoke a callback after all CPUs go through a quiescent state */
void call_rcu(struct rcu_head *head, void (*func)(void *arg), void *arg);
/* Wait until all the CPUs go through a quiescent state */
void synchronize_kernel(void);
In this approach of RCU, completion of a quiescent cycle where all CPUs go through a quiescent state is detected by counting and monitoring the quiescent states for all CPUs. Monitoring of the quiescent state counters can be done in various different ways. We have experimented with the following algorithms -
These implementations can be downloaded from .
Rusty is maintaining this patch .
The deferred update mechanism provided by Read-Copy Update can be useful in providing a two phase cleanup logic to solve the race conditions involved in module unloading. The following examples illustrate how RCU can be exploited here -
module_unloading-2.4.2-0.1.patch - Module unloading using
Read-Copy Update for 2.4.2 kernel (Version 01) provides a new cleanup logic.
Readme explaining module unloading using Read-Copy Update.
Test cases for module unloading using Read-Copy Update.
A new framework for module unloading using RCU is being developed by Rusty Russell.
The per-task files_struct can be shared between tasks created using clone() with CLONE_FILES flag set. Due to bouncing of the cache line containing the rwlock in files_struct, such workloads can get slowed significantly, specially in higher-end SMP and NUMA machines. RCU provides a way to do lock-less lookup of file descriptors thereby avoiding this problem completely. Our experiments show that on a benchmark like "chat", the performance improvement can be as high as 30% even on a 4-way system.
The details of the problem and the proposed solution with improved results can be found here. The patch is files_struct_rcu-2.4.13pre5-06.patch.
The patches for lock-less route cache lookup can be downloaded from the .