Changes between Version 17 and Version 18 of Commentary/Rts/Scheduler


Ignore:
Timestamp:
May 20, 2010 9:58:15 AM (4 years ago)
Author:
simonmar
Comment:

update to new InCall? story

Legend:

Unmodified
Added
Removed
Modified
  • Commentary/Rts/Scheduler

    v17 v18  
    6666Source files: [[GhcFile(rts/Task.h)]], [[GhcFile(rts/Task.c)]] 
    6767 
    68 A Task is a further layer of abstraction over an OS thread.   
    69  
    70 One Task is created for each ''call-in'' to the runtime.  When a 
    71 call-in is made, a Task is allocated, a new Haskell thread is created, 
    72 and the two are bound together for the duration of the call: 
    73 {{{task->tso}}} points to the TSO, and {{{tso->bound}}} points to the 
    74 Task. 
    75 If a thread makes a call-in, followed by a call-out, and another call-in and so on, there could be a whole stack of tasks associated with a single OS thread. 
    76  
    77 Additionally, there is one Task for each worker OS thread in the 
    78 system.  A worker OS thread is used for executing the unbound Haskell 
    79 threads.  {{{tso->bound}}} is {{{NULL}}} for a worker Task. 
    80  
    81 The function  
     68A Task is a further layer of abstraction over an OS thread.  One `Task` is created for each OS thread known to the runtime.  To get the `Task` associated with with the current OS thread, use the function `myTask`: 
     69 
    8270{{{ 
    8371  Task *myTask (void); 
    8472}}} 
    85 returns the Task associated with the current OS thread.  However, 
    86 there may be multiple Tasks associated with a particular OS thread, 
    87 for example if a call-in executes some code that makes a foreign call, 
    88 and that foreign call makes a further call-in, and so on.  If an OS 
    89 thread has multiple Tasks associated with it, then {{{myTask}}} 
    90 returns the topmost, or most recently created, one.  The {{{myTask}}} 
    91 function is implemented using OS thread-local state. 
     73 
     74The Task contains a mutex and a condition variable used when OS threads in the runtime need to synchronise with each other or sleep waiting for a condition to occur.  The `Task` also points to the `Capability` that the `Task` currently owns (`task->cap`), or `NULL` if the `Task` does not currently own a `Capability`. 
    9275 
    9376The important components of a Task are: 
     
    9578 * The OS thread that owns this Task 
    9679 * The ''Capability'' that this Task holds (see below) 
    97  * The TSO that this Task is bound to, if any 
     80 * The current `InCall` for this Task (see below) 
    9881 * A condition variable on which this Task can put itself to sleep 
    9982 * Some link fields for placing the Task on various queues 
     83 
     84== InCalls == 
     85 
     86When an in-call is made, a Task is allocated (unless the current OS thread already has a Task), and an `InCall` structure is allocated for the call.  The `InCall` structure contains 
     87 
     88 * a pointer to the `Task` that made the in-call 
     89 * a pointer to the `TSO` that is executing the call 
     90 * a slot to save the `TSO` in the event that this `TSO` needs to make a foreign call itself 
     91 * a pointer to the previous `InCall`, if the current `Task` had already made an in-call followed by an out-call that lead to this in-call 
     92 
     93Each task points to its current `InCall`.  A worker Task (i.e. one that was created by the RTS rather than externally) also has an `InCall` structure, but in that case `incall->tso` is NULL. 
     94 
     95When a `TSO` makes a foreign call, the current `InCall` is placed on a queue attached to the `Capability`, `cap->suspended_ccalls`, from where the garbage collector can find the `TSO`s involved in foreign calls.  If one of these threads makes another in-call into Haskell, then another `InCall` is allocated, which points back to the original `InCall` via `incall->prev_stack`.  So we have a representation of the out-call/in-call stack for each `Task`, and we can restore the previous `InCall` when an in-call returns. 
     96 
     97A task has a small cache of spare `InCall` structures so that it can allocate a fresh one quickly and without taking any locks; this is important for in-call performance. 
    10098 
    10199== Capabilities ==