From: Mark Kettenis Subject: Re: rpki-client: pthreads first unlock then signal To: Job Snijders Cc: tech@openbsd.org Date: Tue, 24 Jun 2025 11:11:11 +0200 > Date: Mon, 23 Jun 2025 22:34:08 +0000 > From: Job Snijders > > On Tue, Jun 24, 2025 at 12:25:06AM +0200, Mark Kettenis wrote: > > > Date: Mon, 23 Jun 2025 22:13:51 +0000 > > > From: Job Snijders > > > > > > While this is not fixing a bug, intuition and literature suggest that > > > unlocking mutexes before signaling might help prevent the > > > freshly-woken-up thread from humping against the lock. > > > > Where did you find this questionable advice? > > I quote from The Linux Programming Interface, chapter 30.2 "Signaling > Changes of State: Condition Variables" (page 647) > > """ [Butenhof, 1996] points out that, on some implemenations, > unlocking the mutex and then signaling the condition variable > may yield better performance than performing these steps in the > reverse sequence. If the mutex is unlocked only after the > condition variable is signaled, the thread performing > pthread_cond_wait() may wake up while the mutex is still locked. > This results in two superfluous context switches. Some > implementations eliminate this problem by employing a technique > called "wait morphing", which moves the signaled thread from the > condition variable wait queue to the mutex wait queue without > performing a context switch if the mutex is locked.""" That reference is a bit dated, but Butenhof probably did know what he was talking about. I suspect we don't do any "wait morphing" in our implementation. > Is there a reason to signal and then unlock? POSIX says this: The pthread_cond_broadcast() or pthread_cond_signal() functions may be called by a thread whether or not it currently owns the mutex that threads calling pthread_cond_clockwait(), pthread_cond_timedwait(), or pthread_cond_wait() have associated with the condition variable during their waits; however, if predictable scheduling behavior is required, then that mutex shall be locked by the thread calling pthread_cond_broadcast() or pthread_cond_signal(). Which I have always interpreted as a strong hint to release the mutex *after* the pthread_cond_signal() call. So I'd stick to that pattern unless you can prove doing it the other way results in a measurable speedup. > If that is the case, shouldn't the calls around line 1268 > parser.c:proc_parser() be be reversed? Yes.