Add ksem_timedwait() to complement ksem_wait().

Glanced at by:	alfred
This commit is contained in:
Daniel Eischen 2004-02-03 05:08:32 +00:00
parent 4f638130c3
commit aae94fbbb6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=125368
4 changed files with 64 additions and 6 deletions

View File

@ -628,5 +628,6 @@
int attrnamespace, void *data, size_t nbytes); } int attrnamespace, void *data, size_t nbytes); }
440 MSTD { int kse_switchin(const struct __mcontext *mcp, \ 440 MSTD { int kse_switchin(const struct __mcontext *mcp, \
long val, long *loc); } long val, long *loc); }
441 MNOSTD { int ksem_timedwait(semid_t id, struct timespec *abstime); }
; Please copy any additions and changes to the following compatability tables: ; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master ; sys/compat/freebsd32/syscalls.master

View File

@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/sysent.h> #include <sys/sysent.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/fcntl.h> #include <sys/fcntl.h>
@ -63,7 +64,8 @@ static int sem_hasopen(struct thread *td, struct ksem *ks);
static int kern_sem_close(struct thread *td, semid_t id); static int kern_sem_close(struct thread *td, semid_t id);
static int kern_sem_post(struct thread *td, semid_t id); static int kern_sem_post(struct thread *td, semid_t id);
static int kern_sem_wait(struct thread *td, semid_t id, int tryflag); static int kern_sem_wait(struct thread *td, semid_t id, int tryflag,
struct timespec *abstime);
static int kern_sem_init(struct thread *td, int dir, unsigned int value, static int kern_sem_init(struct thread *td, int dir, unsigned int value,
semid_t *idp); semid_t *idp);
static int kern_sem_open(struct thread *td, int dir, const char *name, static int kern_sem_open(struct thread *td, int dir, const char *name,
@ -475,7 +477,7 @@ sem_hasopen(td, ks)
struct ksem *ks; struct ksem *ks;
{ {
return ((ks->ks_name == NULL && sem_perm(td, ks)) return ((ks->ks_name == NULL && sem_perm(td, ks) == 0)
|| sem_getuser(td->td_proc, ks) != NULL); || sem_getuser(td->td_proc, ks) != NULL);
} }
@ -653,7 +655,37 @@ ksem_wait(td, uap)
struct ksem_wait_args *uap; struct ksem_wait_args *uap;
{ {
return (kern_sem_wait(td, uap->id, 0)); return (kern_sem_wait(td, uap->id, 0, NULL));
}
#ifndef _SYS_SYSPROTO_H_
struct ksem_timedwait_args {
semid_t id;
struct timespec *abstime;
};
int ksem_timedwait(struct thread *td, struct ksem_timedwait_args *uap);
#endif
int
ksem_timedwait(td, uap)
struct thread *td;
struct ksem_timedwait_args *uap;
{
struct timespec abstime;
struct timespec *ts;
int error;
/* We allow a null timespec (wait forever). */
if (uap->abstime == NULL)
ts = NULL;
else {
error = copyin(uap->abstime, &abstime, sizeof(abstime));
if (error != 0)
return (error);
if (abstime.tv_nsec >= 1000000000 || abstime.tv_nsec < 0)
return (EINVAL);
ts = &abstime;
}
return (kern_sem_wait(td, uap->id, 0, ts));
} }
#ifndef _SYS_SYSPROTO_H_ #ifndef _SYS_SYSPROTO_H_
@ -668,15 +700,18 @@ ksem_trywait(td, uap)
struct ksem_trywait_args *uap; struct ksem_trywait_args *uap;
{ {
return (kern_sem_wait(td, uap->id, 1)); return (kern_sem_wait(td, uap->id, 1, NULL));
} }
static int static int
kern_sem_wait(td, id, tryflag) kern_sem_wait(td, id, tryflag, abstime)
struct thread *td; struct thread *td;
semid_t id; semid_t id;
int tryflag; int tryflag;
struct timespec *abstime;
{ {
struct timespec ts1, ts2;
struct timeval tv;
struct ksem *ks; struct ksem *ks;
int error; int error;
@ -697,7 +732,26 @@ kern_sem_wait(td, id, tryflag)
DP(("kern_sem_wait value = %d, tryflag %d\n", ks->ks_value, tryflag)); DP(("kern_sem_wait value = %d, tryflag %d\n", ks->ks_value, tryflag));
if (ks->ks_value == 0) { if (ks->ks_value == 0) {
ks->ks_waiters++; ks->ks_waiters++;
error = tryflag ? EAGAIN : cv_wait_sig(&ks->ks_cv, &sem_lock); if (tryflag != 0)
error = EAGAIN;
else if (abstime == NULL)
error = cv_wait_sig(&ks->ks_cv, &sem_lock);
else {
for (;;) {
ts1 = *abstime;
getnanotime(&ts2);
timespecsub(&ts1, &ts2);
TIMESPEC_TO_TIMEVAL(&tv, &ts1);
if (tv.tv_sec < 0) {
error = ETIMEDOUT;
break;
}
error = cv_timedwait_sig(&ks->ks_cv,
&sem_lock, tvtohz(&tv));
if (error != EWOULDBLOCK)
break;
}
}
ks->ks_waiters--; ks->ks_waiters--;
if (error) if (error)
goto err; goto err;
@ -839,6 +893,7 @@ SYSCALL_MODULE_HELPER(ksem_unlink);
SYSCALL_MODULE_HELPER(ksem_close); SYSCALL_MODULE_HELPER(ksem_close);
SYSCALL_MODULE_HELPER(ksem_post); SYSCALL_MODULE_HELPER(ksem_post);
SYSCALL_MODULE_HELPER(ksem_wait); SYSCALL_MODULE_HELPER(ksem_wait);
SYSCALL_MODULE_HELPER(ksem_timedwait);
SYSCALL_MODULE_HELPER(ksem_trywait); SYSCALL_MODULE_HELPER(ksem_trywait);
SYSCALL_MODULE_HELPER(ksem_getvalue); SYSCALL_MODULE_HELPER(ksem_getvalue);
SYSCALL_MODULE_HELPER(ksem_destroy); SYSCALL_MODULE_HELPER(ksem_destroy);

View File

@ -57,6 +57,7 @@ int ksem_close(semid_t id);
int ksem_post(semid_t id); int ksem_post(semid_t id);
int ksem_wait(semid_t id); int ksem_wait(semid_t id);
int ksem_trywait(semid_t id); int ksem_trywait(semid_t id);
int ksem_timedwait(semid_t id, struct timespec *abstime);
int ksem_init(semid_t *idp, unsigned int value); int ksem_init(semid_t *idp, unsigned int value);
int ksem_open(semid_t *idp, const char *name, int oflag, mode_t mode, int ksem_open(semid_t *idp, const char *name, int oflag, mode_t mode,
unsigned int value); unsigned int value);

View File

@ -57,6 +57,7 @@ int ksem_close(semid_t id);
int ksem_post(semid_t id); int ksem_post(semid_t id);
int ksem_wait(semid_t id); int ksem_wait(semid_t id);
int ksem_trywait(semid_t id); int ksem_trywait(semid_t id);
int ksem_timedwait(semid_t id, struct timespec *abstime);
int ksem_init(semid_t *idp, unsigned int value); int ksem_init(semid_t *idp, unsigned int value);
int ksem_open(semid_t *idp, const char *name, int oflag, mode_t mode, int ksem_open(semid_t *idp, const char *name, int oflag, mode_t mode,
unsigned int value); unsigned int value);