summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2018-03-22 14:06:07 -0700
committerGarrett D'Amore <garrett@damore.org>2018-03-22 14:06:07 -0700
commit53d5c2766d90a53d3f6c0437bc59c1ad63ec701a (patch)
treebc622efccbfaf9b05eca1c6c7ff8203011660651
parent1dc090d39eded06eee7725bd507599d8f59a3379 (diff)
downloadnng-53d5c2766d90a53d3f6c0437bc59c1ad63ec701a.tar.gz
nng-53d5c2766d90a53d3f6c0437bc59c1ad63ec701a.tar.bz2
nng-53d5c2766d90a53d3f6c0437bc59c1ad63ec701a.zip
Add documentation for supplemental functions.
This includes platform portability stuff like mutexes and threads, etc. While here we fixed a problem with nng_opts_parse and we addressed the type of the platform API.
-rw-r--r--docs/man/libnng.3.adoc17
-rw-r--r--docs/man/nng_clock.3supp.adoc58
-rw-r--r--docs/man/nng_cv_alloc.3supp.adoc58
-rw-r--r--docs/man/nng_cv_free.3supp.adoc41
-rw-r--r--docs/man/nng_cv_until.3supp.adoc89
-rw-r--r--docs/man/nng_cv_wait.3supp.adoc85
-rw-r--r--docs/man/nng_cv_wake.3supp.adoc60
-rw-r--r--docs/man/nng_cv_wake1.3supp.adoc61
-rw-r--r--docs/man/nng_msleep.3supp.adoc48
-rw-r--r--docs/man/nng_mtx_alloc.3supp.adoc56
-rw-r--r--docs/man/nng_mtx_free.3supp.adoc42
-rw-r--r--docs/man/nng_mtx_lock.3supp.adoc63
-rw-r--r--docs/man/nng_mtx_unlock.3supp.adoc47
-rw-r--r--docs/man/nng_opts_parse.3supp.adoc (renamed from docs/man/nng_opts_parse.3supp)0
-rw-r--r--docs/man/nng_random.3supp.adoc44
-rw-r--r--docs/man/nng_thread_create.3supp.adoc85
-rw-r--r--docs/man/nng_thread_destroy.3supp.adoc46
-rw-r--r--src/supplemental/util/platform.h2
18 files changed, 900 insertions, 2 deletions
diff --git a/docs/man/libnng.3.adoc b/docs/man/libnng.3.adoc
index 2fd0109f..feab3ebf 100644
--- a/docs/man/libnng.3.adoc
+++ b/docs/man/libnng.3.adoc
@@ -214,7 +214,22 @@ network applications with _NNG_, but they are made available
as a convenience to aid in creating portable applications.
|===
-|<<nng_opts_parse.3#,nng_opts_parse()>>|parse command line options
+|<<nng_clock.3supp#,nng_clock()>>|get time
+|<<nng_cv_alloc.3supp#,nng_cv_alloc()>>|allocate condition variable
+|<<nng_cv_free.3supp#,nng_cv_free()>>|free condition variable
+|<<nng_cv_until.3supp#,nng_cv_until()>>|wait for condition or timeout
+|<<nng_cv_wait.3supp#,nng_cv_wait()>>|wait for condition
+|<<nng_cv_wake.3supp#,nng_cv_wake()>>|wake all waiters
+|<<nng_cv_wake1.3supp#,nng_cv_wake()>>|wake one waiter
+|<<nng_msleep.3supp#,nng_msleep()>>|sleep for milliseconds
+|<<nng_mtx_alloc.3supp#,nng_mtx_alloc()>>|allocate mutex
+|<<nng_mtx_free.3supp#,nng_mtx_free()>>|free mutex
+|<<nng_mtx_lock.3supp#,nng_mtx_lock()>>|lock mutex
+|<<nng_mtx_unlock.3supp#,nng_mtx_unlock()>>|unlock mutex
+|<<nng_opts_parse.3supp#,nng_opts_parse()>>|parse command line options
+|<<nng_random.3supp#,nng_random()>>|get random number
+|<<nng_thread_create.3supp#,nng_thread_create()>>|create thread
+|<<nng_thread_destroy.3supp#,nng_thread_destroy()>>|reap thread
|===
diff --git a/docs/man/nng_clock.3supp.adoc b/docs/man/nng_clock.3supp.adoc
new file mode 100644
index 00000000..cfbf0bf3
--- /dev/null
+++ b/docs/man/nng_clock.3supp.adoc
@@ -0,0 +1,58 @@
+= nng_clock(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_clock - get time
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+typedef uint64_t nng_time;
+
+nng_time nng_clock(void);
+----
+
+== DESCRIPTION
+
+The `nng_clock()` returns the number of elapsed milliseconds since some
+arbitrary time in the past.
+The resolution of the clock depends on the underlying timing facilities
+of the system.
+This function may be used for timing, but applications should not expect
+very fine grained values.
+
+IMPORTANT: The reference time will be the same for a given program,
+but different programs may have different references.
+
+TIP: This function is intended mostly to help with setting appropriate
+timeouts using <<nng_cv_until.3supp#,nng_cv_until(3supp)>>.
+
+== RETURN VALUES
+
+Milliseconds since reference time.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_sleep_aio.3#,nng_sleep_aio(3)>>,
+<<nng_strerror.3#,nng_strerror(3)>>,
+<<nng_cv_until.3supp#,nng_cv_until(3supp)>>,
+<<nng_msleep.3supp#,nng_msleep(3supp)>>,
+<<nng_duration.5#,nng_duration(5)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_cv_alloc.3supp.adoc b/docs/man/nng_cv_alloc.3supp.adoc
new file mode 100644
index 00000000..0668298f
--- /dev/null
+++ b/docs/man/nng_cv_alloc.3supp.adoc
@@ -0,0 +1,58 @@
+= nng_cv_alloc(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_cv_alloc - allocate condition variable
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+typedef struct nng_cv nng_cv;
+
+int nng_cv_alloc(nng_cv **cvp, nng_mtx *mtx);
+----
+
+== DESCRIPTION
+
+The `nng_cv_alloc()` function allocates a condition variable, using
+the mutex _mtx_, and returns it in _cvp_.
+
+Every condition variable is associated with a mutex, which must be
+owned when a thread waits for the condition using
+<<nng_cv_wait.3supp#,`nng_cv_wait()`>> or
+<<nng_cv_until.3supp#,`nng_cv_until()`>>.
+The mutex must also be owned when signaling the condition using the
+<<nng_cv_wake.3supp#,`nng_cv_wake()`>> or
+<<nng_cv_wake1.3supp#,`nng_cv_wake1()`>> functions.
+
+== RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+== ERRORS
+
+`NNG_ENOMEM`:: Insufficient free memory exists.
+
+== SEE ALSO
+
+<<nng_cv_free.3supp#,nng_cv_free(3supp)>>,
+<<nng_cv_until.3supp#,nng_cv_until(3supp)>>,
+<<nng_cv_wait.3supp#,nng_cv_wait(3supp)>>,
+<<nng_cv_wake.3supp#,nng_cv_wake(3supp)>>,
+<<nng_cv_wake1.3supp#,nng_cv_wake1(3supp)>>,
+<<nng_mtx_alloc.3supp#,nng_mtx_alloc(3supp)>>,
+<<nng_strerror.3#,nng_strerror(3)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_cv_free.3supp.adoc b/docs/man/nng_cv_free.3supp.adoc
new file mode 100644
index 00000000..3c076093
--- /dev/null
+++ b/docs/man/nng_cv_free.3supp.adoc
@@ -0,0 +1,41 @@
+= nng_cv_free(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_cv_free - free condition variable
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_cv_free(nng_cv *cv);
+----
+
+== DESCRIPTION
+
+The `nng_cv_free()` function frees the condition variable _cv_.
+
+== RETURN VALUES
+
+None.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_cv_alloc.3supp#,nng_cv_alloc(3supp)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_cv_until.3supp.adoc b/docs/man/nng_cv_until.3supp.adoc
new file mode 100644
index 00000000..4d39ecc0
--- /dev/null
+++ b/docs/man/nng_cv_until.3supp.adoc
@@ -0,0 +1,89 @@
+= nng_cv_until(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_cv_until - wait for condition or timeout
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+int nng_cv_wait(nng_cv *cv, nng_time when);
+----
+
+== DESCRIPTION
+
+The `nng_cv_until()` waits until either the condition variable _cv_ is signaled
+by another thread calling either <<nng_cv_wake.3supp#,`nng_cv_wake()`>> or
+<<nng_cv_wake1.3supp#,`nng_cv_wake1()`>>, or the system clock (as tracked
+by <<nng_clock.3supp#,`nng_clock()`>>) reaches _when_.
+
+The caller must have have ownership of the mutex that was used when
+_cv_ was allocated.
+This function will drop the ownership of that mutex, and reacquire it
+atomically just before returning to the caller.
+(The waiting is done without holding the mutex.)
+
+NOTE: Any condition may be used or checked, but the condition must be
+checked, as it is possible for this function to wake up "`spuriously`".
+The best way to do this is inside a loop that repeats until the condition
+tests for true.
+
+== EXAMPLE
+
+The following example demonstrates use of this function:
+
+.Example 1: Waiting for the condition
+[source, c]
+----
+
+ nng_mtx_lock(m); // assume cv was allocated using m
+ while (!condition_true) {
+ if (nng_cv_wait(cv) == NNG_ETIMEDOUT) {
+ printf("Time out reached!\n");
+ break;
+ }
+ }
+ // condition_true is true
+ nng_mtx_unlock(m);
+----
+
+.Example 2: Signaling the condition
+[source, c]
+----
+ nng_mtx_lock(m);
+ condition_true = true;
+ cv_wake(cv);
+ nng_mtx_unlock(m);
+----
+
+== RETURN VALUES
+
+None.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_cv_alloc.3supp#,nng_cv_alloc(3supp)>>,
+<<nng_cv_wait.3supp#,nng_cv_wait(3supp)>>,
+<<nng_cv_wake.3supp#,nng_cv_wake(3supp)>>,
+<<nng_cv_wake1.3supp#,nng_cv_wake1(3supp)>>,
+<<nng_mtx_alloc.3supp#,nng_mtx_alloc(3supp)>>,
+<<nng_mtx_lock.3supp#,nng_mtx_lock(3supp)>>,
+<<nng_mtx_unlock.3supp#,nng_mtx_unlock(3supp)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_cv_wait.3supp.adoc b/docs/man/nng_cv_wait.3supp.adoc
new file mode 100644
index 00000000..034b3ea9
--- /dev/null
+++ b/docs/man/nng_cv_wait.3supp.adoc
@@ -0,0 +1,85 @@
+= nng_cv_wait(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_cv_wait - wait for condition
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_cv_wait(nng_cv *cv);
+----
+
+== DESCRIPTION
+
+The `nng_cv_wait()` waits for the condition variable _cv_ to be signaled
+by another thread calling either <<nng_cv_wake.3supp#,`nng_cv_wake()`>> or
+<<nng_cv_wake1.3supp#,`nng_cv_wake1()`>>.
+
+The caller must have have ownership of the mutex that was used when
+_cv_ was allocated.
+This function will drop the ownership of that mutex, and reacquire it
+atomically just before returning to the caller.
+(The waiting is done without holding the mutex.)
+
+NOTE: Any condition may be used or checked, but the condition must be
+checked, as it is possible for this function to wake up "`spuriously`".
+The best way to do this is inside a loop that repeats until the condition
+tests for true.
+
+== EXAMPLE
+
+The following example demonstrates use of this function:
+
+.Example 1: Waiting for the condition
+[source, c]
+----
+
+ nng_mtx_lock(m); // assume cv was allocated using m
+ while (!condition_true) {
+ nng_cv_wait(cv);
+ }
+ // condition_true is true
+ nng_mtx_unlock(m);
+----
+
+.Example 2: Signaling the condition
+[source, c]
+----
+ nng_mtx_lock(m);
+ condition_true = true;
+ cv_wake(cv);
+ nng_mtx_unlock(m);
+----
+
+== RETURN VALUES
+
+None.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_cv_alloc.3supp#,nng_cv_alloc(3supp)>>,
+<<nng_cv_until.3supp#,nng_cv_until(3supp)>>,
+<<nng_cv_wake.3supp#,nng_cv_wake(3supp)>>,
+<<nng_cv_wake1.3supp#,nng_cv_wake1(3supp)>>,
+<<nng_mtx_alloc.3supp#,nng_mtx_alloc(3supp)>>,
+<<nng_mtx_lock.3supp#,nng_mtx_lock(3supp)>>,
+<<nng_mtx_unlock.3supp#,nng_mtx_unlock(3supp)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_cv_wake.3supp.adoc b/docs/man/nng_cv_wake.3supp.adoc
new file mode 100644
index 00000000..ad8dadfe
--- /dev/null
+++ b/docs/man/nng_cv_wake.3supp.adoc
@@ -0,0 +1,60 @@
+= nng_cv_wake(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_cv_wake - wake all waiters
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_cv_wake(nng_cv *cv);
+----
+
+== DESCRIPTION
+
+The `nng_cv_wake()` wakes any threads waiting for the condition variable _cv_
+to be signaled in the <<nng_cv_wait.3supp#,`nng_cv_wait()`>> or
+<<nng_cv_until.3supp#,`nng_cv_until()`>> functions.
+
+The caller must have have ownership of the mutex that was used when
+_cv_ was allocated.
+
+NOTE: The caller should already have set the condition that the waiters
+will check, while holding the mutex.
+
+TIP: This function wakes all threads, which is generally safer but can
+lead to a problem known as the "`thundering herd`" when there are many
+waiters, as they are all woken simultaneously.
+See <<nng_cv_wake1.3supp#,`nng_cv_wake1()`>> for a solution to this problem.
+
+== RETURN VALUES
+
+None.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_cv_alloc.3supp#,nng_cv_alloc(3supp)>>,
+<<nng_cv_until.3supp#,nng_cv_until(3supp)>>,
+<<nng_cv_wait.3supp#,nng_cv_wait(3supp)>>,
+<<nng_cv_wake1.3supp#,nng_cv_wake1(3supp)>>,
+<<nng_mtx_alloc.3supp#,nng_mtx_alloc(3supp)>>,
+<<nng_mtx_lock.3supp#,nng_mtx_lock(3supp)>>,
+<<nng_mtx_unlock.3supp#,nng_mtx_unlock(3supp)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_cv_wake1.3supp.adoc b/docs/man/nng_cv_wake1.3supp.adoc
new file mode 100644
index 00000000..1938a702
--- /dev/null
+++ b/docs/man/nng_cv_wake1.3supp.adoc
@@ -0,0 +1,61 @@
+= nng_cv_wake1(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_cv_wake1 - wake one waiter
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_cv_wake1(nng_cv *cv);
+----
+
+== DESCRIPTION
+
+The `nng_cv_wake1()` wakes at most one thread waiting for the condition
+variable _cv_
+to be signaled in the <<nng_cv_wait.3supp#,`nng_cv_wait()`>> or
+<<nng_cv_until.3supp#,`nng_cv_until()`>> functions.
+
+The caller must have have ownership of the mutex that was used when
+_cv_ was allocated.
+
+NOTE: The caller should already have set the condition that the waiters
+will check, while holding the mutex.
+
+TIP: While this function avoids the "`thundering herd`" problem, the
+caller cannot predict which waiter will be woken, and so the design must
+ensure that it is sufficient that _any_ waiter be woken.
+When in doubt, it is safer to use <<nng_cv_wake.3supp#,`nng_cv_wake()`>>.
+
+== RETURN VALUES
+
+None.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_cv_alloc.3supp#,nng_cv_alloc(3supp)>>,
+<<nng_cv_until.3supp#,nng_cv_until(3supp)>>,
+<<nng_cv_wait.3supp#,nng_cv_wait(3supp)>>,
+<<nng_cv_wake.3supp#,nng_cv_wake(3supp)>>,
+<<nng_mtx_alloc.3supp#,nng_mtx_alloc(3supp)>>,
+<<nng_mtx_lock.3supp#,nng_mtx_lock(3supp)>>,
+<<nng_mtx_unlock.3supp#,nng_mtx_unlock(3supp)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_msleep.3supp.adoc b/docs/man/nng_msleep.3supp.adoc
new file mode 100644
index 00000000..f3e7f25c
--- /dev/null
+++ b/docs/man/nng_msleep.3supp.adoc
@@ -0,0 +1,48 @@
+= nng_msleep(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_msleep - sleep milliseconds
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_msleep(nng_duration msec);
+----
+
+== DESCRIPTION
+
+The `nng_msleep()` blocks the caller for at least _msec_ milliseconds.
+
+NOTE: This function may block for longer than requested.
+The actual wait time is determined by the capabilities of the
+underlying system.
+
+== RETURN VALUES
+
+None.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_sleep_aio.3#,nng_sleep_aio(3)>>,
+<<nng_strerror.3#,nng_strerror(3)>>,
+<<nng_clock.3supp#,nng_clock(3supp)>>,
+<<nng_duration.5#,nng_duration(5)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_mtx_alloc.3supp.adoc b/docs/man/nng_mtx_alloc.3supp.adoc
new file mode 100644
index 00000000..ba4e0c06
--- /dev/null
+++ b/docs/man/nng_mtx_alloc.3supp.adoc
@@ -0,0 +1,56 @@
+= nng_mtx_alloc(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_mtx_alloc - allocate mutex
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+typedef struct nng_mtx nng_mtx;
+
+int nng_mtx_alloc(nng_mtx **mtxp);
+----
+
+== DESCRIPTION
+
+The `nng_mtx_alloc()` function allocates mutex and returns it in _mtxp_.
+
+The mutex objects created by this function are suitable only for
+simple lock and unlock operations, and are not recursive.
+Every effort has been made to use light-weight underlying primitives when available.
+
+Mutex (mutual exclusion) objects can be thought of as binary semaphores,
+where only a single thread of execution is permitted to "`own`" the semaphore.
+
+Furthermore, a mutex can only be unlocked by the thread that locked it.
+
+== RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+== ERRORS
+
+`NNG_ENOMEM`:: Insufficient free memory exists.
+
+== SEE ALSO
+
+<<nng_cv_alloc.3supp#,nng_cv_alloc(3supp)>>,
+<<nng_mtx_free.3supp#,nng_mtx_free(3supp)>>,
+<<nng_mtx_lock.3supp#,nng_mtx_lock(3supp)>>,
+<<nng_mtx_unlock.3supp#,nng_mtx_unlock(3supp)>>,
+<<nng_strerror.3#,nng_strerror(3)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_mtx_free.3supp.adoc b/docs/man/nng_mtx_free.3supp.adoc
new file mode 100644
index 00000000..f0cb44de
--- /dev/null
+++ b/docs/man/nng_mtx_free.3supp.adoc
@@ -0,0 +1,42 @@
+= nng_mtx_free(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_mtx_free - free mutex
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_mtx_free(nng_mtx *mtx);
+----
+
+== DESCRIPTION
+
+The `nng_mtx_free()` function frees the mutex _mtx_.
+The mutex must not be locked when this function is called.
+
+== RETURN VALUES
+
+None.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_mtx_alloc.3supp#,nng_mtx_alloc(3supp)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_mtx_lock.3supp.adoc b/docs/man/nng_mtx_lock.3supp.adoc
new file mode 100644
index 00000000..54aacd37
--- /dev/null
+++ b/docs/man/nng_mtx_lock.3supp.adoc
@@ -0,0 +1,63 @@
+= nng_mtx_lock(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_mtx_lock - lock mutex
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_mtx_lock(nng_mtx *mtx);
+----
+
+== DESCRIPTION
+
+The `nng_mtx_lock()` acquires exclusive ownership of the mutex _mtx_.
+If the lock is already owned, this function will wait until the current
+owner releases it with <<nng_mtx_unlock.3supp#,`nng_mtx_unlock()`>>.
+
+If multiple threads are waiting for the lock, the order of acquisition
+is not specified.
+
+NOTE: A mutex can _only_ be unlocked by the thread that locked it.
+
+IMPORTANT: Mutex locks are _not_ recursive; attempts to reacquire the
+same mutex may result in deadlock or aborting the current program.
+It is a programming error for the owner of a mutex to attempt to
+reacquire it.
+
+****
+_NNG_ offers neither a "`trylock`" operation, nor recursive mutexes.
+This is by design, as _NNG_ itself does not use such things,
+and most often the need for them is the result of poor design.
+If such capabilities are needed, they may be synthesized fairly
+easily from mutexes and condition variables.
+****
+
+== RETURN VALUES
+
+None.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_cv_alloc.3supp#,nng_cv_alloc(3supp)>>,
+<<nng_mtx_alloc.3supp#,nng_mtx_alloc(3supp)>>,
+<<nng_mtx_unlock.3supp#,nng_mtx_unlock(3supp)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_mtx_unlock.3supp.adoc b/docs/man/nng_mtx_unlock.3supp.adoc
new file mode 100644
index 00000000..281a3f1e
--- /dev/null
+++ b/docs/man/nng_mtx_unlock.3supp.adoc
@@ -0,0 +1,47 @@
+= nng_mtx_unlock(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_mtx_lock - lock mutex
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_mtx_unlock(nng_mtx *mtx);
+----
+
+== DESCRIPTION
+
+The `nng_mtx_unlock()` reqlinquishes ownership of the mutex _mtx_ that
+was previously acquired via <<nng_mtx_lock.3supp#,`nng_mtx_lock()`>>.
+
+IMPORTANT: A mutex can _only_ be unlocked by the thread that locked it.
+Attempting to unlock a mutex that is not owned by the caller will result
+in undefined behavior.
+
+== RETURN VALUES
+
+None.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_mtx_alloc.3supp#,nng_mtx_alloc(3supp)>>,
+<<nng_mtx_lock.3supp#,nng_mtx_lock(3supp)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_opts_parse.3supp b/docs/man/nng_opts_parse.3supp.adoc
index 6fc22a7f..6fc22a7f 100644
--- a/docs/man/nng_opts_parse.3supp
+++ b/docs/man/nng_opts_parse.3supp.adoc
diff --git a/docs/man/nng_random.3supp.adoc b/docs/man/nng_random.3supp.adoc
new file mode 100644
index 00000000..9003fea8
--- /dev/null
+++ b/docs/man/nng_random.3supp.adoc
@@ -0,0 +1,44 @@
+= nng_random(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_random - get random number
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+uint32_t nng_random(void);
+----
+
+== DESCRIPTION
+
+The `nng_random()` returns a random number.
+The value returned is suitable for use with cryptographic functions such as
+key generation.
+The value is obtained using platform specific cryptographically strong random
+number facilities when available.
+
+== RETURN VALUES
+
+Random number.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_thread_create.3supp.adoc b/docs/man/nng_thread_create.3supp.adoc
new file mode 100644
index 00000000..359dabab
--- /dev/null
+++ b/docs/man/nng_thread_create.3supp.adoc
@@ -0,0 +1,85 @@
+= nng_thread_create(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_thread_create - create thread
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+typedef struct nng_thread nng_thread;
+
+int nng_thread_create(nng_thread **thrp, void (*func)(void *), void *arg);
+----
+
+== DESCRIPTION
+
+The `nng_thread_create()` function creates a single thread of execution,
+running _func_ with the argument _arg_.
+The thread is started immediately.
+A pointer to the thread object is returned in _thrp_.
+
+The intention of this program is to facilitate writing parallel programs.
+Threads created by this program will be based upon the underlying
+threading mechanism of the system that _NNG_ is running on.
+This may include use of so-called "`green threads`" or coroutines.
+
+Using threads created by this function can make it easy to write
+programs that use simple sequential execution, using functions in the
+_NNG_ suite that would otherwise normally "`block`".
+
+When the thread is no longer needed, the
+<<nng_thread_destroy.3supp#,`nng_thread_destroy()`>>
+function should be used to reap it.
+(This function will block waiting for _func_ to return.)
+
+IMPORTANT: Thread objects created by this function may not be "`real`"
+threads capable of performing blocking I/O operations using normal blocking
+system calls.
+If use of blocking system calls is required (not including APIs provided
+by the _NNG_ library itself of course), then real OS-specific threads
+should be created instead (such as with `pthread_create()` or similar
+functions.)
+
+IMPORTANT: Thread objects created by this function cannot be passed
+to any system threading functions.
+
+TIP: The system may impose limits on the number of threads that can be
+created.
+Typically applications should not create more than a few dozen of these.
+If greater concurrency or scalability is needed, consider instead using
+an asynchronous model using <<nng_aio.5#,`nng_aio`>> structures.
+
+TIP: Threads can be synchronized using
+<<nng_mtx_alloc.3supp#,mutexes>> and
+<<nng_cv_alloc.3supp#,condition variables>>.
+
+== RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+== ERRORS
+
+`NNG_ENOMEM`:: Insufficient free memory exists.
+
+== SEE ALSO
+
+<<nng_strerror.3#,nng_strerror(3)>>,
+<<nng_cv_alloc.3supp#,nng_cv_alloc(3supp)>>,
+<<nng_mtx_alloc.3supp#,nng_mtx_alloc(3supp)>>,
+<<nng_thread_destroy.3supp#,nng_thread_destroy(3supp)>>,
+<<nng_aio.5#,nng_aio(5)>>,
+<<nng.7#,nng(7)>>
diff --git a/docs/man/nng_thread_destroy.3supp.adoc b/docs/man/nng_thread_destroy.3supp.adoc
new file mode 100644
index 00000000..b58c623b
--- /dev/null
+++ b/docs/man/nng_thread_destroy.3supp.adoc
@@ -0,0 +1,46 @@
+= nng_thread_destroy(3supp)
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This document is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+== NAME
+
+nng_thread_destroy - reap thread
+
+== SYNOPSIS
+
+[source, c]
+----
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_thread_destroy(nng_thread *thread);
+----
+
+== DESCRIPTION
+
+The `nng_thread_destroy()` function reaps the _thread_.
+It waits for the thread function to return, and then deallocates
+the resources for the thread.
+
+IMPORTANT: Do not call this function from the thread function itself,
+or a deadlock will occur.
+
+== RETURN VALUES
+
+None.
+
+== ERRORS
+
+None.
+
+== SEE ALSO
+
+<<nng_thread_create.3supp#,nng_thread_create(3supp)>>,
+<<nng.7#,nng(7)>>
diff --git a/src/supplemental/util/platform.h b/src/supplemental/util/platform.h
index fd287713..0fcc7d16 100644
--- a/src/supplemental/util/platform.h
+++ b/src/supplemental/util/platform.h
@@ -34,7 +34,7 @@ typedef uint64_t nng_time;
// Return an absolute time from some arbitrary point. The value is
// provided in milliseconds, and is of limited resolution based on the
// system clock. (Do not use it for fine grained performance measurements.)
-NNG_DECL uint64_t nng_clock(void);
+NNG_DECL nng_time nng_clock(void);
// Sleep for specified msecs.
NNG_DECL void nng_msleep(nng_duration);