Permalink
Switch branches/tags
Commits on Sep 4, 2012
  1. working Rubinius.lock

    committed Sep 4, 2012
  2. working Rubinius.lock

    committed Sep 4, 2012
  3. working Rubinius.lock

    committed Sep 4, 2012
  4. clean up

    committed Sep 4, 2012
  5. working Rubinius.lock

    committed Sep 4, 2012
  6. Completely fix deadlocks of Thread#raise

    In some cases, an exception isn't correctly raised by Thread#raise. If that is
    the case, Thread#join on that thread leads to the deadlock.
    
    Consider the following example:
    
      thread = Thread.new do
      end
      thread.raise(RuntimeError) # interrupts thread incorrectly
      begin
        thread.join # thread is dead, but thread.join never returns; deadlock
      rescue
      end
    
    There are several problems in the current code:
    
      1. raise_prim in Thread#raise isn't inside @lock
      2. The cleanup of thread execution dones't lock correctly
      3. Thread::wakeup called from Thread#raise. And it wakes up even sleeping
         threads waiting for locked channels
    
    In the end, there should be only the following three good timings:
    
                   Time
                   ------------------------------------------------------->
      main thread  prepare - wakeup |
      new thread                    | call (interrupted) | lock - cleanup
    
                   Time
                   ------------------------------------------------------->
      main thread       | prepare - wakeup |
      new thread   call |                  | lock - cleanup
    
                   Time
                   ------------------------------------------------------->
      main thread                        | prepare (no-op) - wakeup (no-op)
      new thread   call | lock - cleanup |
    
    To fix all of these cause of deadlocks, this commmit does the followings:
    
      1. Put raise_prim in Thread#raise under @lock
      2. introduce Channel#uninterrupted_receive and Rubinius.check_interrupts to
         make the cleanup of thread execution lock correctly.
      3. Remove waiting_channel to make Thread#wakeup not be so eager that it wakes
         up purposedly sleeping threads
    committed Sep 4, 2012
  7. Refine comment

    committed Sep 4, 2012
  8. Refine comment

    committed Sep 4, 2012
  9. Refine comment

    committed Sep 4, 2012
  10. Refine comment

    committed Sep 4, 2012
  11. Refine comment

    committed Sep 4, 2012
  12. Refine comment

    committed Sep 4, 2012
  13. clean up

    committed Sep 4, 2012
  14. clean up

    committed Sep 4, 2012
  15. clean up

    committed Sep 4, 2012
  16. clean up

    committed Sep 4, 2012
  17. clean up

    committed Sep 4, 2012
  18. clean up

    committed Sep 4, 2012
  19. clean up

    committed Sep 4, 2012
Commits on Sep 3, 2012
  1. add a spec

    committed Sep 3, 2012
  2. add a spec

    committed Sep 3, 2012
  3. remove wait_on_channel

    committed Sep 3, 2012
  4. clean up

    committed Sep 3, 2012
  5. clean up

    committed Sep 3, 2012
  6. clean up

    committed Sep 3, 2012
  7. clean up

    committed Sep 3, 2012
  8. another Thread#kill deadlock

    committed Sep 3, 2012
  9. Merge pull request #1884 from ryoqun/thread-join-deadlock

    Fix Thread#join deadlock from use of Thread#kill and sleep
    dbussink committed Sep 3, 2012
Commits on Sep 2, 2012
  1. Fix timing issue of Thread#kill and sleep

    In some cases, a thread isn't correctly killed by Thread#kill. If that is the
    case, Thread#join on that thread leads to the deadlock.
    
    Consider the following example:
    
        thread = Thread.new do
          sleep
        end
        thread.kill # actually, don't kill
        thread.join # thread lives forever; deadlock
    
    Thread#kill does 2 things to kill a thread:
        1. prepares the thread to be terminated and
        2. wakes up the thread.
    
    Most of time, the wake-up is executed after the sleep in the killed thread.
    
    However, it is possible the wake-up is executed BEFORE the sleep in some rare
    cases. If that is the case, the wake-up does nothing because the thread is
    still waking up at that time. Then, the thread begins to sleep forever. As a
    result, Thread#join never returns.
    
    To avoid such a deadlock, Thread#sleep must check to terminate or not before
    actually sleeping. In addition, it must be asssured that the wake-up isn't
    executed AFTER the check BEFORE the sleep.
    
    The follwing diagrams illustrate the good and bad timings.
    
    Good timings:
    
                     Time
                     ------------------------------------------------------>
        main thread  prepare - wakeup (no-op) |
        new thread                            | check - no sleep - terminate
    
                     Time
                     ------------------------------------------------------>
        main thread                | prepare - wake-up |
        new thread   check - sleep |                   | terminate
    
                     Time
                     ------------------------------------------------------>
        main thread        | prepare |       | wake-up |
        new thread   check |         | sleep |         | terminate
    
    Bad timing:
    
                     Time
                     ------------------------------------------------------>
        main thread        | prepare - wake-up (no-op) |
        new thread   check |                           | sleep forever
    
    To fix the deadlock, this commit makes check_async be called before sleeping
    inside the park mutex.
    committed Sep 2, 2012
Commits on Aug 30, 2012
  1. Renamed VMMethod to MachineCode.

    This was a difficult name choice but it is consistent with CompiledCode
    and (not yet used) SourceCode. The CompiledCode is an abstraction of
    computation that is the focal point around which much revolves. MachineCode
    is a representation of computation specialized for our (virtual) machine.
    
    While there is possible ambiguity against the idea of JIT'd machine code,
    our MachineCode is a proper data structure, not just the format of bits
    resulting from the JIT compilation process. Also, our MachineCode is properly
    scoped differently than any such class/concept in LLVM (or more generally,
    the JIT).
    
    Regarding naming of instances of MachineCode, the following rationale is used:
    
    * parameters/variables have been named 'mcode' since the use of the variable
      is elaborated by the surrounding code (ie making ambiguity less an issue)
      and long variable names can sometimes make code unweildy.
    * attributes/fields/accessors have been name 'machine_code' because they have
      less context to disambiguate.
    brixen committed Aug 28, 2012
  2. Implement rb_iter_break()

    dbussink committed Aug 30, 2012
  3. Add specs for rb_iter_break

    dbussink committed Aug 30, 2012