Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / exp / ogle / goroutine.go
blob5104ec6d479e10106841a5513a2dfbce2724b486
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package ogle
7 import (
8 "debug/proc"
9 "exp/eval"
10 "fmt"
11 "os"
14 // A Goroutine represents a goroutine in a remote process.
15 type Goroutine struct {
16 g remoteStruct
17 frame *Frame
18 dead bool
21 func (t *Goroutine) String() string {
22 if t.dead {
23 return "<dead thread>"
25 // TODO(austin) Give threads friendly ID's, possibly including
26 // the name of the entry function.
27 return fmt.Sprintf("thread %#x", t.g.addr().base)
30 // isG0 returns true if this thread if the internal idle thread
31 func (t *Goroutine) isG0() bool { return t.g.addr().base == t.g.r.p.sys.g0.addr().base }
33 func (t *Goroutine) resetFrame() (err os.Error) {
34 // TODO(austin) Reuse any live part of the current frame stack
35 // so existing references to Frame's keep working.
36 t.frame, err = newFrame(t.g)
37 return
40 // Out selects the caller frame of the current frame.
41 func (t *Goroutine) Out() os.Error {
42 f, err := t.frame.Outer()
43 if f != nil {
44 t.frame = f
46 return err
49 // In selects the frame called by the current frame.
50 func (t *Goroutine) In() os.Error {
51 f := t.frame.Inner()
52 if f != nil {
53 t.frame = f
55 return nil
58 func readylockedBP(ev Event) (EventAction, os.Error) {
59 b := ev.(*Breakpoint)
60 p := b.Process()
62 // The new g is the only argument to this function, so the
63 // stack will have the return address, then the G*.
64 regs, err := b.osThread.Regs()
65 if err != nil {
66 return EAStop, err
68 sp := regs.SP()
69 addr := sp + proc.Word(p.PtrSize())
70 arg := remotePtr{remote{addr, p}, p.runtime.G}
71 var gp eval.Value
72 err = try(func(a aborter) { gp = arg.aGet(a) })
73 if err != nil {
74 return EAStop, err
76 if gp == nil {
77 return EAStop, UnknownGoroutine{b.osThread, 0}
79 gs := gp.(remoteStruct)
80 g := &Goroutine{gs, nil, false}
81 p.goroutines[gs.addr().base] = g
83 // Enqueue goroutine creation event
84 parent := b.Goroutine()
85 if parent.isG0() {
86 parent = nil
88 p.postEvent(&GoroutineCreate{commonEvent{p, g}, parent})
90 // If we don't have any thread selected, select this one
91 if p.curGoroutine == nil {
92 p.curGoroutine = g
95 return EADefault, nil
98 func goexitBP(ev Event) (EventAction, os.Error) {
99 b := ev.(*Breakpoint)
100 p := b.Process()
102 g := b.Goroutine()
103 g.dead = true
105 addr := g.g.addr().base
106 p.goroutines[addr] = nil, false
108 // Enqueue thread exit event
109 p.postEvent(&GoroutineExit{commonEvent{p, g}})
111 // If we just exited our selected goroutine, selected another
112 if p.curGoroutine == g {
113 p.selectSomeGoroutine()
116 return EADefault, nil