diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2014-12-05 22:26:11 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2014-12-05 22:26:11 +0000 |
commit | 90b12bd71bb9fc79a4640b9112c13ef529d0196a (patch) | |
tree | 523b3f4ee2969e7a729bab2ba749c4b924ae62af /doc/libs6lock/index.html | |
download | s6-90b12bd71bb9fc79a4640b9112c13ef529d0196a.tar.xz |
Initial commit
Diffstat (limited to 'doc/libs6lock/index.html')
-rw-r--r-- | doc/libs6lock/index.html | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/doc/libs6lock/index.html b/doc/libs6lock/index.html new file mode 100644 index 0000000..3696b41 --- /dev/null +++ b/doc/libs6lock/index.html @@ -0,0 +1,256 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6: the s6lock library interface</title> + <meta name="Description" content="s6: the s6lock library interface" /> + <meta name="Keywords" content="s6 timed lock s6lock libs6lock library interface" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="../">s6</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6lock</tt> library interface </h1> + +<h2> General information </h2> + +<p> + <tt>libs6lock</tt> is a C interface to timed locks. Unix natively provides +locks, but the locking primitives are synchronous, so either they are +unbounded in execution time or they require polling. libs6lock provides +poll-free locks that can timeout during attempted acquisition. +</p> + +<h2> Compiling </h2> + +<ul> + <li> Make sure the s6 headers, as well as the skalibs headers, +are visible in your header search path. </li> + <li> Use <tt>#include <s6/s6lock.h></tt> </li> +</ul> + +<h2> Linking </h2> + +<ul> + <li> Make sure the s6 libraries, as well as the skalibs libraries, +are visible in your library search path. </li> + <li> Link against <tt>-ls6</tt>, <tt>-lskarnet</tt>, +<tt>`cat $sysdeps/socket.lib`</tt>, and +<tt>`cat $sysdeps/tainnow.lib`</tt>, +if <tt>$sysdeps</tt> is your skalibs installation's sysdeps directory. </li> +</ul> + +<h2> Programming </h2> + +<ul> + <li> Check the <tt>s6/s6lock.h</tt> header +for the prototypes. The functions documented here are +often simplified macros, for instance relying on the STAMP global variable +to hold the current time. Fully reentrant functions with more control +options are usually available. </li> + <li> Given the nature of the s6lock library, it makes sense to use a +<a href="http://skarnet.org/software/s6-networking/localservice.html">s6lockd service</a> concurrently +accessed by several applications using such locks to gate shared +resources. </li> + <li> If you're not using a s6lockd service, +make sure your application is not disturbed by children it doesn't +know it has. Using nonblocking waits, ignoring pids you don't know, and +using a +<a href="http://skarnet.org/software/skalibs/libstddjb/selfpipe.html">self-pipe</a> +if your application is built around an event loop, are good programming +practices. </li> +</ul> + +<h3> Starting and ending a session </h3> + +<pre> +s6lock_t a = S6LOCK_ZERO ; +struct taia deadline ; + +taia_now_g() ; +taia_addsec_g(&deadline, 2) + +char const *path = S6LOCK_IPCPATH ; +s6lock_start_g(&a, path, &deadline) ; +// char const *lockdir = "/tmp/lock" ; +// s6lock_startf_g(&a, lockdir, &deadline) ; +</pre> + +<p> +<tt>s6lock_start_g</tt> starts a session by connecting to a s6lockd service +listening on <em>path</em>. The working directory is set by the administrator +of the service. <br /> +<tt>s6lock_startf_g</tt> starts a session with a s6lockd process as a child, +using <em>lockdir</em> as its working directory. +<br /> +<tt>a</tt> is a s6lock_t structure that must be declared in the stack and +initialized to S6LOCK_ZERO. +If the session initialization fails, the function returns 0 and errno is set; +else the function returns 1. +</p> +<p> +If the absolute time <tt>deadline</tt> is reached and the function +has not returned yet, it immediately returns 0 with errno set to ETIMEDOUT. + +Only local interprocess communications are involved; unless your system is +heavily overloaded, the function should return near-instantly. One or two +seconds of delay between the current time and <tt>deadline</tt> should be +enough: if the function takes more than that to return, then there is a +problem with the underlying processes. +</p> + +<p> + You can have more than one session open in parallel, by declaring +several distinct <tt>s6lock_t</tt> structures and calling +<tt>s6lock_startf_g</tt> (or <tt>s6lock_start_g</tt>) more than once. +However, one single session can handle +virtually as many concurrent locks as your application needs, so +opening several sessions is only useful if you need to acquire locks +in various distinct lock directories. +</p> + +<pre> +s6lock_end(&a) ; +</pre> + +<p> +<tt>s6lock_end</tt> frees all the resources used by the session. The +<tt>a</tt> structure is then reusable for another session. +</p> + +<h3> Acquiring and releasing locks </h3> + +<pre> +uint16 id ; +char const *file = "lockfile" ; +struct taia limit ; +struct taia deadline ; + +int r = s6lock_acquire_sh_g (&a, &id, file, &limit, &deadline) ; +/* int r = s6lock_acquire_ex_g (&a, &id, file, &limit, &deadline) ; */ +r = s6lock_release_g(&a, id, &deadline) ; +</pre> + +<p> +<tt>s6lock_acquire_sh_g</tt> instructs the +<a href="s6lockd.html">s6lockd daemon</a>, related to the open +session represented by the <tt>a</tt> handle, to try and acquire a +shared lock on the +<em>file</em> file located under that daemon's working directory +(typically <tt>/var/lock</tt>). <em>file</em> will be interpreted as +relative to the daemon's working directory even if it starts with a +slash; however, slashes in the middle of <em>file</em> are likely to +result in an error. +</p> + +<p> +<em>limit</em> and <em>deadline</em> are two absolute dates. +<em>deadline</em> is a deadline for the execution of the +function: if by <em>deadline</em> the function has not returned, +then it instantly returns 0 and sets errno to ETIMEDOUT. The +function is normally near-instantaneous, so <em>deadline</em> can +be very close in the future and serves only as a protection against +malicious servers. <em>limit</em> is the acquisition deadline: if +by <em>limit</em> the daemon still has not been able to acquire a lock +on <em>file</em>, then it will report a timeout to the client. +</p> + +<p> +The function returns 1 in case of success, or 0 if an error occurs, +with errno set to a suitable value. If it succeeds, then a 16-bit +number is stored into *<em>id</em>; this number serves as an identifier +for this lock. +</p> + +<p> +<tt>s6lock_acquire_ex_g</tt> works just like <tt>s6lock_acquire_sh_g</tt>, +except that the daemon tries to acquire an exclusive lock. +</p> + +<p> +<tt>s6lock_release_g</tt> releases the lock identified by <em>id</em>. +It normally returns 1. It can return 0 with errno set to a suitable +value if it fails. <em>id</em> is not valid after the corresponding +lock has been released. The function normally returns instantly, with +<em>deadline</em> as a safeguard. +</p> + +<h3> Asynchronously waiting for locks </h3> + +<p> +<em> (from now on, the functions are listed with their prototypes instead +of usage examples.) </em> +</p> + +<pre> +int s6lock_fd (s6lock_t const *a) +</pre> + +<p> + Returns a file descriptor to select on for reading. Do not +<tt>read()</tt> it though. +</p> + +<pre> +int s6lock_update (s6lock_t *a) +</pre> + +<p> + Call this function whenever the fd checks readability: it will +update <em>a</em>'s internal structures with information from the +<a href="s6lockd.html">s6lockd</a> daemon. It returns -1 if an error +occurs; in case of success, it returns the number of identifiers for +which something happened. +</p> + +<p> + When <tt>s6lock_update</tt> returns, +<tt>genalloc_s(uint16, &a->list)</tt> points to an array of +<tt>genalloc_len(uint16, &a->list)</tt> 16-bit unsigned +integers. Those integers are ids waiting to be passed to +<tt>s6lock_check</tt>. +</p> + +<pre> +int s6lock_check (s6lock_t *a, uint16 id, char *what) +</pre> + +<p> + Checks whether the lock identified by <em>id</em> has +been acquired. Use after a call to <tt>s6lock_update()</tt>. +</p> + +<ul> + <li> If an error occurred, returns -1 and sets errno. The error +number may have been transmitted from +<a href="s6lockd.html">s6lockd</a>. </li> + <li> If the lock has not been acquired yet, returns 0. </li> + <li> If the lock has been acquired, returns 1. </li> +</ul> + +<h3> Synchronously waiting for locks </h3> + +<p> +<code> int s6lock_wait_or_g (s6lock_t *a, uint16 const *idlist, unsigned int n, struct taia const *deadline) </code> <br /> +Synchronously waits for <em>one</em> of the locks represented by the array pointed to +by <em>idlist</em> of length <em>n</em> to be acquired. Returns -1 if it fails, +or a nonnegative number on success, which is the index in <em>idlist</em> of the +acquired lock's id. If no result has been obtained by <em>deadline</em>, the +function returns -1 ETIMEDOUT. +</p> + +<p> +<code> int s6lock_wait_and_g (s6lock_t *a, uint16 const *idlist, unsigned int n, struct taia const *deadline) </code> <br /> +Synchronously waits for <em>all</em> of the locks represented by the array pointed to +by <em>idlist</em> of length <em>n</em> to be acquired. Returns -1 if it fails and +0 if it succeeds. If no result has been obtained by <em>deadline</em>, the +function returns -1 ETIMEDOUT. +</p> + +</body> +</html> |