The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=0cc6c442964d6294b796537522d9e462656bf16f
commit 0cc6c442964d6294b796537522d9e462656bf16f Author: Konstantin Belousov <[email protected]> AuthorDate: 2026-08-25 08:18:35 +0000 Commit: Konstantin Belousov <[email protected]> CommitDate: 2026-08-29 09:42:40 +0000 condvars(9): add cv_wait_sig_unlock() Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D59132 --- sys/kern/kern_condvar.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ sys/sys/condvar.h | 3 +++ 2 files changed, 58 insertions(+) diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c index 517b83d90243..79d6e2dcd41f 100644 --- a/sys/kern/kern_condvar.c +++ b/sys/kern/kern_condvar.c @@ -287,6 +287,61 @@ _cv_wait_sig(struct cv *cvp, struct lock_object *lock) return (rval); } +int +_cv_wait_sig_unlock(struct cv *cvp, struct lock_object *lock) +{ + WITNESS_SAVE_DECL(lock_witness); +#ifdef KTRACE + char wmesg[WMESGLEN + 1]; +#endif + struct lock_class *class; + struct thread *td __ktrace_used; + int rval; + + td = curthread; + CV_ASSERT(cvp, lock, td); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, + "Waiting on \"%s\"", cvp->cv_description); + KASSERT(lock != &Giant.lock_object, + ("cv_wait_sig_unlock cannot be used with Giant")); + + if (SCHEDULER_STOPPED()) + return (0); + +#ifdef KTRACE + if (KTRPOINT(td, KTR_CSW)) { + strlcpy(wmesg, cv_wmesg(cvp), sizeof(wmesg)); + ktrcsw(1, 0, wmesg); + } else { + wmesg[0] = '\0'; + } +#endif + + class = LOCK_CLASS(lock); + sleepq_lock(cvp); + + CV_WAITERS_INC(cvp); + DROP_GIANT(); + + sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR | + SLEEPQ_INTERRUPTIBLE, 0); + if (class->lc_flags & LC_SLEEPABLE) + sleepq_release(cvp); + WITNESS_SAVE(lock, lock_witness); + class->lc_unlock(lock); + if (class->lc_flags & LC_SLEEPABLE) + sleepq_lock(cvp); + rval = sleepq_wait_sig(cvp, 0); + +#ifdef KTRACE + if (KTRPOINT(td, KTR_CSW)) + ktrcsw(0, 0, wmesg); +#endif + PICKUP_GIANT(); + + return (rval); +} + /* * Wait on a condition variable for (at most) the value specified in sbt * argument. Returns 0 if the process was resumed by cv_signal or cv_broadcast, diff --git a/sys/sys/condvar.h b/sys/sys/condvar.h index cd16c85024d4..9d351da02bc0 100644 --- a/sys/sys/condvar.h +++ b/sys/sys/condvar.h @@ -51,6 +51,7 @@ void cv_destroy(struct cv *cvp); void _cv_wait(struct cv *cvp, struct lock_object *lock); void _cv_wait_unlock(struct cv *cvp, struct lock_object *lock); int _cv_wait_sig(struct cv *cvp, struct lock_object *lock); +int _cv_wait_sig_unlock(struct cv *cvp, struct lock_object *lock); int _cv_timedwait_sbt(struct cv *cvp, struct lock_object *lock, sbintime_t sbt, sbintime_t pr, int flags); int _cv_timedwait_sig_sbt(struct cv *cvp, struct lock_object *lock, @@ -65,6 +66,8 @@ void cv_broadcastpri(struct cv *cvp, int pri); _cv_wait_unlock((cvp), &(lock)->lock_object) #define cv_wait_sig(cvp, lock) \ _cv_wait_sig((cvp), &(lock)->lock_object) +#define cv_wait_sig_unlock(cvp, lock) \ + _cv_wait_sig_unlock((cvp), &(lock)->lock_object) #define cv_timedwait(cvp, lock, timo) \ _cv_timedwait_sbt((cvp), &(lock)->lock_object, \ tick_sbt * (timo), 0, C_HARDCLOCK)
