X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=rts%2FCapability.h;h=ff6e3681301a13da550cb21f29b8577ac8a2da4e;hp=89545780a4d84718b87ca3e0026980b7beafaa98;hb=5270423a6afe69f1dc57e5e5a474812182718d40;hpb=1d14a6cd5f563507135d450a63cf2bd7e870fe55 diff --git a/rts/Capability.h b/rts/Capability.h index 8954578..ff6e368 100644 --- a/rts/Capability.h +++ b/rts/Capability.h @@ -4,39 +4,32 @@ * * Capabilities * - * The notion of a capability is used when operating in multi-threaded - * environments (which the THREADED_RTS build of the RTS does), to - * hold all the state an OS thread/task needs to run Haskell code: - * its STG registers, a pointer to its TSO, a nursery etc. During - * STG execution, a pointer to the capabilitity is kept in a - * register (BaseReg). + * A Capability holds all the state an OS thread/task needs to run + * Haskell code: its STG registers, a pointer to its TSO, a nursery + * etc. During STG execution, a pointer to the Capabilitity is kept in + * a register (BaseReg). * - * Only in an THREADED_RTS build will there be multiple capabilities, - * in the non-threaded builds there is one global capability, namely + * Only in a THREADED_RTS build will there be multiple capabilities, + * in the non-threaded RTS there is one global capability, called * MainCapability. * - * This header file contains the functions for working with capabilities. - * (the main, and only, consumer of this interface is the scheduler). - * * --------------------------------------------------------------------------*/ #ifndef CAPABILITY_H #define CAPABILITY_H -#include "RtsFlags.h" +#include "sm/GC.h" // for evac_fn #include "Task.h" #include "Sparks.h" +BEGIN_RTS_PRIVATE + struct Capability_ { // State required by the STG virtual machine when running Haskell // 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. @@ -50,6 +43,9 @@ struct Capability_ { // catching unsafe call-ins. rtsBool in_haskell; + // true if this Capability is currently in the GC + rtsBool in_gc; + // The run queue. The Task owning this Capability has exclusive // access to its run queue, so can wake up threads without // taking a lock, and the common path through the scheduler is @@ -66,10 +62,15 @@ 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 + + // block for allocating pinned objects into + bdescr *pinned_object_block; // Context switch flag. We used to have one global flag, now one // per capability. Locks required : none (conflicts are harmless) @@ -144,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. @@ -175,14 +174,14 @@ INLINE_HEADER void releaseCapability_ (Capability* cap STG_UNUSED, rtsBool always_wakeup STG_UNUSED) {}; #endif -#if !IN_STG_CODE -// one global capability -extern Capability MainCapability; -#endif +// declared in includes/rts/Threads.h: +// extern Capability MainCapability; + +// declared in includes/rts/Threads.h: +// extern nat n_capabilities; // Array of all the capabilities // -extern nat n_capabilities; extern Capability *capabilities; // The Capability that was last free. Used as a good guess for where @@ -191,6 +190,8 @@ extern Capability *capabilities; extern Capability *last_free_capability; // GC indicator, in scope for the scheduler +#define PENDING_GC_SEQ 1 +#define PENDING_GC_PAR 2 extern volatile StgWord waiting_for_gc; // Acquires a capability at a return point. If *cap is non-NULL, then @@ -237,6 +238,7 @@ void wakeupThreadOnCapability (Capability *my_cap, Capability *other_cap, // need to service some global event. // void prodOneCapability (void); +void prodCapability (Capability *cap, Task *task); // Similar to prodOneCapability(), but prods all of them. // @@ -274,11 +276,12 @@ 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); -// FOr the GC: +// For the GC: void markSomeCapabilities (evac_fn evac, void *user, nat i0, nat delta, rtsBool prune_sparks); void markCapabilities (evac_fn evac, void *user); @@ -320,4 +323,18 @@ 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; +} + +END_RTS_PRIVATE + #endif /* CAPABILITY_H */