RTS and thread safety
Frank Heckenbach
ih8mj at fjf.gnu.de
Sat Feb 25 06:14:56 CET 2006
Adriaan van Os wrote:
> Forwarding a message from Jonas Mabe to the MacPascal mailing list:
>
> Peter N Lewis wrote:
>
> > To properly handle MP threading, the RTS would, at the least, require
> > everything to have a returned error result, rather than using
> > IOResult, which would be a big change (although this would be
> > desirable for New as well).
>
> FWIW, in Free Pascal we solved this problem with the introduction of
> the "threadvar" keyword (which may have been copied from Delphi, I
> don't know). A threadvar consists of two parts:
>
> a) first an index into some structure which contains the value of
> this variable in case of a multi-threaded program
How are these indices allocated? AFAICS, they must be globally
unique, even across units. Do you do something like a base-index per
unit, and running indices within unit? Or an extra pass in the main
program to sort all indices in the units used?
> b) next room to contain the value of this variable in case of a
> single-threaded program.
Interesting idea. Of course, it adds a little storage (one index per
variable) even in the single-threaded case, but since there
shouldn't be too many thread variable, that seems quite acceptable.
> E.g. the assignment in this program:
>
> threadvar
> a: longint;
>
> begin
> a := 5;
> end.
>
>
> is compiled into this:
>
> # [5] a := 5;
> lis r2,ha16(FPC_THREADVAR_RELOCATE)
> lwz r2,lo16(FPC_THREADVAR_RELOCATE)(r2)
> cmplwi cr0,r2,0
> beq cr0,L5
> lis r4,ha16(U_P$PROGRAM_A)
> lwz r3,lo16(U_P$PROGRAM_A)(r4)
> mtctr r2
> bctrl
> b L6
> L5:
> lis r3,ha16(U_P$PROGRAM_A+4)
> addi r3,r3,lo16(U_P$PROGRAM_A+4)
> L6:
> li r2,5
> stw r2,0(r3)
My speaking of PPC assembler is not really good, but I read it as
something like this, right?
if FPC_THREADVAR_RELOCATE <> nil then
r3 := FPC_THREADVAR_RELOCATE^ (a)
else
r3 := Pointer (@a) + 4;
LongInt (r3^) := 5;
> Of course, such a solution for ioresult is slower than returning an
> error from a function,
Sure, the function call is expensive. Of course, it's only needed
when actually multi-threaded which is a plus as far as I'm
concerned. Still, it would be good if it could be avoided. One way
might be to store offsets instead of indices, but computing
globally-contiguous offsets is even harder than globally-unique
indices. (AFAICS, it could be done in an extra pass in the compiler
or perhaps easier by automatically "registering" all thread
variables at runtime.)
> but on the other hand it is fully compatible
> with existing code (also in the RTL/RTS, except if such variables are
> somewhere used in assembler code).
Fortunately, we don't have to worry about assembler code in the RTS.
So this might be an option. (But again, first I'd like to see which
variables are actually affected and thus how big the effects would
actually be. InOutRes might well be the worst, because most-often
used one, but not the only one, of course.)
Frank
--
Frank Heckenbach, frank at g-n-u.de, http://fjf.gnu.de/, 7977168E
GPC To-Do list, latest features, fixed bugs:
http://www.gnu-pascal.de/todo.html
GPC download signing key: ACB3 79B2 7EB2 B7A7 EFDE D101 CD02 4C9D 0FE0 E5E8
More information about the Gpc
mailing list