home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.modula3
- Path: sparky!uunet!decwrl!pa.dec.com!src.dec.com!src.dec.com!mjordan
- From: mjordan@src.dec.com (Mick Jordan)
- Subject: Re: Failing system calls and threads
- Message-ID: <1992Nov23.173612.16490@src.dec.com>
- Sender: news@src.dec.com (News)
- Organization: DEC Systems Research Center
- References: <1992Nov20.120734.23671@rdg.dec.com>
- Date: Mon, 23 Nov 92 17:36:12 GMT
- Lines: 69
-
- In article <1992Nov20.120734.23671@rdg.dec.com>, jch@rdg.dec.com (John Haxby) writes:
-
- |> 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).
-
- In general, when you are dealing with a library that exports shared global
- variables, written in any language (including Modula-3), multi-threaded clients
- must use locks to synchronise the operations and access to the variables.
- In the specific case you mention of errno, one of the standard tricks in
- the C world is to treat errno as a macro and define it as a function that
- accesses a thread specific value. This is what thread-friendly C libraries
- do. But most systems dont have thread-friendly libraries and unless all
- C code has been recompiled against the functional errno, the solution
- doesnt work.
-
- However, the overhead in acquiring the lock is (should be) negligible
- in comparision with entering the operating system. So, for example, we
- chose your first solution for the Olivetti Modula-3 library.
-
- |> 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 :-):
- |>
-
- |> 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?)
-
- In the days before Modula code and C code intermixed so easily, it was
- possible to adopt this solution, since the Modula libraries typically
- preempted all the Unix interface and dealt directly with the Unix
- kernel entry rather than the C library. In general, of course, it is
- neither possible nor desirable to modify the code of the library to
- make it more thread friendly. In particular one cant usually find
- a layer just below the surface on which you can layer a more suitable
- veneer. Therefore if large scale exploitation of C and C++ code from
- Modula-3 is to be possible, we have to lobby for thread-friendly designs
- at the C and C++ level.
-
- Mick Jordan
-
-
-