Commit 55cea17a authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent c532b502
......@@ -123,16 +123,22 @@ func (tc *TraceChecker) ExpectNetTx(src, dst string, pkt string) {
// M drives cluster with 1 S through recovery -> verification -> service -> shutdown
func TestMasterStorage(t *testing.T) {
println("server: &_neo_traceConnSend:", &_neo_traceConnSend)
tracer := &MyTracer{xtesting.NewSyncTracer()}
tc := xtesting.NewTraceChecker(t, tracer.SyncTracer)
net := pipenet.New("testnet") // test network
// XXX change back after test
_neo_traceConnRecv = tracer.traceNeoConnRecv
_neo_traceConnSend = tracer.traceNeoConnSend
tracing.Lock()
neo_traceConnRecv_Attach(tracer.traceNeoConnRecv)
neo_traceConnSend_Attach(tracer.traceNeoConnSend)
tracing.Unlock()
defer func() {
tracing.Lock()
defer tracing.Unlock()
tctx.Done()
}()
// shortcut for addresses
xaddr := func(addr string) *pipenet.Addr {
......
......@@ -26,8 +26,8 @@ import (
// TODO autogenerate vvv from "//trace:import path/to/neo"
// + check consistency (e.g. by hash in neo.trace and here must be the same)
//go:linkname neo_traceConnRecv aaaneo._traceConnRecv
var _neo_traceConnRecv func(*neo.Conn, neo.Msg)
//go:linkname neo_traceConnRecv_Attach _/home/kirr/src/wendelin/neo/neoppod-t/go/neo.traceConnRecv_Attach
func neo_traceConnRecv_Attach(func(*neo.Conn, neo.Msg))
//go:linkname neo_traceConnSend neo._traceConnSend
var _neo_traceConnSend func(*neo.Conn, neo.Msg)
//go:linkname neo_traceConnSend_Attach _/home/kirr/src/wendelin/neo/neoppod-t/go/neo.traceConnSend_Attach
func neo_traceConnSend_Attach(func(*neo.Conn, neo.Msg))
// empty .s so `go build` does not use -complete
......@@ -18,7 +18,15 @@
package neo
// tracepoints
import (
"unsafe"
"../xcommon/tracing"
)
// XXX put under 'build +tracedef'
//trace:event
// func traceConnRecv(c *Conn, msg Msg)
// func traceConnSend(c *Conn, msg Msg) // XXX -> traceConnSendPre ?
......@@ -30,20 +38,45 @@ package neo
// XXX do we need *_Enabled() ?
var _traceConnRecv func(*Conn, Msg)
var _traceConnRecv []func(*Conn, Msg)
func traceConnRecv(c *Conn, msg Msg) {
println("A traceConnRecv", &_traceConnRecv)
if _traceConnRecv != nil {
println(" _traceConnRecv")
_traceConnRecv(c, msg)
if _traceConnRecv == nil {
return
}
for _, probe := range _traceConnRecv {
probe(c, msg)
}
}
var _traceConnSend func(*Conn, Msg)
// Must be called under tracing.Lock
func traceConnRecv_Attach(probe func(*Conn, Msg)) {
_traceConnRecv = append(_traceConnRecv, probe)
}
// traceevent: traceConnSend(c *Conn, msg Msg)
type _t_traceConnSend struct {
tracing.Probe
probefunc func(*Conn, Msg)
}
var _traceConnSend *_t_traceConnSend
func traceConnSend(c *Conn, msg Msg) {
println("A traceConnSend", &_traceConnSend)
if _traceConnSend != nil {
println(" _traceConnSend")
_traceConnSend(c, msg)
_traceConnSend_runprobev(c, msg)
}
}
func _traceConnSend_runprobev(c *Conn, msg Msg) {
for p := _traceConnSend; p != nil; p = (*_t_traceConnSend)(unsafe.Pointer(p.Next())) {
p.probefunc(c, msg)
}
}
func traceConnSend_Attach(probe func(*Conn, Msg)) *tracing.Probe {
p := _t_traceConnSend{probefunc: probe}
tracing.AttachProbe((**tracing.Probe)(unsafe.Pointer(&_traceConnSend)), &p.Probe)
return &p.Probe
}
// Copyright (C) 2016-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 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.
// Package tracing provides runtime support for Go tracing facilities
// TODO describe how to define tracepoints
package tracing
import (
"sync"
"sync/atomic"
_ "unsafe"
)
// XXX move StopTheWorld to xruntime ?
//go:linkname runtime_stopTheWorld runtime.stopTheWorld
func runtime_stopTheWorld(string)
//go:linkname runtime_startTheWorld runtime.startTheWorld
func runtime_startTheWorld()
// big tracing lock
var traceMu sync.Mutex
var traceLocked int32 // for cheap protective checks whether Lock is held
// Lock serializes modification access to tracepoints
//
// Under Lock it is safe to attach/detach probes to/from tracepoints:
// - no other goroutine is attaching or detaching probes from tracepoints,
// - a tracepoint readers won't be neither confused nor raced by such adjustments.
//
// Lock returns with the world stopped.
func Lock() {
traceMu.Lock()
runtime_stopTheWorld("tracing lock")
atomic.StoreInt32(&traceLocked, 1)
}
// Unlock is the opposite to Lock and returns with the world resumed
func Unlock() {
atomic.StoreInt32(&traceLocked, 0)
runtime_startTheWorld()
traceMu.Unlock()
}
// verifyLocked makes sure tracing is locked and panics otherwise
func verifyLocked() {
if atomic.LoadInt32(&traceLocked) == 0 {
panic("tracing must be locked")
}
}
// Probe describes one probe attached to a tracepoint XXX
type Probe struct {
prev, next *Probe
// probefunc interface{} // func(some arguments)
}
// Next return next probe attached to the same tracepoint
func (p *Probe) Next() *Probe {
return p.next
}
// AttachProbe attaches Probe to the end of a probe list
// Must be called under Lock
func AttachProbe(listp **Probe, probe *Probe) {
verifyLocked()
var last *Probe
for p := *listp; p != nil; p = p.next {
last = p
}
// p := &Probe{prev: last, next: nil, probefunc: probefunc}
if last != nil {
last.next = probe
probe.prev = last
} else {
*listp = probe
}
// return p
}
// Detach detaches probe from a tracepoint
// Must be called under Lock
func (p *Probe) Detach() {
verifyLocked()
// protection: already detached
if p.prev == p {
return
}
// we can safely change prev.next pointer:
// - no reader is currently reading it
// - either a reader already read prev.next, and will proceed with our probe entry, or
// - it will read updated prev.next and will proceed with p.next probe entry
if p.prev != nil {
p.prev.next = p.next
}
// we can safely change next.prev pointer:
// - readers only go through list forward
// - there is no other updater because we are under Lock
if p.next != nil {
p.next.prev = p.prev
}
// mark us detached so that if Detach is erroneously called the second
// time it does not do harm
p.prev = p
}
// empty .s so `go build` does not use -complete
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