Add Thread#native_thread_id [Feature #17853]
This commit is contained in:
parent
88e3848fca
commit
46655156dc
@ -1334,6 +1334,27 @@ q.pop
|
|||||||
assert_equal("foo", c.new {Thread.current.name}.value, bug12290)
|
assert_equal("foo", c.new {Thread.current.name}.value, bug12290)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_thread_native_thread_id
|
||||||
|
skip "don't support native_thread_id" unless (Thread.main.native_thread_id rescue nil)
|
||||||
|
assert_instance_of Integer, Thread.main.native_thread_id
|
||||||
|
|
||||||
|
th1 = Thread.start{sleep}
|
||||||
|
|
||||||
|
# newly created thread which doesn't run yet returns nil or integer
|
||||||
|
assert_include [NilClass, Integer], th1.native_thread_id.class
|
||||||
|
|
||||||
|
Thread.pass until th1.stop?
|
||||||
|
|
||||||
|
# After a thread starts (and execute `sleep`), it returns native_thread_id
|
||||||
|
assert_instance_of Integer, th1.native_thread_id
|
||||||
|
|
||||||
|
th1.wakeup
|
||||||
|
Thread.pass while th1.alive?
|
||||||
|
|
||||||
|
# dead thread returns nil
|
||||||
|
assert_nil th1.native_thread_id
|
||||||
|
end
|
||||||
|
|
||||||
def test_thread_interrupt_for_killed_thread
|
def test_thread_interrupt_for_killed_thread
|
||||||
opts = { timeout: 5, timeout_error: nil }
|
opts = { timeout: 5, timeout_error: nil }
|
||||||
|
|
||||||
|
31
thread.c
31
thread.c
@ -3402,6 +3402,36 @@ rb_thread_setname(VALUE thread, VALUE name)
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* thr.native_thread_id -> integer
|
||||||
|
*
|
||||||
|
* Return the native thread ID which is used by the Ruby thread.
|
||||||
|
*
|
||||||
|
* The ID depends on the OS. (not POSIX thread ID returned by pthread_self(3))
|
||||||
|
* * On Linux it is TID returned by gettid(2).
|
||||||
|
* * On macOS it is the system-wide unique integral ID of thread returned
|
||||||
|
* by pthread_threadid_np(3).
|
||||||
|
* * On FreeBSD it is the unique integral ID of the thread returned by
|
||||||
|
* pthread_getthreadid_np(3).
|
||||||
|
* * On Windows it is the thread identifier returned by GetThreadId().
|
||||||
|
* * On other platforms, it raises NotImplementedError.
|
||||||
|
*
|
||||||
|
* NOTE:
|
||||||
|
* If the thread is not associated yet or already deassociated with a native
|
||||||
|
* thread, it returns _nil_.
|
||||||
|
* If the Ruby implementation uses M:N thread model, the ID may change
|
||||||
|
* depending on the timing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_thread_native_thread_id(VALUE thread)
|
||||||
|
{
|
||||||
|
rb_thread_t *target_th = rb_thread_ptr(thread);
|
||||||
|
if (rb_threadptr_dead(target_th)) return Qnil;
|
||||||
|
return native_thread_native_thread_id(target_th);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* thr.to_s -> string
|
* thr.to_s -> string
|
||||||
@ -5494,6 +5524,7 @@ Init_Thread(void)
|
|||||||
|
|
||||||
rb_define_method(rb_cThread, "name", rb_thread_getname, 0);
|
rb_define_method(rb_cThread, "name", rb_thread_getname, 0);
|
||||||
rb_define_method(rb_cThread, "name=", rb_thread_setname, 1);
|
rb_define_method(rb_cThread, "name=", rb_thread_setname, 1);
|
||||||
|
rb_define_method(rb_cThread, "native_thread_id", rb_thread_native_thread_id, 0);
|
||||||
rb_define_method(rb_cThread, "to_s", rb_thread_to_s, 0);
|
rb_define_method(rb_cThread, "to_s", rb_thread_to_s, 0);
|
||||||
rb_define_alias(rb_cThread, "inspect", "to_s");
|
rb_define_alias(rb_cThread, "inspect", "to_s");
|
||||||
|
|
||||||
|
@ -34,6 +34,9 @@
|
|||||||
#if defined(__HAIKU__)
|
#if defined(__HAIKU__)
|
||||||
#include <kernel/OS.h>
|
#include <kernel/OS.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/syscall.h> /* for SYS_gettid */
|
||||||
|
#endif
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
@ -659,11 +662,26 @@ Init_native_thread(rb_thread_t *th)
|
|||||||
posix_signal(SIGVTALRM, null_func);
|
posix_signal(SIGVTALRM, null_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RB_THREAD_T_HAS_NATIVE_ID
|
||||||
|
static int
|
||||||
|
get_native_thread_id(void)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
return (int)syscall(SYS_gettid);
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
return pthread_getthreadid_np();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
native_thread_init(rb_thread_t *th)
|
native_thread_init(rb_thread_t *th)
|
||||||
{
|
{
|
||||||
native_thread_data_t *nd = &th->native_thread_data;
|
native_thread_data_t *nd = &th->native_thread_data;
|
||||||
|
|
||||||
|
#ifdef RB_THREAD_T_HAS_NATIVE_ID
|
||||||
|
th->tid = get_native_thread_id();
|
||||||
|
#endif
|
||||||
#ifdef USE_UBF_LIST
|
#ifdef USE_UBF_LIST
|
||||||
list_node_init(&nd->node.ubf);
|
list_node_init(&nd->node.ubf);
|
||||||
#endif
|
#endif
|
||||||
@ -1708,6 +1726,25 @@ native_set_another_thread_name(rb_nativethread_id_t thread_id, VALUE name)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
native_thread_native_thread_id(rb_thread_t *target_th)
|
||||||
|
{
|
||||||
|
#if !defined(RB_THREAD_T_HAS_NATIVE_ID) && !defined(__APPLE__)
|
||||||
|
rb_notimplement();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RB_THREAD_T_HAS_NATIVE_ID
|
||||||
|
int tid = target_th->tid;
|
||||||
|
if (tid == 0) return Qnil;
|
||||||
|
return INT2FIX(tid);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
uint64_t tid;
|
||||||
|
int e = pthread_threadid_np(target_th->thread_id, &tid);
|
||||||
|
if (e != 0) rb_syserr_fail(e, "pthread_threadid_np");
|
||||||
|
return ULL2NUM((unsigned long long)tid);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ubf_timer_invalidate(void)
|
ubf_timer_invalidate(void)
|
||||||
{
|
{
|
||||||
|
@ -835,6 +835,14 @@ native_set_thread_name(rb_thread_t *th)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
native_thread_native_thread_id(rb_thread_t *th)
|
||||||
|
{
|
||||||
|
DWORD tid = GetThreadId(th->thread_id);
|
||||||
|
if (tid == 0) rb_sys_fail("GetThreadId");
|
||||||
|
return ULONG2NUM(tid);
|
||||||
|
}
|
||||||
|
|
||||||
#if USE_MJIT
|
#if USE_MJIT
|
||||||
static unsigned long __stdcall
|
static unsigned long __stdcall
|
||||||
mjit_worker(void *arg)
|
mjit_worker(void *arg)
|
||||||
|
@ -942,6 +942,10 @@ struct rb_ext_config {
|
|||||||
|
|
||||||
typedef struct rb_ractor_struct rb_ractor_t;
|
typedef struct rb_ractor_struct rb_ractor_t;
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__FreeBSD__)
|
||||||
|
# define RB_THREAD_T_HAS_NATIVE_ID
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct rb_thread_struct {
|
typedef struct rb_thread_struct {
|
||||||
struct list_node lt_node; // managed by a ractor
|
struct list_node lt_node; // managed by a ractor
|
||||||
VALUE self;
|
VALUE self;
|
||||||
@ -963,6 +967,9 @@ typedef struct rb_thread_struct {
|
|||||||
rb_nativethread_id_t thread_id;
|
rb_nativethread_id_t thread_id;
|
||||||
#ifdef NON_SCALAR_THREAD_ID
|
#ifdef NON_SCALAR_THREAD_ID
|
||||||
rb_thread_id_string_t thread_id_string;
|
rb_thread_id_string_t thread_id_string;
|
||||||
|
#endif
|
||||||
|
#ifdef RB_THREAD_T_HAS_NATIVE_ID
|
||||||
|
int tid;
|
||||||
#endif
|
#endif
|
||||||
BITFIELD(enum rb_thread_status, status, 2);
|
BITFIELD(enum rb_thread_status, status, 2);
|
||||||
/* bit flags */
|
/* bit flags */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user