summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McDonald <danmcd@joyent.com>2022-03-16 10:41:36 -0400
committerDan McDonald <danmcd@joyent.com>2022-03-16 10:41:36 -0400
commiteae574cd3b89246be0d09bdc9a0516998487580e (patch)
tree5c3dc204feaaf2cc24d520ec45d2b79fdb1e1e0b
parentbff406848a57f4f8d67eb0e8c84224377034048e (diff)
parente8d712970f7ec76e09d5013b0b9aa5f0e0cf3e62 (diff)
downloadillumos-joyent-eae574cd3b89246be0d09bdc9a0516998487580e.tar.gz
[illumos-gate merge]
commit e8d712970f7ec76e09d5013b0b9aa5f0e0cf3e62 14517 bhyve EVF_VNODE mevent on plain file fires on every data change commit 7bb0eb348e1119aed76a61d633a9106b6b9912f1 14521 bhyve should use error checking mutexes and check results 14522 Provide PTHREAD_{ERRORCHECK,RECURSIVE}_MUTEX_INITIALIZER_NP commit 499bc737cd392291f0c92dcebcb576970689f5d8 14561 fwflash -l on ufm without known PCI device id crashes Conflicts: usr/src/cmd/bhyve/Makefile
-rw-r--r--usr/src/cmd/bhyve/Makefile3
-rw-r--r--usr/src/cmd/bhyve/mevent.c148
-rw-r--r--usr/src/cmd/bhyve/pci_nvme.c10
-rw-r--r--usr/src/cmd/bhyve/pci_virtio_console.c4
-rw-r--r--usr/src/cmd/bhyve/pci_virtio_rnd.c4
-rw-r--r--usr/src/cmd/bhyve/rfb.c4
-rw-r--r--usr/src/cmd/bhyve/test/Makefile.com2
-rw-r--r--usr/src/cmd/bhyve/test/tests/mevent/vnode_file.c21
-rw-r--r--usr/src/cmd/fwflash/Makefile.com3
-rw-r--r--usr/src/cmd/fwflash/plugins/transport/common/ufm.c4
-rw-r--r--usr/src/compat/bhyve/pthread.h61
-rw-r--r--usr/src/head/pthread.h15
-rw-r--r--usr/src/lib/libc/port/mapfile-vers2
-rw-r--r--usr/src/lib/libc/port/threads/synch.c18
-rw-r--r--usr/src/man/man3c/pthread_mutex_init.3c349
-rw-r--r--usr/src/man/man3head/pthread.h.3head239
16 files changed, 441 insertions, 446 deletions
diff --git a/usr/src/cmd/bhyve/Makefile b/usr/src/cmd/bhyve/Makefile
index f9857645a7..fcf93c5647 100644
--- a/usr/src/cmd/bhyve/Makefile
+++ b/usr/src/cmd/bhyve/Makefile
@@ -158,14 +158,13 @@ $(PROG) := LDLIBS += \
-ldladm \
-lmd \
-lnvpair \
- -lproc \
-lsunw_crypto \
-luuid \
-lvmmapi \
-lz
NATIVE_LIBS += libz.so libsunw_crypto.so
$(ZHYVE_PROG) := LDLIBS += -lnvpair
-$(MEVENT_TEST_PROG) := LDLIBS += -lsocket -lproc
+$(MEVENT_TEST_PROG) := LDLIBS += -lsocket
$(PROG) := LDFLAGS += $(ZASLR)
.KEEP_STATE:
diff --git a/usr/src/cmd/bhyve/mevent.c b/usr/src/cmd/bhyve/mevent.c
index 576ba3390e..29f7d7fcfc 100644
--- a/usr/src/cmd/bhyve/mevent.c
+++ b/usr/src/cmd/bhyve/mevent.c
@@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$");
#include <sys/siginfo.h>
#include <sys/queue.h>
#include <sys/debug.h>
-#include <libproc.h>
+#include <sys/stat.h>
#endif
#include <sys/time.h>
@@ -114,8 +114,6 @@ struct mevent {
port_notify_t me_notify;
struct sigevent me_sigev;
boolean_t me_auto_requeue;
- struct file_obj me_fobj;
- char *me_fname;
struct {
int mp_fd;
off_t mp_size;
@@ -356,41 +354,6 @@ mevent_clarify_state(struct mevent *mevp)
return (B_TRUE);
}
-static char *
-mevent_fdpath(int fd)
-{
- prfdinfo_t *fdinfo;
- char *path;
- size_t len;
-
- fdinfo = proc_get_fdinfo(getpid(), fd);
- if (fdinfo == NULL) {
- (void) fprintf(stderr, "%s: proc_get_fdinfo(%d) failed: %s\n",
- __func__, fd, strerror(errno));
- path = NULL;
- } else {
- path = (char *)proc_fdinfo_misc(fdinfo, PR_PATHNAME, &len);
- }
-
- if (path == NULL) {
- (void) fprintf(stderr, "%s: Fall back to /proc/self/fd/%d\n",
- __func__, fd);
- (void) asprintf(&path, "/proc/self/fd/%d", fd);
- } else {
- path = strdup(path);
- }
-
- proc_fdinfo_free(fdinfo);
-
- if (path == NULL) {
- (void) fprintf(stderr,
- "%s: Error building path for fd %d: %s\n", __func__,
- fd, strerror(errno));
- }
-
- return (path);
-}
-
static void
mevent_poll_file_attrib(int fd, enum ev_type type, void *param)
{
@@ -398,18 +361,17 @@ mevent_poll_file_attrib(int fd, enum ev_type type, void *param)
struct stat st;
if (fstat(mevp->me_poll.mp_fd, &st) != 0) {
- (void) fprintf(stderr, "%s: fstat(%d) \"%s\" failed: %s\n",
- __func__, fd, mevp->me_fname, strerror(errno));
+ (void) fprintf(stderr, "%s: fstat(%d) failed: %s\n",
+ __func__, fd, strerror(errno));
return;
}
- if (mevp->me_poll.mp_size != st.st_size ||
- mevp->me_fobj.fo_ctime.tv_sec != st.st_ctim.tv_sec ||
- mevp->me_fobj.fo_ctime.tv_nsec != st.st_ctim.tv_nsec) {
+ /*
+ * The only current consumer of file attribute monitoring is
+ * blockif, which wants to know about size changes.
+ */
+ if (mevp->me_poll.mp_size != st.st_size) {
mevp->me_poll.mp_size = st.st_size;
- mevp->me_fobj.fo_atime = st.st_atim;
- mevp->me_fobj.fo_mtime = st.st_mtim;
- mevp->me_fobj.fo_ctime = st.st_ctim;
(*mevp->me_poll.mp_func)(mevp->me_poll.mp_fd, EVF_VNODE,
mevp->me_poll.mp_param);
@@ -508,13 +470,10 @@ mevent_update_one_timer(struct mevent *mevp)
static void
mevent_update_one_vnode(struct mevent *mevp)
{
- int portfd = mevp->me_notify.portnfy_port;
-
- mevp->me_auto_requeue = B_FALSE;
-
switch (mevp->me_state) {
case EV_ENABLE:
{
+ struct stat st;
int events = 0;
if ((mevp->me_fflags & EVFF_ATTRIB) != 0)
@@ -522,76 +481,44 @@ mevent_update_one_vnode(struct mevent *mevp)
assert(events != 0);
- if (mevp->me_fname == NULL) {
- mevp->me_fname = mevent_fdpath(mevp->me_fd);
- if (mevp->me_fname == NULL)
- return;
- }
-
- bzero(&mevp->me_fobj, sizeof (mevp->me_fobj));
- mevp->me_fobj.fo_name = mevp->me_fname;
-
- if (port_associate(portfd, PORT_SOURCE_FILE,
- (uintptr_t)&mevp->me_fobj, events, mevp) != 0) {
- /*
- * If this file does not support event ports
- * (e.g. ZVOLs do not yet have support)
- * then convert this to a timer event and poll for
- * file attribute changes.
- */
- struct stat st;
-
- if (errno != ENOTSUP) {
- (void) fprintf(stderr,
- "port_associate fd %d (%s) %p failed: %s"
- ", polling instead\n",
- mevp->me_fd, mevp->me_fname, mevp,
- strerror(errno));
- }
+ /*
+ * It is tempting to use the PORT_SOURCE_FILE type for this in
+ * conjunction with the FILE_ATTRIB event type. Unfortunately
+ * this event type triggers on any change to the file's
+ * ctime, and therefore for every write as well as attribute
+ * changes. It also does not work for ZVOLs.
+ *
+ * Convert this to a timer event and poll for the file
+ * attribute changes that we care about.
+ */
- if (fstat(mevp->me_fd, &st) != 0) {
- (void) fprintf(stderr,
- "fstat(%d) \"%s\" failed: %s\n",
- mevp->me_fd, mevp->me_fname,
- strerror(errno));
- return;
- }
+ if (fstat(mevp->me_fd, &st) != 0) {
+ (void) fprintf(stderr, "fstat(%d) failed: %s\n",
+ mevp->me_fd, strerror(errno));
+ return;
+ }
- mevp->me_fobj.fo_atime = st.st_atim;
- mevp->me_fobj.fo_mtime = st.st_mtim;
- mevp->me_fobj.fo_ctime = st.st_ctim;
+ mevp->me_poll.mp_fd = mevp->me_fd;
+ mevp->me_poll.mp_size = st.st_size;
- mevp->me_poll.mp_fd = mevp->me_fd;
- mevp->me_poll.mp_size = st.st_size;
+ mevp->me_poll.mp_func = mevp->me_func;
+ mevp->me_poll.mp_param = mevp->me_param;
+ mevp->me_func = mevent_poll_file_attrib;
+ mevp->me_param = mevp;
- mevp->me_poll.mp_func = mevp->me_func;
- mevp->me_poll.mp_param = mevp->me_param;
- mevp->me_func = mevent_poll_file_attrib;
- mevp->me_param = mevp;
+ mevp->me_type = EVF_TIMER;
+ mevp->me_timid = -1;
+ mevp->me_msecs = mevent_file_poll_interval_ms;
+ mevent_update_one_timer(mevp);
- mevp->me_type = EVF_TIMER;
- mevp->me_timid = -1;
- mevp->me_msecs = mevent_file_poll_interval_ms;
- mevent_update_one_timer(mevp);
- }
return;
}
case EV_DISABLE:
case EV_DELETE:
/*
- * A disable that comes in while an event is being
- * handled will result in an ENOENT.
+ * These events do not really exist as they are converted to
+ * timers; fall through to abort.
*/
- if (port_dissociate(portfd, PORT_SOURCE_FILE,
- (uintptr_t)&mevp->me_fobj) != 0 &&
- errno != ENOENT) {
- (void) fprintf(stderr, "port_dissociate "
- "portfd %d fd %d mevp %p failed: %s\n",
- portfd, mevp->me_fd, mevp, strerror(errno));
- }
- free(mevp->me_fname);
- mevp->me_fname = NULL;
- return;
default:
(void) fprintf(stderr, "%s: unhandled state %d\n", __func__,
mevp->me_state);
@@ -654,7 +581,6 @@ mevent_update_pending()
LIST_REMOVE(mevp, me_list);
if (mevp->me_state & EV_DELETE) {
- free(mevp->me_fname);
free(mevp);
} else {
LIST_INSERT_HEAD(&global_head, mevp, me_list);
@@ -669,8 +595,6 @@ mevent_handle_pe(port_event_t *pe)
{
struct mevent *mevp = pe->portev_user;
- mevent_qunlock();
-
(*mevp->me_func)(mevp->me_fd, mevp->me_type, mevp->me_param);
mevent_qlock();
diff --git a/usr/src/cmd/bhyve/pci_nvme.c b/usr/src/cmd/bhyve/pci_nvme.c
index 73e8ab0371..a69c49a388 100644
--- a/usr/src/cmd/bhyve/pci_nvme.c
+++ b/usr/src/cmd/bhyve/pci_nvme.c
@@ -460,8 +460,13 @@ pci_nvme_init_queues(struct pci_nvme_softc *sc, uint32_t nsq, uint32_t ncq)
} else {
struct nvme_submission_queue *sq = sc->submit_queues;
+#ifndef __FreeBSD__
+ for (i = 0; i < sc->num_squeues + 1; i++)
+ pthread_mutex_init(&sq[i].mtx, NULL);
+#else
for (i = 0; i < sc->num_squeues; i++)
pthread_mutex_init(&sq[i].mtx, NULL);
+#endif
}
/*
@@ -483,8 +488,13 @@ pci_nvme_init_queues(struct pci_nvme_softc *sc, uint32_t nsq, uint32_t ncq)
} else {
struct nvme_completion_queue *cq = sc->compl_queues;
+#ifndef __FreeBSD__
+ for (i = 0; i < sc->num_cqueues + 1; i++)
+ pthread_mutex_init(&cq[i].mtx, NULL);
+#else
for (i = 0; i < sc->num_cqueues; i++)
pthread_mutex_init(&cq[i].mtx, NULL);
+#endif
}
}
diff --git a/usr/src/cmd/bhyve/pci_virtio_console.c b/usr/src/cmd/bhyve/pci_virtio_console.c
index 998d5e1d4c..a153dc7ae3 100644
--- a/usr/src/cmd/bhyve/pci_virtio_console.c
+++ b/usr/src/cmd/bhyve/pci_virtio_console.c
@@ -725,6 +725,10 @@ pci_vtcon_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl)
sc->vsc_config->cols = 80;
sc->vsc_config->rows = 25;
+#ifndef __FreeBSD__
+ pthread_mutex_init(&sc->vsc_mtx, NULL);
+#endif
+
vi_softc_linkup(&sc->vsc_vs, &vtcon_vi_consts, sc, pi, sc->vsc_queues);
sc->vsc_vs.vs_mtx = &sc->vsc_mtx;
diff --git a/usr/src/cmd/bhyve/pci_virtio_rnd.c b/usr/src/cmd/bhyve/pci_virtio_rnd.c
index 7807bac7a8..8e7f995e9f 100644
--- a/usr/src/cmd/bhyve/pci_virtio_rnd.c
+++ b/usr/src/cmd/bhyve/pci_virtio_rnd.c
@@ -179,6 +179,10 @@ pci_vtrnd_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl)
sc = calloc(1, sizeof(struct pci_vtrnd_softc));
+#ifndef __FreeBSD__
+ pthread_mutex_init(&sc->vrsc_mtx, NULL);
+#endif
+
vi_softc_linkup(&sc->vrsc_vs, &vtrnd_vi_consts, sc, pi, &sc->vrsc_vq);
sc->vrsc_vs.vs_mtx = &sc->vrsc_mtx;
diff --git a/usr/src/cmd/bhyve/rfb.c b/usr/src/cmd/bhyve/rfb.c
index a441deb398..86b0d6d456 100644
--- a/usr/src/cmd/bhyve/rfb.c
+++ b/usr/src/cmd/bhyve/rfb.c
@@ -1361,9 +1361,9 @@ rfb_init_unix(const char *path, int wait, char *password, const char *name)
if (wait) {
DPRINTF(("Waiting for rfb client...\n"));
- VERIFY3S(pthread_mutex_lock(&rc->mtx), ==, 0);
+ pthread_mutex_lock(&rc->mtx);
VERIFY3S(pthread_cond_wait(&rc->cond, &rc->mtx), ==, 0);
- VERIFY3S(pthread_mutex_unlock(&rc->mtx), ==, 0);
+ pthread_mutex_unlock(&rc->mtx);
}
return (0);
diff --git a/usr/src/cmd/bhyve/test/Makefile.com b/usr/src/cmd/bhyve/test/Makefile.com
index 1d1aa1e630..df86846eff 100644
--- a/usr/src/cmd/bhyve/test/Makefile.com
+++ b/usr/src/cmd/bhyve/test/Makefile.com
@@ -29,8 +29,6 @@ CPPFLAGS = -I$(COMPAT)/bhyve -I$(CONTRIB)/bhyve \
-I$(SRC)/cmd/bhyve \
-DWITHOUT_CAPSICUM
-LDFLAGS += -lproc
-
SMOFF += all_func_returns
CLOBBERFILES += $(PROG)
diff --git a/usr/src/cmd/bhyve/test/tests/mevent/vnode_file.c b/usr/src/cmd/bhyve/test/tests/mevent/vnode_file.c
index 850ac1be27..c3df405edb 100644
--- a/usr/src/cmd/bhyve/test/tests/mevent/vnode_file.c
+++ b/usr/src/cmd/bhyve/test/tests/mevent/vnode_file.c
@@ -29,7 +29,7 @@
#include "testlib.h"
#include "mevent.h"
-static char *cookie = "Chocolate chip with fudge stripes";
+static char *cookie = "Shortcake";
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
@@ -67,8 +67,6 @@ test_fd(int fd, char *tag)
for (uint_t i = 0; cookie[i] != '\0'; i++) {
ssize_t written;
- pthread_mutex_lock(&mtx);
-
if (i > 0) {
/*
* Check that no events are emitted for writes which do
@@ -78,12 +76,21 @@ test_fd(int fd, char *tag)
FAIL_ERRNO("lseek");
if (write(fd, "X", 1) == -1)
FAIL_ERRNO("write");
+ /*
+ * Allow time for the callback to fire if it is going
+ * to.
+ */
+ VERBOSE(("Write within"));
+ usleep(100);
}
+ pthread_mutex_lock(&mtx);
+
written = write(fd, cookie + i, 1);
if (written < 0)
FAIL_ERRNO("bad write");
ASSERT_INT64_EQ(("write byte %d of cookie", i), written, 1);
+ VERBOSE(("Write extend"));
/* Wait for the size change to be processed */
pthread_cond_wait(&cv, &mtx);
@@ -93,7 +100,7 @@ test_fd(int fd, char *tag)
* for mevent to re-associate the port or the next write could
* be missed.
*/
- usleep(500);
+ usleep(100);
}
err = mevent_disable(evp);
@@ -105,10 +112,12 @@ test_fd(int fd, char *tag)
int
main(int argc, const char **argv)
{
- start_test(argv[0], 5);
- start_event_thread();
int fd;
+ start_test(argv[0], 20);
+ set_mevent_file_poll_interval_ms(500);
+ start_event_thread();
+
/* Test with a temporary file in /tmp */
char *template = strdup("/tmp/mevent.vnode.XXXXXX");
ASSERT_PTR_NEQ(("strdup"), template, NULL);
diff --git a/usr/src/cmd/fwflash/Makefile.com b/usr/src/cmd/fwflash/Makefile.com
index 08b90ce62b..9ada7accb3 100644
--- a/usr/src/cmd/fwflash/Makefile.com
+++ b/usr/src/cmd/fwflash/Makefile.com
@@ -26,7 +26,6 @@
# common rules for $SRC/cmd/fwflash
CERRWARN += -_gcc=-Wno-parentheses
-CERRWARN += $(CNOWARN_UNINIT)
CERRWARN += -_gcc=-Wno-address
# not linted
@@ -94,7 +93,7 @@ $(ROOTUSRSBIN)/%: %
$(POFILE): $(POFILES)
$(RM) $@
- cat $(POFILES) >$@
+ cat $(POFILES) >$@
LINTFLAGS += -D_POSIX_PTHREAD_SEMANTICS -erroff=E_CONSTANT_CONDITION \
-erroff=E_SUPPRESSION_DIRECTIVE_UNUSED
diff --git a/usr/src/cmd/fwflash/plugins/transport/common/ufm.c b/usr/src/cmd/fwflash/plugins/transport/common/ufm.c
index 5e9cb3abc6..9b6709f3c8 100644
--- a/usr/src/cmd/fwflash/plugins/transport/common/ufm.c
+++ b/usr/src/cmd/fwflash/plugins/transport/common/ufm.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright 2020 Oxide Computer Company
+ * Copyright 2022 Oxide Computer Company
*/
/*
@@ -299,7 +299,7 @@ ufmfw_fill_vpd(struct devicelist *flashdev, di_node_t node)
}
flashdev->ident->vid = vstr;
- if (dstr != NULL) {
+ if (dev != NULL) {
dstr = strdup(pcidb_device_name(dev));
} else {
(void) asprintf(&dstr, "pci:%x", did[0]);
diff --git a/usr/src/compat/bhyve/pthread.h b/usr/src/compat/bhyve/pthread.h
new file mode 100644
index 0000000000..de975971b5
--- /dev/null
+++ b/usr/src/compat/bhyve/pthread.h
@@ -0,0 +1,61 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
+ */
+
+#ifndef _COMPAT_FREEBSD_PTHREAD_H_
+#define _COMPAT_FREEBSD_PTHREAD_H_
+
+#include <sys/debug.h>
+#include_next <pthread.h>
+
+/*
+ * Mutexes on FreeBSD are error-checking by default. Wrap pthread_mutex_*()
+ * to deliver the same, and check for errors.
+ */
+
+#undef PTHREAD_MUTEX_INITIALIZER
+#define PTHREAD_MUTEX_INITIALIZER PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+
+static __inline int
+checked_pthread_mutex_init(pthread_mutex_t *restrict mutex,
+ const pthread_mutexattr_t *restrict cattr)
+{
+ if (cattr != NULL) {
+ VERIFY0(pthread_mutex_init(mutex, cattr));
+ } else {
+ pthread_mutexattr_t attr = { 0 };
+
+ VERIFY0(pthread_mutexattr_init(&attr));
+ VERIFY0(pthread_mutexattr_settype(&attr,
+ PTHREAD_MUTEX_ERRORCHECK));
+ VERIFY0(pthread_mutex_init(mutex, &attr));
+ VERIFY0(pthread_mutexattr_destroy(&attr));
+ }
+
+ return (0);
+}
+
+static __inline int
+checked_pthread_mutex_destroy(pthread_mutex_t *mutex)
+{
+ VERIFY0(pthread_mutex_destroy(mutex));
+ return (0);
+}
+
+#define pthread_mutex_init(m, a) checked_pthread_mutex_init(m, a)
+#define pthread_mutex_destroy(m) checked_pthread_mutex_destroy(m)
+#define pthread_mutex_lock(m) pthread_mutex_enter_np(m)
+#define pthread_mutex_unlock(m) pthread_mutex_exit_np(m)
+
+#endif /* _COMPAT_FREEBSD_PTHREAD_H_ */
diff --git a/usr/src/head/pthread.h b/usr/src/head/pthread.h
index 490a93f1b2..a4db3e262b 100644
--- a/usr/src/head/pthread.h
+++ b/usr/src/head/pthread.h
@@ -22,6 +22,7 @@
/*
* Copyright 2014 Garrett D'Amore <garrett@damore.org>
* Copyright 2018 Joyent, Inc.
+ * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -110,6 +111,14 @@ extern "C" {
#define PTHREAD_MUTEX_INITIALIZER /* = DEFAULTMUTEX */ \
{{0, 0, 0, PTHREAD_PROCESS_PRIVATE, _MUTEX_MAGIC}, {{{0}}}, 0}
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP /* = ERRORCHECKMUTEX */ \
+ {{0, 0, 0, PTHREAD_PROCESS_PRIVATE | PTHREAD_MUTEX_ERRORCHECK, \
+ _MUTEX_MAGIC}, {{{0}}}, 0}
+
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP /* = RECURSIVEMUTEX */ \
+ {{0, 0, 0, PTHREAD_PROCESS_PRIVATE | PTHREAD_MUTEX_RECURSIVE | \
+ PTHREAD_MUTEX_ERRORCHECK, _MUTEX_MAGIC}, {{{0}}}, 0}
+
#define PTHREAD_COND_INITIALIZER /* = DEFAULTCV */ \
{{{0, 0, 0, 0}, PTHREAD_PROCESS_PRIVATE, _COND_MAGIC}, 0}
@@ -346,9 +355,11 @@ extern int pthread_mutexattr_getrobust_np(
* These are non-standardized extensions that we provide. Their origins are
* documented in their manual pages.
*/
-#if !defined(_STRICT_SYMBOLS) || defined(__EXTENSIONS__)
+#if !defined(_STRICT_SYMBOLS)
extern int pthread_attr_get_np(pthread_t, pthread_attr_t *);
-#endif /* !_STRICT_SYMBOLS || __EXTENSIONS__ */
+extern void pthread_mutex_enter_np(pthread_mutex_t *);
+extern void pthread_mutex_exit_np(pthread_mutex_t *);
+#endif /* !_STRICT_SYMBOLS */
#endif /* _ASM */
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index aa208035dc..46f3fa5f07 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -3760,6 +3760,8 @@ $endif
_psignal;
pthread_attr_getdaemonstate_np;
pthread_attr_setdaemonstate_np;
+ pthread_mutex_enter_np;
+ pthread_mutex_exit_np;
_pthread_setcleanupinit;
__putwchar_xpg5;
__putwc_xpg5;
diff --git a/usr/src/lib/libc/port/threads/synch.c b/usr/src/lib/libc/port/threads/synch.c
index 3ec76f7c21..b2c5980f9a 100644
--- a/usr/src/lib/libc/port/threads/synch.c
+++ b/usr/src/lib/libc/port/threads/synch.c
@@ -1781,7 +1781,7 @@ stall(void)
*/
int
mutex_lock_queue(ulwp_t *self, tdb_mutex_stats_t *msp, mutex_t *mp,
- timespec_t *tsp)
+ timespec_t *tsp)
{
uberdata_t *udp = curthread->ul_uberdata;
queue_head_t *qp;
@@ -2316,6 +2316,7 @@ mutex_lock(mutex_t *mp)
return (mutex_lock_impl(mp, NULL));
}
+#pragma weak pthread_mutex_enter_np = mutex_enter
void
mutex_enter(mutex_t *mp)
{
@@ -2341,7 +2342,7 @@ mutex_enter(mutex_t *mp)
int
pthread_mutex_timedlock(pthread_mutex_t *_RESTRICT_KYWD mp,
- const struct timespec *_RESTRICT_KYWD abstime)
+ const struct timespec *_RESTRICT_KYWD abstime)
{
timespec_t tslocal;
int error;
@@ -2356,7 +2357,7 @@ pthread_mutex_timedlock(pthread_mutex_t *_RESTRICT_KYWD mp,
int
pthread_mutex_reltimedlock_np(pthread_mutex_t *_RESTRICT_KYWD mp,
- const struct timespec *_RESTRICT_KYWD reltime)
+ const struct timespec *_RESTRICT_KYWD reltime)
{
timespec_t tslocal;
int error;
@@ -2598,6 +2599,7 @@ slow_unlock:
return (mutex_unlock_internal(mp, 0));
}
+#pragma weak pthread_mutex_exit_np = mutex_exit
void
mutex_exit(mutex_t *mp)
{
@@ -3574,7 +3576,7 @@ cond_wait(cond_t *cvp, mutex_t *mp)
*/
int
pthread_cond_wait(pthread_cond_t *_RESTRICT_KYWD cvp,
- pthread_mutex_t *_RESTRICT_KYWD mp)
+ pthread_mutex_t *_RESTRICT_KYWD mp)
{
int error;
@@ -3633,8 +3635,8 @@ cond_timedwait(cond_t *cvp, mutex_t *mp, const timespec_t *abstime)
*/
int
pthread_cond_timedwait(pthread_cond_t *_RESTRICT_KYWD cvp,
- pthread_mutex_t *_RESTRICT_KYWD mp,
- const struct timespec *_RESTRICT_KYWD abstime)
+ pthread_mutex_t *_RESTRICT_KYWD mp,
+ const struct timespec *_RESTRICT_KYWD abstime)
{
int error;
@@ -3677,8 +3679,8 @@ cond_reltimedwait(cond_t *cvp, mutex_t *mp, const timespec_t *reltime)
int
pthread_cond_reltimedwait_np(pthread_cond_t *_RESTRICT_KYWD cvp,
- pthread_mutex_t *_RESTRICT_KYWD mp,
- const struct timespec *_RESTRICT_KYWD reltime)
+ pthread_mutex_t *_RESTRICT_KYWD mp,
+ const struct timespec *_RESTRICT_KYWD reltime)
{
int error;
diff --git a/usr/src/man/man3c/pthread_mutex_init.3c b/usr/src/man/man3c/pthread_mutex_init.3c
index afaccd3574..2c34ddbe3a 100644
--- a/usr/src/man/man3c/pthread_mutex_init.3c
+++ b/usr/src/man/man3c/pthread_mutex_init.3c
@@ -43,192 +43,183 @@
.\" Copyright 1991, 1992, 1994, The X/Open Company Ltd.
.\" Copyright (c) 2001, The IEEE and The Open Group. All Rights Reserved.
.\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
.\"
-.TH PTHREAD_MUTEX_INIT 3C "Nov 11, 2008"
-.SH NAME
-pthread_mutex_init, pthread_mutex_destroy \- initialize or destroy a mutex
-.SH SYNOPSIS
-.LP
-.nf
-cc -mt [ \fIflag\fR... ] \fIfile\fR... -lpthread [ \fIlibrary\fR... ]
-#include <pthread.h>
-
-\fBint\fR \fBpthread_mutex_init\fR(\fBpthread_mutex_t *restrict\fR \fImutex\fR,
- \fBconst pthread_mutexattr_t *restrict\fR \fIattr\fR);
-.fi
-
-.LP
-.nf
-\fBint\fR \fBpthread_mutex_destroy\fR(\fBpthread_mutex_t *\fR\fImutex\fR);
-.fi
-
-.LP
-.nf
-\fBpthread_mutex_t\fR \fImutex\fR= \fBPTHREAD_MUTEX_INITIALIZER\fR;
-.fi
-
-.SH DESCRIPTION
-.sp
-.LP
-The \fBpthread_mutex_init()\fR function initializes the mutex referenced by
-\fImutex\fR with attributes specified by \fIattr\fR. If \fIattr\fR is
-\fINULL\fR, the default mutex attributes are used; the effect is the same as
-passing the address of a default mutex attributes object. Upon successful
+.Dd February 18, 2022
+.Dt PTHREAD_MUTEX_INIT 3C
+.Os
+.Sh NAME
+.Nm pthread_mutex_init ,
+.Nm pthread_mutex_destroy
+.Nd initialize or destroy a mutex
+.Sh SYNOPSIS
+.In pthread.h
+.Ft int
+.Fo pthread_mutex_init
+.Fa "pthread_mutex_t *restrict mutex"
+.Fa "const pthread_mutexattr_t *restrict attr"
+.Fc
+.Ft int
+.Fo pthread_mutex_destroy
+.Fa "pthread_mutex_t *mutex"
+.Fc
+.Vt pthread_mutex_t
+.Va mutex
+.No =
+.Dv PTHREAD_MUTEX_INITIALIZER ;
+.Vt pthread_mutex_t
+.Va ecmutex
+.No =
+.Dv PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP ;
+.Vt pthread_mutex_t
+.Va rmutex
+.No =
+.Dv PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ;
+.Sh DESCRIPTION
+The
+.Fn pthread_mutex_init
+function initializes the mutex referenced by
+.Fa mutex
+with attributes specified by
+.Fa attr .
+If
+.Fa attr
+is
+.Dv NULL ,
+the default mutex attributes are used; the effect is the same as
+passing the address of a default mutex attributes object.
+Upon successful
initialization, the state of the mutex becomes initialized and unlocked.
-.sp
-.LP
+.Pp
Except for robust mutexes, attempting to initialize an already initialized
mutex results in undefined behavior.
-.sp
-.LP
-The \fBpthread_mutex_destroy()\fR function destroys the mutex object referenced
-by \fImutex\fR; the mutex object becomes, in effect, uninitialized. A destroyed
-mutex object can be re-initialized using \fBpthread_mutex_init()\fR; the
-results of otherwise referencing the object after it has been destroyed are
+.Pp
+The
+.Fn pthread_mutex_destroy
+function destroys the mutex object referenced by
+.Fa mutex ;
+the mutex object becomes, in effect, uninitialized.
+A destroyed mutex object can be re-initialized using
+.Fn pthread_mutex_init ;
+the results of otherwise referencing the object after it has been destroyed are
undefined.
-.sp
-.LP
-It is safe to destroy an initialized mutex that is unlocked. Attempting to
-destroy a locked mutex results in undefined behavior.
-.sp
-.LP
+.Pp
+It is safe to destroy an initialized mutex that is unlocked.
+Attempting to destroy a locked mutex results in undefined behavior.
+.Pp
In cases where default mutex attributes are appropriate, the macro
-\fBPTHREAD_MUTEX_INITIALIZER\fR can be used to initialize mutexes that are
-statically allocated. The effect is equivalent to dynamic initialization by a
-call to \fBpthread_mutex_init()\fR with parameter \fIattr\fR specified as
-\fINULL\fR, except that no error checks are performed.
-.SH RETURN VALUES
-.sp
-.LP
-If successful, the \fBpthread_mutex_init()\fR and \fBpthread_mutex_destroy()\fR
-functions return \fB0\fR. Otherwise, an error number is returned to indicate
-the error.
-.SH ERRORS
-.sp
-.LP
-The \fBpthread_mutex_init()\fR function will fail if:
-.sp
-.ne 2
-.na
-\fB\fBEAGAIN\fR\fR
-.ad
-.RS 10n
-The system lacked the necessary resources (other than memory) to initialize
-another mutex.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBEBUSY\fR\fR
-.ad
-.RS 10n
-An attempt was detected to re-initialize a robust mutex previously initialized
-but not yet destroyed. See \fBpthread_mutexattr_setrobust\fR(3C).
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBEINVAL\fR\fR
-.ad
-.RS 10n
+.Dv PTHREAD_MUTEX_INITIALIZER
+can be used to initialize mutexes that are statically allocated.
+The effect is equivalent to dynamic initialization by a call to
+.Fn pthread_mutex_init
+with parameter
+.Fa attr
+specified as
+.Dv NULL .
+.Pp
+In cases where error checking mutex attributes are appropriate, the macro
+.Dv PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+can be used to initialize mutexes that are statically allocated.
+The effect is equivalent to dynamic initialization by a call to
+.Fn pthread_mutex_init
+with parameter
+.Fa attr
+initialized with
+.Xr pthread_mutexattr_init 3C
+and its type set to
+.Dv PTHREAD_MUTEX_ERRORCHECK .
+.Pp
+In cases where recursive mutex attributes are appropriate, the macro
+.Dv PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+can be used to initialize mutexes that are statically allocated.
+The effect is equivalent to dynamic initialization by a call to
+.Fn pthread_mutex_init
+with parameter
+.Fa attr
+initialized with
+.Xr pthread_mutexattr_init 3C
+and its type set to
+.Dv PTHREAD_MUTEX_RECURSIVE .
+.Sh RETURN VALUES
+If successful, the
+.Fn pthread_mutex_init
+and
+.Fn pthread_mutex_destroy
+functions return
+.Sy 0 .
+Otherwise, an error number is returned to indicate the error.
+.Sh ERRORS
+The
+.Fn pthread_mutex_init
+function will fail if:
+.Bl -tag -width Er
+.It Er EAGAIN
+The system lacked the necessary resources
+.Pq other than memory
+to initialize another mutex.
+.It Er EBUSY
An attempt was detected to re-initialize a robust mutex previously initialized
-with a different set of attributes. See \fBpthread_mutexattr_setrobust\fR(3C).
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBENOMEM\fR\fR
-.ad
-.RS 10n
+but not yet destroyed.
+See
+.Xr pthread_mutexattr_setrobust 3C .
+.It Ev EINVAL
+An attempt was detected to re-initialize a robust mutex previously initialized
+with a different set of attributes.
+See
+.Xr pthread_mutexattr_setrobust 3C .
+.It Er ENOMEM
Insufficient memory exists to initialize the mutex.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBEPERM\fR\fR
-.ad
-.RS 10n
+.It Er EPERM
The caller does not have the privilege to perform the operation.
-.RE
-
-.sp
-.LP
-The \fBpthread_mutex_init()\fR function may fail if:
-.sp
-.ne 2
-.na
-\fB\fBEBUSY\fR\fR
-.ad
-.RS 10n
-An attempt was detected to re-initialize the object referenced by \fImutex\fR,
+.El
+.Pp
+The
+.Fn pthread_mutex_init
+function may fail if:
+.Bl -tag -width Er
+.It Er EBUSY
+An attempt was detected to re-initialize the object referenced by
+.Fa mutex ,
a mutex previously initialized but not yet destroyed.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBEINVAL\fR\fR
-.ad
-.RS 10n
-The value specified by \fIattr\fR or \fImutex\fR is invalid.
-.RE
-
-.sp
-.LP
-The \fBpthread_mutex_destroy()\fR function may fail if:
-.sp
-.ne 2
-.na
-\fB\fBEBUSY\fR\fR
-.ad
-.RS 10n
-An attempt was detected to destroy the object referenced by \fImutex\fR while
-it is locked or referenced (for example, while being used in a
-\fBpthread_cond_wait\fR(3C) or \fBpthread_cond_timedwait\fR(3C)) by another
-thread.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBEINVAL\fR\fR
-.ad
-.RS 10n
-The value specified by \fImutex\fR is invalid.
-.RE
-
-.SH ATTRIBUTES
-.sp
-.LP
-See \fBattributes\fR(7) for descriptions of the following attributes:
-.sp
-
-.sp
-.TS
-box;
-c | c
-l | l .
-ATTRIBUTE TYPE ATTRIBUTE VALUE
-_
-Interface Stability Standard
-_
-MT-Level MT-Safe
-.TE
-
-.SH SEE ALSO
-.sp
-.LP
-.BR pthread_cond_wait (3C),
-.BR pthread_mutex_lock (3C),
-.BR pthread_mutexattr_setprioceiling (3C),
-.BR pthread_mutexattr_setprotocol (3C),
-.BR pthread_mutexattr_setpshared (3C),
-.BR pthread_mutexattr_setrobust (3C),
-.BR pthread_mutexattr_settype (3C),
-.BR attributes (7),
-.BR mutex (7),
-.BR standards (7)
+.It Er EINVAL
+The value specified by
+.Fa attr
+or
+.Fa mutex
+is invalid.
+.El
+.Pp
+The
+.Fn pthread_mutex_destroy
+function may fail if:
+.Bl -tag -width Er
+.It Er EBUSY
+An attempt was detected to destroy the object referenced by
+.Fa mutex
+while it is locked or referenced
+.Po
+for example, while being used in a
+.Xr pthread_cond_wait 3C
+or
+.Xr pthread_cond_timedwait 3C
+.Pc
+by another thread.
+.It Er EINVAL
+The value specified by
+.Fa mutex
+is invalid.
+.El
+.Sh INTERFACE STABILITY
+.Sy Committed
+.Sh MT-LEVEL
+.Sy MT-Safe
+.Sh SEE ALSO
+.Xr pthread_cond_timedwait 3C ,
+.Xr pthread_cond_wait 3C ,
+.Xr pthread_muteattr_init 3C ,
+.Xr pthread_mutex_lock 3C ,
+.Xr pthread_mutexattr_init 3C ,
+.Xr pthread_mutexattr_setrobust 3C ,
+.Xr pthread_mutexattr_settype 3C ,
+.Xr attributes 7 ,
+.Xr mutex 7
diff --git a/usr/src/man/man3head/pthread.h.3head b/usr/src/man/man3head/pthread.h.3head
index 174969ad5f..d5094d2b2d 100644
--- a/usr/src/man/man3head/pthread.h.3head
+++ b/usr/src/man/man3head/pthread.h.3head
@@ -42,133 +42,114 @@
.\"
.\" Copyright (c) 2001, The IEEE and The Open Group. All Rights Reserved.
.\" Portions Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
.\"
-.TH PTHREAD.H 3HEAD "Nov 11, 2008"
-.SH NAME
-pthread.h, pthread \- threads
-.SH SYNOPSIS
-.LP
-.nf
-#include <\fBpthread.h\fR>
-.fi
-
-.SH DESCRIPTION
-.sp
-.LP
-The <\fBpthread.h\fR> header defines the following symbols:
-.sp
-.in +2
-.nf
-PTHREAD_BARRIER_SERIAL_THREAD
-PTHREAD_CANCEL_ASYNCHRONOUS
-PTHREAD_CANCEL_ENABLE
-PTHREAD_CANCEL_DEFERRED
-PTHREAD_CANCEL_DISABLE
-PTHREAD_CANCELED
-PTHREAD_COND_INITIALIZER
-PTHREAD_CREATE_DETACHED
-PTHREAD_CREATE_JOINABLE
-PTHREAD_EXPLICIT_SCHED
-PTHREAD_INHERIT_SCHED
-PTHREAD_MUTEX_DEFAULT
-PTHREAD_MUTEX_ERRORCHECK
-PTHREAD_MUTEX_INITIALIZER
-PTHREAD_MUTEX_NORMAL
-PTHREAD_MUTEX_RECURSIVE
-PTHREAD_MUTEX_ROBUST
-PTHREAD_MUTEX_STALLED
-PTHREAD_ONCE_INIT
-PTHREAD_PRIO_INHERIT
-PTHREAD_PRIO_NONE
-PTHREAD_PRIO_PROTECT
-PTHREAD_PROCESS_SHARED
-PTHREAD_PROCESS_PRIVATE
-PTHREAD_RWLOCK_INITIALIZER
-PTHREAD_SCOPE_PROCESS
-PTHREAD_SCOPE_SYSTEM
-.fi
-.in -2
-
-.sp
-.LP
-The types listed below are defined as described in <\fBsys/types.h\fR>. See
-\fBtypes.h\fR(3HEAD).
-.sp
-.in +2
-.nf
-pthread_attr_t
-pthread_barrier_t
-pthread_barrierattr_t
-pthread_cond_t
-pthread_condattr_t
-pthread_key_t
-pthread_mutex_t
-pthread_mutexattr_t
-pthread_once_t
-pthread_rwlock_t
-pthread_rwlockattr_t
-pthread_spinlock_t
-pthread_t
-.fi
-.in -2
-
-.SH ATTRIBUTES
-.sp
-.LP
-See \fBattributes\fR(7) for descriptions of the following attributes:
-.sp
-
-.sp
-.TS
-box;
-c | c
-l | l .
-ATTRIBUTE TYPE ATTRIBUTE VALUE
-_
-Interface Stability Standard
-.TE
-
-.SH SEE ALSO
-.sp
-.LP
-.BR pthread_attr_getguardsize (3C),
-.BR pthread_attr_init (3C),
-.BR pthread_attr_setscope (3C),
-.BR pthread_cancel (3C),
-.BR pthread_cleanup_pop (3C),
-.BR pthread_cond_init (3C),
-.BR pthread_cond_signal (3C),
-.BR pthread_cond_wait (3C),
-.BR pthread_condattr_init (3C),
-.BR pthread_create (3C),
-.BR pthread_detach (3C),
-.BR pthread_equal (3C),
-.BR pthread_exit (3C),
-.BR pthread_getconcurrency (3C),
-.BR pthread_getschedparam (3C),
-.BR pthread_join (3C),
-.BR pthread_key_create (3C),
-.BR pthread_key_delete (3C),
-.BR pthread_mutex_consistent (3C),
-.BR pthread_mutex_init (3C),
-.BR pthread_mutex_lock (3C),
-.BR pthread_mutex_setprioceiling (3C),
-.BR pthread_mutexattr_getprotocol (3C),
-.BR pthread_mutexattr_getrobust (3C),
-.BR pthread_mutexattr_gettype (3C),
-.BR pthread_mutexattr_init (3C),
-.BR pthread_once (3C),
-.BR pthread_rwlock_init (3C),
-.BR pthread_rwlock_rdlock (3C),
-.BR pthread_rwlock_unlock (3C),
-.BR pthread_rwlock_wrlock (3C),
-.BR pthread_rwlockattr_getpshared (3C),
-.BR pthread_rwlockattr_init (3C),
-.BR pthread_self (3C),
-.BR pthread_setcancelstate (3C),
-.BR pthread_setspecific (3C),
-.BR sched.h (3HEAD),
-.BR time.h (3HEAD),
-.BR types.h (3HEAD),
-.BR attributes (7),
-.BR standards (7)
+.Dd February 19, 2022
+.Dt PTHREAD.H 3HEAD
+.Os
+.Sh NAME
+.Nm pthread.h ,
+.Nm pthread
+.Nd threads
+.Sh SYNOPSIS
+.In pthread.h
+.Sh DESCRIPTION
+The
+.In pthread.h
+header defines the following symbols:
+.Pp
+.Bl -inset -offset Ds -compact
+.It Dv PTHREAD_BARRIER_SERIAL_THREAD
+.It Dv PTHREAD_CANCEL_ASYNCHRONOUS
+.It Dv PTHREAD_CANCEL_ENABLE
+.It Dv PTHREAD_CANCEL_DEFERRED
+.It Dv PTHREAD_CANCEL_DISABLE
+.It Dv PTHREAD_CANCELED
+.It Dv PTHREAD_COND_INITIALIZER
+.It Dv PTHREAD_CREATE_DETACHED
+.It Dv PTHREAD_CREATE_JOINABLE
+.It Dv PTHREAD_EXPLICIT_SCHED
+.It Dv PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+.It Dv PTHREAD_INHERIT_SCHED
+.It Dv PTHREAD_MUTEX_DEFAULT
+.It Dv PTHREAD_MUTEX_ERRORCHECK
+.It Dv PTHREAD_MUTEX_INITIALIZER
+.It Dv PTHREAD_MUTEX_NORMAL
+.It Dv PTHREAD_MUTEX_RECURSIVE
+.It Dv PTHREAD_MUTEX_ROBUST
+.It Dv PTHREAD_MUTEX_STALLED
+.It Dv PTHREAD_ONCE_INIT
+.It Dv PTHREAD_PRIO_INHERIT
+.It Dv PTHREAD_PRIO_NONE
+.It Dv PTHREAD_PRIO_PROTECT
+.It Dv PTHREAD_PROCESS_SHARED
+.It Dv PTHREAD_PROCESS_PRIVATE
+.It Dv PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+.It Dv PTHREAD_RWLOCK_INITIALIZER
+.It Dv PTHREAD_SCOPE_PROCESS
+.It Dv PTHREAD_SCOPE_SYSTEM
+.El
+.Pp
+The types listed below are defined as described in
+.In sys/types.h .
+See
+.Xr types.h 3HEAD .
+.Pp
+.Bl -inset -offset Ds -compact
+.It Vt pthread_attr_t
+.It Vt pthread_barrier_t
+.It Vt pthread_barrierattr_t
+.It Vt pthread_cond_t
+.It Vt pthread_condattr_t
+.It Vt pthread_key_t
+.It Vt pthread_mutex_t
+.It Vt pthread_mutexattr_t
+.It Vt pthread_once_t
+.It Vt pthread_rwlock_t
+.It Vt pthread_rwlockattr_t
+.It Vt pthread_spinlock_t
+.It Vt pthread_t
+.El
+.Sh INTERFACE STABILITY
+.Sy Committed
+.Sh SEE ALSO
+.Xr pthread_attr_getguardsize 3C ,
+.Xr pthread_attr_init 3C ,
+.Xr pthread_attr_setscope 3C ,
+.Xr pthread_cancel 3C ,
+.Xr pthread_cleanup_pop 3C ,
+.Xr pthread_cond_init 3C ,
+.Xr pthread_cond_signal 3C ,
+.Xr pthread_cond_wait 3C ,
+.Xr pthread_condattr_init 3C ,
+.Xr pthread_create 3C ,
+.Xr pthread_detach 3C ,
+.Xr pthread_equal 3C ,
+.Xr pthread_exit 3C ,
+.Xr pthread_getconcurrency 3C ,
+.Xr pthread_getschedparam 3C ,
+.Xr pthread_join 3C ,
+.Xr pthread_key_create 3C ,
+.Xr pthread_key_delete 3C ,
+.Xr pthread_mutex_consistent 3C ,
+.Xr pthread_mutex_init 3C ,
+.Xr pthread_mutex_lock 3C ,
+.Xr pthread_mutex_setprioceiling 3C ,
+.Xr pthread_mutexattr_getprotocol 3C ,
+.Xr pthread_mutexattr_getrobust 3C ,
+.Xr pthread_mutexattr_gettype 3C ,
+.Xr pthread_mutexattr_init 3C ,
+.Xr pthread_once 3C ,
+.Xr pthread_rwlock_init 3C ,
+.Xr pthread_rwlock_rdlock 3C ,
+.Xr pthread_rwlock_unlock 3C ,
+.Xr pthread_rwlock_wrlock 3C ,
+.Xr pthread_rwlockattr_getpshared 3C ,
+.Xr pthread_rwlockattr_init 3C ,
+.Xr pthread_self 3C ,
+.Xr pthread_setcancelstate 3C ,
+.Xr pthread_setspecific 3C ,
+.Xr sched.h 3HEAD ,
+.Xr time.h 3HEAD ,
+.Xr types.h 3HEAD ,
+.Xr attributes 7