X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=includes%2FGranSim.h;fp=includes%2FGranSim.h;h=be5aa83a52a0b53a5900ec60fb4778ab10fdd90b;hb=0065d5ab628975892cea1ec7303f968c3338cbe1;hp=0000000000000000000000000000000000000000;hpb=28a464a75e14cece5db40f2765a29348273ff2d2;p=ghc-hetmet.git diff --git a/includes/GranSim.h b/includes/GranSim.h new file mode 100644 index 0000000..be5aa83 --- /dev/null +++ b/includes/GranSim.h @@ -0,0 +1,331 @@ +/* + Headers for GranSim specific objects. + + Note that in GranSim we have one run-queue and blocking-queue for each + processor. Therefore, this header file redefines variables like + run_queue_hd to be relative to CurrentProc. The main arrays of runnable + and blocking queues are defined in Schedule.c. The important STG-called + GranSim macros (e.g. for fetching nodes) are at the end of this + file. Usually they are just wrappers to proper C functions in GranSim.c. +*/ + +#ifndef GRANSIM_H +#define GRANSIM_H + +#if !defined(GRAN) + +/* Dummy definitions for basic GranSim macros called from STG land */ +#define DO_GRAN_ALLOCATE(n) /* nothing */ +#define DO_GRAN_UNALLOCATE(n) /* nothing */ +#define DO_GRAN_FETCH(node) /* nothing */ +#define DO_GRAN_EXEC(arith,branch,load,store,floats) /* nothing */ +#define GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter) /* nothing */ +#define GRAN_RESCHEDULE(liveness_mask,reenter) /* nothing */ + +#endif + +#if defined(GRAN) /* whole file */ + +extern StgTSO *CurrentTSO; + +/* + * @node Headers for GranSim specific objects, , , + * @section Headers for GranSim specific objects + * + * @menu + * * Externs and prototypes:: + * * Run and blocking queues:: + * * Spark queues:: + * * Processor related stuff:: + * * GranSim costs:: + * * STG called GranSim functions:: + * * STG-called routines:: + * @end menu + * + * @node Externs and prototypes, Run and blocking queues, Includes, Headers for GranSim specific objects + * @subsection Externs and prototypes + */ + +/* Global constants */ +extern char *gran_event_names[]; +extern char *proc_status_names[]; +extern char *event_names[]; + +/* Vars checked from within STG land */ +extern rtsBool NeedToReSchedule, IgnoreEvents, IgnoreYields; +; +extern rtsTime TimeOfNextEvent, TimeOfLastEvent, EndOfTimeSlice; + +/* costs for basic operations (copied from RTS flags) */ +extern nat gran_arith_cost, gran_branch_cost, gran_load_cost, gran_store_cost, gran_float_cost; + +extern nat SparksAvail; /* How many sparks are available */ +extern nat SurplusThreads; /* How many excess threads are there */ +extern nat sparksIgnored, sparksCreated; + +/* + * @node Run and blocking queues, Spark queues, Externs and prototypes, Headers for GranSim specific objects + * @subsection Run and blocking queues + */ + +/* declared in Schedule.c */ +extern StgTSO *run_queue_hds[], *run_queue_tls[]; +extern StgTSO *blocked_queue_hds[], *blocked_queue_tls[]; +extern StgTSO *ccalling_threadss[]; + +#define run_queue_hd run_queue_hds[CurrentProc] +#define run_queue_tl run_queue_tls[CurrentProc] +#define blocked_queue_hd blocked_queue_hds[CurrentProc] +#define blocked_queue_tl blocked_queue_tls[CurrentProc] +#define pending_sparks_hd pending_sparks_hds[CurrentProc] +#define pending_sparks_tl pending_sparks_tls[CurrentProc] +#define ccalling_threads ccalling_threadss[CurrentProc] + +/* + * @node Spark queues, Processor related stuff, Run and blocking queues, Headers for GranSim specific objects + * @subsection Spark queues + */ + +/* + In GranSim we use a double linked list to represent spark queues. + + This is more flexible, but slower, than the array of pointers + representation used in GUM. We use the flexibility to define new fields in + the rtsSpark structure, representing e.g. granularity info (see HWL's PhD + thesis), or info about the parent of a spark. +*/ + +/* Sparks and spark queues */ +typedef struct rtsSpark_ +{ + StgClosure *node; + nat name, global; + nat gran_info; /* for granularity improvement mechanisms */ + PEs creator; /* PE that created this spark (unused) */ + struct rtsSpark_ *prev, *next; +} rtsSpark; +typedef rtsSpark *rtsSparkQ; + +/* The spark queues, proper */ +/* In GranSim this is a globally visible array of spark queues */ +extern rtsSparkQ pending_sparks_hds[]; +extern rtsSparkQ pending_sparks_tls[]; + +/* Prototypes of those spark routines visible to compiler generated .hc */ +/* Routines only used inside the RTS are defined in rts/parallel GranSimRts.h */ +rtsSpark *newSpark(StgClosure *node, + nat name, nat gran_info, nat size_info, + nat par_info, nat local); +/* void add_to_spark_queue(rtsSpark *spark); */ + +/* + * @node Processor related stuff, GranSim costs, Spark queues, Headers for GranSim specific objects + * @subsection Processor related stuff + */ + +extern PEs CurrentProc; +extern rtsTime CurrentTime[]; + +/* Maximum number of PEs that can be simulated */ +#define MAX_PROC 32 /* (BITS_IN(StgWord)) */ /* ToDo: fix this!! */ +/* +#if MAX_PROC==16 +#else +#error MAX_PROC should be 32 on this architecture +#endif +*/ + +/* #define CurrentTSO CurrentTSOs[CurrentProc] */ + +/* Processor numbers to bitmasks and vice-versa */ +#define MainProc 0 /* Id of main processor */ +#define NO_PRI 0 /* dummy priority */ +#define MAX_PRI 10000 /* max possible priority */ +#define MAIN_PRI MAX_PRI /* priority of main thread */ + +/* GrAnSim uses IdleProcs as bitmask to indicate which procs are idle */ +#define PE_NUMBER(n) (1l << (long)n) +#define ThisPE PE_NUMBER(CurrentProc) +#define MainPE PE_NUMBER(MainProc) +#define Everywhere (~0l) +#define Nowhere (0l) +#define Now CurrentTime[CurrentProc] + +#define IS_LOCAL_TO(ga,proc) ((1l << (PEs) proc) & ga) + +#define GRAN_TIME_SLICE 1000 /* max time between 2 ReSchedules */ + +/* + * @node GranSim costs, STG called GranSim functions, Processor related stuff, Headers for GranSim specific objects + * @subsection GranSim costs + */ + +/* Default constants for communication (see RtsFlags on how to change them) */ + +#define LATENCY 1000 /* Latency for single packet */ +#define ADDITIONAL_LATENCY 100 /* Latency for additional packets */ +#define BASICBLOCKTIME 10 +#define FETCHTIME (LATENCY*2+MSGUNPACKTIME) +#define LOCALUNBLOCKTIME 10 +#define GLOBALUNBLOCKTIME (LATENCY+MSGUNPACKTIME) + +#define MSGPACKTIME 0 /* Cost of creating a packet */ +#define MSGUNPACKTIME 0 /* Cost of receiving a packet */ +#define MSGTIDYTIME 0 /* Cost of cleaning up after send */ + +/* How much to increase GrAnSims internal packet size if an overflow + occurs. + NB: This is a GrAnSim internal variable and is independent of the + simulated packet buffer size. +*/ + +#define GRANSIM_DEFAULT_PACK_BUFFER_SIZE 400 +#define REALLOC_SZ 200 + +/* extern W_ gran_mpacktime, gran_mtidytime, gran_munpacktime; */ + +/* Thread cost model */ +#define THREADCREATETIME (25+THREADSCHEDULETIME) +#define THREADQUEUETIME 12 /* Cost of adding a thread to the running/runnable queue */ +#define THREADDESCHEDULETIME 75 /* Cost of descheduling a thread */ +#define THREADSCHEDULETIME 75 /* Cost of scheduling a thread */ +#define THREADCONTEXTSWITCHTIME (THREADDESCHEDULETIME+THREADSCHEDULETIME) + +/* Instruction Cost model (SPARC, including cache misses) */ +#define ARITH_COST 1 +#define BRANCH_COST 2 +#define LOAD_COST 4 +#define STORE_COST 4 +#define FLOAT_COST 1 /* ? */ + +#define HEAPALLOC_COST 11 + +#define PRI_SPARK_OVERHEAD 5 +#define PRI_SCHED_OVERHEAD 5 + +/* + * @node STG called GranSim functions, STG-called routines, GranSim costs, Headers for GranSim specific objects + * @subsection STG called GranSim functions + */ + +/* STG called GranSim functions */ +void GranSimAllocate(StgInt n); +void GranSimUnallocate(StgInt n); +void GranSimExec(StgWord ariths, StgWord branches, StgWord loads, StgWord stores, StgWord floats); +StgInt GranSimFetch(StgClosure *node); +void GranSimSpark(StgInt local, StgClosure *node); +void GranSimSparkAt(rtsSpark *spark, StgClosure *where,StgInt identifier); +void GranSimSparkAtAbs(rtsSpark *spark, PEs proc, StgInt identifier); +void GranSimBlock(StgTSO *tso, PEs proc, StgClosure *node); + + +/* + * @node STG-called routines, , STG called GranSim functions, Headers for GranSim specific objects + * @subsection STG-called routines + */ + +/* Wrapped version of calls to GranSim-specific STG routines */ + +/* +#define DO_PERFORM_RESCHEDULE(liveness, always_reenter_node) PerformReschedule_wrapper(liveness, always_reenter_node) +*/ +#define DO_GRAN_ALLOCATE(n) STGCALL1(GranSimAllocate, n) +#define DO_GRAN_UNALLOCATE(n) STGCALL1(GranSimUnallocate, n) +#define DO_GRAN_FETCH(node) STGCALL1(GranSimFetch, node) +#define DO_GRAN_EXEC(arith,branch,load,store,floats) GranSimExec(arith,branch,load,store,floats) + +/* + ToDo: Clean up this mess of GRAN macros!!! -- HWL +*/ +/* DO_GRAN_FETCH((StgClosure*)R1.p); */ +#define GRAN_FETCH() /* nothing */ + +#define GRAN_FETCH_AND_RESCHEDULE(liveness,reenter) \ + DO_GRAN_FETCH((StgClosure*)R1.p); \ + DO_GRAN_YIELD(liveness,ENTRY_CODE((D_)(*R1.p))); +/* RESTORE_EVERYTHING is done implicitly before entering threaded world again */ + +/* + This is the only macro currently enabled; + It should check whether it is time for the current thread to yield + (e.g. if there is a more recent event in the queue) and it should check + whether node is local, via a call to GranSimFetch. + ToDo: split this in 2 routines: + - GRAN_YIELD (as it is below) + - GRAN_FETCH (the rest of this macro) + emit only these 2 macros based on node's liveness + node alive: emit both macros + node not alive: do only a GRAN_YIELD + + replace gran_yield_? with gran_block_? (they really block the current + thread) +*/ +#define GRAN_RESCHEDULE(liveness,ptrs) \ + if (RET_STGCALL1(StgInt, GranSimFetch, (StgClosure*)R1.p)) {\ + EXTFUN_RTS(gran_block_##ptrs); \ + JMP_(gran_block_##ptrs); \ + } else { \ + if (TimeOfLastEvent < CurrentTime[CurrentProc] && \ + HEAP_ALLOCED((StgClosure *)R1.p) && \ + LOOKS_LIKE_GHC_INFO(get_itbl((StgClosure *)R1.p))) { \ + EXTFUN_RTS(gran_yield_##ptrs); \ + JMP_(gran_yield_##ptrs); \ + } \ + /* GRAN_YIELD(ptrs) */ \ + } + + +/* YIELD(liveness,reenter) */ + +/* GRAN_YIELD(liveness_mask); */ + +/* GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter) */ + +#define THREAD_CONTEXT_SWITCH(liveness_mask,reenter) \ + do { \ + if (context_switch /* OR_INTERVAL_EXPIRED */) { \ + GRAN_RESCHEDULE(liveness_mask,reenter); \ + } }while(0) + +#define GRAN_EXEC(arith,branch,load,store,floats) \ + { \ + W_ cost = gran_arith_cost*arith + \ + gran_branch_cost*branch + \ + gran_load_cost*load + \ + gran_store_cost*store + \ + gran_float_cost*floats; \ + CurrentTSO->gran.exectime += cost; \ + CurrentTime[CurrentProc] += cost; \ + } + +/* In GranSim we first check whether there is an event to handle; only if + this is the case (or the time slice is over in case of fair scheduling) + we do a yield, which is very similar to that in the concurrent world + ToDo: check whether gran_yield_? can be merged with other yielding codes +*/ + +#define DO_GRAN_YIELD(ptrs) if (!IgnoreYields && \ + TimeOfLastEvent < CurrentTime[CurrentProc] && \ + HEAP_ALLOCED((StgClosure *)R1.p) && \ + LOOKS_LIKE_GHC_INFO(get_itbl((StgClosure *)R1.p))) { \ + EXTFUN_RTS(gran_yield_##ptrs); \ + JMP_(gran_yield_##ptrs); \ + } + +#define GRAN_YIELD(ptrs) \ + { \ + extern int context_switch; \ + if ( (CurrentTime[CurrentProc]>=EndOfTimeSlice) || \ + ((CurrentTime[CurrentProc]>=TimeOfNextEvent) && \ + (TimeOfNextEvent!=0) && !IgnoreEvents )) { \ + /* context_switch = 1; */ \ + DO_GRAN_YIELD(ptrs); \ + } \ + } + +#define ADD_TO_SPARK_QUEUE(spark) \ + STGCALL1(add_to_spark_queue,spark) \ + +#endif /* GRAN */ + +#endif /* GRANSIM_H */