Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(152)

Delta Between Two Patch Sets: src/pkg/runtime/lock_futex.c

Issue 160200044: [dev.power64] code review 160200044: build: merge default into dev.power64 (Closed)
Left Patch Set: diff -r be0c14f62257b42485019e9e1db23cf40d2e249f https://code.google.com/p/go Created 10 years, 4 months ago
Right Patch Set: diff -r be0c14f62257b42485019e9e1db23cf40d2e249f https://code.google.com/p/go Created 10 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/runtime/lfstack.goc ('k') | src/pkg/runtime/lock_futex.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // 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 dragonfly freebsd linux
6
7 #include "runtime.h"
8 #include "stack.h"
9 #include "../../cmd/ld/textflag.h"
10
11 // This implementation depends on OS-specific implementations of
12 //
13 // runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
14 // Atomically,
15 // if(*addr == val) sleep
16 // Might be woken up spuriously; that's allowed.
17 // Don't sleep longer than ns; ns < 0 means forever.
18 //
19 // runtime·futexwakeup(uint32 *addr, uint32 cnt)
20 // If any procs are sleeping on addr, wake up at most cnt.
21
22 enum
23 {
24 MUTEX_UNLOCKED = 0,
25 MUTEX_LOCKED = 1,
26 MUTEX_SLEEPING = 2,
27
28 ACTIVE_SPIN = 4,
29 ACTIVE_SPIN_CNT = 30,
30 PASSIVE_SPIN = 1,
31 };
32
33 // Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
34 // MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
35 // Note that there can be spinning threads during all states - they do not
36 // affect mutex's state.
37 void
38 runtime·lock(Lock *l)
39 {
40 uint32 i, v, wait, spin;
41
42 if(g->m->locks++ < 0)
43 runtime·throw("runtime·lock: lock count");
44
45 // Speculative grab for lock.
46 v = runtime·xchg((uint32*)&l->key, MUTEX_LOCKED);
47 if(v == MUTEX_UNLOCKED)
48 return;
49
50 // wait is either MUTEX_LOCKED or MUTEX_SLEEPING
51 // depending on whether there is a thread sleeping
52 // on this mutex. If we ever change l->key from
53 // MUTEX_SLEEPING to some other value, we must be
54 // careful to change it back to MUTEX_SLEEPING before
55 // returning, to ensure that the sleeping thread gets
56 // its wakeup call.
57 wait = v;
58
59 // On uniprocessor's, no point spinning.
60 // On multiprocessors, spin for ACTIVE_SPIN attempts.
61 spin = 0;
62 if(runtime·ncpu > 1)
63 spin = ACTIVE_SPIN;
64
65 for(;;) {
66 // Try for lock, spinning.
67 for(i = 0; i < spin; i++) {
68 while(l->key == MUTEX_UNLOCKED)
69 if(runtime·cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
70 return;
71 runtime·procyield(ACTIVE_SPIN_CNT);
72 }
73
74 // Try for lock, rescheduling.
75 for(i=0; i < PASSIVE_SPIN; i++) {
76 while(l->key == MUTEX_UNLOCKED)
77 if(runtime·cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
78 return;
79 runtime·osyield();
80 }
81
82 // Sleep.
83 v = runtime·xchg((uint32*)&l->key, MUTEX_SLEEPING);
84 if(v == MUTEX_UNLOCKED)
85 return;
86 wait = MUTEX_SLEEPING;
87 runtime·futexsleep((uint32*)&l->key, MUTEX_SLEEPING, -1);
88 }
89 }
90
91 void
92 runtime·unlock(Lock *l)
93 {
94 uint32 v;
95
96 v = runtime·xchg((uint32*)&l->key, MUTEX_UNLOCKED);
97 if(v == MUTEX_UNLOCKED)
98 runtime·throw("unlock of unlocked lock");
99 if(v == MUTEX_SLEEPING)
100 runtime·futexwakeup((uint32*)&l->key, 1);
101
102 if(--g->m->locks < 0)
103 runtime·throw("runtime·unlock: lock count");
104 if(g->m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
105 g->stackguard0 = StackPreempt;
106 }
107
108 // One-time notifications.
109 void
110 runtime·noteclear(Note *n)
111 {
112 n->key = 0;
113 }
114
115 void
116 runtime·notewakeup(Note *n)
117 {
118 uint32 old;
119
120 old = runtime·xchg((uint32*)&n->key, 1);
121 if(old != 0) {
122 runtime·printf("notewakeup - double wakeup (%d)\n", old);
123 runtime·throw("notewakeup - double wakeup");
124 }
125 runtime·futexwakeup((uint32*)&n->key, 1);
126 }
127
128 void
129 runtime·notesleep(Note *n)
130 {
131 if(g != g->m->g0)
132 runtime·throw("notesleep not on g0");
133 while(runtime·atomicload((uint32*)&n->key) == 0) {
134 g->m->blocked = true;
135 runtime·futexsleep((uint32*)&n->key, 0, -1);
136 g->m->blocked = false;
137 }
138 }
139
140 #pragma textflag NOSPLIT
141 static bool
142 notetsleep(Note *n, int64 ns, int64 deadline, int64 now)
143 {
144 // Conceptually, deadline and now are local variables.
145 // They are passed as arguments so that the space for them
146 // does not count against our nosplit stack sequence.
147
148 if(ns < 0) {
149 while(runtime·atomicload((uint32*)&n->key) == 0) {
150 g->m->blocked = true;
151 runtime·futexsleep((uint32*)&n->key, 0, -1);
152 g->m->blocked = false;
153 }
154 return true;
155 }
156
157 if(runtime·atomicload((uint32*)&n->key) != 0)
158 return true;
159
160 deadline = runtime·nanotime() + ns;
161 for(;;) {
162 g->m->blocked = true;
163 runtime·futexsleep((uint32*)&n->key, 0, ns);
164 g->m->blocked = false;
165 if(runtime·atomicload((uint32*)&n->key) != 0)
166 break;
167 now = runtime·nanotime();
168 if(now >= deadline)
169 break;
170 ns = deadline - now;
171 }
172 return runtime·atomicload((uint32*)&n->key) != 0;
173 }
174
175 bool
176 runtime·notetsleep(Note *n, int64 ns)
177 {
178 bool res;
179
180 if(g != g->m->g0 && !g->m->gcing)
181 runtime·throw("notetsleep not on g0");
182
183 res = notetsleep(n, ns, 0, 0);
184 return res;
185 }
186
187 // same as runtime·notetsleep, but called on user g (not g0)
188 // calls only nosplit functions between entersyscallblock/exitsyscall
189 bool
190 runtime·notetsleepg(Note *n, int64 ns)
191 {
192 bool res;
193
194 if(g == g->m->g0)
195 runtime·throw("notetsleepg on g0");
196
197 runtime·entersyscallblock();
198 res = notetsleep(n, ns, 0, 0);
199 runtime·exitsyscall();
200 return res;
201 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b