Documentation |
Documentation -> Development Manual 3.1 -> Locking APIThis page has been visited 1093 times. Pages for other versions: devel 3.5 3.4 Older versions: 3.3 3.2 3.1
Table of Content (hide) OpenSIPS has it's own locking API, and it is recommended to use it instead of the system exposed locks, since they offer greater flexibility - depending on the usage case and the menuconfig provided compilation flags, the OpenSIPS generic locks can be converted either to busy locks, futexes, SysV locks, etc.
1. Single Lock APIThe API can be used by including “locking.h” . The OpenSIPS generic lock is defined by the gen_lock_t structure. /* Returns : A shared memory allocated lock, or NULL in case of an error. */ gen_lock_t *lock_alloc(void);
/* Parameters : lock - the lock instance to be initialized Returns : The initialized lock in case of success, or NULL in case of error. */ gen_lock_t* lock_init(gen_lock_t* lock);
/* Parameters : lock - the lock to be acquired */ void lock_get(gen_lock_t *lock);
/* Parameters : lock - the lock to be released. */ void lock_release(gen_lock_t *lock);
/* Parameters : lock - the lock to be destroyed */ void lock_destroy(gen_lock_t *lock); /* Parameters : lock - the lock to be deallocated */ void lock_dealloc(gen_lock_t *lock);
gen_lock_t *my_lock; int init_function(void) { /* … */ my_lock = lock_alloc(); if (my_lock == NULL) { LM_ERR(“Failed to allocate lock \n”); return -1; } if (lock_init(my_lock) == NULL) { LM_ERR(“Failed to init lock \n”); return -1; } /* … */ return 0; } int do_work(void) { /* … */ lock_get(my_lock) /* critical region protected by our lock generally recommended to keep critical regions short I/O operations to be avoided in such critical regions */ lock_release(my_lock) /* … */ } void destroy_function(void) { /* … */ lock_destroy(my_lock); lock_dealloc(my_lock); /* … */ } 2. Lock Set APIOperating on an entire array of locks can become very useful when dealing with structures like hashes, where you would need a lock per each hash entry. /* Returns : A shared memory allocated lock set, or NULL in case of an error. */ gen_lock_set_t *lock_set_alloc(void);
/* Parameters : lock - the lock set instance to be initialized Returns : The initialized lock in case of success, or NULL in case of error. */ gen_lock_set_t* lock_set_init(gen_lock_set_t* lock);
/* Parameters : lock - the lock to be acquired entry - the entry in the lock set that needs to be acquired */ void lock_set_get(gen_lock_set_t *lock,int entry);
/* Parameters : lock - the lock to be released. entry - the entry in the lock set that needs to be released */ void lock_set_release(gen_lock_set_t *lock,int entry);
/* Parameters : lock - the lock set to be destroyed */ void lock_set_destroy(gen_lock_set_t *lock); /* Parameters : lock - the lock set to be deallocated */ void lock_set_dealloc(gen_lock_set_t *lock);
gen_lock_set_t *my_lock; int init_function(void) { /* … */ /* allocate lock set with 32 entries */ my_lock = lock_set_alloc(32); if (my_lock == NULL) { LM_ERR(“Failed to allocate lock set \n”); return -1; } if (lock_set_init(my_lock) == NULL) { LM_ERR(“Failed to init lock set \n”); return -1; } /* … */ return 0; } int do_work(void) { /* … */ /* acquire entry 5 in the lock set */ lock_set_get(my_lock,5) /* also acquire entry 21 in the lock set */ lock_set_get(my_lock,21); /* critical region protected by our lock generally recommended to keep critical regions short I/O operations to be avoided in such critical regions */ lock_set_release(my_lock,21); lock_set_release(my_lock,5); /* … */ } void destroy_function(void) { /* … */ lock_set_destroy(my_lock); lock_set_dealloc(my_lock); /* … */ } 3. Readers-Writers Locking APIA readers-writer lock is like a mutex, in that it controls access to a shared resource, allowing concurrent access to multiple threads for reading but restricting access to a single thread for writes (or other changes) to the resource. Allocating a new readers-writers lock into shared memory and initializing it is done by calling lock_init_rw : /* Returns : A shared memory allocated rw lock, or NULL in case of an error. */ inline static rw_lock_t * lock_init_rw(void);
/* Parameters : lock - the lock to be acquired */ void lock_start_read(rw_lock_t * lock);
/* Parameters : lock - the lock to be released */ void lock_stop_read(rw_lock_t * lock);
/* Parameters : lock - the lock to be acquired */ void lock_start_write(rw_lock_t * lock);
/* Parameters : lock - the lock to be release */ void lock_stop_write(rw_lock_t * lock);
/* Parameters : lock - the lock to be destroyed */ void lock_destroy_rw(rw_lock_t * lock); |