git: da7cee20aa7a - stable/13 - sysvsem: Add a timeout argument to the semop.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 17 Jun 2022 19:39:52 UTC
The branch stable/13 has been updated by dchagin:
URL: https://cgit.FreeBSD.org/src/commit/?id=da7cee20aa7ad5ebdc56d2780bc8f3bbd85d3e8b
commit da7cee20aa7ad5ebdc56d2780bc8f3bbd85d3e8b
Author: Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-06 16:51:48 +0000
Commit: Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-06-17 19:34:42 +0000
sysvsem: Add a timeout argument to the semop.
For future use in the Linux emulation layer for the semtimedop syscall
split the sys_semop syscall into two counterparts and add
struct timespec *timeout argument to the last one.
Reviewed by: jhb, kib
Differential revision: https://reviews.freebsd.org/D35121
MFC after: 2 weeks
(cherry picked from commit f04534f5c84e58009efbb7f378803da3f33585b9)
---
sys/kern/sysv_sem.c | 50 ++++++++++++++++++++++++++++++++++++++------------
sys/sys/syscallsubr.h | 3 +++
2 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index dd8925246d1e..14487cd16282 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -1097,11 +1097,18 @@ struct semop_args {
#endif
int
sys_semop(struct thread *td, struct semop_args *uap)
+{
+
+ return (kern_semop(td, uap->semid, uap->sops, uap->nsops, NULL));
+}
+
+int
+kern_semop(struct thread *td, int usemid, struct sembuf *usops,
+ size_t nsops, struct timespec *timeout)
{
#define SMALL_SOPS 8
struct sembuf small_sops[SMALL_SOPS];
- int semid = uap->semid;
- size_t nsops = uap->nsops;
+ int semid;
struct prison *rpr;
struct sembuf *sops;
struct semid_kernel *semakptr;
@@ -1109,6 +1116,7 @@ sys_semop(struct thread *td, struct semop_args *uap)
struct sem *semptr = NULL;
struct sem_undo *suptr;
struct mtx *sema_mtxp;
+ sbintime_t sbt, precision;
size_t i, j, k;
int error;
int do_wakeup, do_undos;
@@ -1117,18 +1125,35 @@ sys_semop(struct thread *td, struct semop_args *uap)
#ifdef SEM_DEBUG
sops = NULL;
#endif
- DPRINTF(("call to semop(%d, %p, %u)\n", semid, sops, nsops));
+ DPRINTF(("call to semop(%d, %p, %u)\n", usemid, usops, nsops));
- AUDIT_ARG_SVIPC_ID(semid);
+ AUDIT_ARG_SVIPC_ID(usemid);
rpr = sem_find_prison(td->td_ucred);
if (sem == NULL)
return (ENOSYS);
- semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
+ semid = IPCID_TO_IX(usemid); /* Convert back to zero origin */
if (semid < 0 || semid >= seminfo.semmni)
return (EINVAL);
+ if (timeout != NULL) {
+ if (!timespecvalid_interval(timeout))
+ return (EINVAL);
+ precision = 0;
+ if (timespecisset(timeout)) {
+ if (timeout->tv_sec < INT32_MAX / 2) {
+ precision = tstosbt(*timeout);
+ if (TIMESEL(&sbt, precision))
+ sbt += tc_tick_sbt;
+ sbt += precision;
+ precision >>= tc_precexp;
+ } else
+ sbt = 0;
+ } else
+ sbt = -1;
+ } else
+ precision = sbt = 0;
/* Allocate memory for sem_ops */
if (nsops <= SMALL_SOPS)
@@ -1152,9 +1177,9 @@ sys_semop(struct thread *td, struct semop_args *uap)
sops = malloc(nsops * sizeof(*sops), M_TEMP, M_WAITOK);
}
- if ((error = copyin(uap->sops, sops, nsops * sizeof(sops[0]))) != 0) {
+ if ((error = copyin(usops, sops, nsops * sizeof(sops[0]))) != 0) {
DPRINTF(("error = %d from copyin(%p, %p, %d)\n", error,
- uap->sops, sops, nsops * sizeof(sops[0])));
+ usops, sops, nsops * sizeof(sops[0])));
if (sops != small_sops)
free(sops, M_TEMP);
return (error);
@@ -1168,7 +1193,7 @@ sys_semop(struct thread *td, struct semop_args *uap)
goto done2;
}
seq = semakptr->u.sem_perm.seq;
- if (seq != IPCID_TO_SEQ(uap->semid)) {
+ if (seq != IPCID_TO_SEQ(usemid)) {
error = EINVAL;
goto done2;
}
@@ -1286,8 +1311,8 @@ sys_semop(struct thread *td, struct semop_args *uap)
semptr->semncnt++;
DPRINTF(("semop: good night!\n"));
- error = msleep(semakptr, sema_mtxp, (PZERO - 4) | PCATCH,
- "semwait", 0);
+ error = msleep_sbt(semakptr, sema_mtxp, (PZERO - 4) | PCATCH,
+ "semwait", sbt, precision, C_ABSOLUTE);
DPRINTF(("semop: good morning (error=%d)!\n", error));
/* return code is checked below, after sem[nz]cnt-- */
@@ -1296,7 +1321,7 @@ sys_semop(struct thread *td, struct semop_args *uap)
*/
seq = semakptr->u.sem_perm.seq;
if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 ||
- seq != IPCID_TO_SEQ(uap->semid)) {
+ seq != IPCID_TO_SEQ(usemid)) {
error = EIDRM;
goto done2;
}
@@ -1323,7 +1348,8 @@ sys_semop(struct thread *td, struct semop_args *uap)
* need to decrement sem[nz]cnt either way.)
*/
if (error != 0) {
- error = EINTR;
+ if (error == ERESTART)
+ error = EINTR;
goto done2;
}
DPRINTF(("semop: good morning!\n"));
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index 09eae475cb2c..a0fedf7fb49d 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -58,6 +58,7 @@ struct ogetdirentries_args;
struct rlimit;
struct rusage;
struct sched_param;
+struct sembuf;
union semun;
struct sockaddr;
struct stat;
@@ -323,6 +324,8 @@ int kern_ktimer_settime(struct thread *td, int timer_id, int flags,
int kern_ktimer_gettime(struct thread *td, int timer_id,
struct itimerspec *val);
int kern_ktimer_getoverrun(struct thread *td, int timer_id);
+int kern_semop(struct thread *td, int usemid, struct sembuf *usops,
+ size_t nsops, struct timespec *timeout);
int kern_thr_alloc(struct proc *, int pages, struct thread **);
int kern_thr_exit(struct thread *td);
int kern_thr_new(struct thread *td, struct thr_param *param);