Add an implementation of pthread_rwlock_timed{rd,wr}lock() to libthr with
attendant documentation.
This commit is contained in:
parent
5af038f21a
commit
e3c786562f
@ -40,13 +40,17 @@
|
||||
__weak_reference(_pthread_rwlock_destroy, pthread_rwlock_destroy);
|
||||
__weak_reference(_pthread_rwlock_init, pthread_rwlock_init);
|
||||
__weak_reference(_pthread_rwlock_rdlock, pthread_rwlock_rdlock);
|
||||
__weak_reference(_pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock);
|
||||
__weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock);
|
||||
__weak_reference(_pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock);
|
||||
__weak_reference(_pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);
|
||||
__weak_reference(_pthread_rwlock_unlock, pthread_rwlock_unlock);
|
||||
__weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock);
|
||||
|
||||
static int rwlock_rdlock_common(pthread_rwlock_t *, int);
|
||||
static int rwlock_wrlock_common(pthread_rwlock_t *, int);
|
||||
static int rwlock_rdlock_common(pthread_rwlock_t *, int,
|
||||
const struct timespec *);
|
||||
static int rwlock_wrlock_common(pthread_rwlock_t *, int,
|
||||
const struct timespec *);
|
||||
|
||||
int
|
||||
_pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
|
||||
@ -116,7 +120,8 @@ out_mutex:
|
||||
* it is greater than 0 it will return immediately with EBUSY.
|
||||
*/
|
||||
static int
|
||||
rwlock_rdlock_common(pthread_rwlock_t *rwlock, int nonblocking)
|
||||
rwlock_rdlock_common(pthread_rwlock_t *rwlock, int nonblocking,
|
||||
const struct timespec *timeout)
|
||||
{
|
||||
pthread_rwlock_t prwlock;
|
||||
int ret;
|
||||
@ -124,6 +129,13 @@ rwlock_rdlock_common(pthread_rwlock_t *rwlock, int nonblocking)
|
||||
if (rwlock == NULL || *rwlock == NULL)
|
||||
return(EINVAL);
|
||||
|
||||
/*
|
||||
* Check for validity of the timeout parameter.
|
||||
*/
|
||||
if (timeout != NULL &&
|
||||
(timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000))
|
||||
return (EINVAL);
|
||||
|
||||
prwlock = *rwlock;
|
||||
|
||||
/* grab the monitor lock */
|
||||
@ -143,7 +155,12 @@ rwlock_rdlock_common(pthread_rwlock_t *rwlock, int nonblocking)
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
ret = pthread_cond_wait(&prwlock->read_signal, &prwlock->lock);
|
||||
if (timeout == NULL)
|
||||
ret = pthread_cond_wait(&prwlock->read_signal,
|
||||
&prwlock->lock);
|
||||
else
|
||||
ret = pthread_cond_timedwait(&prwlock->read_signal,
|
||||
&prwlock->lock, timeout);
|
||||
|
||||
if (ret != 0 && ret != EINTR) {
|
||||
/* can't do a whole lot if this fails */
|
||||
@ -168,13 +185,20 @@ rwlock_rdlock_common(pthread_rwlock_t *rwlock, int nonblocking)
|
||||
int
|
||||
_pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
return (rwlock_rdlock_common(rwlock, 0));
|
||||
return (rwlock_rdlock_common(rwlock, 0, NULL));
|
||||
}
|
||||
|
||||
int
|
||||
_pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock,
|
||||
const struct timespec *timeout)
|
||||
{
|
||||
return (rwlock_rdlock_common(rwlock, 0, timeout));
|
||||
}
|
||||
|
||||
int
|
||||
_pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
return (rwlock_rdlock_common(rwlock, 1));
|
||||
return (rwlock_rdlock_common(rwlock, 1, NULL));
|
||||
}
|
||||
|
||||
int
|
||||
@ -215,13 +239,20 @@ _pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
|
||||
int
|
||||
_pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
return (rwlock_wrlock_common(rwlock, 0));
|
||||
return (rwlock_wrlock_common(rwlock, 0, NULL));
|
||||
}
|
||||
|
||||
int
|
||||
_pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
|
||||
const struct timespec *timeout)
|
||||
{
|
||||
return (rwlock_wrlock_common(rwlock, 0, timeout));
|
||||
}
|
||||
|
||||
int
|
||||
_pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
return (rwlock_wrlock_common(rwlock, 1));
|
||||
return (rwlock_wrlock_common(rwlock, 1, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -229,7 +260,8 @@ _pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
|
||||
* it is greater than 0 it will return immediately with EBUSY.
|
||||
*/
|
||||
static int
|
||||
rwlock_wrlock_common(pthread_rwlock_t *rwlock, int nonblocking)
|
||||
rwlock_wrlock_common(pthread_rwlock_t *rwlock, int nonblocking,
|
||||
const struct timespec *timeout)
|
||||
{
|
||||
pthread_rwlock_t prwlock;
|
||||
int ret;
|
||||
@ -237,6 +269,13 @@ rwlock_wrlock_common(pthread_rwlock_t *rwlock, int nonblocking)
|
||||
if (rwlock == NULL || *rwlock == NULL)
|
||||
return(EINVAL);
|
||||
|
||||
/*
|
||||
* Check the timeout value for validity.
|
||||
*/
|
||||
if (timeout != NULL &&
|
||||
(timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000))
|
||||
return (EINVAL);
|
||||
|
||||
prwlock = *rwlock;
|
||||
|
||||
/* grab the monitor lock */
|
||||
@ -251,8 +290,12 @@ rwlock_wrlock_common(pthread_rwlock_t *rwlock, int nonblocking)
|
||||
|
||||
++prwlock->blocked_writers;
|
||||
|
||||
ret = pthread_cond_wait(&prwlock->write_signal,
|
||||
&prwlock->lock);
|
||||
if (timeout == NULL)
|
||||
ret = pthread_cond_wait(&prwlock->write_signal,
|
||||
&prwlock->lock);
|
||||
else
|
||||
ret = pthread_cond_timedwait(&prwlock->write_signal,
|
||||
&prwlock->lock, timeout);
|
||||
|
||||
if (ret != 0 && ret != EINTR) {
|
||||
--prwlock->blocked_writers;
|
||||
|
@ -155,6 +155,8 @@ MAN+= pthread.3 \
|
||||
pthread_rwlock_destroy.3 \
|
||||
pthread_rwlock_init.3 \
|
||||
pthread_rwlock_rdlock.3 \
|
||||
pthread_rwlock_timedrdlock.3 \
|
||||
pthread_rwlock_timedwrlock.3 \
|
||||
pthread_rwlock_unlock.3 \
|
||||
pthread_rwlock_wrlock.3 \
|
||||
pthread_rwlockattr_destroy.3 \
|
||||
|
118
share/man/man3/pthread_rwlock_timedrdlock.3
Normal file
118
share/man/man3/pthread_rwlock_timedrdlock.3
Normal file
@ -0,0 +1,118 @@
|
||||
.\" Copyright (c) 2004 Michael Telahun Makonnen
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 16, 2004
|
||||
.Dt PTHREAD_RWLOCK_TIMEDRDLOCK 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pthread_rwlock_timedrdlock ,
|
||||
.Nd acquire a read-write lock for reading or give up after a specified period
|
||||
.Sh LIBRARY
|
||||
.Lb libpthread
|
||||
.Lb libthr
|
||||
.Sh SYNOPSIS
|
||||
.In pthread.h
|
||||
.Ft int
|
||||
.Fn pthread_rwlock_timedrdlock "pthread_rwlock_t *rwlock" "const struct timespec *abs_timeout"
|
||||
.Sh DESCRIPTION
|
||||
This function acquires a read lock on the read-write lock
|
||||
.Fa rwlock .
|
||||
However, if the lock cannot be
|
||||
acquired without waiting for another thread to
|
||||
unlock the lock,
|
||||
this wait shall be terminated when
|
||||
.Fa abs_timeout
|
||||
expires.
|
||||
.Pp
|
||||
.Pp
|
||||
A thread may hold multiple concurrent read locks.
|
||||
The
|
||||
.Fn pthread_rwlock_unlock
|
||||
function must be called once for each lock acquired.
|
||||
.Pp
|
||||
If the thread should be interrupted by a signal,
|
||||
the
|
||||
.Fn pthread_rwlock_wrlock
|
||||
function will be automatically restarted after the thread returns from
|
||||
the signal handler.
|
||||
.Pp
|
||||
The calling thread may deadlock if
|
||||
at the time the call is made it holds a write lock on
|
||||
.Fa rwlock .
|
||||
The results are undefined if this function is called with
|
||||
an uninitialized read-write lock.
|
||||
.Sh IMPLEMENTATION NOTES
|
||||
To prevent writer starvation, writers are favored over readers.
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_rwlock_timedrdlock
|
||||
function will return zero. Otherwise an error number will be returned
|
||||
to indicate the error.
|
||||
.Pp
|
||||
This function shall not return an error code of EINTR.
|
||||
.Sh ERRORS
|
||||
The
|
||||
.Fn pthread_rwlock_timedrdlock
|
||||
function will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er ETIMEDOUT
|
||||
The lock could not be acquired before the specified timeout expired
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn pthread_rwlock_timedrdlock
|
||||
function may fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EAGAIN
|
||||
The read lock could not be
|
||||
acquired because the maximum number of read locks for
|
||||
.Fa rwlock
|
||||
would be exceeded.
|
||||
.It Bq Er EDEADLK
|
||||
The calling thread already holds a write lock on
|
||||
.Fa rwlock .
|
||||
.It Bq Er EINVAL
|
||||
The value specified by
|
||||
.Fa rwlock
|
||||
does not refer to an initialized read-write lock object,
|
||||
or the
|
||||
.Fa abs_timeout nanosecond value is less than zero or
|
||||
greater than or equal to 1 billion.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_rwlock_init 3 ,
|
||||
.Xr pthread_rwlock_timedwrlock 3
|
||||
.Xr pthread_rwlock_unlock 3 ,
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Fn pthread_rwlock_timedrdlock
|
||||
function is expected to conform to
|
||||
.St -p1003.1-96 .
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn pthread_rwlock_timedrdlock
|
||||
function first appeared in
|
||||
.Fx 5.2 .
|
107
share/man/man3/pthread_rwlock_timedwrlock.3
Normal file
107
share/man/man3/pthread_rwlock_timedwrlock.3
Normal file
@ -0,0 +1,107 @@
|
||||
.\" Copyright (c) 2004 Michael Telahun Makonnen
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 16, 2004
|
||||
.Dt PTHREAD_RWLOCK_TIMEDWRLOCK 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pthread_rwlock_timedwrlock ,
|
||||
.Nd acquire a read-write lock for writing or give up after a specified period
|
||||
.Sh LIBRARY
|
||||
.Lb libpthread
|
||||
.Lb libthr
|
||||
.Sh SYNOPSIS
|
||||
.In pthread.h
|
||||
.Ft int
|
||||
.Fn pthread_rwlock_timedwrlock "pthread_rwlock_t *rwlock" "const struct timespec *abs_timeout"
|
||||
.Sh DESCRIPTION
|
||||
This function acquires a write lock on the read-write lock
|
||||
.Fa rwlock .
|
||||
However, if the lock cannot be
|
||||
acquired without waiting for another thread to
|
||||
unlock the lock,
|
||||
this wait shall be terminated when
|
||||
.Fa abs_timeout
|
||||
expires.
|
||||
.Pp
|
||||
If the thread should be interrupted by a signal,
|
||||
the
|
||||
.Fn pthread_rwlock_wrlock
|
||||
function will be automatically restarted after the thread returns from
|
||||
the signal handler.
|
||||
.Pp
|
||||
The calling thread may deadlock if
|
||||
at the time the call is made it holds
|
||||
.Fa rwlock .
|
||||
The results are undefined if this function is called with
|
||||
an uninitialized read-write lock.
|
||||
.Sh IMPLEMENTATION NOTES
|
||||
To prevent writer starvation, writers are favored over readers.
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_rwlock_timedwrlock
|
||||
function will return zero. Otherwise an error number will be returned
|
||||
to indicate the error.
|
||||
.Pp
|
||||
This function shall not return an error code of EINTR.
|
||||
.Sh ERRORS
|
||||
The
|
||||
.Fn pthread_rwlock_timedwrlock
|
||||
function shall fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er ETIMEDOUT
|
||||
The lock could not be acquired before the specified timeout expired
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn pthread_rwlock_timedrwlock
|
||||
function may fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EDEADLK
|
||||
The calling thread already holds
|
||||
.Fa rwlock .
|
||||
.It Bq Er EINVAL
|
||||
The value specified by
|
||||
.Fa rwlock
|
||||
does not refer to an initialized read-write lock object,
|
||||
or the
|
||||
.Fa abs_timeout nanosecond value is less than zero or
|
||||
greater than or equal to 1 billion.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_rwlock_init 3 ,
|
||||
.Xr pthread_rwlock_timedrdlock 3
|
||||
.Xr pthread_rwlock_unlock 3 ,
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Fn pthread_rwlock_timedwrlock
|
||||
function is expected to conform to
|
||||
.St -p1003.1-96 .
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn pthread_rwlock_timedwrlock
|
||||
function first appeared in
|
||||
.Fx 5.2 .
|
Loading…
x
Reference in New Issue
Block a user