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