aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2015-12-16 17:10:52 +0100
committerDmitry Vyukov <dvyukov@google.com>2015-12-17 14:38:46 +0100
commitd665e11e9df6cd99160817aad775bacdbbd2e26f (patch)
tree0d9092bced32d534e4023de269d7a281d0990abc /ipc
parentce0bb4c05d45db0bba56c5ab11d2b1d7c17e002a (diff)
move Gate type to ipc package and use it in stress tool
This allows to print what programs stress executes.
Diffstat (limited to 'ipc')
-rw-r--r--ipc/gate.go54
1 files changed, 54 insertions, 0 deletions
diff --git a/ipc/gate.go b/ipc/gate.go
new file mode 100644
index 000000000..941dc9f2a
--- /dev/null
+++ b/ipc/gate.go
@@ -0,0 +1,54 @@
+// Copyright 2015 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+package ipc
+
+import (
+ "sync"
+)
+
+// Gate limits concurrency level and window to the given value.
+// Limitation of concurrency window means that if a very old activity is still
+// running it will not let new activities to start even if concurrency level is low.
+type Gate struct {
+ cv *sync.Cond
+ busy []bool
+ pos int
+}
+
+func NewGate(c int) *Gate {
+ return &Gate{
+ cv: sync.NewCond(new(sync.Mutex)),
+ busy: make([]bool, c),
+ }
+}
+
+func (g *Gate) Enter() int {
+ g.cv.L.Lock()
+ for g.busy[g.pos] {
+ g.cv.Wait()
+ }
+ idx := g.pos
+ g.pos++
+ if g.pos >= len(g.busy) {
+ g.pos = 0
+ }
+ g.busy[idx] = true
+ g.cv.L.Unlock()
+ return idx
+}
+
+func (g *Gate) Leave(idx int, f func()) {
+ g.cv.L.Lock()
+ if !g.busy[idx] {
+ panic("broken gate")
+ }
+ if f != nil {
+ f()
+ }
+ g.busy[idx] = false
+ if idx == g.pos {
+ g.cv.Broadcast()
+ }
+ g.cv.L.Unlock()
+}