mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
fix haiku
This commit is contained in:
@@ -14,7 +14,7 @@ Errno :: i32
|
|||||||
|
|
||||||
MAX_PATH :: haiku.PATH_MAX
|
MAX_PATH :: haiku.PATH_MAX
|
||||||
|
|
||||||
ENOSYS :: haiku.Errno.POSIX_ERROR_BASE + 9
|
ENOSYS :: int(haiku.Errno.POSIX_ERROR_BASE) + 9
|
||||||
|
|
||||||
INVALID_HANDLE :: ~Handle(0)
|
INVALID_HANDLE :: ~Handle(0)
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+84
-1
@@ -2,6 +2,9 @@
|
|||||||
package sys_haiku
|
package sys_haiku
|
||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
import "core:sys/unix"
|
||||||
|
|
||||||
|
foreign import libroot "system:c"
|
||||||
|
|
||||||
PATH_MAX :: 1024
|
PATH_MAX :: 1024
|
||||||
NAME_MAX :: 256
|
NAME_MAX :: 256
|
||||||
@@ -120,7 +123,6 @@ cpu_topology_node_info :: struct {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
foreign import libroot "system:c"
|
|
||||||
foreign libroot {
|
foreign libroot {
|
||||||
get_system_info :: proc(info: ^system_info) -> status_t ---
|
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 ---
|
_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.
|
to re-enable the default debugger pass a zero.
|
||||||
*/
|
*/
|
||||||
disable_debugger :: proc(state: c.int) -> c.int ---
|
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
|
clockid_t :: i32
|
||||||
|
|
||||||
time_t :: i64 when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 else 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_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_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 ---
|
sched_yield :: proc() -> c.int ---
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user