summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/Makefile.inc1
-rw-r--r--lib/libc/gen/Symbol.map4
-rw-r--r--lib/libc/gen/sem_new.c53
-rw-r--r--lib/libc/gen/sem_timedwait.362
-rw-r--r--lib/libc/include/namespace.h1
-rw-r--r--lib/libc/include/un-namespace.h1
6 files changed, 97 insertions, 25 deletions
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index a75a0d1..f1d1378 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -461,6 +461,7 @@ MLINKS+=scandir.3 alphasort.3
MLINKS+=sem_open.3 sem_close.3 \
sem_open.3 sem_unlink.3
MLINKS+=sem_wait.3 sem_trywait.3
+MLINKS+=sem_timedwait.3 sem_clockwait_np.3
MLINKS+=send.2 sendmmsg.2
MLINKS+=setjmp.3 _longjmp.3 \
setjmp.3 _setjmp.3 \
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 0d5dfec..f452297 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -418,6 +418,10 @@ FBSD_1.4 {
stravis;
};
+FBSD_1.5 {
+ sem_clockwait_np;
+};
+
FBSDprivate_1.0 {
/* needed by thread libraries */
__thr_jtable;
diff --git a/lib/libc/gen/sem_new.c b/lib/libc/gen/sem_new.c
index 8fe027f..d36d1e2 100644
--- a/lib/libc/gen/sem_new.c
+++ b/lib/libc/gen/sem_new.c
@@ -56,6 +56,7 @@ __weak_reference(_sem_init, sem_init);
__weak_reference(_sem_open, sem_open);
__weak_reference(_sem_post, sem_post);
__weak_reference(_sem_timedwait, sem_timedwait);
+__weak_reference(_sem_clockwait_np, sem_clockwait_np);
__weak_reference(_sem_trywait, sem_trywait);
__weak_reference(_sem_unlink, sem_unlink);
__weak_reference(_sem_wait, sem_wait);
@@ -345,23 +346,34 @@ usem_wake(struct _usem2 *sem)
}
static __inline int
-usem_wait(struct _usem2 *sem, const struct timespec *abstime)
+usem_wait(struct _usem2 *sem, clockid_t clock_id, int flags,
+ const struct timespec *rqtp, struct timespec *rmtp)
{
- struct _umtx_time *tm_p, timeout;
+ struct {
+ struct _umtx_time timeout;
+ struct timespec remain;
+ } tms;
+ void *tm_p;
size_t tm_size;
+ int retval;
- if (abstime == NULL) {
+ if (rqtp == NULL) {
tm_p = NULL;
tm_size = 0;
} else {
- timeout._clockid = CLOCK_REALTIME;
- timeout._flags = UMTX_ABSTIME;
- timeout._timeout = *abstime;
- tm_p = &timeout;
- tm_size = sizeof(timeout);
+ tms.timeout._clockid = clock_id;
+ tms.timeout._flags = (flags & TIMER_ABSTIME) ? UMTX_ABSTIME : 0;
+ tms.timeout._timeout = *rqtp;
+ tm_p = &tms;
+ tm_size = sizeof(tms);
}
- return _umtx_op(sem, UMTX_OP_SEM2_WAIT, 0,
- (void *)tm_size, __DECONST(void*, tm_p));
+ retval = _umtx_op(sem, UMTX_OP_SEM2_WAIT, 0, (void *)tm_size, tm_p);
+ if (retval == -1 && errno == EINTR && (flags & TIMER_ABSTIME) == 0 &&
+ rqtp != NULL && rmtp != NULL) {
+ *rmtp = tms.remain;
+ }
+
+ return (retval);
}
int
@@ -381,8 +393,8 @@ _sem_trywait(sem_t *sem)
}
int
-_sem_timedwait(sem_t * __restrict sem,
- const struct timespec * __restrict abstime)
+_sem_clockwait_np(sem_t * __restrict sem, clockid_t clock_id, int flags,
+ const struct timespec *rqtp, struct timespec *rmtp)
{
int val, retval;
@@ -393,7 +405,8 @@ _sem_timedwait(sem_t * __restrict sem,
_pthread_testcancel();
for (;;) {
while (USEM_COUNT(val = sem->_kern._count) > 0) {
- if (atomic_cmpset_acq_int(&sem->_kern._count, val, val - 1))
+ if (atomic_cmpset_acq_int(&sem->_kern._count, val,
+ val - 1))
return (0);
}
@@ -406,20 +419,28 @@ _sem_timedwait(sem_t * __restrict sem,
* The timeout argument is only supposed to
* be checked if the thread would have blocked.
*/
- if (abstime != NULL) {
- if (abstime->tv_nsec >= 1000000000 || abstime->tv_nsec < 0) {
+ if (rqtp != NULL) {
+ if (rqtp->tv_nsec >= 1000000000 || rqtp->tv_nsec < 0) {
errno = EINVAL;
return (-1);
}
}
_pthread_cancel_enter(1);
- retval = usem_wait(&sem->_kern, abstime);
+ retval = usem_wait(&sem->_kern, clock_id, flags, rqtp, rmtp);
_pthread_cancel_leave(0);
}
return (retval);
}
int
+_sem_timedwait(sem_t * __restrict sem,
+ const struct timespec * __restrict abstime)
+{
+ return (_sem_clockwait_np(sem, CLOCK_REALTIME, TIMER_ABSTIME, abstime,
+ NULL));
+};
+
+int
_sem_wait(sem_t *sem)
{
return _sem_timedwait(sem, NULL);
diff --git a/lib/libc/gen/sem_timedwait.3 b/lib/libc/gen/sem_timedwait.3
index 254af60..1623ebe 100644
--- a/lib/libc/gen/sem_timedwait.3
+++ b/lib/libc/gen/sem_timedwait.3
@@ -34,18 +34,22 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 3, 2008
+.Dd March 10, 2017
.Dt SEM_TIMEDWAIT 3
.Os
.Sh NAME
-.Nm sem_timedwait
+.Nm sem_timedwait ,
+.Nm sem_clockwait_np
.Nd "lock a semaphore"
.Sh LIBRARY
.Lb libpthread
.Sh SYNOPSIS
.In semaphore.h
+.In time.h
.Ft int
.Fn sem_timedwait "sem_t *sem" "const struct timespec *abs_timeout"
+.Ft int
+.Fn sem_clockwait_np "sem_t * restrict sem" "clockid_t clock_id" "int flags" "const struct timespec * rqtp" "struct timespec * rmtp"
.Sh DESCRIPTION
The
.Fn sem_timedwait
@@ -77,10 +81,40 @@ clock.
The validity of the
.Fa abs_timeout
is not checked if the semaphore can be locked immediately.
-.Sh RETURN VALUES
+.Pp
The
-.Fn sem_timedwait
-function returns zero if the calling process successfully performed the
+.Fn sem_clockwait_np
+function is a more flexible variant of
+.Fn sem_timedwait .
+The
+.Fa clock_id
+parameter specifies the reference clock.
+If the
+.Fa flags
+parameter contains
+.Dv TIMER_ABSTIME ,
+then the requested timeout
+.Pq Fa rqtp
+is an absolute timeout; otherwise,
+the timeout is relative.
+If this function fails with
+.Er EINTR
+and the timeout is relative,
+a non-NULL
+.Fa rmtp
+will be updated to contain the amount of time remaining in the interval
+.Po
+the requested time minus the time actually slept
+.Pc .
+An absolute timeout has no effect on
+.Fa rmtp .
+A single structure can be used for both
+.Fa rqtp
+and
+.Fa rmtp .
+.Sh RETURN VALUES
+These
+functions return zero if the calling process successfully performed the
semaphore lock operation on the semaphore designated by
.Fa sem .
If the call was unsuccessful, the state of the semaphore is unchanged,
@@ -88,9 +122,7 @@ and the function returns a value of \-1 and sets the global variable
.Va errno
to indicate the error.
.Sh ERRORS
-The
-.Fn sem_timedwait
-function will fail if:
+These functions will fail if:
.Bl -tag -width Er
.It Bq Er EINVAL
The
@@ -114,6 +146,18 @@ The
.Fn sem_timedwait
function conforms to
.St -p1003.1-2004 .
+The
+.Fn sem_clockwait_np
+function is not specified by any standard;
+it exists only on
+.Fx
+at the time of this writing.
.Sh HISTORY
-The function first appeared in
+The
+.Fn sem_timedwait
+function first appeared in
.Fx 5.0 .
+The
+.Fn sem_clockwait_np
+function first appeared in
+.Fx 12.0 .
diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h
index c95829e..52e9b25 100644
--- a/lib/libc/include/namespace.h
+++ b/lib/libc/include/namespace.h
@@ -217,6 +217,7 @@
#define sem_open _sem_open
#define sem_post _sem_post
#define sem_timedwait _sem_timedwait
+#define sem_clockwait_np _sem_clockwait_np
#define sem_trywait _sem_trywait
#define sem_unlink _sem_unlink
#define sem_wait _sem_wait
diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h
index 0233348..e40e6fd 100644
--- a/lib/libc/include/un-namespace.h
+++ b/lib/libc/include/un-namespace.h
@@ -198,6 +198,7 @@
#undef sem_open
#undef sem_post
#undef sem_timedwait
+#undef sem_clockwait_np
#undef sem_trywait
#undef sem_unlink
#undef sem_wait
OpenPOWER on IntegriCloud