Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Commits on Feb 2, 2011
  1. @simonmar

    GC refactoring and cleanup

    simonmar authored
    Now we keep any partially-full blocks in the gc_thread[] structs after
    each GC, rather than moving them to the generation.  This should give
    us slightly better locality (though I wasn't able to measure any
    Also in this patch: better sanity checking with THREADED.
Commits on Dec 16, 2010
  1. @simonmar

    fix warning

    simonmar authored
Commits on Dec 15, 2010
  1. @simonmar
  2. @simonmar

    Implement stack chunks and separate TSO/STACK objects

    simonmar authored
    This patch makes two changes to the way stacks are managed:
    1. The stack is now stored in a separate object from the TSO.
    This means that it is easier to replace the stack object for a thread
    when the stack overflows or underflows; we don't have to leave behind
    the old TSO as an indirection any more.  Consequently, we can remove
    ThreadRelocated and deRefTSO(), which were a pain.
    This is obviously the right thing, but the last time I tried to do it
    it made performance worse.  This time I seem to have cracked it.
    2. Stacks are now represented as a chain of chunks, rather than
       a single monolithic object.
    The big advantage here is that individual chunks are marked clean or
    dirty according to whether they contain pointers to the young
    generation, and the GC can avoid traversing clean stack chunks during
    a young-generation collection.  This means that programs with deep
    stacks will see a big saving in GC overhead when using the default GC
    A secondary advantage is that there is much less copying involved as
    the stack grows.  Programs that quickly grow a deep stack will see big
    In some ways the implementation is simpler, as nothing special needs
    to be done to reclaim stack as the stack shrinks (the GC just recovers
    the dead stack chunks).  On the other hand, we have to manage stack
    underflow between chunks, so there's a new stack frame
    (UNDERFLOW_FRAME), and we now have separate TSO and STACK objects.
    The total amount of code is probably about the same as before.
    There are new RTS flags:
       -ki<size> Sets the initial thread stack size (default 1k)  Egs: -ki4k -ki2m
       -kc<size> Sets the stack chunk size (default 32k)
       -kb<size> Sets the stack chunk buffer size (default 1k)
    -ki was previously called just -k, and the old name is still accepted
    for backwards compatibility.  These new options are documented.
Commits on Dec 2, 2010
  1. @simonmar
Commits on Oct 13, 2010
  1. @simonmar


    simonmar authored
Commits on Sep 19, 2010
  1. @ezyang

    Interruptible FFI calls with pthread_kill and CancelSynchronousIO. v4

    ezyang authored
    This is patch that adds support for interruptible FFI calls in the form
    of a new foreign import keyword 'interruptible', which can be used
    instead of 'safe' or 'unsafe'.  Interruptible FFI calls act like safe
    FFI calls, except that the worker thread they run on may be interrupted.
    Internally, it replaces BlockedOnCCall_NoUnblockEx with
    BlockedOnCCall_Interruptible, and changes the behavior of the RTS
    to not modify the TSO_ flags on the event of an FFI call from
    a thread that was interruptible.  It also modifies the bytecode
    format for foreign call, adding an extra Word16 to indicate
    The semantics of interruption vary from platform to platform, but the
    intent is that any blocking system calls are aborted with an error code.
    This is most useful for making function calls to system library
    functions that support interrupting.  There is no support for pre-Vista
    There is a partner testsuite patch which adds several tests for this
Commits on Aug 23, 2010
  1. @simonmar

    Add a couple of missing tests for EAGER_BLACKHOLE

    simonmar authored
    This was leading to looping and excessive allocation, when the
    computation should have just blocked on the black hole.  
    Reported by Christian Höner zu Siederdissen <>
    on glasgow-haskell-users.
Commits on Apr 7, 2010
  1. @simonmar
Commits on Apr 6, 2010
  1. @simonmar
Commits on Apr 1, 2010
  1. @simonmar

    fix bug in migrateThread()

    simonmar authored
  2. @simonmar

    Change the representation of the MVar blocked queue

    simonmar authored
    The list of threads blocked on an MVar is now represented as a list of
    separately allocated objects rather than being linked through the TSOs
    themselves.  This lets us remove a TSO from the list in O(1) time
    rather than O(n) time, by marking the list object.  Removing this
    linear component fixes some pathalogical performance cases where many
    threads were blocked on an MVar and became unreachable simultaneously
    (nofib/smp/threads007), or when sending an asynchronous exception to a
    TSO in a long list of thread blocked on an MVar.
    MVar performance has actually improved by a few percent as a result of
    this change, slightly to my surprise.
    This is the final cleanup in the sequence, which let me remove the old
    way of waking up threads (unblockOne(), MSG_WAKEUP) in favour of the
    new way (tryWakeupThread and MSG_TRY_WAKEUP, which is idempotent).  It
    is now the case that only the Capability that owns a TSO may modify
    its state (well, almost), and this simplifies various things.  More of
    the RTS is based on message-passing between Capabilities now.
Commits on Mar 29, 2010
  1. @simonmar
  2. @simonmar

    New implementation of BLACKHOLEs

    simonmar authored
    This replaces the global blackhole_queue with a clever scheme that
    enables us to queue up blocked threads on the closure that they are
    blocked on, while still avoiding atomic instructions in the common
     - gets rid of a locked global data structure and some tricky GC code
       (replacing it with some per-thread data structures and different
       tricky GC code :)
     - wakeups are more prompt: parallel/concurrent performance should
       benefit.  I haven't seen anything dramatic in the parallel
       benchmarks so far, but a couple of threading benchmarks do improve
       a bit.
     - waking up a thread blocked on a blackhole is now O(1) (e.g. if
       it is the target of throwTo).
     - less sharing and better separation of Capabilities: communication
       is done with messages, the data structures are strictly owned by a
       Capability and cannot be modified except by sending messages.
     - this change will utlimately enable us to do more intelligent
       scheduling when threads block on each other.  This is what started
       off the whole thing, but it isn't done yet (#3838).
    I'll be documenting all this on the wiki in due course.
Commits on Mar 11, 2010
  1. @simonmar

    Use message-passing to implement throwTo in the RTS

    simonmar authored
    This replaces some complicated locking schemes with message-passing
    in the implementation of throwTo. The benefits are
     - previously it was impossible to guarantee that a throwTo from
       a thread running on one CPU to a thread running on another CPU
       would be noticed, and we had to rely on the GC to pick up these
       forgotten exceptions. This no longer happens.
     - the locking regime is simpler (though the code is about the same
     - threads can be unblocked from a blocked_exceptions queue without
       having to traverse the whole queue now.  It's a rare case, but
       replaces an O(n) operation with an O(1).
     - generally we move in the direction of sharing less between
       Capabilities (aka HECs), which will become important with other
       changes we have planned.
    Also in this patch I replaced several STM-specific closure types with
    a generic MUT_PRIM closure type, which allowed a lot of code in the GC
    and other places to go away, hence the line-count reduction.  The
    message-passing changes resulted in about a net zero line-count
Commits on Mar 9, 2010
  1. @simonmar

    Split part of the Task struct into a separate struct InCall

    simonmar authored
    The idea is that this leaves Tasks and OSThread in one-to-one
    correspondence.  The part of a Task that represents a call into
    Haskell from C is split into a separate struct InCall, pointed to by
    the Task and the TSO bound to it.  A given OSThread/Task thus always
    uses the same mutex and condition variable, rather than getting a new
    one for each callback.  Conceptually it is simpler, although there are
    more types and indirections in a few places now.
    This improves callback performance by removing some of the locks that
    we had to take when making in-calls.  Now we also keep the current Task
    in a thread-local variable if supported by the OS and gcc (currently
    only Linux).
Commits on Dec 17, 2009
  1. @simonmar
Commits on Dec 12, 2009
  1. @mchakravarty

    Expose all EventLog events as DTrace probes

    mchakravarty authored
    - Defines a DTrace provider, called 'HaskellEvent', that provides a probe
      for every event of the eventlog framework.
    - In contrast to the original eventlog, the DTrace probes are available in
      all flavours of the runtime system (DTrace probes have virtually no
      overhead if not enabled); when -DTRACING is defined both the regular
      event log as well as DTrace probes can be used.
    - Currently, Mac OS X only.  User-space DTrace probes are implemented
      differently on Mac OS X than in the original DTrace implementation.
      Nevertheless, it shouldn't be too hard to enable these probes on other
      platforms, too.
    - Documentation is at
Commits on Dec 3, 2009
  1. @simonmar

    GC refactoring, remove "steps"

    simonmar authored
    The GC had a two-level structure, G generations each of T steps.
    Steps are for aging within a generation, mostly to avoid premature
    Measurements show that more than 2 steps is almost never worthwhile,
    and 1 step is usually worse than 2.  In theory fractional steps are
    possible, so the ideal number of steps is somewhere between 1 and 3.
    GHC's default has always been 2.
    We can implement 2 steps quite straightforwardly by having each block
    point to the generation to which objects in that block should be
    promoted, so blocks in the nursery point to generation 0, and blocks
    in gen 0 point to gen 1, and so on.
    This commit removes the explicit step structures, merging generations
    with steps, thus simplifying a lot of code.  Performance is
    unaffected.  The tunable number of steps is now gone, although it may
    be replaced in the future by a way to tune the aging in generation 0.
Commits on Dec 1, 2009
  1. @simonmar

    Make allocatePinned use local storage, and other refactorings

    simonmar authored
    This is a batch of refactoring to remove some of the GC's global
    state, as we move towards CPU-local GC.  
      - allocateLocal() now allocates large objects into the local
        nursery, rather than taking a global lock and allocating
        then in gen 0 step 0.
      - allocatePinned() was still allocating from global storage and
        taking a lock each time, now it uses local storage. 
        (mallocForeignPtrBytes should be faster with -threaded).
      - We had a gen 0 step 0, distinct from the nurseries, which are
        stored in a separate nurseries[] array.  This is slightly strange.
        I removed the g0s0 global that pointed to gen 0 step 0, and
        removed all uses of it.  I think now we don't use gen 0 step 0 at
        all, except possibly when there is only one generation.  Possibly
        more tidying up is needed here.
      - I removed the global allocate() function, and renamed
        allocateLocal() to allocate().
      - the alloc_blocks global is gone.  MAYBE_GC() and
        doYouWantToGC() now check the local nursery only.
Commits on Aug 29, 2009
  1. @simonmar

    Unify event logging and debug tracing.

    simonmar authored
      - tracing facilities are now enabled with -DTRACING, and -DDEBUG
        additionally enables debug-tracing.  -DEVENTLOG has been
      - -debug now implies -eventlog
      - events can be printed to stderr instead of being sent to the
        binary .eventlog file by adding +RTS -v (which is implied by the
        +RTS -Dx options).
      - -Dx debug messages can be sent to the binary .eventlog file
        by adding +RTS -l.  This should help debugging by reducing
        the impact of debug tracing on execution time.
      - Various debug messages that duplicated the information in events
        have been removed.
Commits on Aug 18, 2009
  1. @simonmar

    Fix #3429: a tricky race condition

    simonmar authored
    There were two bugs, and had it not been for the first one we would
    not have noticed the second one, so this is quite fortunate.
    The first bug is in stg_unblockAsyncExceptionszh_ret, when we found a
    pending exception to raise, but don't end up raising it, there was a
    missing adjustment to the stack pointer.  
    The second bug was that this case was actually happening at all: it
    ought to be incredibly rare, because the pending exception thread
    would have to be killed between us finding it and attempting to raise
    the exception.  This made me suspicious.  It turned out that there was
    a race condition on the tso->flags field; multiple threads were
    updating this bitmask field non-atomically (one of the bits is the
    dirty-bit for the generational GC).  The fix is to move the dirty bit
    into its own field of the TSO, making the TSO one word larger (sadly).
Commits on Aug 2, 2009
  1. @simonmar

    RTS tidyup sweep, first phase

    simonmar authored
    The first phase of this tidyup is focussed on the header files, and in
    particular making sure we are exposinng publicly exactly what we need
    to, and no more.
     - Rts.h now includes everything that the RTS exposes publicly,
       rather than a random subset of it.
     - Most of the public header files have moved into subdirectories, and
       many of them have been renamed.  But clients should not need to
       include any of the other headers directly, just #include the main
       public headers: Rts.h, HsFFI.h, RtsAPI.h.
     - All the headers needed for via-C compilation have moved into the
       stg subdirectory, which is self-contained.  Most of the headers for
       the rest of the RTS APIs have moved into the rts subdirectory.
     - I left MachDeps.h where it is, because it is so widely used in
       Haskell code.
     - I left a deprecated stub for RtsFlags.h in place.  The flag
       structures are now exposed by Rts.h.
     - Various internal APIs are no longer exposed by public header files.
     - Various bits of dead code and declarations have been removed
     - More gcc warnings are turned on, and the RTS code is more
     - More source files #include "PosixSource.h", and hence only use
       standard POSIX (1003.1c-1995) interfaces.
    There is a lot more tidying up still to do, this is just the first
    pass.  I also intend to standardise the names for external RTS APIs
    (e.g use the rts_ prefix consistently), and declare the internal APIs
    as hidden for shared libraries.
Commits on Jun 2, 2009
  1. @simonmar

    Remove old GUM/GranSim code

    simonmar authored
Commits on May 29, 2009
  1. @simonmar
Commits on May 28, 2009
  1. @simonmar

    Round stack size to a whole number of megablocks

    simonmar authored
    This is not a bug fix, it just makes better use of memory
Commits on Mar 17, 2009
  1. @simonmar

    Add fast event logging

    simonmar authored
    Generate binary log files from the RTS containing a log of runtime
    events with timestamps.  The log file can be visualised in various
    ways, for investigating runtime behaviour and debugging performance
    problems.  See for example the forthcoming ThreadScope viewer.
    New GHC option:
      -eventlog   (link-time option) Enables event logging.
      +RTS -l     (runtime option) Generates <prog>.eventlog with
                  the binary event information.
    This replaces some of the tracing machinery we already had in the RTS:
    e.g. +RTS -vg  for GC tracing (we should do this using the new event
    logging instead).
    Event logging has almost no runtime cost when it isn't enabled, though
    in the future we might add more fine-grained events and this might
    change; hence having a link-time option and compiling a separate
    version of the RTS for event logging.  There's a small runtime cost
    for enabling event-logging, for most programs it shouldn't make much
    (Todo: docs)
Commits on Mar 13, 2009
  1. @simonmar

    Instead of a separate context-switch flag, set HpLim to zero

    simonmar authored
    This reduces the latency between a context-switch being triggered and
    the thread returning to the scheduler, which in turn should reduce the
    cost of the GC barrier when there are many cores.
    We still retain the old context_switch flag which is checked at the
    end of each block of allocation.  The idea is that setting HpLim may
    fail if the the target thread is modifying HpLim at the same time; the
    context_switch flag is a fallback.  It also allows us to "context
    switch soon" without forcing an immediate switch, which can be costly.
Commits on Jan 7, 2009
  1. @simonmar
Commits on Sep 19, 2008
  1. @simonmar

    Move the context_switch flag into the Capability

    simonmar authored
    Fixes a long-standing bug that could in some cases cause sub-optimal
    scheduling behaviour.
Commits on Sep 10, 2008
  1. Fix debug message formatting on Windows authored
Commits on Sep 9, 2008
  1. @simonmar

    Fix race condition in wakeupThreadOnCapability() (#2574)

    simonmar authored
    wakeupThreadOnCapbility() is used to signal another capability that
    there is a thread waiting to be added to its run queue.  It adds the
    thread to the (locked) wakeup queue on the remote capability.  In
    order to do this, it has to modify the TSO's link field, which has a
    write barrier.  The write barrier might put the TSO on the mutable
    list, and the bug was that it was using the mutable list of the
    *target* capability, which we do not have exclusive access to.  We
    should be using the current Capabilty's mutable list in this case.
Commits on Apr 16, 2008
  1. Don't traverse the entire list of threads on every GC (phase 1)

    Simon Marlow authored
    Instead of keeping a single list of all threads, keep one per step
    and only look at the threads belonging to steps that we are
  2. Add a write barrier to the TSO link field (#1589)

    Simon Marlow authored
Commits on Apr 3, 2007
  1. @igfoo

    Fix C/Haskell type mismatches

    igfoo authored
Something went wrong with that request. Please try again.