summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorvangyzen <vangyzen@FreeBSD.org>2017-03-14 17:52:43 +0000
committervangyzen <vangyzen@FreeBSD.org>2017-03-14 17:52:43 +0000
commit72aa1fdeceef03818eb7b197915d42ca76873919 (patch)
treed9d7b7537c9253168899b020c5c974ba352aa542 /lib
parent32ef1c0934519221b6371ba801fb798f33c6c9f8 (diff)
downloadFreeBSD-src-72aa1fdeceef03818eb7b197915d42ca76873919.zip
FreeBSD-src-72aa1fdeceef03818eb7b197915d42ca76873919.tar.gz
MFC r314179 r314206 r314424
Add sem_clockwait_np() This function allows the caller to specify the reference clock and choose between absolute and relative mode. In relative mode, the remaining time can be returned. The API is similar to clock_nanosleep(3). Thanks to Ed Schouten for that suggestion. While I'm here, reduce the sleep time in the semaphore "child" test to greatly reduce its runtime. Also add a reasonable timeout. Relnotes: yes Sponsored by: Dell EMC
Diffstat (limited to 'lib')
-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