OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [sync/] [mutex.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// 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.
4
 
5
// Package sync provides basic synchronization primitives such as mutual
6
// exclusion locks.  Other than the Once and WaitGroup types, most are intended
7
// for use by low-level library routines.  Higher-level synchronization is
8
// better done via channels and communication.
9
//
10
// Values containing the types defined in this package should not be copied.
11
package sync
12
 
13
import (
14
        "runtime"
15
        "sync/atomic"
16
)
17
 
18
// A Mutex is a mutual exclusion lock.
19
// Mutexes can be created as part of other structures;
20
// the zero value for a Mutex is an unlocked mutex.
21
type Mutex struct {
22
        state int32
23
        sema  uint32
24
}
25
 
26
// A Locker represents an object that can be locked and unlocked.
27
type Locker interface {
28
        Lock()
29
        Unlock()
30
}
31
 
32
const (
33
        mutexLocked = 1 << iota // mutex is locked
34
        mutexWoken
35
        mutexWaiterShift = iota
36
)
37
 
38
// Lock locks m.
39
// If the lock is already in use, the calling goroutine
40
// blocks until the mutex is available.
41
func (m *Mutex) Lock() {
42
        // Fast path: grab unlocked mutex.
43
        if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {
44
                return
45
        }
46
 
47
        awoke := false
48
        for {
49
                old := m.state
50
                new := old | mutexLocked
51
                if old&mutexLocked != 0 {
52
                        new = old + 1<
53
                }
54
                if awoke {
55
                        // The goroutine has been woken from sleep,
56
                        // so we need to reset the flag in either case.
57
                        new &^= mutexWoken
58
                }
59
                if atomic.CompareAndSwapInt32(&m.state, old, new) {
60
                        if old&mutexLocked == 0 {
61
                                break
62
                        }
63
                        runtime.Semacquire(&m.sema)
64
                        awoke = true
65
                }
66
        }
67
}
68
 
69
// Unlock unlocks m.
70
// It is a run-time error if m is not locked on entry to Unlock.
71
//
72
// A locked Mutex is not associated with a particular goroutine.
73
// It is allowed for one goroutine to lock a Mutex and then
74
// arrange for another goroutine to unlock it.
75
func (m *Mutex) Unlock() {
76
        // Fast path: drop lock bit.
77
        new := atomic.AddInt32(&m.state, -mutexLocked)
78
        if (new+mutexLocked)&mutexLocked == 0 {
79
                panic("sync: unlock of unlocked mutex")
80
        }
81
 
82
        old := new
83
        for {
84
                // If there are no waiters or a goroutine has already
85
                // been woken or grabbed the lock, no need to wake anyone.
86
                if old>>mutexWaiterShift == 0 || old&(mutexLocked|mutexWoken) != 0 {
87
                        return
88
                }
89
                // Grab the right to wake someone.
90
                new = (old - 1<
91
                if atomic.CompareAndSwapInt32(&m.state, old, new) {
92
                        runtime.Semrelease(&m.sema)
93
                        return
94
                }
95
                old = m.state
96
        }
97
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.