On Thu, Jun 24, 2010 at 02:13:55AM +0100, Federico G. Schwindt wrote:
> On Wed, Jun 23, 2010 at 05:32:13PM -0700, Matthew Dempsky wrote:
> > On Wed, Jun 23, 2010 at 4:10 PM, Joerg Goltermann <[email protected]> wrote:
> > > I am working on a port and need the POSIX function sem_timedwait. Does
> > > anyone
> > > have a nice/simple idea how to mimic this function? Is anyone working on
> > > an
> > > implementation in libpthread?
> >
> > It looks like it should be simple enough to add. We already have
> > pthread_cond_timedwait, so sem_timedwait should just be a variant of
> > sem_wait using that instead of pthread_cond_wait.
> >
> > I'll write one up unless someone with actual libpthread expertise
> > beats me to it. =]
>
> i just wrote it but for some reason is not working as expected, which is
> odd
> since it's relying on pthread_cond_timedwait. maybe the tests are wrong.
> being 2am i think i call it a day.
and the diff, including the manpage bits.
f.-
Index: include/semaphore.h
===================================================================
RCS file: /cvs/src/lib/libpthread/include/semaphore.h,v
retrieving revision 1.3
diff -u -p include/semaphore.h
--- include/semaphore.h 16 Feb 2002 21:27:25 -0000 1.3
+++ include/semaphore.h 24 Jun 2010 01:20:08 -0000
@@ -58,6 +58,7 @@ sem_t *sem_open(const char *, int, ...);
int sem_close(sem_t *);
int sem_unlink(const char *);
int sem_wait(sem_t *);
+int sem_timedwait(sem_t *, const struct timespec *);
int sem_trywait(sem_t *);
int sem_post(sem_t *);
int sem_getvalue(sem_t *, int *);
Index: man/Makefile.inc
===================================================================
RCS file: /cvs/src/lib/libpthread/man/Makefile.inc,v
retrieving revision 1.24
diff -u -p man/Makefile.inc
--- man/Makefile.inc 12 Apr 2010 01:54:23 -0000 1.24
+++ man/Makefile.inc 24 Jun 2010 01:20:08 -0000
@@ -105,5 +105,6 @@ MLINKS+=flockfile.3 funlockfile.3 \
pthread_getconcurrency.3 pthread_setconcurrency.3 \
sem_open.3 sem_close.3 \
sem_open.3 sem_unlink.3 \
+ sem_wait.3 sem_timedwait.3 \
sem_wait.3 sem_trywait.3
Index: man/sem_wait.3
===================================================================
RCS file: /cvs/src/lib/libpthread/man/sem_wait.3,v
retrieving revision 1.6
diff -u -p man/sem_wait.3
--- man/sem_wait.3 31 May 2007 19:19:37 -0000 1.6
+++ man/sem_wait.3 24 Jun 2010 01:20:08 -0000
@@ -33,6 +33,7 @@
.Os
.Sh NAME
.Nm sem_wait ,
+.Nm sem_timedwait ,
.Nm sem_trywait
.Nd decrement (lock) a semaphore
.Sh SYNOPSIS
@@ -41,6 +42,10 @@
.Fn sem_wait "sem_t *sem"
.Ft int
.Fn sem_trywait "sem_t *sem"
+.Fd #include <semaphore.h>
+.Fd #include <time.h>
+.Ft int
+.Fn sem_timedwait "sem_t *sem" "const struct timespec *abstime"
.Sh DESCRIPTION
The
.Fn sem_wait
@@ -51,12 +56,19 @@ but blocks if the value of
is zero, until the value is non-zero and the value can be decremented.
.Pp
The
+.Fn sem_timedwait
+function performs the same action, but will not wait beyond
+.Fa abstime
+to decrement (lock) the semaphore before returning.
+.Pp
+The
.Fn sem_trywait
function decrements (locks) the semaphore pointed to by
.Fa sem
only if the value is non-zero.
Otherwise, the semaphore is not decremented and
an error is returned.
+.Pp
.Sh RETURN VALUES
.Rv -std sem_wait
.Sh ERRORS
@@ -68,6 +80,19 @@ will fail if:
.It Bq Er EINVAL
.Fa sem
points to an invalid semaphore.
+.El
+.Pp
+.Fn sem_timedwait
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+.Fa sem
+points to an invalid semaphore or
+.Fa abstime
+is invalid.
+.It Bq Er ETIMEDOUT
+The system time has reached or exceeded the time specified in
+.Fa abstime .
.El
.Pp
Additionally,
Index: uthread/uthread_sem.c
===================================================================
RCS file: /cvs/src/lib/libpthread/uthread/uthread_sem.c,v
retrieving revision 1.3
diff -u -p uthread/uthread_sem.c
--- uthread/uthread_sem.c 20 Jun 2008 02:58:00 -0000 1.3
+++ uthread/uthread_sem.c 24 Jun 2010 01:20:08 -0000
@@ -184,6 +184,36 @@ sem_wait(sem_t *sem)
}
int
+sem_timedwait(sem_t *sem, const struct timespec *abstime)
+{
+ int retval = 0;
+
+ _thread_enter_cancellation_point();
+
+ _SEM_CHECK_VALIDITY(sem);
+
+ pthread_mutex_lock(&(*sem)->lock);
+
+ while ((*sem)->count == 0 && retval == 0) {
+ (*sem)->nwaiters++;
+ retval = pthread_cond_timedwait(&(*sem)->gtzero,
+ &(*sem)->lock, abstime);
+ (*sem)->nwaiters--;
+ }
+ if (retval != 0) {
+ errno = retval;
+ retval = -1;
+ } else
+ (*sem)->count--;
+
+ pthread_mutex_unlock(&(*sem)->lock);
+
+ RETURN:
+ _thread_leave_cancellation_point();
+ return retval;
+}
+
+int
sem_trywait(sem_t *sem)
{
int retval;