Previous mail
Next mail
Unformatted/full headers
Overview 10 days
Subject
Date
Thread
Author
From: Frank Heckenbach
Subject: RTS and thread safety
Date: 24 Feb 2006, 09:37:38
Peter N Lewis wrote:
> 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.
As you prefer, but since many features, including most I/O, memory
allocation and string routines, call the RTS internally, I'm not
sure I'd call the remains really Pascal. ;-) And we don't actually
guarantee that any particular built-in feature does/will not use RTS
routines. The RTS is tied rather strictly to the compiler (unlike C
and libc, e.g. -- more like GCC and the internally called libgcc.a).
> > > 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).
Or newly written for GPC, using any of those standard or dialect
features, which includes pretty much everything of my own code, for
example ...
> > > 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.
For user-called routines, sure. But IMHO the tricky parts are the
compiler-called ones such as your example WriteStr, and of course,
the whole I/O-result handling (which depends to a large degree on
compiler magic).
> >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.
This way wouldn't cope with reference passing (address taking), so
we'd need something more like `ThreadGetInOutResPointer^ := 123'.
But according to Waldek, this won't be necessary when the backend
supports per-thread variables.
> 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.
For some parts, this could work. And for some, we can perhaps even
eliminate the problems. (Some global variables might be avoidable,
though probably not many, as I usually don't use them unwarranted.
Some are only there for optimization, such as LastReadWriteStrFDR,
and some are mostly read-only such as ExpEpsReal, perhaps we can do
something easier with them.)
For non-thread-safe routines only called by the user we can probably
add thread-safe interfaces where necessary (and perhaps declare
obsolete and later remove the other ones, unless they are required
for compatibility with something).
But again, the real problem are the compiler-called ones. Just one
example, the I/O system keeps a list of all currently open files.
This list must obviously be global. So it seems its access should be
somehow synchronized (mutex etc.) -- which, in this particular case
is not a matter of efficiency, as opening and closing are "rare" and
costly operations anyway, but it raises the questions of thread
library selection and dependence. Unless perhaps, we provide hooks
for the synchronization code that default to nops and that the user
has to fill in if threaded. This is just a quick idea, and may be a
kludge, I'd have to think about it more. (And whether it's really
viable might depend on how many such areas really are there, which I
don't know offhand.)
BTW, I'm aware of the irony -- hooks = global (pointer) variables,
which are generally to be avoided in threading. (But obviously,
these hooks would have to be set before starting threads, and not
changed within threads, so they're not actually a problem AFAICS.)
> >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.
So we can only assume what's guaranteed by POSIX etc.
> 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.
POSIX-compatible (well, mostly ;-) systems, as usual.
> Anyway, I wasn't really suggesting that a major exercise be
> undertaken to make the RTS thread safe,
Since several people have asked for this over time, it suggest it
should perhaps be done sometime. But I'm not one of them. ;-)
> 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).
Which is probably the hardest part anyway, unfortunately ...
Frank
Previous mail
Next mail
Unformatted/full headers
Overview 10 days
Subject
Date
Thread
Author
| Author | Subject | Date |
|---|---|---|
| Peter N Lewis | RTS and thread safety | 23 Feb 2006, 22:26:33 |
| Frank Heckenbach | RTS and thread safety | 24 Feb 2006, 01:54:39 |
| Peter N Lewis | RTS and thread safety | 24 Feb 2006, 12:49:27 |
Note: This page contains information that does not originate from the owner of this web site, but from the authors of the mails archived. The owner of this web site is not responsible for the content of such information. Any use of that infomation requires the consent of the respective author.
Where WWW addresses (URLs) in the mails archived are marked as hyperlinks, this is only for the comfort of the reader. The content of the web pages linked to like this does not necessarily reflect the opinion of the owner of this web site or of the authors of the mails archived. The owner of this web site is not responsible for the content of such web pages. Those pages are explicitly not to be considered as part of the content of this page, but merely as references.
This page was created by Crystal 0.999 (Linux 2.4.27/i686).