Browse Source

small fixes

avanspector 1 year ago
parent
commit
38c69b9691
4 changed files with 78 additions and 28 deletions
  1. 55 15
      core/sync/futex_haiku.odin
  2. 13 3
      core/sys/haiku/errors.odin
  3. 8 8
      core/sys/haiku/os.odin
  4. 2 2
      core/sys/haiku/types.odin

+ 55 - 15
core/sync/futex_haiku.odin

@@ -2,7 +2,6 @@
 package sync
 
 import "core:c"
-import "core:c/libc"
 import "core:runtime"
 import "core:sys/haiku"
 import "core:sys/unix"
@@ -15,23 +14,21 @@ Wait_Node :: struct {
 	prev, next: ^Wait_Node,
 }
 @(private="file")
+atomic_flag :: distinct bool
+@(private="file")
 Wait_Queue :: struct {
-	lock: libc.atomic_flag,
+	lock: atomic_flag,
 	list: Wait_Node,
 }
 @(private="file")
 waitq_lock :: proc "contextless" (waitq: ^Wait_Queue) {
-	// FIXME: Get rid of context here.
-	context = runtime.default_context()
-	for libc.atomic_flag_test_and_set_explicit(&waitq.lock, .acquire) {
-		; // spin...
+	for cast(bool)atomic_exchange_explicit(&waitq.lock, atomic_flag(true), .Acquire) {
+		cpu_relax() // spin...
 	}
 }
 @(private="file")
 waitq_unlock :: proc "contextless" (waitq: ^Wait_Queue) {
-	// FIXME: Get rid of context here.
-	context = runtime.default_context()
-	libc.atomic_flag_clear_explicit(&waitq.lock, .release)
+	atomic_store_explicit(&waitq.lock, atomic_flag(false), .Release)
 }
 
 // FIXME: This approach may scale badly in the future,
@@ -55,7 +52,7 @@ get_waitq :: #force_inline proc "contextless" (f: ^Futex) -> ^Wait_Queue {
 	return &g_waitq
 }
 
-_futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> bool {
+_futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> (ok: bool) {
 	waitq := get_waitq(f)
 	waitq_lock(waitq)
 	defer waitq_unlock(waitq)
@@ -82,6 +79,8 @@ _futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> bool {
 		
 		sig: c.int
 		haiku.sigwait(&mask, &sig)
+		errno := haiku.errno() 
+		ok = errno == .OK
 	}
 
 	waiter.prev.next = waiter.next
@@ -90,13 +89,54 @@ _futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> bool {
  	unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil)
 
  	// FIXME: Add error handling!
- 	return true
+ 	return
 }
 
-_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration: time.Duration) -> bool {
-	// FIXME: Add timeout!
-	_ = duration
-	return _futex_wait(f, expect)
+_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration: time.Duration) -> (ok: bool) {
+	if duration <= 0 {
+		return false
+	}
+	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)
+		
+		info: haiku.siginfo_t
+		ts := unix.timespec{
+			tv_sec  = i64(duration / 1e9),
+			tv_nsec = i64(duration % 1e9),
+		}
+		haiku.sigtimedwait(&mask, &info, &ts)
+		errno := haiku.errno() 
+		ok = errno == .EAGAIN || errno == .OK
+	}
+
+	waiter.prev.next = waiter.next
+	waiter.next.prev = waiter.prev
+
+ 	unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil)
+
+ 	// FIXME: Add error handling!
+ 	return 
 }
 
 _futex_signal :: proc "contextless" (f: ^Futex) {

+ 13 - 3
core/sys/haiku/errors.odin

@@ -1,9 +1,11 @@
 //+build haiku
 package sys_haiku
 
+import "core:c"
+
 Errno :: enum i32 {
 	// Error baselines
-	GENERAL_ERROR_BASE     = min(i32),
+	GENERAL_ERROR_BASE     = -(1<<31),
 	OS_ERROR_BASE          = GENERAL_ERROR_BASE + 0x1000,
 	APP_ERROR_BASE         = GENERAL_ERROR_BASE + 0x2000,
 	INTERFACE_ERROR_BASE   = GENERAL_ERROR_BASE + 0x3000,
@@ -113,6 +115,8 @@ Errno :: enum i32 {
 	EOVERFLOW                         = POSIX_ERROR_BASE + 41,
 	EOPNOTSUPP                        = POSIX_ERROR_BASE + 43,
 
+	EAGAIN                            = WOULD_BLOCK,
+
 	// New error codes that can be mapped to POSIX errors
 	TOO_MANY_ARGS_NEG                 = E2BIG,
 	FILE_TOO_LARGE_NEG                = EFBIG,
@@ -221,8 +225,14 @@ Errno :: enum i32 {
 	ILLEGAL_DATA                 = TRANSLATION_ERROR_BASE + 2,
 }
 
+errno :: #force_inline proc "contextless" () -> Errno {
+	return Errno(_errnop()^)
+}
+
 foreign import libroot "system:c"
 foreign libroot {
-	_to_positive_error :: proc(error: i32) -> i32 ---
-	_to_negative_error :: proc(error: i32) -> i32 ---
+	_to_positive_error :: proc(error: c.int) -> c.int ---
+	_to_negative_error :: proc(error: c.int) -> c.int ---
+
+	_errnop :: proc() -> ^c.int ---
 }

+ 8 - 8
core/sys/haiku/os.odin

@@ -193,9 +193,9 @@ sigval :: struct #raw_union {
 }
 
 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_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
@@ -207,11 +207,11 @@ siginfo_t :: struct {
 
 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 ---
+	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 ---

+ 2 - 2
core/sys/haiku/types.odin

@@ -9,9 +9,9 @@ nanotime_t     :: i64
 type_code      :: u32
 perform_code   :: u32
 
-phys_addr_t    :: u64 when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 else u32
+phys_addr_t    :: uintptr
 phys_size_t    :: phys_addr_t
-generic_addr_t :: u64 when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 else u32
+generic_addr_t :: uintptr
 generic_size_t :: generic_addr_t
 
 area_id        :: i32