summaryrefslogtreecommitdiff
path: root/doc/libs6lock/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/libs6lock/index.html')
-rw-r--r--doc/libs6lock/index.html256
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 &lt;s6/s6lock.h&gt;</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(&amp;deadline, 2)
+
+char const *path = S6LOCK_IPCPATH ;
+s6lock_start_g(&amp;a, path, &amp;deadline) ;
+// char const *lockdir = "/tmp/lock" ;
+// s6lock_startf_g(&amp;a, lockdir, &amp;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(&amp;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 (&amp;a, &amp;id, file, &amp;limit, &amp;deadline) ;
+/* int r = s6lock_acquire_ex_g (&amp;a, &amp;id, file, &amp;limit, &amp;deadline) ; */
+r = s6lock_release_g(&amp;a, id, &amp;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, &amp;a-&gt;list)</tt> points to an array of
+<tt>genalloc_len(uint16, &amp;a-&gt;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>