--- /dev/null
+// Copyright 2013 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.
+
+// +build linux freebsd
+
+package runtime
+
+func futexsleep(addr *uint32, val uint32, ns int64)
+func futexwakeup(addr *uint32, val uint32)
+
+var Futexsleep = futexsleep
+var Futexwakeup = futexwakeup
--- /dev/null
+// Copyright 2013 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.
+
+// +build linux freebsd
+
+package runtime_test
+
+import (
+ . "runtime"
+ "testing"
+ "time"
+)
+
+func TestFutexsleep(t *testing.T) {
+ ch := make(chan bool, 1)
+ var dummy uint32
+ start := time.Now()
+ go func() {
+ Entersyscall()
+ Futexsleep(&dummy, 0, (1<<31+100)*1e9)
+ Exitsyscall()
+ ch <- true
+ }()
+ select {
+ case <-ch:
+ t.Errorf("futexsleep finished early after %s!", time.Since(start))
+ case <-time.After(time.Second):
+ Futexwakeup(&dummy, 1)
+ }
+}
runtime·mach_semacquire(uint32 sem, int64 ns)
{
int32 r;
+ int64 secs;
if(ns >= 0) {
- r = runtime·mach_semaphore_timedwait(sem, ns/1000000000LL, ns%1000000000LL);
+ secs = ns/1000000000LL;
+ // Avoid overflow
+ if(secs > 1LL<<30)
+ secs = 1LL<<30;
+ r = runtime·mach_semaphore_timedwait(sem, secs, ns%1000000000LL);
if(r == KERN_ABORTED || r == KERN_OPERATION_TIMED_OUT)
return -1;
if(r != 0)
{
int32 ret;
Timespec ts, *tsp;
+ int64 secs;
if(ns < 0)
tsp = nil;
else {
- ts.tv_sec = ns / 1000000000LL;
+ secs = ns / 1000000000LL;
+ // Avoid overflow
+ if(secs > 1LL<<30)
+ secs = 1LL<<30;
+ ts.tv_sec = secs;
ts.tv_nsec = ns % 1000000000LL;
tsp = &ts;
}
runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
{
Timespec ts, *tsp;
+ int64 secs;
if(ns < 0)
tsp = nil;
else {
- ts.tv_sec = ns/1000000000LL;
- ts.tv_nsec = ns%1000000000LL;
+ secs = ns/1000000000LL;
// Avoid overflow
- if(ts.tv_sec > 1<<30)
- ts.tv_sec = 1<<30;
+ if(secs > 1LL<<30)
+ secs = 1LL<<30;
+ ts.tv_sec = secs;
+ ts.tv_nsec = ns%1000000000LL;
tsp = &ts;
}
runtime·semasleep(int64 ns)
{
Timespec ts;
+ int64 secs;
// spin-mutex lock
while(runtime·xchg(&m->waitsemalock, 1))
runtime·lwp_park(nil, 0, &m->waitsemacount, nil);
} else {
ns += runtime·nanotime();
- ts.tv_sec = ns/1000000000LL;
+ secs = ns/1000000000LL;
+ // Avoid overflow
+ if(secs > 1LL<<30)
+ secs = 1LL<<30;
+ ts.tv_sec = secs;
ts.tv_nsec = ns%1000000000LL;
// TODO(jsing) - potential deadlock!
// See above for details.
runtime·semasleep(int64 ns)
{
Timespec ts;
+ int64 secs;
// spin-mutex lock
while(runtime·xchg(&m->waitsemalock, 1))
runtime·thrsleep(&m->waitsemacount, 0, nil, &m->waitsemalock, nil);
else {
ns += runtime·nanotime();
- ts.tv_sec = ns/1000000000LL;
+ secs = ns/1000000000LL;
+ // Avoid overflow
+ if(secs > 1LL<<30)
+ secs = 1LL<<30;
+ ts.tv_sec = secs;
ts.tv_nsec = ns%1000000000LL;
runtime·thrsleep(&m->waitsemacount, CLOCK_REALTIME, &ts, &m->waitsemalock, nil);
}