[M3devel] heapalloc/try during initialization
Jay
jay.krell at cornell.edu
Wed May 6 23:56:56 CEST 2009
Ok. I commited my version that seems ok and seems to work but you can overwrite it.
Something that only takes the lock once would be preferred.
And perhaps always uses/try/finally when it does take the lock instead of my less consistent harder to maintain form.
Probably move yours away, update, copy yours on top of mine, compare. Resolving conflicts in cvs is lame..
Also, another obvious approach is to duplicate the LongAlloc initialization,
such that the fast path works for the first allocation.
Or even for all allocations until the GC is ready.
I was reluctant to duplicate that tricky coe, but it's only a few lines
really and could be moved into a shared function.
Either way I think AllocTraced should not have TRY, to speed up the fast path.
- Jay
----------------------------------------
> From: hosking at cs.purdue.edu
> To: jay.krell at cornell.edu
> Date: Thu, 7 May 2009 07:27:29 +1000
> CC: m3devel at elegosoft.com
> Subject: Re: [M3devel] heapalloc/try during initialization
>
> I'm working on this today. Let me get back to you.
>
> On 6 May 2009, at 23:53, Jay wrote:
>
>>
>> Something like the attached?
>>
>> (I don't trust email to be formated as expected, so the attachment
>> is canonical and the rest might not be readable.)
>>
>>
>> The idea is to provide a split CollectEnough for AllocTraced to call.
>> It's a little lose on the locking but it should be ok and slows down
>> the slow path with extra unlock/relock.
>>
>>
>>
>> It's good to get the try out of the fast path in either case.
>>
>>
>>
>> PROCEDURE LockedCollectEnough (allocator := FALSE) =
>> BEGIN
>> TRY
>> CollectEnough(allocator);
>> FINALLY
>> RTOS.UnlockHeap();
>> END;
>> END LockedCollectEnough;
>>
>>
>>
>> AllocTraced calls this:
>>
>>
>>
>> PROCEDURE UnlockedCollectEnough (allocator := FALSE) =
>> BEGIN
>> RTOS.LockHeap();
>> IF collectorOn THEN RTOS.UnlockHeap(); RETURN END; (* duplicated
>> from CollectEnough *)
>> IF NOT Behind() THEN RTOS.UnlockHeap(); RETURN END; (* duplicated
>> from CollectEnough *)
>>
>> ThreadF.Init shouldn't get here:
>>
>>
>>
>> LockedCollectEnough(allocator);
>> END UnlockedCollectEnough;
>>
>>
>> AllocTraced slow path excerpt:
>>
>>
>> IF nextPtr> thread.newPool.limit THEN
>> (* not enough space left in the pool, take the long route *)
>> res := NIL; nextPtr := NIL; (* in case of GC... *)
>> DEC(thread.inCritical);
>> (* make sure the collector gets a chance to keep up with NEW...
>> *)
>> UnlockedCollectEnough(allocator := TRUE); (***)
>> RTOS.LockHeap(); (***)
>> res := LongAlloc (dataSize, dataAlignment, thread.newPool,
>> Note.Allocated, pure := FALSE);
>> IF res = NIL THEN
>> RTOS.UnlockHeap(); (***)
>> RuntimeError.Raise(RuntimeError.T.OutOfMemory);
>> END;
>> INC(thread.inCritical);
>> LOOPHOLE(res - ADRSIZE(Header), RefHeader)^ :=
>> Header{typecode := def.typecode, dirty := TRUE};
>> IF initProc # NIL THEN initProc (res) END;
>> RTOS.UnlockHeap(); (***)
>>
>> DEC(thread.inCritical);
>> RETURN LOOPHOLE(res, REFANY);
>>
>>
>> This is all for user threads.
>> There /may/ have been issues with pthreads/ntthreads, but I don't
>> there are now.
>> Your changed didn't break cygwin pthreads but it did break FreeBSD
>> user threads.
>> I only checked each case once so might have made mistakes and gotten
>> it backwards or whatever.
>>
>>
>> Ignorant question/suggestion similar to previous:
>> Thread.T vs. Activation? Userthreads does traced allocations where
>> pthreads/win32threads don't. Maybe change userthreads?
>> Maybe give up on userthreads? This isn't a great reason, granted.
>> I actually would hope the traced thread.t vs. activation could go
>> away, it is ugly. Kudos for user threads for not having it?? (I
>> wonder if there is something around the fact that thread locals
>> aren't visible to the garbage collector..?)
>>
>>
>> - Jay
>
More information about the M3devel
mailing list