mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-20 21:35:19 +00:00
fix haiku
This commit is contained in:
@@ -14,7 +14,7 @@ Errno :: i32
|
||||
|
||||
MAX_PATH :: haiku.PATH_MAX
|
||||
|
||||
ENOSYS :: haiku.Errno.POSIX_ERROR_BASE + 9
|
||||
ENOSYS :: int(haiku.Errno.POSIX_ERROR_BASE) + 9
|
||||
|
||||
INVALID_HANDLE :: ~Handle(0)
|
||||
|
||||
|
||||
115
core/sync/futex_haiku.odin
Normal file
115
core/sync/futex_haiku.odin
Normal file
@@ -0,0 +1,115 @@
|
||||
//+private
|
||||
package sync
|
||||
|
||||
import "core:c"
|
||||
import "core:c/libc"
|
||||
import "core:sys/haiku"
|
||||
import "core:sys/unix"
|
||||
|
||||
@(private="file")
|
||||
Wait_Node :: struct {
|
||||
thread: unix.pthread_t,
|
||||
futex: ^Futex,
|
||||
prev, next: Wait_Node,
|
||||
}
|
||||
@(private="file")
|
||||
Wait_Queue :: struct {
|
||||
lock: libc.atomic_flag,
|
||||
list: Wait_Node,
|
||||
}
|
||||
@(private="file")
|
||||
waitq_lock :: proc(waitq: ^Wait_Queue) {
|
||||
for libc.atomic_flag_test_and_set_explicit(&waitq.lock, .Acquire) {
|
||||
; // spin...
|
||||
}
|
||||
}
|
||||
@(private="file")
|
||||
waitq_unlock :: proc(waitq: ^Wait_Queue) {
|
||||
libc.atomic_flag_clear(&waitq.lock, .Release)
|
||||
}
|
||||
|
||||
// FIXME: This approach may scale badly in the future,
|
||||
// possible solution - hash map (leads to deadlocks now).
|
||||
@(private="file")
|
||||
g_waitq := Wait_Queue{
|
||||
list = {
|
||||
prev = &g_waitq.list,
|
||||
next = &g_waitq.list,
|
||||
},
|
||||
}
|
||||
@(private="file")
|
||||
get_waitq :: #force_inline proc "contextless" (f: ^Futex) -> ^Wait_Queue {
|
||||
_ = f
|
||||
return &g_waitq
|
||||
}
|
||||
|
||||
_futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> bool {
|
||||
waitq := get_waitq(f)
|
||||
waitq_lock(&waitq)
|
||||
defer waitq_unlock(&waitq)
|
||||
|
||||
head := &waitq.list
|
||||
waiter := Wait_Node{
|
||||
thread = unix.pthread_self(),
|
||||
futex = f,
|
||||
prev = head,
|
||||
next = head.next,
|
||||
}
|
||||
|
||||
waiter.prev.next = &waiter
|
||||
waiter.next.prev = &waiter
|
||||
|
||||
old_mask, mask: haiku.sigset_t
|
||||
haiku.sigemptyset(&mask)
|
||||
haiku.sigaddset(&mask, haiku.SIGCONT)
|
||||
unix.pthread_sigmask(haiku.SIG_BLOCK, &mask, &old_mask)
|
||||
|
||||
if u32(atomic_load_explicit(f, .Acquire)) == expect {
|
||||
waitq_unlock(&waitq)
|
||||
defer waitq_lock(&waitq)
|
||||
|
||||
sig: c.int
|
||||
haiku.sigwait(&mask, &sig)
|
||||
}
|
||||
|
||||
waiter.prev.next = waiter.next
|
||||
waiter.next.prev = waiter.prev
|
||||
|
||||
unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil)
|
||||
|
||||
// FIXME: Add error handling!
|
||||
return true
|
||||
}
|
||||
|
||||
_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration: time.Duration) -> bool {
|
||||
// FIXME: Add timeout!
|
||||
_ = duration
|
||||
return _futex_wait(f, expect)
|
||||
}
|
||||
|
||||
_futex_signal :: proc "contextless" (f: ^Futex) {
|
||||
waitq := get_waitq(f)
|
||||
waitq_lock(&waitq)
|
||||
defer waitq_unlock(&waitq)
|
||||
|
||||
head := &waitq.list
|
||||
for waiter := head.next; waiter != head; waiter = waiter.next {
|
||||
if waiter.futex == f {
|
||||
unix.pthread_kill(waiter.thread, haiku.SIGCONT)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_futex_broadcast :: proc "contextless" (f: ^Futex) {
|
||||
waitq := get_waitq(f)
|
||||
waitq_lock(&waitq)
|
||||
defer waitq_unlock(&waitq)
|
||||
|
||||
head := &waitq.list
|
||||
for waiter := head.next; waiter != head; waiter = waiter.next {
|
||||
if waiter.futex == f {
|
||||
unix.pthread_kill(waiter.thread, haiku.SIGCONT)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,9 @@
|
||||
package sys_haiku
|
||||
|
||||
import "core:c"
|
||||
import "core:sys/unix"
|
||||
|
||||
foreign import libroot "system:c"
|
||||
|
||||
PATH_MAX :: 1024
|
||||
NAME_MAX :: 256
|
||||
@@ -120,7 +123,6 @@ cpu_topology_node_info :: struct {
|
||||
},
|
||||
}
|
||||
|
||||
foreign import libroot "system:c"
|
||||
foreign libroot {
|
||||
get_system_info :: proc(info: ^system_info) -> status_t ---
|
||||
_get_cpu_info_etc :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: c.size_t) -> status_t ---
|
||||
@@ -136,4 +138,85 @@ foreign libroot {
|
||||
to re-enable the default debugger pass a zero.
|
||||
*/
|
||||
disable_debugger :: proc(state: c.int) -> c.int ---
|
||||
|
||||
find_thread(name: cstring) -> thread_id ---
|
||||
}
|
||||
|
||||
// Signal.h
|
||||
|
||||
SIG_BLOCK :: 1
|
||||
SIG_UNBLOCK :: 2
|
||||
SIG_SETMASK :: 3
|
||||
|
||||
/*
|
||||
* The list of all defined signals:
|
||||
*
|
||||
* The numbering of signals for Haiku attempts to maintain
|
||||
* some consistency with UN*X conventions so that things
|
||||
* like "kill -9" do what you expect.
|
||||
*/
|
||||
|
||||
SIGHUP :: 1 // hangup -- tty is gone!
|
||||
SIGINT :: 2 // interrupt
|
||||
SIGQUIT :: 3 // `quit' special character typed in tty
|
||||
SIGILL :: 4 // illegal instruction
|
||||
SIGCHLD :: 5 // child process exited
|
||||
SIGABRT :: 6 // abort() called, dont' catch
|
||||
SIGPIPE :: 7 // write to a pipe w/no readers
|
||||
SIGFPE :: 8 // floating point exception
|
||||
SIGKILL :: 9 // kill a team (not catchable)
|
||||
SIGSTOP :: 10 // suspend a thread (not catchable)
|
||||
SIGSEGV :: 11 // segmentation violation (read: invalid pointer)
|
||||
SIGCONT :: 12 // continue execution if suspended
|
||||
SIGTSTP :: 13 // `stop' special character typed in tty
|
||||
SIGALRM :: 14 // an alarm has gone off (see alarm())
|
||||
SIGTERM :: 15 // termination requested
|
||||
SIGTTIN :: 16 // read of tty from bg process
|
||||
SIGTTOU :: 17 // write to tty from bg process
|
||||
SIGUSR1 :: 18 // app defined signal 1
|
||||
SIGUSR2 :: 19 // app defined signal 2
|
||||
SIGWINCH :: 20 // tty window size changed
|
||||
SIGKILLTHR :: 21 // be specific: kill just the thread, not team
|
||||
SIGTRAP :: 22 // Trace/breakpoint trap
|
||||
SIGPOLL :: 23 // Pollable event
|
||||
SIGPROF :: 24 // Profiling timer expired
|
||||
SIGSYS :: 25 // Bad system call
|
||||
SIGURG :: 26 // High bandwidth data is available at socket
|
||||
SIGVTALRM :: 27 // Virtual timer expired
|
||||
SIGXCPU :: 28 // CPU time limit exceeded
|
||||
SIGXFSZ :: 29 // File size limit exceeded
|
||||
SIGBUS :: 30 // access to undefined portion of a memory object
|
||||
|
||||
sigval :: struct #raw_union {
|
||||
sival_int: c.int,
|
||||
sival_ptr: rawptr,
|
||||
}
|
||||
|
||||
siginfo_t :: struct {
|
||||
si_signo: c.int, // signal number
|
||||
si_code: c.int, // signal code
|
||||
si_errno: c.int, // if non zero, an error number associated with this signal
|
||||
|
||||
si_pid: pid_t, // sending process ID
|
||||
si_uid: uid_t, // real user ID of sending process
|
||||
si_addr: rawptr, // address of faulting instruction
|
||||
si_status: c.int, // exit value or signal
|
||||
si_band: c.long, // band event for SIGPOLL
|
||||
si_value: sigval, // signal value
|
||||
}
|
||||
|
||||
foreign libroot {
|
||||
// signal set (sigset_t) manipulation
|
||||
sigemptyset :: proc(set: ^sigset_t) -> c.int ---
|
||||
sigfillset :: proc(set: ^sigset_t) -> c.int ---
|
||||
sigaddset :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
|
||||
sigdelset :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
|
||||
sigismember :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
|
||||
// querying and waiting for signals
|
||||
sigpending :: proc(set: ^sigset_t) -> c.int ---
|
||||
sigsuspend :: proc(mask: ^sigset_t) -> c.int ---
|
||||
sigpause :: proc(_signal: c.int) -> c.int ---
|
||||
sigwait :: proc(set: ^sigset_t, _signal: ^c.int) -> c.int ---
|
||||
sigwaitinfo :: proc(set: ^sigset_t, info: ^siginfo_t) -> c.int ---
|
||||
sigtimedwait :: proc(set: ^sigset_t, info: ^siginfo_t, timeout: ^unix.timespec) -> c.int ---
|
||||
}
|
||||
|
||||
@@ -45,3 +45,6 @@ key_t :: i32
|
||||
clockid_t :: i32
|
||||
|
||||
time_t :: i64 when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 else i32
|
||||
|
||||
sig_atomic_t :: c.int
|
||||
sigset_t :: u64
|
||||
|
||||
@@ -52,6 +52,8 @@ foreign pthread {
|
||||
pthread_attr_setstack :: proc(attrs: ^pthread_attr_t, stack_ptr: rawptr, stack_size: u64) -> c.int ---
|
||||
pthread_attr_getstack :: proc(attrs: ^pthread_attr_t, stack_ptr: ^rawptr, stack_size: ^u64) -> c.int ---
|
||||
|
||||
pthread_sigmask :: proc(how: c.int, set: rawptr, oldset: rawptr) -> c.int ---
|
||||
|
||||
sched_yield :: proc() -> c.int ---
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user