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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [runtime/] [lock_futex.c] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2011 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
// +build freebsd linux
6
 
7
#include "runtime.h"
8
 
9
// This implementation depends on OS-specific implementations of
10
//
11
//      runtime_futexsleep(uint32 *addr, uint32 val, int64 ns)
12
//              Atomically,
13
//                      if(*addr == val) sleep
14
//              Might be woken up spuriously; that's allowed.
15
//              Don't sleep longer than ns; ns < 0 means forever.
16
//
17
//      runtime_futexwakeup(uint32 *addr, uint32 cnt)
18
//              If any procs are sleeping on addr, wake up at most cnt.
19
 
20
enum
21
{
22
        MUTEX_UNLOCKED = 0,
23
        MUTEX_LOCKED = 1,
24
        MUTEX_SLEEPING = 2,
25
 
26
        ACTIVE_SPIN = 4,
27
        ACTIVE_SPIN_CNT = 30,
28
        PASSIVE_SPIN = 1,
29
};
30
 
31
// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
32
// MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
33
// Note that there can be spinning threads during all states - they do not
34
// affect mutex's state.
35
void
36
runtime_lock(Lock *l)
37
{
38
        uint32 i, v, wait, spin;
39
 
40
        if(runtime_m()->locks++ < 0)
41
                runtime_throw("runtime_lock: lock count");
42
 
43
        // Speculative grab for lock.
44
        v = runtime_xchg(&l->key, MUTEX_LOCKED);
45
        if(v == MUTEX_UNLOCKED)
46
                return;
47
 
48
        // wait is either MUTEX_LOCKED or MUTEX_SLEEPING
49
        // depending on whether there is a thread sleeping
50
        // on this mutex.  If we ever change l->key from
51
        // MUTEX_SLEEPING to some other value, we must be
52
        // careful to change it back to MUTEX_SLEEPING before
53
        // returning, to ensure that the sleeping thread gets
54
        // its wakeup call.
55
        wait = v;
56
 
57
        // On uniprocessor's, no point spinning.
58
        // On multiprocessors, spin for ACTIVE_SPIN attempts.
59
        spin = 0;
60
        if(runtime_ncpu > 1)
61
                spin = ACTIVE_SPIN;
62
 
63
        for(;;) {
64
                // Try for lock, spinning.
65
                for(i = 0; i < spin; i++) {
66
                        while(l->key == MUTEX_UNLOCKED)
67
                                if(runtime_cas(&l->key, MUTEX_UNLOCKED, wait))
68
                                        return;
69
                        runtime_procyield(ACTIVE_SPIN_CNT);
70
                }
71
 
72
                // Try for lock, rescheduling.
73
                for(i=0; i < PASSIVE_SPIN; i++) {
74
                        while(l->key == MUTEX_UNLOCKED)
75
                                if(runtime_cas(&l->key, MUTEX_UNLOCKED, wait))
76
                                        return;
77
                        runtime_osyield();
78
                }
79
 
80
                // Sleep.
81
                v = runtime_xchg(&l->key, MUTEX_SLEEPING);
82
                if(v == MUTEX_UNLOCKED)
83
                        return;
84
                wait = MUTEX_SLEEPING;
85
                runtime_futexsleep(&l->key, MUTEX_SLEEPING, -1);
86
        }
87
}
88
 
89
void
90
runtime_unlock(Lock *l)
91
{
92
        uint32 v;
93
 
94
        if(--runtime_m()->locks < 0)
95
                runtime_throw("runtime_unlock: lock count");
96
 
97
        v = runtime_xchg(&l->key, MUTEX_UNLOCKED);
98
        if(v == MUTEX_UNLOCKED)
99
                runtime_throw("unlock of unlocked lock");
100
        if(v == MUTEX_SLEEPING)
101
                runtime_futexwakeup(&l->key, 1);
102
}
103
 
104
// One-time notifications.
105
void
106
runtime_noteclear(Note *n)
107
{
108
        n->key = 0;
109
}
110
 
111
void
112
runtime_notewakeup(Note *n)
113
{
114
        runtime_xchg(&n->key, 1);
115
        runtime_futexwakeup(&n->key, 1);
116
}
117
 
118
void
119
runtime_notesleep(Note *n)
120
{
121
        while(runtime_atomicload(&n->key) == 0)
122
                runtime_futexsleep(&n->key, 0, -1);
123
}
124
 
125
void
126
runtime_notetsleep(Note *n, int64 ns)
127
{
128
        int64 deadline, now;
129
 
130
        if(ns < 0) {
131
                runtime_notesleep(n);
132
                return;
133
        }
134
 
135
        if(runtime_atomicload(&n->key) != 0)
136
                return;
137
 
138
        deadline = runtime_nanotime() + ns;
139
        for(;;) {
140
                runtime_futexsleep(&n->key, 0, ns);
141
                if(runtime_atomicload(&n->key) != 0)
142
                        return;
143
                now = runtime_nanotime();
144
                if(now >= deadline)
145
                        return;
146
                ns = deadline - now;
147
        }
148
}

powered by: WebSVN 2.1.0

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