fix haiku

This commit is contained in:
avanspector
2024-02-26 07:43:10 +01:00
parent 1d79521e81
commit 9d4c2ba0d8
5 changed files with 205 additions and 2 deletions

View File

@@ -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
View 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)
}
}
}

View File

@@ -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 ---
}

View File

@@ -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

View File

@@ -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 ---
}