123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- // Copyright 2009 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.
- #include "runtime.h"
- #include "defs.h"
- #include "signal_unix.h"
- // Linux futex.
- //
- // futexsleep(uint32 *addr, uint32 val)
- // futexwakeup(uint32 *addr)
- //
- // Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
- // Futexwakeup wakes up threads sleeping on addr.
- // Futexsleep is allowed to wake up spuriously.
- #include <errno.h>
- #include <string.h>
- #include <time.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <syscall.h>
- #include <linux/futex.h>
- typedef struct timespec Timespec;
- // Atomically,
- // if(*addr == val) sleep
- // Might be woken up spuriously; that's allowed.
- // Don't sleep longer than ns; ns < 0 means forever.
- void
- runtime_futexsleep(uint32 *addr, uint32 val, int64 ns)
- {
- Timespec ts;
- int32 nsec;
- // Some Linux kernels have a bug where futex of
- // FUTEX_WAIT returns an internal error code
- // as an errno. Libpthread ignores the return value
- // here, and so can we: as it says a few lines up,
- // spurious wakeups are allowed.
- if(ns < 0) {
- syscall(__NR_futex, addr, FUTEX_WAIT, val, nil, nil, 0);
- return;
- }
- ts.tv_sec = runtime_timediv(ns, 1000000000LL, &nsec);
- ts.tv_nsec = nsec;
- syscall(__NR_futex, addr, FUTEX_WAIT, val, &ts, nil, 0);
- }
- // If any procs are sleeping on addr, wake up at most cnt.
- void
- runtime_futexwakeup(uint32 *addr, uint32 cnt)
- {
- int64 ret;
- ret = syscall(__NR_futex, addr, FUTEX_WAKE, cnt, nil, nil, 0);
- if(ret >= 0)
- return;
- // I don't know that futex wakeup can return
- // EAGAIN or EINTR, but if it does, it would be
- // safe to loop and call futex again.
- runtime_printf("futexwakeup addr=%p returned %D\n", addr, ret);
- *(int32*)0x1006 = 0x1006;
- }
- void
- runtime_osinit(void)
- {
- runtime_ncpu = getproccount();
- }
- void
- runtime_goenvs(void)
- {
- runtime_goenvs_unix();
- }
|