This page has been visited 405 times.
Pages for other versions: devel 3.5 3.4 Older versions: 3.3 3.2 3.1
Locking API |
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.
The Locking API offers two distinct functionalities, one for using single lock elements, and another for operating on entire sets of locks.
The API can be used by including “locking.h” . The OpenSIPS generic lock is defined by the gen_lock_t structure.
Allocating a new lock is done by calling lock_alloc :
Since the locks usually have to be reachable by all processes fighting on some resource, the locks are allocated by default in shared memory. Also, note that it is not necessary to always allocate the lock separately - if the lock is embedded within a structure which is allocated in SHM, the effect is the same.
Before any operation on the lock, it must be initialized :
In order to acquire a lock, one must use the lock_get function :
The function will block if the lock is acquired by another process, and will only return once the lock has been acquired by the current process.
For releasing a lock, lock_release should be used :
Once a lock is no longer needed, one must first destroy the lock, and then the lock can be safely deallocated.
Here is a code snippet showing the typical code used when dealing with single lock instances :
Operating 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.
The API can be used by including locking.h . The OpenSIPS generic array of locks is defined by the gen_lock_set_t structure, and working with it is very similar in concept to operating a single lock entry.
Allocating a new lock set is done by calling lock_set_alloc :
Since the locks usually have to be reachable by all processes fighting on some resource, the locks are allocated by default in shared memory. Also, note that it is not necessary to always allocate the lock set separately - if the lock set is embedded within a structure which is allocated in SHM, the effect is the same.
Before any operation on the lock set, it must be initialized :
In order to acquire a lock in a lock set, one must use the lock_set_get function :
The function will block if the lock is acquired by another process, and will only return once the lock has been acquired by the current process.
For releasing a lock, lock_set_release should be used :
Once a lock set is no longer needed, one must first destroy the lock set, and then the lock set can be safely deallocated.
Here is a code snippet showing the typical code used when dealing with single lock instances :
A 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.
This can prove very useful when having an use case where all the OpenSIPS processes need read-only access to a resource, but you need to have an MI command to reload that resource ( eg. from a database ). In such scenarios, using a readers-writers lock can improve performance by a considerable margin.
The API can be used by including “rw_locking.h” . The OpenSIPS generic lock is defined by the rw_lock_t structure.
Allocating a new readers-writers lock into shared memory and initializing it is done by calling lock_init_rw :
In order to acquire the lock for reading purpose, one should use lock_start_read :
In case there is currently a write access ongoing, the lock will block until the write is done. Otherwise, the lock will be acquired immediately.
After the read is finished, you must call lock_stop_read :
For requesting a write access, you can use lock_start_write :
In case there are other ongoing writes, the op will block until the other writes complete. Otherwise, the lock will block until all the existing readers finish reading.
After the write operation is finished, call lock_stop_write :
Upon calling the above function, readers will again be allowed in the critical section.
For destroying and deallocating a rw lock, use lock_destroy_rw :