diff --git a/src/crystal/system/thread.cr b/src/crystal/system/thread.cr index d9dc6acf17dc..431708c5cc11 100644 --- a/src/crystal/system/thread.cr +++ b/src/crystal/system/thread.cr @@ -23,6 +23,14 @@ module Crystal::System::Thread # private def stack_address : Void* # private def system_name=(String) : String + + # def self.init_suspend_resume : Nil + + # private def system_suspend : Nil + + # private def system_wait_suspended : Nil + + # private def system_resume : Nil end {% if flag?(:wasi) %} @@ -66,6 +74,14 @@ class Thread @@threads.try(&.unsafe_each { |thread| yield thread }) end + def self.lock : Nil + threads.@mutex.lock + end + + def self.unlock : Nil + threads.@mutex.unlock + end + # Creates and starts a new system thread. def initialize(@name : String? = nil, &@func : Thread ->) @system_handle = uninitialized Crystal::System::Thread::Handle @@ -168,6 +184,26 @@ class Thread # Holds the GC thread handler property gc_thread_handler : Void* = Pointer(Void).null + + def suspend : Nil + system_suspend + end + + def wait_suspended : Nil + system_wait_suspended + end + + def resume : Nil + system_resume + end + + def self.stop_world : Nil + GC.stop_world + end + + def self.start_world : Nil + GC.start_world + end end require "./thread_linked_list" diff --git a/src/crystal/system/unix/pthread.cr b/src/crystal/system/unix/pthread.cr index d38e52ee012a..b55839ff2784 100644 --- a/src/crystal/system/unix/pthread.cr +++ b/src/crystal/system/unix/pthread.cr @@ -1,5 +1,6 @@ require "c/pthread" require "c/sched" +require "../panic" module Crystal::System::Thread alias Handle = LibC::PthreadT @@ -153,6 +154,80 @@ module Crystal::System::Thread {% end %} name end + + @suspended = Atomic(Bool).new(false) + + def self.init_suspend_resume : Nil + install_sig_suspend_signal_handler + install_sig_resume_signal_handler + end + + private def self.install_sig_suspend_signal_handler + action = LibC::Sigaction.new + action.sa_flags = LibC::SA_SIGINFO + action.sa_sigaction = LibC::SigactionHandlerT.new do |_, _, _| + # notify that the thread has been interrupted + Thread.current_thread.@suspended.set(true) + + # block all signals but SIG_RESUME + mask = LibC::SigsetT.new + LibC.sigfillset(pointerof(mask)) + LibC.sigdelset(pointerof(mask), SIG_RESUME) + + # suspend the thread until it receives the SIG_RESUME signal + LibC.sigsuspend(pointerof(mask)) + end + LibC.sigemptyset(pointerof(action.@sa_mask)) + LibC.sigaction(SIG_SUSPEND, pointerof(action), nil) + end + + private def self.install_sig_resume_signal_handler + action = LibC::Sigaction.new + action.sa_flags = 0 + action.sa_sigaction = LibC::SigactionHandlerT.new do |_, _, _| + # do nothing (a handler is still required to receive the signal) + end + LibC.sigemptyset(pointerof(action.@sa_mask)) + LibC.sigaction(SIG_RESUME, pointerof(action), nil) + end + + private def system_suspend : Nil + @suspended.set(false) + + if LibC.pthread_kill(@system_handle, SIG_SUSPEND) == -1 + System.panic("pthread_kill()", Errno.value) + end + end + + private def system_wait_suspended : Nil + until @suspended.get + Thread.yield_current + end + end + + private def system_resume : Nil + if LibC.pthread_kill(@system_handle, SIG_RESUME) == -1 + System.panic("pthread_kill()", Errno.value) + end + end + + # the suspend/resume signals follow BDWGC + + private SIG_SUSPEND = + {% if flag?(:linux) %} + LibC::SIGPWR + {% elsif LibC.has_constant?(:SIGRTMIN) %} + LibC::SIGRTMIN + 6 + {% else %} + LibC::SIGXFSZ + {% end %} + + private SIG_RESUME = + {% if LibC.has_constant?(:SIGRTMIN) %} + LibC::SIGRTMIN + 5 + {% else %} + LibC::SIGXCPU + {% end %} end # In musl (alpine) the calls to unwind API segfaults diff --git a/src/crystal/system/wasi/thread.cr b/src/crystal/system/wasi/thread.cr index 6f0c0cbe8260..1e8f6957d526 100644 --- a/src/crystal/system/wasi/thread.cr +++ b/src/crystal/system/wasi/thread.cr @@ -38,4 +38,19 @@ module Crystal::System::Thread # TODO: Implement Pointer(Void).null end + + def self.init_suspend_resume : Nil + end + + private def system_suspend : Nil + raise NotImplementedError.new("Crystal::System::Thread.system_suspend") + end + + private def system_wait_suspended : Nil + raise NotImplementedError.new("Crystal::System::Thread.system_wait_suspended") + end + + private def system_resume : Nil + raise NotImplementedError.new("Crystal::System::Thread.system_resume") + end end diff --git a/src/crystal/system/win32/thread.cr b/src/crystal/system/win32/thread.cr index ddfe3298b20a..1a4f61a41738 100644 --- a/src/crystal/system/win32/thread.cr +++ b/src/crystal/system/win32/thread.cr @@ -1,5 +1,6 @@ require "c/processthreadsapi" require "c/synchapi" +require "../panic" module Crystal::System::Thread alias Handle = LibC::HANDLE @@ -87,4 +88,31 @@ module Crystal::System::Thread {% end %} name end + + def self.init_suspend_resume : Nil + end + + private def system_suspend : Nil + if LibC.SuspendThread(@system_handle) == -1 + Crystal::System.panic("SuspendThread()", WinError.value) + end + end + + private def system_wait_suspended : Nil + # context must be aligned on 16 bytes but we lack a mean to force the + # alignment on the struct, so we overallocate then realign the pointer: + local = uninitialized UInt8[sizeof(Tuple(LibC::CONTEXT, UInt8[15]))] + thread_context = Pointer(LibC::CONTEXT).new(local.to_unsafe.address &+ 15_u64 & ~15_u64) + thread_context.value.contextFlags = LibC::CONTEXT_FULL + + if LibC.GetThreadContext(@system_handle, thread_context) == -1 + Crystal::System.panic("GetThreadContext()", WinError.value) + end + end + + private def system_resume : Nil + if LibC.ResumeThread(@system_handle) == -1 + Crystal::System.panic("ResumeThread()", WinError.value) + end + end end diff --git a/src/gc/boehm.cr b/src/gc/boehm.cr index 8ccc1bb7b6e8..0ce6a1366b6d 100644 --- a/src/gc/boehm.cr +++ b/src/gc/boehm.cr @@ -161,6 +161,9 @@ lib LibGC alias WarnProc = LibC::Char*, Word -> fun set_warn_proc = GC_set_warn_proc(WarnProc) $warn_proc = GC_current_warn_proc : WarnProc + + fun stop_world_external = GC_stop_world_external + fun start_world_external = GC_start_world_external end module GC @@ -470,4 +473,14 @@ module GC GC.unlock_write end {% end %} + + # :nodoc: + def self.stop_world : Nil + LibGC.stop_world_external + end + + # :nodoc: + def self.start_world : Nil + LibGC.start_world_external + end end diff --git a/src/gc/none.cr b/src/gc/none.cr index 640e6e8f927d..3943bd265ed9 100644 --- a/src/gc/none.cr +++ b/src/gc/none.cr @@ -5,6 +5,7 @@ require "crystal/tracing" module GC def self.init + Crystal::System::Thread.init_suspend_resume end # :nodoc: @@ -138,4 +139,57 @@ module GC # :nodoc: def self.push_stack(stack_top, stack_bottom) end + + # Stop and start the world. + # + # This isn't a GC-safe stop-the-world implementation (it may allocate objects + # while stopping the world), but the guarantees are enough for the purpose of + # gc_none. It could be GC-safe if Thread::LinkedList(T) became a struct, and + # Thread::Mutex either became a struct or provide low level abstraction + # methods that directly interact with syscalls (without allocating). + # + # Thread safety is guaranteed by the mutex in Thread::LinkedList: either a + # thread is starting and hasn't added itself to the list (it will block until + # it can acquire the lock), or is currently adding itself (the current thread + # will block until it can acquire the lock). + # + # In both cases there can't be a deadlock since we won't suspend another + # thread until it has successfuly added (or removed) itself to (from) the + # linked list and released the lock, and the other thread won't progress until + # it can add (or remove) itself from the list. + # + # Finally, we lock the mutex and keep it locked until we resume the world, so + # any thread waiting on the mutex will only be resumed when the world is + # resumed. + + # :nodoc: + def self.stop_world : Nil + current_thread = Thread.current + + # grab the lock (and keep it until the world is restarted) + Thread.lock + + # tell all threads to stop (async) + Thread.unsafe_each do |thread| + thread.suspend unless thread == current_thread + end + + # wait for all threads to have stopped + Thread.unsafe_each do |thread| + thread.wait_suspended unless thread == current_thread + end + end + + # :nodoc: + def self.start_world : Nil + current_thread = Thread.current + + # tell all threads to resume + Thread.unsafe_each do |thread| + thread.resume unless thread == current_thread + end + + # finally, we can release the lock + Thread.unlock + end end diff --git a/src/lib_c/aarch64-android/c/signal.cr b/src/lib_c/aarch64-android/c/signal.cr index 741c8f0efb65..27676c3f733f 100644 --- a/src/lib_c/aarch64-android/c/signal.cr +++ b/src/lib_c/aarch64-android/c/signal.cr @@ -79,6 +79,7 @@ lib LibC fun kill(__pid : PidT, __signal : Int) : Int fun pthread_sigmask(__how : Int, __new_set : SigsetT*, __old_set : SigsetT*) : Int + fun pthread_kill(__thread : PthreadT, __sig : Int) : Int fun sigaction(__signal : Int, __new_action : Sigaction*, __old_action : Sigaction*) : Int fun sigaltstack(__new_signal_stack : StackT*, __old_signal_stack : StackT*) : Int {% if ANDROID_API >= 21 %} @@ -89,5 +90,6 @@ lib LibC fun sigaddset(__set : SigsetT*, __signal : Int) : Int fun sigdelset(__set : SigsetT*, __signal : Int) : Int fun sigismember(__set : SigsetT*, __signal : Int) : Int + fun sigsuspend(__mask : SigsetT*) : Int {% end %} end diff --git a/src/lib_c/aarch64-darwin/c/signal.cr b/src/lib_c/aarch64-darwin/c/signal.cr index e58adc30289f..0034eef42834 100644 --- a/src/lib_c/aarch64-darwin/c/signal.cr +++ b/src/lib_c/aarch64-darwin/c/signal.cr @@ -77,6 +77,7 @@ lib LibC fun kill(x0 : PidT, x1 : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(x0 : Int, x1 : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -85,4 +86,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/aarch64-linux-gnu/c/signal.cr b/src/lib_c/aarch64-linux-gnu/c/signal.cr index 1f7d82eb2145..7ff9fcda1b07 100644 --- a/src/lib_c/aarch64-linux-gnu/c/signal.cr +++ b/src/lib_c/aarch64-linux-gnu/c/signal.cr @@ -78,6 +78,7 @@ lib LibC fun kill(pid : PidT, sig : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(sig : Int, handler : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -86,4 +87,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/aarch64-linux-musl/c/signal.cr b/src/lib_c/aarch64-linux-musl/c/signal.cr index 5bfa187b14ec..c65fbb0ff653 100644 --- a/src/lib_c/aarch64-linux-musl/c/signal.cr +++ b/src/lib_c/aarch64-linux-musl/c/signal.cr @@ -77,6 +77,7 @@ lib LibC fun kill(x0 : PidT, x1 : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(x0 : Int, x1 : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -85,4 +86,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/arm-linux-gnueabihf/c/signal.cr b/src/lib_c/arm-linux-gnueabihf/c/signal.cr index d94d657e1ca8..0113c045341c 100644 --- a/src/lib_c/arm-linux-gnueabihf/c/signal.cr +++ b/src/lib_c/arm-linux-gnueabihf/c/signal.cr @@ -77,6 +77,7 @@ lib LibC fun kill(pid : PidT, sig : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(sig : Int, handler : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -85,4 +86,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/i386-linux-gnu/c/signal.cr b/src/lib_c/i386-linux-gnu/c/signal.cr index 11aab8bfe6bb..1a5260073c2d 100644 --- a/src/lib_c/i386-linux-gnu/c/signal.cr +++ b/src/lib_c/i386-linux-gnu/c/signal.cr @@ -77,6 +77,7 @@ lib LibC fun kill(pid : PidT, sig : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(sig : Int, handler : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -85,4 +86,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/i386-linux-musl/c/signal.cr b/src/lib_c/i386-linux-musl/c/signal.cr index f2e554942b69..ac374b684c76 100644 --- a/src/lib_c/i386-linux-musl/c/signal.cr +++ b/src/lib_c/i386-linux-musl/c/signal.cr @@ -76,6 +76,7 @@ lib LibC fun kill(x0 : PidT, x1 : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(x0 : Int, x1 : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -84,4 +85,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/x86_64-darwin/c/signal.cr b/src/lib_c/x86_64-darwin/c/signal.cr index e58adc30289f..0034eef42834 100644 --- a/src/lib_c/x86_64-darwin/c/signal.cr +++ b/src/lib_c/x86_64-darwin/c/signal.cr @@ -77,6 +77,7 @@ lib LibC fun kill(x0 : PidT, x1 : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(x0 : Int, x1 : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -85,4 +86,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/x86_64-dragonfly/c/signal.cr b/src/lib_c/x86_64-dragonfly/c/signal.cr index 1751eeed3176..e362ef1fa218 100644 --- a/src/lib_c/x86_64-dragonfly/c/signal.cr +++ b/src/lib_c/x86_64-dragonfly/c/signal.cr @@ -90,6 +90,7 @@ lib LibC fun kill(x0 : PidT, x1 : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(x0 : Int, x1 : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -98,4 +99,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/x86_64-freebsd/c/signal.cr b/src/lib_c/x86_64-freebsd/c/signal.cr index fd8d07cfd4cc..c79d0630511b 100644 --- a/src/lib_c/x86_64-freebsd/c/signal.cr +++ b/src/lib_c/x86_64-freebsd/c/signal.cr @@ -8,31 +8,33 @@ lib LibC SIGILL = 4 SIGTRAP = 5 SIGIOT = LibC::SIGABRT - SIGABRT = 6 - SIGFPE = 8 - SIGKILL = 9 - SIGBUS = 10 - SIGSEGV = 11 - SIGSYS = 12 - SIGPIPE = 13 - SIGALRM = 14 - SIGTERM = 15 - SIGURG = 16 - SIGSTOP = 17 - SIGTSTP = 18 - SIGCONT = 19 - SIGCHLD = 20 - SIGTTIN = 21 - SIGTTOU = 22 - SIGIO = 23 - SIGXCPU = 24 - SIGXFSZ = 25 - SIGVTALRM = 26 - SIGUSR1 = 30 - SIGUSR2 = 31 - SIGEMT = 7 - SIGINFO = 29 - SIGWINCH = 28 + SIGABRT = 6 + SIGFPE = 8 + SIGKILL = 9 + SIGBUS = 10 + SIGSEGV = 11 + SIGSYS = 12 + SIGPIPE = 13 + SIGALRM = 14 + SIGTERM = 15 + SIGURG = 16 + SIGSTOP = 17 + SIGTSTP = 18 + SIGCONT = 19 + SIGCHLD = 20 + SIGTTIN = 21 + SIGTTOU = 22 + SIGIO = 23 + SIGXCPU = 24 + SIGXFSZ = 25 + SIGVTALRM = 26 + SIGUSR1 = 30 + SIGUSR2 = 31 + SIGEMT = 7 + SIGINFO = 29 + SIGWINCH = 28 + SIGRTMIN = 65 + SIGRTMAX = 126 SIGSTKSZ = 2048 + 32768 # MINSIGSTKSZ + 32768 SIG_SETMASK = 3 @@ -85,6 +87,7 @@ lib LibC fun kill(x0 : PidT, x1 : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(x0 : Int, x1 : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -93,4 +96,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/x86_64-linux-gnu/c/signal.cr b/src/lib_c/x86_64-linux-gnu/c/signal.cr index 07d8e0fe1ae6..b5ed2f8c8fb3 100644 --- a/src/lib_c/x86_64-linux-gnu/c/signal.cr +++ b/src/lib_c/x86_64-linux-gnu/c/signal.cr @@ -78,6 +78,7 @@ lib LibC fun kill(pid : PidT, sig : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(sig : Int, handler : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -86,4 +87,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/x86_64-linux-musl/c/signal.cr b/src/lib_c/x86_64-linux-musl/c/signal.cr index bba7e0c7c21a..42c2aead3e0f 100644 --- a/src/lib_c/x86_64-linux-musl/c/signal.cr +++ b/src/lib_c/x86_64-linux-musl/c/signal.cr @@ -77,6 +77,7 @@ lib LibC fun kill(x0 : PidT, x1 : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(x0 : Int, x1 : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -85,4 +86,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/x86_64-netbsd/c/signal.cr b/src/lib_c/x86_64-netbsd/c/signal.cr index 93d42e38b093..0b21c5c3f839 100644 --- a/src/lib_c/x86_64-netbsd/c/signal.cr +++ b/src/lib_c/x86_64-netbsd/c/signal.cr @@ -77,6 +77,7 @@ lib LibC fun kill(x0 : PidT, x1 : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(x0 : Int, x1 : Int -> Void) : Int -> Void fun sigaction = __sigaction14(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack = __sigaltstack14(x0 : StackT*, x1 : StackT*) : Int @@ -85,4 +86,5 @@ lib LibC fun sigaddset = __sigaddset14(SigsetT*, Int) : Int fun sigdelset = __sigdelset14(SigsetT*, Int) : Int fun sigismember = __sigismember14(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/x86_64-openbsd/c/signal.cr b/src/lib_c/x86_64-openbsd/c/signal.cr index 04aa27000219..1c9b86137e4a 100644 --- a/src/lib_c/x86_64-openbsd/c/signal.cr +++ b/src/lib_c/x86_64-openbsd/c/signal.cr @@ -76,6 +76,7 @@ lib LibC fun kill(x0 : PidT, x1 : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(x0 : Int, x1 : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -84,4 +85,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/x86_64-solaris/c/signal.cr b/src/lib_c/x86_64-solaris/c/signal.cr index 9bde30946054..ee502aa621e4 100644 --- a/src/lib_c/x86_64-solaris/c/signal.cr +++ b/src/lib_c/x86_64-solaris/c/signal.cr @@ -90,6 +90,7 @@ lib LibC fun kill(x0 : PidT, x1 : Int) : Int fun pthread_sigmask(Int, SigsetT*, SigsetT*) : Int + fun pthread_kill(PthreadT, Int) : Int fun signal(x0 : Int, x1 : Int -> Void) : Int -> Void fun sigaction(x0 : Int, x1 : Sigaction*, x2 : Sigaction*) : Int fun sigaltstack(x0 : StackT*, x1 : StackT*) : Int @@ -98,4 +99,5 @@ lib LibC fun sigaddset(SigsetT*, Int) : Int fun sigdelset(SigsetT*, Int) : Int fun sigismember(SigsetT*, Int) : Int + fun sigsuspend(SigsetT*) : Int end diff --git a/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr b/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr index d1e13eced324..1fcaee65a01c 100644 --- a/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr +++ b/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr @@ -59,5 +59,9 @@ lib LibC fun SwitchToThread : BOOL fun QueueUserAPC(pfnAPC : PAPCFUNC, hThread : HANDLE, dwData : ULONG_PTR) : DWORD + fun GetThreadContext(hThread : HANDLE, lpContext : CONTEXT*) : DWORD + fun ResumeThread(hThread : HANDLE) : DWORD + fun SuspendThread(hThread : HANDLE) : DWORD + PROCESS_QUERY_INFORMATION = 0x0400 end