Date: Fri, 6 Nov 1998 11:36:01 -0800 (PST) From: Matthew Dillon <dillon@apollo.backplane.com> To: Tor.Egge@fast.no Cc: cvs-committers@FreeBSD.ORG Subject: Re: sendfile.2 (was Re: cvs commit: ...) Message-ID: <199811061936.LAA00920@apollo.backplane.com> References: <199811060401.UAA00767@apollo.backplane.com> <199811061214.NAA01603@midten.fast.no>
next in thread | previous in thread | raw e-mail | index | archive | help
:> to implement. A simple MAP_PRIVATE replacement of __srefill() and maybe
:> a little code to avoid unnecessary copy-on-write ops.
:
:Enabling vfs_ioopts does most of this implicitly. Unfortunately,
:there is a bug involved, that might cause a deadlock when
:reading the last "fragment" of the file.
:
:The same deadlock can be triggered by explicit use of mmap, e.g. PR 8416.
:
:- Tor Egge
We have the choice of either implementing automatic deadlock
detection (icky), allowing the already non-zero shared count to be bumped
and risking resource starvation (also icky), or keeping track of shared
locks with an extra linked-in structure on a per-pid basis in order to
specifically allow the recursive-shared-lock case to override an
exclusive lock request.
Actually, that isn't a bad idea. Why not use the supervisor stack to
manage the locks and formally require that locks either (a) not be
held past the procedure obtaining them or (b) that if a procedure is
supposed to return a locked object, that the lock extension structure
be passed to the procedure as an argument.
procedure()
{
lock_extension_structure fubar;
/*
* shared_lock links fubar into the lock structure
*/
shared_lock(&someLock, &fubar);
... do stuff that might result in recursive locks ...
/*
* must always unlock since fubar goes invalid on the return from
* procedure.
*/
shared_unlock(&fubar);
}
There are major advantages to this scheme. Amoung other things, we win
big if we formally disallow these sorts of locks to be held past the
return-from-procedure. No more cases of "Who really controls that lock"...
if a procedure is supposed to return a locked object, the caller *must*
supply the lock extension structure to the procedure. There would be
no other way to do it.
(also note: I'm not talking about VM page structure locks, only vnode and
inode style 'temporary' locks).
The advantages:
* no allocation of structures.
* coding of locks and especially the returning of an object with a
retained lock becomes crystal clear. No more confusion over who
owns the lock or whether an object is supposed to be returned in
a locked state.
* debugging is easier - both shared and exclusive locks can be
tracked rather then just exclusive locks. Many of the lockups
we've had in the past have been due to shared locks that
we could track.
* system can later be extended to deal with deadlock detection
* system can deal with recursive shared locks (i.e. not block
on recursive shared locks within a pid in the face of a pending
exclusive lock, block otherwise).
* the unlock call can wakeup lock holders even more easily then it is
done now.
The disadvantages:
* linked lists are used, but it should be pointed out that linked lists
are already used in tsleep/wakeup. With the new system, processes
tsleep on the lock extension structure so the linked lists on wakeup
become degenerate. The linked lists effectively migrate to the
lock structure (i.e. we have a linked list of lock extension
structures applied to the lock).
Not much of a disadvantage, IMHO.
* critical state is stored on the supervisor stack. Not much of a
disadvantage here either.
-Matt
Matthew Dillon Engineering, HiWay Technologies, Inc. & BEST Internet
Communications & God knows what else.
<dillon@backplane.com> (Please include original email in any response)
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe cvs-all" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199811061936.LAA00920>
