diff options
| author | Russ Cox <rsc@golang.org> | 2008-12-04 12:51:36 -0800 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2008-12-04 12:51:36 -0800 |
| commit | bf3dd3f0efe5b45947a991e22660c62d4ce6b671 (patch) | |
| tree | ec0ffdfb73b32bedaed4f9f6e830f1368267e9c2 /src/lib/sync | |
| parent | 3e8faa640fa49f432060097e8dabbf8e4ecc2ef9 (diff) | |
| download | go-bf3dd3f0efe5b45947a991e22660c62d4ce6b671.tar.xz | |
add mutex.Mutex
R=r
DELTA=349 (348 added, 0 deleted, 1 changed)
OCL=20380
CL=20472
Diffstat (limited to 'src/lib/sync')
| -rw-r--r-- | src/lib/sync/Makefile | 56 | ||||
| -rw-r--r-- | src/lib/sync/asm_amd64.s | 23 | ||||
| -rw-r--r-- | src/lib/sync/mutex.go | 39 | ||||
| -rw-r--r-- | src/lib/sync/mutex_test.go | 53 |
4 files changed, 171 insertions, 0 deletions
diff --git a/src/lib/sync/Makefile b/src/lib/sync/Makefile new file mode 100644 index 0000000000..86aeeef8b1 --- /dev/null +++ b/src/lib/sync/Makefile @@ -0,0 +1,56 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# DO NOT EDIT. Automatically generated by gobuild. +# gobuild -m >Makefile +O=6 +GC=$(O)g +CC=$(O)c -w +AS=$(O)a +AR=$(O)ar + +default: packages + +clean: + rm -f *.$O *.a $O.out + +test: packages + gotest + +coverage: packages + gotest + 6cov -g `pwd` | grep -v '_test\.go:' + +%.$O: %.go + $(GC) $*.go + +%.$O: %.c + $(CC) $*.c + +%.$O: %.s + $(AS) $*.s + +O1=\ + asm_$(GOARCH).$O\ + mutex.$O\ + +sync.a: a1 + +a1: $(O1) + $(AR) grc sync.a asm_$(GOARCH).$O mutex.$O + rm -f $(O1) + +newpkg: clean + $(AR) grc sync.a + +$(O1): newpkg + +nuke: clean + rm -f $(GOROOT)/pkg/sync.a + +packages: sync.a + +install: packages + cp sync.a $(GOROOT)/pkg/sync.a + diff --git a/src/lib/sync/asm_amd64.s b/src/lib/sync/asm_amd64.s new file mode 100644 index 0000000000..07389dd3b5 --- /dev/null +++ b/src/lib/sync/asm_amd64.s @@ -0,0 +1,23 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// func cas(val *int32, old, new int32) bool +// Atomically: +// if *val == old { +// *val = new; +// return true; +// }else +// return false; +TEXT sync·cas(SB), 7, $0 + MOVQ 8(SP), BX + MOVL 16(SP), AX + MOVL 20(SP), CX + LOCK + CMPXCHGL CX, 0(BX) + JZ ok + MOVL $0, 24(SP) + RET +ok: + MOVL $1, 24(SP) + RET diff --git a/src/lib/sync/mutex.go b/src/lib/sync/mutex.go new file mode 100644 index 0000000000..accf55a76a --- /dev/null +++ b/src/lib/sync/mutex.go @@ -0,0 +1,39 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sync + +package func cas(val *int32, old, new int32) bool + +export type Mutex struct { + key int32; + sema int32; +} + +func xadd(val *int32, delta int32) (new int32) { + for { + v := *val; + if cas(val, v, v+delta) { + return v+delta; + } + } + panic("unreached") +} + +func (m *Mutex) Lock() { + if xadd(&m.key, 1) == 1 { + // changed from 0 to 1; we hold lock + return; + } + sys.semacquire(&m.sema); +} + +func (m *Mutex) Unlock() { + if xadd(&m.key, -1) == 0 { + // changed from 1 to 0; no contention + return; + } + sys.semrelease(&m.sema); +} + diff --git a/src/lib/sync/mutex_test.go b/src/lib/sync/mutex_test.go new file mode 100644 index 0000000000..7a6dd1814d --- /dev/null +++ b/src/lib/sync/mutex_test.go @@ -0,0 +1,53 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// GOMAXPROCS=10 gotest + +package sync + +import ( + "sync"; + "testing" +) + +func HammerSemaphore(s *int32, cdone *chan bool) { + for i := 0; i < 1000; i++ { + sys.semacquire(s); + sys.semrelease(s); + } + cdone <- true; +} + +export func TestSemaphore(t *testing.T) { + s := new(int32); + *s = 1; + c := new(chan bool); + for i := 0; i < 10; i++ { + go HammerSemaphore(s, c); + } + for i := 0; i < 10; i++ { + <-c; + } +} + + +func HammerMutex(m *Mutex, cdone *chan bool) { + for i := 0; i < 1000; i++ { + m.Lock(); + m.Unlock(); + } + cdone <- true; +} + +export func TestMutex(t *testing.T) { + m := new(Mutex); + c := new(chan bool); + for i := 0; i < 10; i++ { + go HammerMutex(m, c); + } + for i := 0; i < 10; i++ { + <-c; + } +} + |
