Browse Source

Merge pull request #4438 from laytan/fixing-threads

fix thread_unix for Darwin after pthread corrections in posix package
Laytan 9 months ago
parent
commit
d4d546a63a

+ 1 - 1
core/fmt/fmt.odin

@@ -1531,7 +1531,7 @@ fmt_pointer :: proc(fi: ^Info, p: rawptr, verb: rune) {
 	case 'o': _fmt_int(fi, u,  8, false, 8*size_of(rawptr), __DIGITS_UPPER)
 	case 'o': _fmt_int(fi, u,  8, false, 8*size_of(rawptr), __DIGITS_UPPER)
 	case 'i', 'd': _fmt_int(fi, u, 10, false, 8*size_of(rawptr), __DIGITS_UPPER)
 	case 'i', 'd': _fmt_int(fi, u, 10, false, 8*size_of(rawptr), __DIGITS_UPPER)
 	case 'z': _fmt_int(fi, u, 12, false, 8*size_of(rawptr), __DIGITS_UPPER)
 	case 'z': _fmt_int(fi, u, 12, false, 8*size_of(rawptr), __DIGITS_UPPER)
-	case 'x': _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER)
+	case 'x': _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_LOWER)
 	case 'X': _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER)
 	case 'X': _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER)
 
 
 	case:
 	case:

+ 12 - 2
core/sys/posix/pthread.odin

@@ -355,12 +355,16 @@ Thread_Scope :: enum c.int {
 }
 }
 
 
 Cancel_State :: enum c.int {
 Cancel_State :: enum c.int {
+	// Cancel takes place at next cancellation point.
 	ENABLE  = PTHREAD_CANCEL_ENABLE,
 	ENABLE  = PTHREAD_CANCEL_ENABLE,
+	// Cancel postponed.
 	DISABLE = PTHREAD_CANCEL_DISABLE,
 	DISABLE = PTHREAD_CANCEL_DISABLE,
 }
 }
 
 
 Cancel_Type :: enum c.int {
 Cancel_Type :: enum c.int {
+	// Cancel waits until cancellation point.
 	DEFERRED     = PTHREAD_CANCEL_DEFERRED,
 	DEFERRED     = PTHREAD_CANCEL_DEFERRED,
+	// Cancel occurs immediately.
 	ASYNCHRONOUS = PTHREAD_CANCEL_ASYNCHRONOUS,
 	ASYNCHRONOUS = PTHREAD_CANCEL_ASYNCHRONOUS,
 }
 }
 
 
@@ -372,6 +376,12 @@ when ODIN_OS == .Darwin {
 	PTHREAD_CANCEL_DISABLE      :: 0x00
 	PTHREAD_CANCEL_DISABLE      :: 0x00
 	PTHREAD_CANCEL_ENABLE       :: 0x01
 	PTHREAD_CANCEL_ENABLE       :: 0x01
 
 
+	// PTHREAD_CANCEL_ASYNCHRONOUS :: 1
+	// PTHREAD_CANCEL_DEFERRED     :: 0
+	//
+	// PTHREAD_CANCEL_DISABLE      :: 1
+	// PTHREAD_CANCEL_ENABLE       :: 0
+
 	PTHREAD_CANCELED :: rawptr(uintptr(1))
 	PTHREAD_CANCELED :: rawptr(uintptr(1))
 
 
 	PTHREAD_CREATE_DETACHED :: 2
 	PTHREAD_CREATE_DETACHED :: 2
@@ -434,8 +444,8 @@ when ODIN_OS == .Darwin {
 	PTHREAD_PRIO_NONE    :: 0
 	PTHREAD_PRIO_NONE    :: 0
 	PTHREAD_PRIO_PROTECT :: 2
 	PTHREAD_PRIO_PROTECT :: 2
 
 
-	PTHREAD_PROCESS_SHARED  :: 0
-	PTHREAD_PROCESS_PRIVATE :: 1
+	PTHREAD_PROCESS_SHARED  :: 1
+	PTHREAD_PROCESS_PRIVATE :: 0
 
 
 	PTHREAD_SCOPE_PROCESS   :: 0
 	PTHREAD_SCOPE_PROCESS   :: 0
 	PTHREAD_SCOPE_SYSTEM    :: 2
 	PTHREAD_SCOPE_SYSTEM    :: 2

+ 12 - 4
core/thread/thread_unix.odin

@@ -23,7 +23,9 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
 		t := (^Thread)(t)
 		t := (^Thread)(t)
 
 
 		// We need to give the thread a moment to start up before we enable cancellation.
 		// We need to give the thread a moment to start up before we enable cancellation.
-		can_set_thread_cancel_state := posix.pthread_setcancelstate(.ENABLE, nil) == nil
+		// NOTE(laytan): setting to .DISABLE on darwin, with .ENABLE pthread_cancel would deadlock
+		// most of the time, don't ask me why.
+		can_set_thread_cancel_state := posix.pthread_setcancelstate(.DISABLE when ODIN_OS == .Darwin else .ENABLE, nil) == nil
 
 
 		t.id = sync.current_thread_id()
 		t.id = sync.current_thread_id()
 
 
@@ -36,9 +38,15 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
 		}
 		}
 
 
 		// Enable thread's cancelability.
 		// Enable thread's cancelability.
