From owner-freebsd-arch Wed Nov 29 22:53:20 2000 Delivered-To: freebsd-arch@freebsd.org Received: from smtp04.primenet.com (smtp04.primenet.com [206.165.6.134]) by hub.freebsd.org (Postfix) with ESMTP id 3A33A37B402 for ; Wed, 29 Nov 2000 22:53:17 -0800 (PST) Received: (from daemon@localhost) by smtp04.primenet.com (8.9.3/8.9.3) id XAA24967; Wed, 29 Nov 2000 23:49:23 -0700 (MST) Received: from usr08.primenet.com(206.165.6.208) via SMTP by smtp04.primenet.com, id smtpdAAAUqayRW; Wed Nov 29 23:49:19 2000 Received: (from tlambert@localhost) by usr08.primenet.com (8.8.5/8.8.5) id XAA07381; Wed, 29 Nov 2000 23:53:09 -0700 (MST) From: Terry Lambert Message-Id: <200011300653.XAA07381@usr08.primenet.com> Subject: Re: Modifying FILE to add lock To: marcel@cup.hp.com (Marcel Moolenaar) Date: Thu, 30 Nov 2000 06:53:09 +0000 (GMT) Cc: bright@wintelcom.net (Alfred Perlstein), marcs@znep.com (Marc Slemko), eischen@vigrid.com (Daniel Eischen), arch@FreeBSD.ORG In-Reply-To: <3A258696.EAD7BD7A@cup.hp.com> from "Marcel Moolenaar" at Nov 29, 2000 05:43:34 PM X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: owner-freebsd-arch@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG > > I've never ever looked at the contents of struct FILE except to > > research how stdio works. Why do we need to care about the > > contents of struct FILE (or DIR)? We have funopen do deal with > > creating our own special streams, what's the point of digging > > into struct FILE? > > The fact that you (and I) can't see the point, doesn't mean there is no > point. Ignoring the fact that maybe there's a point somehow or somewhere > is far more worse than reaching general consensus that there likely is > no point at all. > > Modula has some weird architecture and OS dependencies, IIRC. It doesn't > hurt to check it out before we commit the change. There are a number of programs which traditionally need to be able to access the contents of the FILE buffers directly, particularly with regard to things like "unget", and so on. Mostly, these are mixed-mode programs, which do things like bounce in and out of raw mode, or set cbreak, or modify the value of vmin or vtime, and wish to act properly on already typed ahead on ungetc()'ed characters that have been buffered. It would be terrifically useful, for example, for getpass() to use this to permit scripting of the creation of user accounts (as one example). That it does not work that way means you have to resort to "pw" (a perl abomination) to get the job done right. Historically, things like EMACS and simulations that like to implement command "intertia" (no command in the timeout window means the previous command is in effect) tend to directly manipulate buffered input contents. There is at least one "curses"-like library of which I'm aware that actually manipulates buffered output contents to remove redundant output (e.g. "don't draw X there, if you are going to draw Y there immediately afterward). It's very useful for slow links for things like text editors, where I can delete a character, insert another, and end up with only a single character being redrawn once, instead of to the end of the line from the deletion/insertion point needing to be rendered twice. There are also programs which move stdin/out/err around to effect certain features, without telling the program about it (screen used to be one, so that it could support session detach and reattach). Suffice it to say that not everyone uses the macros, and those who do, tend to not want to recompile the world. You might consider using the old "debugging malloc" trick, of allocating one structure, but referring to another, and reference your "hidden" lock at a negative offset. This would let you pass around FILE objects that were allocated larger than they were supposed to be, and reference locks at a negative offset. This would require some simple pointer math on allocation, and would ensure binary backward compatability with old programs and the new libc, without requiring a version bump at all. If you use this trick, be wary of "#pragma pack()" in scope, since unlike the kernel MUTEX() trick, the relative location of the start of the shadow structure will end up moving around, if you aren't explicit. struct foo { whatever; whatever; ... }; struct foo_with_lock { LOCK alfreds_new_lock; struct foo internal_foo; }; Pass around: struct foo *foop = &(foo_with_lockp->internal_foo); Reference the lock with: CVT_TO_LOCKED(struct foo_with_lock, foop)->alfreds_new_lock #define CVT_TO_LOCKED(x,y) \ (void *)(((char *)(y)) - (int)&(((x *)0)->internal_foo)) I would probably force the packing around the declaration in the header file. Terry Lambert terry@lambert.org --- Any opinions in this posting are my own and not those of my present or previous employers. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-arch" in the body of the message