X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FCapability.h;h=d2fcc5ed7bfdb90449773560938618a59cc18a72;hb=de75026f5a48d3d052135a973ab4dff76c5b20f5;hp=478b0f1312e8a9e4aca1bdf6cf9b06041d8c1b8f;hpb=3ebcd3deb769a03f4ded0fca2cf38201048c0214;p=ghc-hetmet.git diff --git a/rts/Capability.h b/rts/Capability.h index 478b0f1..d2fcc5e 100644 --- a/rts/Capability.h +++ b/rts/Capability.h @@ -32,11 +32,7 @@ struct Capability_ { // code. During STG execution, the BaseReg register always points // to the StgRegTable of the current Capability (&cap->r). StgFunTable f; - StgRegTable r GNU_ATTRIBUTE(packed); - // packed eliminates any padding between f and r. Not strictly - // necessary, but it means the negative offsets for accessing - // the fields of f when we are in STG code are as small as - // possible. + StgRegTable r; nat no; // capability number. @@ -69,10 +65,12 @@ struct Capability_ { Task *suspended_ccalling_tasks; // One mutable list per generation, so we don't need to take any - // locks when updating an old-generation thunk. These - // mini-mut-lists are moved onto the respective gen->mut_list at - // each GC. + // locks when updating an old-generation thunk. This also lets us + // keep track of which closures this CPU has been mutating, so we + // can traverse them using the right thread during GC and avoid + // unnecessarily moving the data from one cache to another. bdescr **mut_lists; + bdescr **saved_mut_lists; // tmp use during GC // Context switch flag. We used to have one global flag, now one // per capability. Locks required : none (conflicts are harmless) @@ -147,12 +145,10 @@ struct Capability_ { // Converts a *StgRegTable into a *Capability. // -#define OFFSET(s_type, field) ((size_t)&(((s_type*)0)->field)) - INLINE_HEADER Capability * regTableToCapability (StgRegTable *reg) { - return (Capability *)((void *)((unsigned char*)reg - OFFSET(Capability,r))); + return (Capability *)((void *)((unsigned char*)reg - STG_FIELD_OFFSET(Capability,r))); } // Initialise the available capabilities. @@ -280,6 +276,7 @@ extern void grabCapability (Capability **pCap); // cause all capabilities to context switch as soon as possible. void setContextSwitches(void); +INLINE_HEADER void contextSwitchCapability(Capability *cap); // Free all capabilities void freeCapabilities (void); @@ -326,4 +323,16 @@ discardSparksCap (Capability *cap) { return discardSparks(cap->sparks); } #endif +INLINE_HEADER void +contextSwitchCapability (Capability *cap) +{ + // setting HpLim to NULL ensures that the next heap check will + // fail, and the thread will return to the scheduler. + cap->r.rHpLim = NULL; + // But just in case it didn't work (the target thread might be + // modifying HpLim at the same time), we set the end-of-block + // context-switch flag too: + cap->context_switch = 1; +} + #endif /* CAPABILITY_H */