-		if can_set_thread_cancel_state {
-			posix.pthread_setcanceltype (.ASYNCHRONOUS, nil)
-			posix.pthread_setcancelstate(.ENABLE,       nil)
+		// NOTE(laytan): Darwin does not correctly/fully support all of this, not doing this does
+		// actually make pthread_cancel work in the capacity of my tests, while executing this would
+		// basically always make it deadlock.
+		if ODIN_OS != .Darwin && can_set_thread_cancel_state {
+			err := posix.pthread_setcancelstate(.ENABLE, nil)
+			assert_contextless(err == nil)
+
+			err = posix.pthread_setcanceltype(.ASYNCHRONOUS, nil)
+			assert_contextless(err == nil)
 		}
 		}
 
 
 		{
 		{

+ 24 - 0
tests/core/sys/posix/structs/structs.c

@@ -101,5 +101,29 @@ int main(int argc, char *argv[])
 	printf("timespec %zu %zu\n", sizeof(struct timespec), _Alignof(struct timespec));
 	printf("timespec %zu %zu\n", sizeof(struct timespec), _Alignof(struct timespec));
 	printf("clock_t %zu %zu\n", sizeof(clock_t), _Alignof(clock_t));
 	printf("clock_t %zu %zu\n", sizeof(clock_t), _Alignof(clock_t));
 
 
+	printf("PTHREAD_CANCEL_ASYNCHRONOUS %d\n", PTHREAD_CANCEL_ASYNCHRONOUS);
+	printf("PTHREAD_CANCEL_DEFERRED %d\n",     PTHREAD_CANCEL_DEFERRED);
+
+	printf("PTHREAD_CANCEL_DISABLE %d\n",      PTHREAD_CANCEL_DISABLE);
+	printf("PTHREAD_CANCEL_ENABLE %d\n",       PTHREAD_CANCEL_ENABLE);
+
+	printf("PTHREAD_CANCELED %p\n",            PTHREAD_CANCELED);
+
+	printf("PTHREAD_CREATE_JOINABLE %d\n",     PTHREAD_CREATE_JOINABLE);
+	printf("PTHREAD_CREATE_DETACHED %d\n",     PTHREAD_CREATE_DETACHED);
+
+	printf("PTHREAD_EXPLICIT_SCHED %d\n",      PTHREAD_EXPLICIT_SCHED);
+	printf("PTHREAD_INHERIT_SCHED %d\n",       PTHREAD_INHERIT_SCHED);
+
+	printf("PTHREAD_PRIO_INHERIT %d\n",        PTHREAD_PRIO_INHERIT);
+	printf("PTHREAD_PRIO_NONE %d\n",           PTHREAD_PRIO_NONE);
+	printf("PTHREAD_PRIO_PROTECT %d\n",        PTHREAD_PRIO_PROTECT);
+
+	printf("PTHREAD_PROCESS_SHARED %d\n",      PTHREAD_PROCESS_SHARED);
+	printf("PTHREAD_PROCESS_PRIVATE %d\n",     PTHREAD_PROCESS_PRIVATE);
+
+	printf("PTHREAD_SCOPE_PROCESS %d\n",       PTHREAD_SCOPE_PROCESS);
+	printf("PTHREAD_SCOPE_SYSTEM %d\n",        PTHREAD_SCOPE_SYSTEM);
+
 	return 0;
 	return 0;
 }
 }

+ 24 - 0
tests/core/sys/posix/structs/structs.odin

@@ -75,4 +75,28 @@ main :: proc() {
 	fmt.println("time_t", size_of(posix.time_t), align_of(posix.time_t))
 	fmt.println("time_t", size_of(posix.time_t), align_of(posix.time_t))
 	fmt.println("timespec", size_of(posix.timespec), align_of(posix.timespec))
 	fmt.println("timespec", size_of(posix.timespec), align_of(posix.timespec))
 	fmt.println("clock_t", size_of(posix.clock_t), align_of(posix.clock_t))
 	fmt.println("clock_t", size_of(posix.clock_t), align_of(posix.clock_t))
+
+	fmt.println("PTHREAD_CANCEL_ASYNCHRONOUS", posix.PTHREAD_CANCEL_ASYNCHRONOUS)
+	fmt.println("PTHREAD_CANCEL_DEFERRED",     posix.PTHREAD_CANCEL_DEFERRED)
+
+	fmt.println("PTHREAD_CANCEL_DISABLE",      posix.PTHREAD_CANCEL_DISABLE)
+	fmt.println("PTHREAD_CANCEL_ENABLE",       posix.PTHREAD_CANCEL_ENABLE)
+
+	fmt.printfln("PTHREAD_CANCELED %#x",       posix.PTHREAD_CANCELED)
+
+	fmt.println("PTHREAD_CREATE_JOINABLE",     posix.PTHREAD_CREATE_JOINABLE)
+	fmt.println("PTHREAD_CREATE_DETACHED",     posix.PTHREAD_CREATE_DETACHED)
+
+	fmt.println("PTHREAD_EXPLICIT_SCHED",      posix.PTHREAD_EXPLICIT_SCHED)
+	fmt.println("PTHREAD_INHERIT_SCHED",       posix.PTHREAD_INHERIT_SCHED)
+
+	fmt.println("PTHREAD_PRIO_INHERIT",        posix.PTHREAD_PRIO_INHERIT)
+	fmt.println("PTHREAD_PRIO_NONE",           posix.PTHREAD_PRIO_NONE)
+	fmt.println("PTHREAD_PRIO_PROTECT",        posix.PTHREAD_PRIO_PROTECT)
+
+	fmt.println("PTHREAD_PROCESS_SHARED",      posix.PTHREAD_PROCESS_SHARED)
+	fmt.println("PTHREAD_PROCESS_PRIVATE",     posix.PTHREAD_PROCESS_PRIVATE)
+
+	fmt.println("PTHREAD_SCOPE_PROCESS",       posix.PTHREAD_SCOPE_PROCESS)
+	fmt.println("PTHREAD_SCOPE_SYSTEM",        posix.PTHREAD_SCOPE_SYSTEM)
 }
 }