Hi, Please would you consider including Petr's patch in experimental uploads so that it can be more widely tested?
Thanks! 2011/9/20 Petr Salinger <petr.salin...@seznam.cz>: > Hi, > > as you might know, our eglibc pthread implementation > is still linuxthreads based. I tried to alter current > LT version to use some thread primitives from kernel. > > Instead of processes it uses kernel threads, > there is still a thread manager. > But it should fix #639658. > > The hackish patch is attached, the geting/seting > of pthread scheduler priority have to be reimplemented. > > There is no regression in our glibc testsuite on ka. > But it definitely needs more testing, on both real HW > and inside emulators. > > Please test this partial patch, upload into experimental would be nice. > > Petr -- Robert Millan
diff -u a/linuxthreads/attr.c b/linuxthreads/attr.c --- a/linuxthreads/attr.c 2006-08-17 03:23:45.000000000 +0200 +++ b/linuxthreads/attr.c 2011-09-20 17:02:25.000000000 +0200 @@ -365,11 +365,11 @@ ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); - attr->__schedpolicy = __sched_getscheduler (descr->p_pid); + attr->__schedpolicy = __sched_getscheduler (getpid()); if (attr->__schedpolicy == -1) return errno; - if (__sched_getparam (descr->p_pid, + if (__sched_getparam (getpid(), (struct sched_param *) &attr->__schedparam) != 0) return errno; diff -u a/linuxthreads/cancel.c b/linuxthreads/cancel.c --- a/linuxthreads/cancel.c 2006-08-17 03:23:45.000000000 +0200 +++ b/linuxthreads/cancel.c 2011-09-20 17:02:25.000000000 +0200 @@ -89,7 +89,7 @@ int pthread_cancel(pthread_t thread) { pthread_handle handle = thread_handle(thread); - int pid; + long ktid; int dorestart = 0; pthread_descr th; pthread_extricate_if *pextricate; @@ -112,7 +112,7 @@ } pextricate = th->p_extricate; - pid = th->p_pid; + ktid = th->p_ktid; /* If the thread has registered an extrication interface, then invoke the interface. If it returns 1, then we succeeded in @@ -139,7 +139,7 @@ if (dorestart) restart(th); else - kill(pid, __pthread_sig_cancel); + __thr_kill(ktid, __pthread_sig_cancel); return 0; } diff -u a/linuxthreads/descr.h b/linuxthreads/descr.h --- a/linuxthreads/descr.h 2011-09-20 19:38:20.000000000 +0200 +++ b/linuxthreads/descr.h 2011-09-20 17:44:58.000000000 +0200 @@ -26,6 +26,42 @@ #include <lowlevellock.h> #include <tls.h> + +extern long int syscall (long int __sysno, ...); +#include <sys/syscall.h> +// should be in <sys/thr.h> +struct rtprio; +struct thr_param { + void (*start_func)(void *); /* thread entry function. */ + void *arg; /* argument for entry function. */ + char *stack_base; /* stack base address. */ + size_t stack_size; /* stack size. */ + char *tls_base; /* tls base address. */ + size_t tls_size; /* tls size. */ + long *child_tid; /* address to store new TID. */ + long *parent_tid; /* parent accesses the new TID here. */ + int flags; /* thread flags. */ + struct rtprio *rtp; /* Real-time scheduling priority */ + void *spare[3]; /* TODO: cpu affinity mask etc. */ +}; + +#define KTID_TERMINATED 1 +static inline int __thr_self(long *ktid) +{ return syscall(SYS_thr_self, ktid);}; + +static inline int __thr_kill(long ktid, int signo) +{ return syscall(SYS_thr_kill, ktid, signo);}; + +static inline int __thr_exit(long *ktid) // also *ktid = KTID_TERMINATED, wakeup(ktid) +{ return syscall(SYS_thr_exit, ktid);}; // returns only for last thread in process + +static inline int __thr_new(struct thr_param *param, int param_size) +{ return syscall(SYS_thr_new, param, param_size);}; + +static inline int __lll_wait(long *addr, long val) +{ return syscall(SYS__umtx_op, addr, UMTX_OP_WAIT, val, NULL, NULL);}; + + /* Fast thread-specific data internal to libc. */ enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0, _LIBC_TSD_KEY_DL_ERROR, @@ -202,6 +238,8 @@ size_t p_alloca_cutoff; /* Maximum size which should be allocated using alloca() instead of malloc(). */ /* New elements must be added at the end. */ + long p_ktid; /* kernel thread ID */ + /* This member must be last. */ char end_padding[]; diff -u a/linuxthreads/join.c b/linuxthreads/join.c --- a/linuxthreads/join.c 2006-08-17 03:23:45.000000000 +0200 +++ b/linuxthreads/join.c 2011-09-20 17:02:25.000000000 +0200 @@ -89,6 +89,9 @@ } /* Threads other than the main one terminate without flushing stdio streams or running atexit functions. */ + + __thr_kill(__manager_thread->p_ktid, __pthread_sig_cancel); + __thr_exit(&(self->p_ktid)); _exit(0); } diff -u a/linuxthreads/manager.c b/linuxthreads/manager.c --- a/linuxthreads/manager.c 2006-08-17 03:23:45.000000000 +0200 +++ b/linuxthreads/manager.c 2011-09-20 19:04:23.000000000 +0200 @@ -151,13 +151,16 @@ while(1) { n = __poll(&ufd, 1, 2000); +#if 0 + /* iff the main thread terminated abnormally, the signal should kill all threads already */ /* Check for termination of the main thread */ if (getppid() == 1) { pthread_kill_all_threads(SIGKILL, 0); _exit(0); } +#endif /* Check for dead children */ - if (terminated_children) { + if (terminated_children || main_thread_exiting) { terminated_children = 0; pthread_reap_children(); } @@ -182,7 +185,7 @@ request.req_args.create.fn, request.req_args.create.arg, &request.req_args.create.mask, - request.req_thread->p_pid, + request.req_thread->p_ktid, request.req_thread->p_report_events, &request.req_thread->p_eventbuf.eventmask); restart(request.req_thread); @@ -271,10 +274,13 @@ #endif /* Make sure our pid field is initialized, just in case we get there before our father has initialized it. */ - THREAD_SETMEM(self, p_pid, __getpid()); + // done in kernel + // __thr_self(&ktid); + // THREAD_SETMEM(self, p_ktid, ktid); /* Initial signal mask is that of the creating thread. (Otherwise, we'd just inherit the mask of the thread manager.) */ sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL); +#if 0 /* Set the scheduling policy and priority for the new thread, if needed */ if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0) /* Explicit scheduling attributes were provided: apply them */ @@ -290,6 +296,7 @@ __sched_setscheduler(THREAD_GETMEM(self, p_pid), SCHED_OTHER, &default_params); } +#endif #if !(USE_TLS && HAVE___THREAD) /* Initialize thread-locale current locale to point to the global one. With __thread support, the variable's initializer takes care of this. */ @@ -324,7 +331,9 @@ #endif /* Make sure our pid field is initialized, just in case we get there before our father has initialized it. */ - THREAD_SETMEM(self, p_pid, __getpid()); + // done in kernel + // __thr_self(&ktid); + // THREAD_SETMEM(self, p_ktid, ktid); /* Get the lock the manager will free once all is correctly set up. */ __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); /* Free it immediately. */ @@ -586,7 +595,7 @@ td_thr_events_t *event_maskp) { size_t sseg; - int pid; + int rv; pthread_descr new_thread; char *stack_addr; char * new_thread_bottom; @@ -595,6 +604,7 @@ size_t guardsize = 0, stksize = 0; int pagesize = __getpagesize(); int saved_errno = 0; + struct thr_param p; #ifdef USE_TLS new_thread = _dl_allocate_tls (NULL); @@ -690,6 +700,7 @@ new_thread->p_detached = attr->__detachstate; new_thread->p_userstack = attr->__stackaddr_set; +#if 0 switch(attr->__inheritsched) { case PTHREAD_EXPLICIT_SCHED: new_thread->p_start_args.schedpolicy = attr->__schedpolicy; @@ -702,6 +713,7 @@ __sched_getparam(father_pid, &new_thread->p_start_args.schedparam); break; } +#endif new_thread->p_priority = new_thread->p_start_args.schedparam.sched_priority; } @@ -717,7 +729,7 @@ __pthread_manager_adjust_prio(new_thread->p_priority); /* Do the cloning. We have to use two different functions depending on whether we are debugging or not. */ - pid = 0; /* Note that the thread never can have PID zero. */ + rv = 0; if (report_events) { /* See whether the TD_CREATE event bit is set in any of the @@ -733,30 +745,22 @@ /* We have to report this event. */ #ifdef NEED_SEPARATE_REGISTER_STACK - /* Perhaps this version should be used on all platforms. But - this requires that __clone2 be uniformly supported - everywhere. - - And there is some argument for changing the __clone2 - interface to pass sp and bsp instead, making it more IA64 - specific, but allowing stacks to grow outward from each - other, to get less paging and fewer mmaps. */ - pid = __clone2(pthread_start_thread_event, - (void **)new_thread_bottom, - (char *)stack_addr - new_thread_bottom, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | - __pthread_sig_cancel, new_thread); +#error unimplemented SEPARATE_REGISTER_STACK #elif _STACK_GROWS_UP - pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | - __pthread_sig_cancel, new_thread); +#error unimplemented _STACK_GROWS_UP #else - pid = __clone(pthread_start_thread_event, stack_addr, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | - __pthread_sig_cancel, new_thread); + memset(&p, 0, sizeof(p)); + p.start_func = pthread_start_thread_event; + p.arg = new_thread; + p.stack_base = new_thread_bottom; + p.stack_size = stack_addr - new_thread_bottom; + p.tls_base = new_thread; + p.child_tid = &(new_thread->p_ktid); + + rv = __thr_new(&p, sizeof(p)); #endif saved_errno = errno; - if (pid != -1) + if (rv != -1) { /* Now fill in the information about the new thread in the newly created thread's data structure. We cannot let @@ -769,7 +773,7 @@ /* We have to set the PID here since the callback function in the debug library will need it and we cannot guarantee the child got scheduled before the debugger. */ - new_thread->p_pid = pid; + // kernel already done that /* Now call the function which signals the event. */ __linuxthreads_create_event (); @@ -779,27 +783,31 @@ } } } - if (pid == 0) + + if (rv == 0) { #ifdef NEED_SEPARATE_REGISTER_STACK - pid = __clone2(pthread_start_thread, - (void **)new_thread_bottom, - (char *)stack_addr - new_thread_bottom, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | - __pthread_sig_cancel, new_thread); +#error unimplemented SEPARATE_REGISTER_STACK #elif _STACK_GROWS_UP - pid = __clone(pthread_start_thread, (void *) new_thread_bottom, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | - __pthread_sig_cancel, new_thread); +#error unimplemented _STACK_GROWS_UP #else - pid = __clone(pthread_start_thread, stack_addr, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | - __pthread_sig_cancel, new_thread); + + memset(&p, 0, sizeof(p)); + p.start_func = pthread_start_thread; + p.arg = new_thread; + p.stack_base = new_thread_bottom; + p.stack_size = stack_addr - new_thread_bottom; + p.tls_base = new_thread; + p.child_tid = &(new_thread->p_ktid); + + rv = __thr_new(&p, sizeof(p)); + #endif /* !NEED_SEPARATE_REGISTER_STACK */ saved_errno = errno; } + /* Check if cloning succeeded */ - if (pid == -1) { + if (rv == -1) { /* Free the stack if we allocated it */ if (attr == NULL || !attr->__stackaddr_set) { @@ -843,7 +851,7 @@ __pthread_main_thread->p_nextlive = new_thread; /* Set pid field of the new thread, in case we get there before the child starts. */ - new_thread->p_pid = pid; + // kernel already done that return 0; } @@ -928,17 +936,18 @@ /* Handle threads that have exited */ -static void pthread_exited(pid_t pid) +static void pthread_reap_children(void) { - pthread_descr th; + pthread_descr th, tth; int detached; + /* Find thread with that pid */ for (th = __pthread_main_thread->p_nextlive; th != __pthread_main_thread; th = th->p_nextlive) { - if (th->p_pid == pid) { + if (th->p_ktid == KTID_TERMINATED) { /* Remove thread from list of active threads */ - th->p_nextlive->p_prevlive = th->p_prevlive; + tth = th->p_nextlive->p_prevlive = th->p_prevlive; th->p_prevlive->p_nextlive = th->p_nextlive; /* Mark thread as exited, and if detached, free its resources */ __pthread_lock(th->p_lock, NULL); @@ -966,7 +975,7 @@ __pthread_unlock(th->p_lock); if (detached) pthread_free(th); - break; + th = tth; } } /* If all threads have exited and the main thread is pending on a @@ -978,22 +987,6 @@ } } -static void pthread_reap_children(void) -{ - pid_t pid; - int status; - - while ((pid = waitpid_not_cancel(-1, &status, WNOHANG | __WCLONE)) > 0) { - pthread_exited(pid); - if (WIFSIGNALED(status)) { - /* If a thread died due to a signal, send the same signal to - all other threads, including the main thread. */ - pthread_kill_all_threads(WTERMSIG(status), 1); - _exit(0); - } - } -} - /* Try to free the resources of a thread when requested by pthread_join or pthread_detach on a terminated thread. */ @@ -1030,10 +1023,10 @@ for (th = __pthread_main_thread->p_nextlive; th != __pthread_main_thread; th = th->p_nextlive) { - kill(th->p_pid, sig); + __thr_kill(th->p_ktid, sig); } if (main_thread_also) { - kill(__pthread_main_thread->p_pid, sig); + __thr_kill(__pthread_main_thread->p_ktid, sig); } } @@ -1071,18 +1064,24 @@ for (th = issuing_thread->p_nextlive; th != issuing_thread; th = th->p_nextlive) { - kill(th->p_pid, __pthread_sig_cancel); + __thr_kill(th->p_ktid, __pthread_sig_cancel); } /* Now, wait for all these threads, so that they don't become zombies and their times are properly added to the thread manager's times. */ for (th = issuing_thread->p_nextlive; th != issuing_thread; th = th->p_nextlive) { - waitpid(th->p_pid, NULL, __WCLONE); + if (th == __pthread_main_thread) // it waits for thread manager + continue; + long ktid; + while (KTID_TERMINATED != (ktid = th->p_ktid)) + __lll_wait(&(th->p_ktid), ktid); } __fresetlockfiles(); restart(issuing_thread); - _exit(0); + __thr_exit(&(manager_thread->p_ktid)); + // should not return */ + _exit(__pthread_exit_code); } /* Handler for __pthread_sig_cancel in thread manager thread */ @@ -1114,11 +1113,12 @@ void __pthread_manager_adjust_prio(int thread_prio) { struct sched_param param; - +#if 0 if (thread_prio <= manager_thread->p_priority) return; param.sched_priority = thread_prio < __sched_get_priority_max(SCHED_FIFO) ? thread_prio + 1 : thread_prio; __sched_setscheduler(manager_thread->p_pid, SCHED_FIFO, ¶m); manager_thread->p_priority = thread_prio; +#endif } diff -u a/linuxthreads/pthread.c b/linuxthreads/pthread.c --- a/linuxthreads/pthread.c 2011-09-20 19:38:19.000000000 +0200 +++ b/linuxthreads/pthread.c 2011-09-20 17:28:00.000000000 +0200 @@ -520,6 +522,7 @@ { struct sigaction sa; sigset_t mask; + long ktid; /* If already done (e.g. by a constructor called earlier!), bail out */ if (__pthread_initial_thread_bos != NULL) return; @@ -548,14 +551,16 @@ #endif #ifdef USE_TLS /* Update the descriptor for the initial thread. */ - THREAD_SETMEM (((pthread_descr) NULL), p_pid, __getpid()); + __thr_self(&ktid); + THREAD_SETMEM (((pthread_descr) NULL), p_ktid, ktid); # ifndef HAVE___THREAD /* Likewise for the resolver state _res. */ THREAD_SETMEM (((pthread_descr) NULL), p_resp, &_res); # endif #else /* Update the descriptor for the initial thread. */ - __pthread_initial_thread.p_pid = __getpid(); + __thr_self(&ktid); + __pthread_initial_thread.p_ktid = ktid; /* Likewise for the resolver state _res. */ __pthread_initial_thread.p_resp = &_res; #endif @@ -629,7 +634,8 @@ int __pthread_initialize_manager(void) { int manager_pipe[2]; - int pid; + int rv; + struct thr_param p; struct pthread_request request; int report_events; pthread_descr mgr; @@ -743,7 +749,7 @@ __pthread_manager_reader = manager_pipe[0]; /* reading end */ /* Start the thread manager */ - pid = 0; + rv = 0; #ifdef USE_TLS if (__linuxthreads_initial_report_events != 0) THREAD_SETMEM (((pthread_descr) NULL), p_report_events, @@ -776,24 +782,22 @@ __pthread_lock(mgr->p_lock, NULL); #ifdef NEED_SEPARATE_REGISTER_STACK - pid = __clone2(__pthread_manager_event, - (void **) __pthread_manager_thread_bos, - THREAD_MANAGER_STACK_SIZE, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, - mgr); +#error unimplemented SEPARATE_REGISTER_STACK #elif _STACK_GROWS_UP - pid = __clone(__pthread_manager_event, - (void **) __pthread_manager_thread_bos, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, - mgr); +#error unimplemented STACK_GROWS_UP #else - pid = __clone(__pthread_manager_event, - (void **) __pthread_manager_thread_tos, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, - mgr); + memset(&p, 0, sizeof(p)); + p.start_func = __pthread_manager_event; + p.arg = mgr; + p.stack_base = __pthread_manager_thread_bos; + p.stack_size = __pthread_manager_thread_tos - __pthread_manager_thread_bos; + p.tls_base = mgr; + p.child_tid = &(mgr->p_ktid); + + rv = __thr_new(&p, sizeof(p)); #endif - if (pid != -1) + if (rv != -1) { /* Now fill in the information about the new thread in the newly created thread's data structure. We cannot let @@ -803,7 +807,6 @@ mgr->p_eventbuf.eventnum = TD_CREATE; __pthread_last_event = mgr; mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1; - mgr->p_pid = pid; /* Now call the function which signals the event. */ __linuxthreads_create_event (); @@ -814,21 +817,26 @@ } } - if (__builtin_expect (pid, 0) == 0) + if (__builtin_expect (rv, 0) == 0) { + #ifdef NEED_SEPARATE_REGISTER_STACK - pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos, - THREAD_MANAGER_STACK_SIZE, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr); +#error unimplemented SEPARATE_REGISTER_STACK #elif _STACK_GROWS_UP - pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr); +#error unimplemented STACK_GROWS_UP #else - pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr); + memset(&p, 0, sizeof(p)); + p.start_func = __pthread_manager; + p.arg = mgr; + p.stack_base = __pthread_manager_thread_bos; + p.stack_size = __pthread_manager_thread_tos - __pthread_manager_thread_bos; + p.tls_base = mgr; + p.child_tid = &(mgr->p_ktid); + + rv = __thr_new(&p, sizeof(p)); #endif } - if (__builtin_expect (pid, 0) == -1) { + if (__builtin_expect (rv, 0) == -1) { #ifdef USE_TLS _dl_deallocate_tls (tcbp, true); #endif @@ -838,7 +846,6 @@ return -1; } mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1; - mgr->p_pid = pid; /* Make gdb aware of new thread manager */ if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0) { @@ -998,7 +1005,7 @@ return ESRCH; } th = handle->h_descr; - if (__builtin_expect (__sched_setscheduler(th->p_pid, policy, param) == -1, + if (__builtin_expect (__sched_setscheduler(getpid(), policy, param) == -1, 0)) { __pthread_unlock(&handle->h_lock); return errno; @@ -1022,7 +1029,7 @@ __pthread_unlock(&handle->h_lock); return ESRCH; } - pid = handle->h_descr->p_pid; + pid = getpid(); __pthread_unlock(&handle->h_lock); pol = __sched_getscheduler(pid); if (__builtin_expect (pol, 0) == -1) return errno; @@ -1062,9 +1069,11 @@ if (self == __pthread_main_thread) { #ifdef USE_TLS - waitpid(manager_thread->p_pid, NULL, __WCLONE); + long ktid; + while (KTID_TERMINATED != (ktid = manager_thread->p_ktid)) + __lll_wait(&(manager_thread->p_ktid), ktid); #else - waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#error TLS required #endif /* Since all threads have been asynchronously terminated (possibly holding locks), free cannot be used any more. @@ -1128,9 +1137,11 @@ children, so that timings for main thread account for all threads. */ if (self == __pthread_main_thread) { #ifdef USE_TLS - waitpid(manager_thread->p_pid, NULL, __WCLONE); + long ktid; + while (KTID_TERMINATED != (ktid = manager_thread->p_ktid)) + __lll_wait(&(manager_thread->p_ktid), ktid); #else - waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#error TLS required #endif } _exit(__pthread_exit_code); @@ -1170,6 +1181,7 @@ void __pthread_reset_main_thread(void) { + long ktid; pthread_descr self = thread_self(); if (__pthread_manager_request != -1) { @@ -1183,7 +1195,8 @@ } /* Update the pid of the main thread */ - THREAD_SETMEM(self, p_pid, __getpid()); + __thr_self(&ktid); + THREAD_SETMEM(self, p_ktid, ktid); /* Make the forked thread the main thread */ __pthread_main_thread = self; THREAD_SETMEM(self, p_nextlive, self); @@ -1289,7 +1302,7 @@ void __pthread_restart_old(pthread_descr th) { if (pthread_atomic_increment(&th->p_resume_count) == -1) - kill(th->p_pid, __pthread_sig_restart); + __thr_kill(th->p_ktid, __pthread_sig_restart); } void __pthread_suspend_old(pthread_descr self) @@ -1383,7 +1396,7 @@ memory so the woken thread will have a consistent view. Complementary read barriers are present to the suspend functions. */ WRITE_MEMORY_BARRIER(); - kill(th->p_pid, __pthread_sig_restart); + __thr_kill(th->p_ktid, __pthread_sig_restart); } /* There is no __pthread_suspend_new because it would just diff -u a/linuxthreads/signals.c b/linuxthreads/signals.c --- a/linuxthreads/signals.c 2011-09-20 19:38:19.000000000 +0200 +++ b/linuxthreads/signals.c 2011-09-20 17:02:25.000000000 +0200 @@ -57,16 +57,16 @@ int pthread_kill(pthread_t thread, int signo) { pthread_handle handle = thread_handle(thread); - int pid; + long ktid; __pthread_lock(&handle->h_lock, NULL); if (invalid_handle(handle, thread)) { __pthread_unlock(&handle->h_lock); return ESRCH; } - pid = handle->h_descr->p_pid; + ktid = handle->h_descr->p_ktid; __pthread_unlock(&handle->h_lock); - if (kill(pid, signo) == -1) + if (__thr_kill(ktid, signo) == -1) return errno; else return 0;