diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2021-08-30 19:11:44 +0000 |
---|---|---|
committer | Laurent Bercot <ska@appnovation.com> | 2021-08-30 19:11:44 +0000 |
commit | 691c69e626e4ceb85567a5288348bd04378fd410 (patch) | |
tree | 9ae1c3f2c2984aafa2b9caf7987fe0011fcf6828 /doc/libs6/lock.html | |
parent | 1719a60278cf36558b568349c0c9f9b5eb91c999 (diff) | |
download | s6-691c69e626e4ceb85567a5288348bd04378fd410.tar.xz |
s6-svlink, s6-svunlink, .h changes
Renamed from s6-svdir-(un)link.
Doc added. Full functionality added.
Still need to be tested.
Unrelated: .h names simplified.
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'doc/libs6/lock.html')
-rw-r--r-- | doc/libs6/lock.html | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/doc/libs6/lock.html b/doc/libs6/lock.html new file mode 100644 index 0000000..1cc896d --- /dev/null +++ b/doc/libs6/lock.html @@ -0,0 +1,239 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <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 libs6 library interface" /> + <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">libs6</a><br /> +<a href="../">s6</a><br /> +<a href="//skarnet.org/software/">Software</a><br /> +<a href="//skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6lock</tt> library interface </h1> + +<h2> General information </h2> + +<p> + <tt>s6lock</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. s6lock provides +poll-free locks that can timeout during attempted acquisition. +</p> + +<h2> Programming </h2> + +<ul> + <li> Check the <tt>s6/lock.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="../localservice.html">s6lockd service</a> concurrently +accessed by several applications using such locks to gate shared +resources. </li> + <li> If you're not using an 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="//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 ; +tain_t deadline ; + +tain_now_g() ; +tain_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 an 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 an s6lockd process as a child, +using <em>lockdir</em> as its working directory. +<br /> +<tt>a</tt> is an 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_t id ; +char const *file = "lockfile" ; +tain_t limit ; +tain_t 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_t, &a->list)</tt> points to an array of +<tt>genalloc_len(uint16_t, &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_t 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_t const *idlist, unsigned int n, tain_t 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_t const *idlist, unsigned int n, tain_t 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> |