123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- Kamailio locking interface
- ============================
- 1. Why use it?
- --------------
- The main reason for creating it was to have a single transparent interface to various locking methods.
- For example right now Kamailio uses the following locking methods, depending on their availability on the
- target system:
- FAST_LOCK - fast inline assembly locks, defined in fast_lock.h. They are currently available for
- x86, x86_64, sparc, sparc64, arm , armv6 (no smp mode supported yet), ppc, ppc64, mips, mips64
- and alpha . In general if the assembly code exists for a given arhitecture and the compiler
- knows inline assembly (for example sun cc does not) FAST_LOCK is prefered. The main
- advantage of using FAST_LOCK is very low memory overhead and extremely fast lock/unlock
- operations (like 20 times faster then SYSV semaphores on linux & 40 times on solaris).
- The only thing that comes close to them are pthread mutexes (which are about 3-4 times slower).
- PTHREAD_MUTEX - uses pthread_mutex_lock/unlock. They are quite fast but they work between
- processes only on some systems (they do not work on linux).
- POSIX_SEM - uses posix semaphores (sem_wait/sem_post). They are slower then the previous
- methods but still way faster then SYSV sempahores. Unfortunately they also do not work on
- all the systems (e.g. linux).
-
- SYSV_SEM - this is the most portable but also the slowest locking method. Another problem is
- that the number of semaphores that can be alocated by a process is limited. One also has to
- free them before exiting.
- 2. How to use it?
- -----------------
- First of all you have to include locking.h. Then when compiling the code one or all of FAST_LOCK,
- USE_PTHREAD_MUTEX, USE_PTHREAD_SEM or USE_SYSV_SEM must be defined (the Kamailio Makefile.defs takes
- care of this, you should need to change it only for new arhitectures or compilers).
- locking.h defines 2 new types: gen_lock_t and lock_set_t.
- 3. Simple locks
- ---------------
- The simple locks are simple mutexes. The type is gen_lock_t.
- WARNING: do not make any assumptions on gen_lock_t base type, it does not have to be always an int.
- Allocation & initialization:
- ----------------------------
- The locks are allocated with:
- gen_lock_t* lock_alloc();
- and initialized with:
- gen_lock_t* lock_init(gen_lock_t* lock);
- Both function return 0 on failure.
- The locks must be initialized before use.
- A proper alloc/init sequence looks like:
- gen_lock_t* lock;
- lock=lock_alloc();
- if (lock==0) goto error;
- if (lock_init(lock)==0){
- lock_dealloc(lock);
- goto error; /* could not init lock*/
- }
- ...
- Lock allocation can be skipped in some cases: if the lock is already in shared memory you don't need to
- allocate it again, you can initialize it directly, but keep in mind that the lock MUST be in shared memory.
- Example:
- struct s {
- int foo;
- gen_lock_t lock;
- } bar;
- bar=shm_malloc(sizeof struct s); /* we allocate it in the shared memory */
- if (lock_init(&bar->lock)==0){
- /* error initializing the lock */
- ...
- }
- Destroying & deallocating the locks:
- ------------------------------------
- void lock_destroy(gen_lock_t* lock);
- void lock_dealloc(gen_lock_t* lock);
-
- The lock_destroy function must be called first. It removes the resources associated with the
- lock, but it does not also free the lock shared memory part. Think of sysv rmid.
- Please don't forget to call this function, or you can leave allocated resources in some cases
- (e.g sysv semaphores). Be carefull to call it in your module destroy function if you use any
- global module locks.
- Example:
- lock_destroy(lock);
- lock_dealloc(lock);
- Of course you don't need to call lock_dealloc if your lock was not allocated with lock_alloc.
- Locking & unlocking:
- --------------------
- void lock_get(gen_lock_t* lock); - lock (mutex down)
- void lock_release(gen_lock_t* lock); - unlock (mutex up)
- int lock_try(gen_lock_t* lock); - tries to lock and returns 0
- if succesfull, -1 if not (this is
- a non-blocking lock_get())
- 4. Lock Sets
- ------------
- The lock sets are kind of sysv semaphore sets equivalent. The type is lock_set_t.
- Use them when you need a lot of mutexes. In some cases they waste less system
- resources than arrays of gen_lock_t (e.g. sys v semaphores).
- Allocating & initializing:
- --------------------------
- lock_set_t* lock_set_alloc(int no);
- lock_set_t* lock_set_init(lock_set_t* set);
- Both functions return 0 on failure.
- WARNING: expect the allocation function to fail for large numbers. It depends on the locking
- method used & the system available resources (again the sysv semaphores example).
- Example:
- lock_set_t *lock_set;
- lock_set=lock_set_alloc(100);
- if (lock_set==0) goto error;
- if (lock_set_init(lock_set)==0){
- lock_set_dealloc(lock_set);
- goto error;
- }
- or
- if ((lock_set=lock_set_alloc(100))==0) || (lock_set_init(lock_set)==0)){
- if (lock_set) lock_set_dealloc(lock_set);
- goto error;
- }
- Destroying & deallocating:
- --------------------------
- void lock_set_destroy(lock_set_t* s);
- void lock_set_dealloc(lock_set_t* s);
- Again don't forget to "destroy" the locks.
- Locking & unlocking:
- --------------------
- void lock_set_get(lock_set_t* s, int i);
- void lock_set_release(lock_set_t* s, int i);
- int lock_set_try(lock_set_t* s, int i); - tries to lock the i-th lock
- from the set. If succesfull
- returns 0, if not -1.
- Example:
- lock_set_get(lock_set, 2);
- /* do something */
- lock_set_release(lock_set, 2);
- When to use lock_set_t & when to use gen_lock_t
- -----------------------------------------------
- If you use lots of semaphores and GEN_LOCK_T_PREFERED is undefined then use
- lock_set_t. If GEN_LOCK_T_PREFERED is defined you can safely use gen_lock_t
- arrays instead.
|