home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.modula3
- Path: sparky!uunet!zaphod.mps.ohio-state.edu!cs.utexas.edu!sun-barr!decwrl!pa.dec.com!rdg.dec.com!jch
- From: jch@rdg.dec.com (John Haxby)
- Subject: Failing system calls and threads
- Message-ID: <1992Nov20.120734.23671@rdg.dec.com>
- Sender: news@rdg.dec.com (Mr News)
- Organization: Digital Equipment Corporation
- Date: Fri, 20 Nov 1992 12:07:34 GMT
- Lines: 93
-
- [First, an apology, this is rather longer that I thought it
- would be.]
-
-
- Hello,
-
- While I was writing `cat' (as one does) I tripped up over an
- interesting problem around system calls. The problem revolves around
- accurately dealing with system call failures. In C this is easy, one
- writes:
-
- if (write (fd, buf, sz) < 0)
- if (errno == EINTR)
- /* try again */
- else
- perror ("write")
-
- (more-or-less). The equivalent code in SRC Modula-3 (2.07) is somewhat
- similar, at least in spirit, and this is where the problems arise.
- Obviously, if some other thread gets to run between the call to write() and
- the examination of errno then the value of errno may no longer be valid or
- useful when you come to look at it.
-
- The obvious way around this is to protect the code with some suitable
- mutex, eg
-
- LOCK Cerrno.mu DO
- write (...)
- IF Cerrno.errno ...
- END
-
- but this has at least three significant problems: the overhead in acquiring
- a lock around every system call is non-negligable (I assume); not all uses
- of errno are guaranteed to be protected (especially in uses within C
- libraries); only one outstanding system call is can be permitted (in an
- environement that uses kernel-supported threads).
-
- I was thinking about all this while I was making the children's breakfast
- this morning: these problems do make using the present Modula-3
- implementation somewhat tricky for a good many of the (commercial)
- applications I had in mind. However, whilst putting milk on the Rice
- Krispies, it occurred to me that there is a solution, at least for ULTRIX
- and probably BSD UNIX.
-
- Before I suggest a solution, though, am I barking up the right tree? Does
- what I say make sense or have I missed something in the implementation?
-
-
-
- The solution comes from knowing that errno is introduced by the C library
- and not by the kernel: the kernel returns a result and an indication of
- whether that result is an error code or a returned value. On a VAX, the
- indication is the carry flag, on a (DEC) mips machine, the indication
- is left in a register when the syscall instruction `returns'. The
- implementation of the solution involves re-writing all of the system calls
- so that the are of the form (expressed in C)
-
- int err = sysfunc (&res, arg1, arg2, ...);
-
- The &res is only written to the if the return result is non-zero; the
- return result is otherwise what would be written to errno. The Modula-3
- implementation of, say, Unix.write would then look something like this
- (syntax notwithstanding :-):
-
- PROCEDURE write (fd: INT; buf: REFANY; sz: INTEGER): INTEGER RAISES{syserr} =
- VAR
- err: INTEGER;
- res: INTEGER;
- BEGIN
- err := system.syscall (system.write, res, fd, buf, sz);
- IF err # 0 THEN
- RAISE syserr(err)
- ELSE
- RETURN res
- END
- END write.
-
- Does this make sense? Will it avoid the problems I mentioned earlier?
- And, a question for the other implementations: can this form of solution be
- used? (specifically, are there any implementations out there where errno is
- explicitly known by the kernel?)
-
-
-
-
-
- --
- John Haxby, Definitively Wrong.
- Digital <jch@rdg.dec.com>
- Reading, England <...!uknet!wessex!jch>
-
- ----------------------------------------------------------------
- The opinions expressed herein are my own, not my employers.
-