At 1:54 +0100 24/2/06, Frank Heckenbach wrote:
So I think we should start with a list of RTS variables and classify them to find out how to deal with each. Did you start making such a list already perhaps?
It's a good idea. No, I haven't made a start.
My solution in general is simply not to use the RTS at all (so for example, I just use my own NumToStr routine instead of using ReadStr to parse numbers, and I've always used my own memory allocation routines (except for New(obj) which can't be avoided) and file access routines.
This change would be incompatible with existing RTS routines,
And unfortunately also with existing Pascal standards (for `New') or dialects (for `IOResult').
Yes, that was really what I meant to say. Incompatible with not only the existing RTS (and hence programs using it), but existing Pascal standards (and hence programs using them being ported to GPC).
although it could possible be accomplished by placing a thread safe layer underneath the thread-unsafe standard RTS API, for example (very loose pseudo code) :
procedure WriteStr( xxx ) var error: yyy; begin fh := GetReadWriteStrFDR; error := WriteStrSafe( fh, xxx ) InOutRes := error; conditionally exit with a runtime error end;
It would also likely require additions/changes to the way the compiler interacted with the RTS.
This way would not be BP compatible, since the raising of runtime errors must be done in the caller as it depends on the {$I+} setting (at the place of call).
My point was more that we could implement a thread safe RTS underneath a thread-unsafe API. People needing thread safeness could then use the thread safe API to the RTS instead of the thread unsafe standard API.
Therefore (and because BP allows direct access to InOutRes), it probably has to be a global variable. -- Or at least look like one. The compiler could rewrite read and write usage of it, but what about passing it by reference? BP allows this, and I'm not sure this isn't done in practice (ATM I'm not even sure WRT my own code, though I could check that).
If we look at C, they have a similar issue with `errno'. AFAIK, thread libraries rewrite it (via a macro) to something like `(foo^)' (in Pascal syntax) where foo is a thread-dependent function or expression that returns the address of a per-thread variable. This allows all kinds of usage including reference passing (address taking in C), so it might work with some effort.
Yes, I believe errno is handled that way, as a macro to access a per-thread stored variable.
We could presumably do the same thing with InOutRes and some compiler tricks (so the compiler silently converts InOutRes := 123 to ThreadSetInOutRes( 123 ) for example). But that requires the RTS knowing about per-thread variables, so I'm not sure it is the right way to go.
Any way you slice it, it'd be a fair amount of work to be
entirely thread safe.
I suppose so. It's probably obvious from previous mails that I'm not really a fan of multithreading -- so far, in every case others would have (or have) said requires threading, I solved it with either multiplexed I/O (poll, select) or separate processes (with separate data) -- which are not without problems, either, but to me they seemed easier to handle. I just mention this to say that I'm not going to spend much effort in this direction myself.
Same here, but for different reasons - I use multithreading, but don't use the RTS, so its not a high priority for me either.
One disadvantages I see with your approach is that it adds overhead, even to non-threaded programs, something I obviously don't like. I also wouldn't like requiring a thread library to start with. (I've had bad experience trying to even build some foreign programs that required particular thread libraries ... incompatible versions and what not.) This probably menas we'll need two versions of the RTS library, though, of course, we should be able to build them from the same source, using conditionals -- or even a compiler flag (we might need one for the compiler/RTS interface anyway, as you say, so perhaps we can test this flag with {$ifopt} in the RTS, but that's just a detail).
I agree that the RTS should not depend on the thread library, especially because it varies so much and there is no single thread library (there are at least three different ones on Mac OS, probably more). Similarly, there are different APIs for different mutexes and such.
That's why I'd suggest rather than have the RTS become thread aware, instead have the RTS provide an API that is inherently thread safe because it has kicked the thread-unsafeness up to the programmer. They can then cheerfully ignore the issue if they aren't threaded, or handle it appropriately for their threading architecture if they are.
As far as overhead, generally I would expect this to be very minimal, since the typical requirement is that the thread safe RTS API does part of the job, and the thread unsafe standard API does the rest in the same way it does now. So it probably is not much more than an extra procedure call overhead, though obviously there may be worse cases than that.
We should also, as far as possible, concentrate the differences in as few places as possible, even if this means using some macros or other ugly tricks. But first of all, the fewer variables we need to deal with, the easier it will become.
Of course, apart from variables, we have to look at non-thread-safe library routines. (I'm not sure which are -- what about malloc etc. for a start? Does libc make it thread-safe already?)
That varies from system to system. Most everything under Mac OS X is thread safe now, but not all of it was in earlier releases.
This is another issue which makes the whole problem quite hard. Saying the RTS (or even some API of it) is thread safe is probably not possible without qualifying what systems it is running on.
Anyway, I wasn't really suggesting that a major exercise be undertaken to make the RTS thread safe, more to ensure people are aware that it isn't (and to keep in peoples minds that those parts of the RTS that cannot be avoided, eg parts that the compiler calls without direct knowledge by the programmer, really need to be thread safe).
Enjoy, Peter.