2011-11-02 07:42:01 -06:00
|
|
|
// Copyright 2011 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.
|
|
|
|
|
2011-12-19 13:51:13 -07:00
|
|
|
// +build freebsd linux
|
|
|
|
|
2011-11-02 07:42:01 -06:00
|
|
|
#include "runtime.h"
|
2013-07-17 10:52:37 -06:00
|
|
|
#include "stack.h"
|
2011-11-02 07:42:01 -06:00
|
|
|
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
// This implementation depends on OS-specific implementations of
|
|
|
|
//
|
2011-12-19 21:56:37 -07:00
|
|
|
// runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
// Atomically,
|
|
|
|
// if(*addr == val) sleep
|
|
|
|
// Might be woken up spuriously; that's allowed.
|
|
|
|
// Don't sleep longer than ns; ns < 0 means forever.
|
|
|
|
//
|
2011-12-19 21:56:37 -07:00
|
|
|
// runtime·futexwakeup(uint32 *addr, uint32 cnt)
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
// If any procs are sleeping on addr, wake up at most cnt.
|
|
|
|
|
2011-11-02 07:42:01 -06:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
MUTEX_UNLOCKED = 0,
|
|
|
|
MUTEX_LOCKED = 1,
|
|
|
|
MUTEX_SLEEPING = 2,
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
|
2011-11-02 07:42:01 -06:00
|
|
|
ACTIVE_SPIN = 4,
|
|
|
|
ACTIVE_SPIN_CNT = 30,
|
|
|
|
PASSIVE_SPIN = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
|
|
|
|
// MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
|
|
|
|
// Note that there can be spinning threads during all states - they do not
|
|
|
|
// affect mutex's state.
|
|
|
|
void
|
|
|
|
runtime·lock(Lock *l)
|
|
|
|
{
|
|
|
|
uint32 i, v, wait, spin;
|
|
|
|
|
|
|
|
if(m->locks++ < 0)
|
|
|
|
runtime·throw("runtime·lock: lock count");
|
|
|
|
|
|
|
|
// Speculative grab for lock.
|
2013-04-06 21:07:07 -06:00
|
|
|
v = runtime·xchg((uint32*)&l->key, MUTEX_LOCKED);
|
2011-11-02 07:42:01 -06:00
|
|
|
if(v == MUTEX_UNLOCKED)
|
|
|
|
return;
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
|
2011-11-02 07:42:01 -06:00
|
|
|
// wait is either MUTEX_LOCKED or MUTEX_SLEEPING
|
|
|
|
// depending on whether there is a thread sleeping
|
|
|
|
// on this mutex. If we ever change l->key from
|
|
|
|
// MUTEX_SLEEPING to some other value, we must be
|
|
|
|
// careful to change it back to MUTEX_SLEEPING before
|
|
|
|
// returning, to ensure that the sleeping thread gets
|
|
|
|
// its wakeup call.
|
|
|
|
wait = v;
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
|
2011-11-02 07:42:01 -06:00
|
|
|
// On uniprocessor's, no point spinning.
|
|
|
|
// On multiprocessors, spin for ACTIVE_SPIN attempts.
|
|
|
|
spin = 0;
|
|
|
|
if(runtime·ncpu > 1)
|
|
|
|
spin = ACTIVE_SPIN;
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
|
2011-11-02 07:42:01 -06:00
|
|
|
for(;;) {
|
|
|
|
// Try for lock, spinning.
|
|
|
|
for(i = 0; i < spin; i++) {
|
|
|
|
while(l->key == MUTEX_UNLOCKED)
|
2013-04-06 21:07:07 -06:00
|
|
|
if(runtime·cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
|
2011-11-02 07:42:01 -06:00
|
|
|
return;
|
|
|
|
runtime·procyield(ACTIVE_SPIN_CNT);
|
|
|
|
}
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
|
2011-11-02 07:42:01 -06:00
|
|
|
// Try for lock, rescheduling.
|
|
|
|
for(i=0; i < PASSIVE_SPIN; i++) {
|
|
|
|
while(l->key == MUTEX_UNLOCKED)
|
2013-04-06 21:07:07 -06:00
|
|
|
if(runtime·cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
|
2011-11-02 07:42:01 -06:00
|
|
|
return;
|
|
|
|
runtime·osyield();
|
|
|
|
}
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
|
2011-11-02 07:42:01 -06:00
|
|
|
// Sleep.
|
2013-04-06 21:07:07 -06:00
|
|
|
v = runtime·xchg((uint32*)&l->key, MUTEX_SLEEPING);
|
2011-11-02 07:42:01 -06:00
|
|
|
if(v == MUTEX_UNLOCKED)
|
|
|
|
return;
|
|
|
|
wait = MUTEX_SLEEPING;
|
2013-04-06 21:07:07 -06:00
|
|
|
runtime·futexsleep((uint32*)&l->key, MUTEX_SLEEPING, -1);
|
2011-11-02 07:42:01 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·unlock(Lock *l)
|
|
|
|
{
|
|
|
|
uint32 v;
|
|
|
|
|
2013-04-06 21:07:07 -06:00
|
|
|
v = runtime·xchg((uint32*)&l->key, MUTEX_UNLOCKED);
|
2011-11-02 07:42:01 -06:00
|
|
|
if(v == MUTEX_UNLOCKED)
|
|
|
|
runtime·throw("unlock of unlocked lock");
|
|
|
|
if(v == MUTEX_SLEEPING)
|
2013-04-06 21:07:07 -06:00
|
|
|
runtime·futexwakeup((uint32*)&l->key, 1);
|
2013-05-15 06:48:41 -06:00
|
|
|
|
|
|
|
if(--m->locks < 0)
|
|
|
|
runtime·throw("runtime·unlock: lock count");
|
2013-07-17 10:52:37 -06:00
|
|
|
if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
|
|
|
|
g->stackguard0 = StackPreempt;
|
2011-11-02 07:42:01 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// One-time notifications.
|
|
|
|
void
|
|
|
|
runtime·noteclear(Note *n)
|
|
|
|
{
|
|
|
|
n->key = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·notewakeup(Note *n)
|
|
|
|
{
|
2013-04-06 21:09:02 -06:00
|
|
|
if(runtime·xchg((uint32*)&n->key, 1))
|
2012-12-24 10:06:57 -07:00
|
|
|
runtime·throw("notewakeup - double wakeup");
|
2013-04-06 21:09:02 -06:00
|
|
|
runtime·futexwakeup((uint32*)&n->key, 1);
|
2011-11-02 07:42:01 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·notesleep(Note *n)
|
|
|
|
{
|
2012-02-28 14:18:24 -07:00
|
|
|
if(m->profilehz > 0)
|
|
|
|
runtime·setprof(false);
|
2013-04-06 21:09:02 -06:00
|
|
|
while(runtime·atomicload((uint32*)&n->key) == 0)
|
|
|
|
runtime·futexsleep((uint32*)&n->key, 0, -1);
|
2012-02-28 14:18:24 -07:00
|
|
|
if(m->profilehz > 0)
|
|
|
|
runtime·setprof(true);
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
}
|
|
|
|
|
2013-05-29 01:49:45 -06:00
|
|
|
bool
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
runtime·notetsleep(Note *n, int64 ns)
|
|
|
|
{
|
|
|
|
int64 deadline, now;
|
|
|
|
|
|
|
|
if(ns < 0) {
|
|
|
|
runtime·notesleep(n);
|
2013-05-29 01:49:45 -06:00
|
|
|
return true;
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
}
|
|
|
|
|
2013-04-06 21:09:02 -06:00
|
|
|
if(runtime·atomicload((uint32*)&n->key) != 0)
|
2013-05-29 01:49:45 -06:00
|
|
|
return true;
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
|
2012-02-28 14:18:24 -07:00
|
|
|
if(m->profilehz > 0)
|
|
|
|
runtime·setprof(false);
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
deadline = runtime·nanotime() + ns;
|
|
|
|
for(;;) {
|
2013-04-06 21:09:02 -06:00
|
|
|
runtime·futexsleep((uint32*)&n->key, 0, ns);
|
|
|
|
if(runtime·atomicload((uint32*)&n->key) != 0)
|
2012-02-28 14:18:24 -07:00
|
|
|
break;
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
now = runtime·nanotime();
|
|
|
|
if(now >= deadline)
|
2012-02-28 14:18:24 -07:00
|
|
|
break;
|
runtime: add timer support, use for package time
This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.
It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another. (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)
Fixes #1644.
Fixes #1731.
Fixes #2190.
R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
2011-11-09 13:17:05 -07:00
|
|
|
ns = deadline - now;
|
|
|
|
}
|
2012-02-28 14:18:24 -07:00
|
|
|
if(m->profilehz > 0)
|
|
|
|
runtime·setprof(true);
|
2013-05-29 01:49:45 -06:00
|
|
|
return runtime·atomicload((uint32*)&n->key) != 0;
|
2011-11-02 07:42:01 -06:00
|
|
|
}
|
2013-07-22 13:02:27 -06:00
|
|
|
|
|
|
|
bool
|
|
|
|
runtime·notetsleepg(Note *n, int64 ns)
|
|
|
|
{
|
|
|
|
bool res;
|
|
|
|
|
|
|
|
if(g == m->g0)
|
|
|
|
runtime·throw("notetsleepg on g0");
|
|
|
|
runtime·entersyscallblock();
|
|
|
|
res = runtime·notetsleep(n, ns);
|
|
|
|
runtime·exitsyscall();
|
|
|
|
return res;
|
|
|
|
}
|