bug in limit checks and threads
Stephen Weeks
sweeks@intertrust.com
Wed, 4 Oct 2000 11:20:36 -0700 (PDT)
> There is currently a bug in the way thread switching is handled. The problem is
> caused by the fact that limit check points are the same as context switch
> points. The bug is that a thread checks that there is enough space available
> before switching to another thread and not when it resumes. Hence there is no
> guarantee that there is enough space when the thread resumes. There are three
> possible fixes I see to this problem.
>
> 1. Save the bytesRequested as part of the gc state and have the gc check it
> upon resumption.
> 2. Have the LimitCheck code include a loop that checks again, upon return from
> the GC.
> 3. Have some global max over all (fixed-size) limit checks that the GC
> guarantees is available upon thread resumption. Disallow thread switches
> at variable-sized limit check points.
>
> Any opinions on which way is the right way to go? Other solutions?
I went ahead with a slight modification of Henry's suggestion, which was
> I would guess that the time overhead of changing
> if (less than ??? space)
> do_GC(...);
> to
> while (less than ??? space)
> do_GC(...);
> should be quite minimal, so I would probably vote for that.
To avoid any runtime cost, I left the if test in limit checks alone, and put a
loop inside the gc case. Here is the new LimitCheck macro.
#define LimitCheck(frameSize, ret, b, other) \
do { \
declareFirst; \
\
if (INSTRUMENT) \
MLton_numLimitChecks++; \
if (GC_EVERY_CHECK \
or (GC_FIRST_CHECK and gc_first) \
or frontier + (b) > gcState.limit \
or (other)) { \
do { \
uint bytes = b; \
\
InvokeRuntime(GC_gc(&gcState, bytes, \
GC_EVERY_CHECK or \
(GC_FIRST_CHECK and gc_first), \
__FILE__, __LINE__), \
frameSize, ret); \
} while (frontier + (b) > gcState.limit); \
clearFirst; \
} \
assert(gcState.stackBottom <= stackTop + WORD_SIZE); \
} while (0)