On Tue, 3 Jun 2014, strake...@gmail.com wrote: > Latest version, much unbroken. Mounted filesystem seems fully readable > now, but creation fails queerly: the file name is as long as the > requested name but garbage. I shall hack further...
First off, a utter blocker to this code being included in OpenBSD. In a earlier message you wrote this: > Yes, some code I copied verbatim from plan9port or earlier work of mine, > so that's fully in plan9 or my habitual style. IF YOU COPIED MORE THAN TRIVIAL CODE FROM plan9port YOU MUST ACKNOWLEDGE IT BY INCLUDING THEIR COPYRIGHT ON IT AND ABIDING BY THEIR LICENSE RESTRICTIONS. If that license places more restrictions than the modern 3-clause BSD license, then it will NOT be included in the OpenBSD kernel distribution. Currently your code has *no* copyright statement on it, which means that you've retained all rights to the code and no one can do anything with it. In case you are able to resolve the copyright and license issues with this, here are some comments on the synchronization logic in it: > +.Ft int > +.Fn "tsleep_inc_int" "void *ident" "unsigned int *flagp" "int priority" > "const char *wmesg" "int timo" That raised my monobrow... > +.Fn tsleep_inc_int > +is the same as > +.Fn tsleep , > +but takes another argument: > +.Bl -tag -width priority > +.It Fa flagp > +A pointer to a variable that will be incremented when the process is safely > on the sleep queue. The ...and then this made me wonder if it was actually possible to use safely. The only reason to care whether another kernel thread had made it far enough into tlseep as to be on a sleep queue is if it's calling wakeup() on that thread's wait channel, but you MUST use some sort of lock to protect that shared condition that the tsleeping thread is waiting for, period. For tsleep(), the involved lock is the kernel lock (aka "big lock"), while for msleep() it's the passed mutex. At that point, the int being incremented is just a counter and the thread could increment it itself before calling tsleep(). No need for a new function. > +.Dv PNORELOCK > +flag must be set in the > +.Fa priority > +argument. > +.El This *IS* unsafe. PNORELOCK cannot be used safely with tsleep() because it will do unsafe calls if ktraced. It also is a good sign that your sleep condition is wrong. Back to how you're using tsleep_inc_int(): in this case, the problem is that you're trying to use the int itself to wakeup another thread that spins, but that CANNOT WORK RELIABLY. If you want another thread to block until this one has done something, then it should have its own condition and tsleep() on it. This thread would then wake it after changing the state to one where the thread can make progress. I.e., this code: ... > + if (c = tsleep_inc_int (&requ, &requ.ready, PNORELOCK | curproc -> > p_priority, "awaiting response", 0)) goto end; ... ...combined with this... > + /* Lest we and sender race */ > + while (!requp -> ready); > + *requp -> fcallp = fcall; > + wakeup (requp); ...must change, period. Maybe it's just a matter of changing that while() loop to while (!requp -> ready) tsleep(&requp->ready, PSOCK, "9Precv", 0); and then having p9p_require() call wakeup(&requ.ready) before it calls tsleep(). Side note: the priority passed to tsleep() should be a P* constant from sys/param.h, like PSOCK, or maybe a small adjustment from one of those, so that it's priority is raised when it has something useful to do that may be blocking userspace or other threads. I will comment no further until the copyright and license situation on this is believably resolved, as it's a waste of time if that can't happen. Philip Guenther