Commit 29170dee authored by Kirill Smelkov's avatar Kirill Smelkov

X tracing: Polish

parent 4d0cd894
This diff is collapsed.
// Copyright (C) 2017 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package main
import (
"bytes"
"fmt"
"go/build"
"io/ioutil"
......@@ -28,10 +48,11 @@ func xglob(t *testing.T, pattern string) []string {
type TreePrepareMode int
const (
TreePrepareGolden TreePrepareMode = iota // prepare golden tree - how `gotrace gen` result should look like
TreePrepareWork // prepare work tree - inital state for `gotrace gen` to run
TreePrepareWork // prepare work tree - inital state for `gotrace gen` to run
)
// prepareTestTree copies files from src to dst recursively processing *.ok and *.rm depending on mode
// prepareTestTree copies files from src to dst recursively processing *.ok and *.rm depending on mode.
//
// dst should not initially exist
func prepareTestTree(src, dst string, mode TreePrepareMode) error {
err := os.MkdirAll(dst, 0777)
......@@ -113,12 +134,12 @@ func diffR(patha, pathb string) (diff string, err error) {
return string(out), err
}
func TestGoTraceGen(t *testing.T) {
func TestGoTrace(t *testing.T) {
tmp, err := ioutil.TempDir("", "t-gotrace")
if err != nil {
t.Fatal(err)
}
//defer os.RemoveAll(tmp)
defer os.RemoveAll(tmp)
good := tmp + "/good"
work := tmp + "/work"
......@@ -128,19 +149,19 @@ func TestGoTraceGen(t *testing.T) {
// test build context with GOPATH set to work tree
var tBuildCtx = &build.Context{
GOARCH: "amd64",
GOOS: "linux",
GOROOT: runtime.GOROOT(),
GOPATH: work,
CgoEnabled: true,
Compiler: runtime.Compiler,
GOARCH: "amd64",
GOOS: "linux",
GOROOT: runtime.GOROOT(),
GOPATH: work,
CgoEnabled: true,
Compiler: runtime.Compiler,
}
// XXX autodetect (go list ?)
testv := []string{"a/pkg1", "b/pkg2", "c/pkg3", "d/pkg4"}
//testv := []string{"c/pkg3"}
for _, tpkg := range testv {
// verify `gotrace gen`
err = tracegen(tpkg, tBuildCtx, "" /* = local imorts disabled */)
if err != nil {
t.Errorf("%v: %v", tpkg, err)
......@@ -154,5 +175,22 @@ func TestGoTraceGen(t *testing.T) {
if diff != "" {
t.Errorf("%v: gold & work differ:\n%s", tpkg, diff)
}
// verify `gotrace list`
var tlistBuf bytes.Buffer
err = tracelist(&tlistBuf, tpkg, tBuildCtx, "" /* = local imports disabled */)
if err != nil {
t.Fatalf("%v: %v", tpkg, err)
}
tlistOk, err := ioutil.ReadFile(work + "/src/" + tpkg + "/tracelist.txt")
if err != nil {
t.Fatalf("%v: %v", tpkg, err)
}
tlist := tlistBuf.Bytes()
if !bytes.Equal(tlist, tlistOk) {
t.Errorf("%v: tracelist differ:\nhave:\n%s\nwant:\n%s", tpkg, tlist, tlistOk)
}
}
}
a/pkg1:traceDoSomething
a/pkg1:traceNewT
a/pkg1:traceNewTPre
a/pkg1:traceURLParsed
......@@ -32,7 +32,7 @@ type Buffer struct {
}
func (b *Buffer) emit(format string, argv ...interface{}) {
fmt.Fprintf(b, format + "\n", argv...)
fmt.Fprintf(b, format+"\n", argv...)
}
......
......@@ -27,12 +27,15 @@ import "unsafe"
// symbols are e.g. in go/src/runtime/race/race_linux_amd64.syso
#cgo LDFLAGS: -Wl,--unresolved-symbols=ignore-in-object-files
// __tsan::ThreadIgnoreBegin(__tsan::ThreadState*, unsigned long)
// __tsan::ThreadIgnoreEnd(__tsan::ThreadState*, unsigned long)
extern void _ZN6__tsan17ThreadIgnoreBeginEPNS_11ThreadStateEm(void *, unsigned long);
extern void _ZN6__tsan15ThreadIgnoreEndEPNS_11ThreadStateEm(void *, unsigned long);
*/
import "C"
// NOTE runtime.RaceDisable disables only "sync" part, not "read/write"
// Ways to tell race-detector to ignore "read/write" events from current thread.
// NOTE runtime.RaceDisable disables only "sync" part, not "read/write".
func IgnoreBegin(racectx uintptr) {
C._ZN6__tsan17ThreadIgnoreBeginEPNS_11ThreadStateEm(unsafe.Pointer(racectx), 0)
......
......@@ -23,5 +23,5 @@ package race
// race ignore begin/end stubs
func IgnoreBegin(racectx uintptr) {}
func IgnoreEnd(racectx uintptr) {}
func IgnoreBegin(racectx uintptr) {}
func IgnoreEnd(racectx uintptr) {}
......@@ -10,7 +10,7 @@ govern= # e.g. 109 for go1.9
# goset <goexec> - set <goexec> as current go
goset() {
goexec=$1
# go1.1 go1.2 go1.3 go1.4 go1.5 go1.6 go1.7 go1.8 go1.9 go1.10 -> go1.10`
# go1.1 go1.2 go1.3 go1.4 go1.5 go1.6 go1.7 go1.8 go1.9 go1.10 -> go1.10
gover=`$goexec list -f '{{ range context.ReleaseTags }} {{ .}}{{end}}' runtime |awk '{print $NF}'`
IFS=. read gomaj gomin < <(echo "$gover")
govern=$((${gomaj#go} * 100 + $gomin))
......
......@@ -23,5 +23,5 @@ package xruntime
// empty stubs for Race*()
func RaceIgnoreBegin() {}
func RaceIgnoreEnd() {}
func RaceIgnoreBegin() {}
func RaceIgnoreEnd() {}
......@@ -18,12 +18,11 @@
// See https://www.nexedi.com/licensing for rationale and options.
package xruntime
// stop-the-world that should probably be in xruntime, but I'm (yet) hesitating
// to expose the API to public.
// stop-the-world that should probably be in public xruntime, but I'm (yet)
// hesitating to expose the API to public.
import _ "unsafe"
//go:linkname runtime_stopTheWorld runtime.stopTheWorld
//go:linkname runtime_startTheWorld runtime.startTheWorld
......@@ -41,7 +40,7 @@ func StopTheWorld(reason string) {
runtime_stopTheWorld(reason)
}
// StartTheWorld restarts the world after it was stopped by StopTheWorld
// StartTheWorld restarts the world after it was stopped by StopTheWorld.
func StartTheWorld() {
runtime_startTheWorld()
}
......@@ -21,5 +21,5 @@ package xruntime
//go:generate ./g_typedef
// getg returns pointer to current goroutine descriptor
// getg returns pointer to current goroutine descriptor.
func getg() *g
......@@ -106,9 +106,9 @@ To get better understanding of what happens when it is possible to record
events into a stream and later either visualize or postprocess them.
This is similar to how Go execution tracer works:
https://golang.org/s/go15trace
https://golang.org/pkg/runtime/trace
https://golang.org/cmd/trace
https://golang.org/s/go15trace
https://golang.org/pkg/runtime/trace
https://golang.org/cmd/trace
though there it records only predefined set of events related to Go runtime.
......@@ -146,7 +146,7 @@ a set of goroutines in tested code in question
- produce events in correct order, and
- at every event associated internal state is correct.
TODO example
TODO example.
Cross package tracing
......@@ -291,7 +291,7 @@ func AttachProbe(pg *ProbeGroup, listp **Probe, probe *Probe) {
// Detach detaches probe from a tracepoint.
//
// Must be called under Lock
// Must be called under Lock.
func (p *Probe) Detach() {
verifyLocked()
......@@ -326,7 +326,7 @@ type ProbeGroup struct {
// Add adds a probe to the group.
//
// Must be called under Lock
// Must be called under Lock.
func (pg *ProbeGroup) Add(p *Probe) {
verifyLocked()
pg.probev = append(pg.probev, p)
......@@ -334,7 +334,7 @@ func (pg *ProbeGroup) Add(p *Probe) {
// Done detaches all probes registered to the group.
//
// Must be called under normal conditions, not under Lock
// Must be called under normal conditions, not under Lock.
func (pg *ProbeGroup) Done() {
verifyUnlocked()
Lock()
......
......@@ -30,7 +30,7 @@ import (
)
func TestAttachDetach(t *testing.T) {
var traceX *Probe // list head of a tracing event
var traceX *Probe // list head of a tracing event
// check that traceX probe list has such and such content and also that .prev
// pointers in all elements are right
......@@ -102,7 +102,7 @@ func TestAttachDetach(t *testing.T) {
// should be ok, but since race detector does not know we stopped the world it
// could complain.
func TestUseDetach(t *testing.T) {
var traceX *Probe // list head of a tracing event
var traceX *Probe // list head of a tracing event
// attach probe to traceX
probe := Probe{}
......@@ -114,7 +114,7 @@ func TestUseDetach(t *testing.T) {
go func() {
// delay a bit so that main goroutine first spins some time
// with non-empty probe list
time.Sleep(1*time.Millisecond)
time.Sleep(1 * time.Millisecond)
Lock()
probe.Detach()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment