VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/thread-posix.cpp@ 90392

Last change on this file since 90392 was 90392, checked in by vboxsync, 3 years ago

IPRT/RTThreadCreate: Added RTTHREADFLAGS_NO_SIGNALS (posix only). bugref:6695

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 22.6 KB
Line 
1/* $Id: thread-posix.cpp 90392 2021-07-29 08:25:50Z vboxsync $ */
2/** @file
3 * IPRT - Threads, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_THREAD
32#include <errno.h>
33#include <pthread.h>
34#include <signal.h>
35#include <stdlib.h>
36#if defined(RT_OS_LINUX)
37# include <unistd.h>
38# include <sys/syscall.h>
39#endif
40#if defined(RT_OS_SOLARIS)
41# include <sched.h>
42# include <sys/resource.h>
43#endif
44#if defined(RT_OS_DARWIN)
45# include <mach/thread_act.h>
46# include <mach/thread_info.h>
47# include <mach/host_info.h>
48# include <mach/mach_init.h>
49# include <mach/mach_host.h>
50#endif
51#if defined(RT_OS_DARWIN) /*|| defined(RT_OS_FREEBSD) - later */ \
52 || (defined(RT_OS_LINUX) && !defined(IN_RT_STATIC) /* static + dlsym = trouble */) \
53 || defined(IPRT_MAY_HAVE_PTHREAD_SET_NAME_NP)
54# define IPRT_MAY_HAVE_PTHREAD_SET_NAME_NP
55# include <dlfcn.h>
56#endif
57#if defined(RT_OS_HAIKU)
58# include <OS.h>
59#endif
60
61#include <iprt/thread.h>
62#include <iprt/log.h>
63#include <iprt/assert.h>
64#include <iprt/asm.h>
65#include <iprt/err.h>
66#include <iprt/initterm.h>
67#include <iprt/string.h>
68#include <iprt/semaphore.h>
69#include <iprt/list.h>
70#include <iprt/once.h>
71#include <iprt/critsect.h>
72#include <iprt/req.h>
73#include "internal/thread.h"
74
75
76/*********************************************************************************************************************************
77* Defined Constants And Macros *
78*********************************************************************************************************************************/
79/*#ifndef IN_GUEST - shouldn't need to exclude this now with the non-obtrusive init option. */
80/** Includes RTThreadPoke. */
81# define RTTHREAD_POSIX_WITH_POKE
82/*#endif*/
83
84
85/*********************************************************************************************************************************
86* Global Variables *
87*********************************************************************************************************************************/
88/** The pthread key in which we store the pointer to our own PRTTHREAD structure. */
89static pthread_key_t g_SelfKey;
90#ifdef RTTHREAD_POSIX_WITH_POKE
91/** The signal we use for poking threads.
92 * This is set to -1 if no available signal was found. */
93static int volatile g_iSigPokeThread = -1;
94#endif
95
96#ifdef IPRT_MAY_HAVE_PTHREAD_SET_NAME_NP
97# if defined(RT_OS_DARWIN)
98/**
99 * The Mac OS X (10.6 and later) variant of pthread_setname_np.
100 *
101 * @returns errno.h
102 * @param pszName The new thread name.
103 */
104typedef int (*PFNPTHREADSETNAME)(const char *pszName);
105# else
106/**
107 * The variant of pthread_setname_np most other unix-like systems implement.
108 *
109 * @returns errno.h
110 * @param hThread The thread.
111 * @param pszName The new thread name.
112 */
113typedef int (*PFNPTHREADSETNAME)(pthread_t hThread, const char *pszName);
114# endif
115
116/** Pointer to pthread_setname_np if found. */
117static PFNPTHREADSETNAME g_pfnThreadSetName = NULL;
118#endif /* IPRT_MAY_HAVE_PTHREAD_SET_NAME_NP */
119
120#ifdef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY
121/** Atomic indicator of whether the priority proxy thread has been (attempted) started.
122 *
123 * The priority proxy thread is started under these circumstances:
124 * - RTThreadCreate
125 * - RTThreadSetType
126 * - RTProcSetPriority
127 *
128 * Which means that we'll be single threaded when this is modified.
129 *
130 * Speical values:
131 * - VERR_TRY_AGAIN: Not yet started.
132 * - VERR_WRONG_ORDER: Starting.
133 * - VINF_SUCCESS: Started successfully.
134 * - VERR_PROCESS_NOT_FOUND: Stopping or stopped
135 * - Other error status if failed to start.
136 *
137 * @note We could potentially optimize this by only start it when we lower the
138 * priority of ourselves, the process, or a newly created thread. But
139 * that would means we would need to take multi-threading into account, so
140 * let's not do that for now.
141 */
142static int32_t volatile g_rcPriorityProxyThreadStart = VERR_TRY_AGAIN;
143/** The IPRT thread handle for the priority proxy. */
144static RTTHREAD g_hRTThreadPosixPriorityProxyThread = NIL_RTTHREAD;
145/** The priority proxy queue. */
146static RTREQQUEUE g_hRTThreadPosixPriorityProxyQueue = NIL_RTREQQUEUE;
147#endif /* RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY */
148
149
150/*********************************************************************************************************************************
151* Internal Functions *
152*********************************************************************************************************************************/
153static void *rtThreadNativeMain(void *pvArgs);
154static void rtThreadKeyDestruct(void *pvValue);
155#ifdef RTTHREAD_POSIX_WITH_POKE
156static void rtThreadPosixPokeSignal(int iSignal);
157#endif
158
159
160#ifdef RTTHREAD_POSIX_WITH_POKE
161/**
162 * Try register the dummy signal handler for RTThreadPoke.
163 */
164static void rtThreadPosixSelectPokeSignal(void)
165{
166 /*
167 * Note! Avoid SIGRTMIN thru SIGRTMIN+2 because of LinuxThreads.
168 */
169# if !defined(RT_OS_LINUX) && !defined(RT_OS_SOLARIS) /* glibc defines SIGRTMAX to __libc_current_sigrtmax() and Solaris libc defines it relying on _sysconf(), causing compiler to deploy serialization here. */
170 static
171# endif
172 const int s_aiSigCandidates[] =
173 {
174# ifdef SIGRTMAX
175 SIGRTMAX-3,
176 SIGRTMAX-2,
177 SIGRTMAX-1,
178# endif
179# ifndef RT_OS_SOLARIS
180 SIGUSR2,
181# endif
182 SIGWINCH
183 };
184
185 g_iSigPokeThread = -1;
186 if (!RTR3InitIsUnobtrusive())
187 {
188 for (unsigned iSig = 0; iSig < RT_ELEMENTS(s_aiSigCandidates); iSig++)
189 {
190 struct sigaction SigActOld;
191 if (!sigaction(s_aiSigCandidates[iSig], NULL, &SigActOld))
192 {
193 if ( SigActOld.sa_handler == SIG_DFL
194 || SigActOld.sa_handler == rtThreadPosixPokeSignal)
195 {
196 struct sigaction SigAct;
197 RT_ZERO(SigAct);
198 SigAct.sa_handler = rtThreadPosixPokeSignal;
199 SigAct.sa_flags = 0; /* no SA_RESTART! */
200 sigfillset(&SigAct.sa_mask);
201
202 /* ASSUMES no sigaction race... (lazy bird) */
203 if (!sigaction(s_aiSigCandidates[iSig], &SigAct, NULL))
204 {
205 g_iSigPokeThread = s_aiSigCandidates[iSig];
206 break;
207 }
208 AssertMsgFailed(("rc=%Rrc errno=%d\n", RTErrConvertFromErrno(errno), errno));
209 }
210 }
211 else
212 AssertMsgFailed(("rc=%Rrc errno=%d\n", RTErrConvertFromErrno(errno), errno));
213 }
214 }
215}
216#endif /* RTTHREAD_POSIX_WITH_POKE */
217
218
219DECLHIDDEN(int) rtThreadNativeInit(void)
220{
221 /*
222 * Allocate the TLS (key in posix terms) where we store the pointer to
223 * a threads RTTHREADINT structure.
224 */
225 int rc = pthread_key_create(&g_SelfKey, rtThreadKeyDestruct);
226 if (rc)
227 return VERR_NO_TLS_FOR_SELF;
228
229#ifdef RTTHREAD_POSIX_WITH_POKE
230 rtThreadPosixSelectPokeSignal();
231#endif
232
233#ifdef IPRT_MAY_HAVE_PTHREAD_SET_NAME_NP
234 if (RT_SUCCESS(rc))
235 g_pfnThreadSetName = (PFNPTHREADSETNAME)(uintptr_t)dlsym(RTLD_DEFAULT, "pthread_setname_np");
236#endif
237 return rc;
238}
239
240static void rtThreadPosixBlockSignals(PRTTHREADINT pThread)
241{
242 /*
243 * Mask all signals, including the poke one, if requested.
244 */
245 if ( pThread
246 && (pThread->fFlags & RTTHREADFLAGS_NO_SIGNALS))
247 {
248 sigset_t SigSet;
249 sigfillset(&SigSet);
250 int rc = sigprocmask(SIG_BLOCK, &SigSet, NULL);
251 AssertMsg(rc == 0, ("rc=%Rrc errno=%d\n", RTErrConvertFromErrno(errno), errno)); RT_NOREF(rc);
252 }
253 /*
254 * Block SIGALRM - required for timer-posix.cpp.
255 * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling.
256 * It will not help much if someone creates threads directly using pthread_create. :/
257 */
258 else if (!RTR3InitIsUnobtrusive())
259 {
260 sigset_t SigSet;
261 sigemptyset(&SigSet);
262 sigaddset(&SigSet, SIGALRM);
263 sigprocmask(SIG_BLOCK, &SigSet, NULL);
264 }
265
266#ifdef RTTHREAD_POSIX_WITH_POKE
267 /*
268 * bird 2020-10-28: Not entirely sure why we do this, but it makes sure the signal works
269 * on the new thread. Probably some pre-NPTL linux reasons.
270 */
271 if (g_iSigPokeThread != -1)
272 {
273# if 1 /* siginterrupt() is typically implemented as two sigaction calls, this should be faster and w/o deprecations: */
274 struct sigaction SigActOld;
275 RT_ZERO(SigActOld);
276
277 struct sigaction SigAct;
278 RT_ZERO(SigAct);
279 SigAct.sa_handler = rtThreadPosixPokeSignal;
280 SigAct.sa_flags = 0; /* no SA_RESTART! */
281 sigfillset(&SigAct.sa_mask);
282
283 int rc = sigaction(g_iSigPokeThread, &SigAct, &SigActOld);
284 AssertMsg(rc == 0, ("rc=%Rrc errno=%d\n", RTErrConvertFromErrno(errno), errno)); RT_NOREF(rc);
285 AssertMsg(rc || SigActOld.sa_handler == rtThreadPosixPokeSignal, ("%p\n", SigActOld.sa_handler));
286# else
287 siginterrupt(g_iSigPokeThread, 1);
288# endif
289 }
290#endif
291}
292
293DECLHIDDEN(void) rtThreadNativeReInitObtrusive(void)
294{
295#ifdef RTTHREAD_POSIX_WITH_POKE
296 Assert(!RTR3InitIsUnobtrusive());
297 rtThreadPosixSelectPokeSignal();
298#endif
299 rtThreadPosixBlockSignals(NULL);
300}
301
302
303/**
304 * Destructor called when a thread terminates.
305 * @param pvValue The key value. PRTTHREAD in our case.
306 */
307static void rtThreadKeyDestruct(void *pvValue)
308{
309 /*
310 * Deal with alien threads.
311 */
312 PRTTHREADINT pThread = (PRTTHREADINT)pvValue;
313 if (pThread->fIntFlags & RTTHREADINT_FLAGS_ALIEN)
314 {
315 pthread_setspecific(g_SelfKey, pThread);
316 rtThreadTerminate(pThread, 0);
317 pthread_setspecific(g_SelfKey, NULL);
318 }
319}
320
321
322#ifdef RTTHREAD_POSIX_WITH_POKE
323/**
324 * Dummy signal handler for the poke signal.
325 *
326 * @param iSignal The signal number.
327 */
328static void rtThreadPosixPokeSignal(int iSignal)
329{
330 Assert(iSignal == g_iSigPokeThread);
331 NOREF(iSignal);
332}
333#endif
334
335
336/**
337 * Adopts a thread, this is called immediately after allocating the
338 * thread structure.
339 *
340 * @param pThread Pointer to the thread structure.
341 */
342DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
343{
344 rtThreadPosixBlockSignals(pThread);
345
346 int rc = pthread_setspecific(g_SelfKey, pThread);
347 if (!rc)
348 return VINF_SUCCESS;
349 return VERR_FAILED_TO_SET_SELF_TLS;
350}
351
352
353DECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread)
354{
355 if (pThread == (PRTTHREADINT)pthread_getspecific(g_SelfKey))
356 pthread_setspecific(g_SelfKey, NULL);
357}
358
359
360/**
361 * Wrapper which unpacks the params and calls thread function.
362 */
363static void *rtThreadNativeMain(void *pvArgs)
364{
365 PRTTHREADINT pThread = (PRTTHREADINT)pvArgs;
366 pthread_t Self = pthread_self();
367#if !defined(RT_OS_SOLARIS) /* On Solaris sizeof(pthread_t) = 4 and sizeof(NIL_RTNATIVETHREAD) = 8 */
368 Assert((uintptr_t)Self != NIL_RTNATIVETHREAD);
369#endif
370 Assert(Self == (pthread_t)(RTNATIVETHREAD)Self);
371
372#if defined(RT_OS_LINUX)
373 /*
374 * Set the TID.
375 */
376 pThread->tid = syscall(__NR_gettid);
377 ASMMemoryFence();
378#endif
379
380 rtThreadPosixBlockSignals(pThread);
381
382 /*
383 * Set the TLS entry and, if possible, the thread name.
384 */
385 int rc = pthread_setspecific(g_SelfKey, pThread);
386 AssertReleaseMsg(!rc, ("failed to set self TLS. rc=%d thread '%s'\n", rc, pThread->szName));
387
388#ifdef IPRT_MAY_HAVE_PTHREAD_SET_NAME_NP
389 if (g_pfnThreadSetName)
390# ifdef RT_OS_DARWIN
391 g_pfnThreadSetName(pThread->szName);
392# else
393 g_pfnThreadSetName(Self, pThread->szName);
394# endif
395#endif
396
397 /*
398 * Call common main.
399 */
400 rc = rtThreadMain(pThread, (uintptr_t)Self, &pThread->szName[0]);
401
402 pthread_setspecific(g_SelfKey, NULL);
403 pthread_exit((void *)(intptr_t)rc);
404 return (void *)(intptr_t)rc;
405}
406
407#ifdef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY
408
409/**
410 * @callback_method_impl{FNRTTHREAD,
411 * Priority proxy thread that services g_hRTThreadPosixPriorityProxyQueue.}
412 */
413static DECLCALLBACK(int) rtThreadPosixPriorityProxyThread(PRTTHREADINT, void *)
414{
415 for (;;)
416 {
417 RTREQQUEUE hReqQueue = g_hRTThreadPosixPriorityProxyQueue;
418 if (hReqQueue != NIL_RTREQQUEUE)
419 RTReqQueueProcess(hReqQueue, RT_INDEFINITE_WAIT);
420 else
421 break;
422
423 int32_t rc = ASMAtomicUoReadS32(&g_rcPriorityProxyThreadStart);
424 if (rc != VINF_SUCCESS && rc != VERR_WRONG_ORDER)
425 break;
426 }
427
428 return VINF_SUCCESS;
429}
430
431
432/**
433 * Just returns a non-success status codes to force the thread to re-evaluate
434 * the global shutdown variable.
435 */
436static DECLCALLBACK(int) rtThreadPosixPriorityProxyStopper(void)
437{
438 return VERR_CANCELLED;
439}
440
441
442/**
443 * An atexit() callback that stops the proxy creation/priority thread.
444 */
445static void rtThreadStopProxyThread(void)
446{
447 /*
448 * Signal to the thread that it's time to shut down.
449 */
450 int32_t rc = ASMAtomicXchgS32(&g_rcPriorityProxyThreadStart, VERR_PROCESS_NOT_FOUND);
451 if (RT_SUCCESS(rc))
452 {
453 /*
454 * Grab the associated handles.
455 */
456 RTTHREAD hThread = g_hRTThreadPosixPriorityProxyThread;
457 RTREQQUEUE hQueue = g_hRTThreadPosixPriorityProxyQueue;
458 g_hRTThreadPosixPriorityProxyQueue = NIL_RTREQQUEUE;
459 g_hRTThreadPosixPriorityProxyThread = NIL_RTTHREAD;
460 ASMCompilerBarrier(); /* paranoia */
461
462 AssertReturnVoid(hThread != NIL_RTTHREAD);
463 AssertReturnVoid(hQueue != NIL_RTREQQUEUE);
464
465 /*
466 * Kick the thread so it gets out of any pending RTReqQueueProcess call ASAP.
467 */
468 rc = RTReqQueueCallEx(hQueue, NULL, 0 /*cMillies*/, RTREQFLAGS_IPRT_STATUS | RTREQFLAGS_NO_WAIT,
469 (PFNRT)rtThreadPosixPriorityProxyStopper, 0);
470
471 /*
472 * Wait for the thread to complete.
473 */
474 rc = RTThreadWait(hThread, RT_SUCCESS(rc) ? RT_MS_1SEC * 5 : 32, NULL);
475 if (RT_SUCCESS(rc))
476 RTReqQueueDestroy(hQueue);
477 /* else: just leak the stuff, we're exitting, so nobody cares... */
478 }
479}
480
481
482/**
483 * Ensure that the proxy priority proxy thread has been started.
484 *
485 * Since we will always start a proxy thread when asked to create a thread,
486 * there is no need for serialization here.
487 *
488 * @retval true if started
489 * @retval false if it failed to start (caller must handle this scenario).
490 */
491DECLHIDDEN(bool) rtThreadPosixPriorityProxyStart(void)
492{
493 /*
494 * Read the result.
495 */
496 int rc = ASMAtomicUoReadS32(&g_rcPriorityProxyThreadStart);
497 if (rc != VERR_TRY_AGAIN)
498 return RT_SUCCESS(rc);
499
500 /* If this triggers then there is a very unexpected race somewhere. It
501 should be harmless though. */
502 AssertReturn(ASMAtomicCmpXchgS32(&g_rcPriorityProxyThreadStart, VERR_WRONG_ORDER, VERR_TRY_AGAIN), false);
503
504 /*
505 * Not yet started, so do that.
506 */
507 rc = RTReqQueueCreate(&g_hRTThreadPosixPriorityProxyQueue);
508 if (RT_SUCCESS(rc))
509 {
510 rc = RTThreadCreate(&g_hRTThreadPosixPriorityProxyThread, rtThreadPosixPriorityProxyThread, NULL, 0 /*cbStack*/,
511 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "RTThrdPP");
512 if (RT_SUCCESS(rc))
513 {
514 ASMAtomicWriteS32(&g_rcPriorityProxyThreadStart, VINF_SUCCESS);
515
516 atexit(rtThreadStopProxyThread);
517 return true;
518 }
519 RTReqQueueCreate(&g_hRTThreadPosixPriorityProxyQueue);
520 }
521 ASMAtomicWriteS32(&g_rcPriorityProxyThreadStart, rc != VERR_WRONG_ORDER ? rc : VERR_PROCESS_NOT_FOUND);
522 return false;
523}
524
525
526/**
527 * Calls @a pfnFunction from the priority proxy thread.
528 *
529 * Caller must have called rtThreadPosixStartProxy() to check that the priority
530 * proxy thread is running.
531 *
532 * @returns
533 * @param pTargetThread The target thread, NULL if not applicable. This is
534 * so we can skip calls pertaining to the priority
535 * proxy thread itself.
536 * @param pfnFunction The function to call. Must return IPRT status code.
537 * @param cArgs Number of arguments (see also RTReqQueueCall).
538 * @param ... Arguments (see also RTReqQueueCall).
539 */
540DECLHIDDEN(int) rtThreadPosixPriorityProxyCall(PRTTHREADINT pTargetThread, PFNRT pfnFunction, int cArgs, ...)
541{
542 int rc;
543 if ( !pTargetThread
544 || pTargetThread->pfnThread != rtThreadPosixPriorityProxyThread)
545 {
546 va_list va;
547 va_start(va, cArgs);
548 PRTREQ pReq;
549 rc = RTReqQueueCallV(g_hRTThreadPosixPriorityProxyQueue, &pReq, RT_INDEFINITE_WAIT, RTREQFLAGS_IPRT_STATUS,
550 pfnFunction, cArgs, va);
551 va_end(va);
552 RTReqRelease(pReq);
553 }
554 else
555 rc = VINF_SUCCESS;
556 return rc;
557}
558
559#endif /* !RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY */
560
561/**
562 * Worker for rtThreadNativeCreate that's either called on the priority proxy
563 * thread or directly on the calling thread depending on the proxy state.
564 */
565static DECLCALLBACK(int) rtThreadNativeInternalCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread)
566{
567 /*
568 * Set the default stack size.
569 */
570 if (!pThread->cbStack)
571 pThread->cbStack = 512*1024;
572
573#ifdef RT_OS_LINUX
574 pThread->tid = -1;
575#endif
576
577 /*
578 * Setup thread attributes.
579 */
580 pthread_attr_t ThreadAttr;
581 int rc = pthread_attr_init(&ThreadAttr);
582 if (!rc)
583 {
584 rc = pthread_attr_setdetachstate(&ThreadAttr, PTHREAD_CREATE_DETACHED);
585 if (!rc)
586 {
587 rc = pthread_attr_setstacksize(&ThreadAttr, pThread->cbStack);
588 if (!rc)
589 {
590 /*
591 * Create the thread.
592 */
593 pthread_t ThreadId;
594 rc = pthread_create(&ThreadId, &ThreadAttr, rtThreadNativeMain, pThread);
595 if (!rc)
596 {
597 pthread_attr_destroy(&ThreadAttr);
598 *pNativeThread = (uintptr_t)ThreadId;
599 return VINF_SUCCESS;
600 }
601 }
602 }
603 pthread_attr_destroy(&ThreadAttr);
604 }
605 return RTErrConvertFromErrno(rc);
606}
607
608
609DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread)
610{
611#ifdef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY
612 /*
613 * If we have a priority proxy thread, use it. Make sure to ignore the
614 * staring of the proxy thread itself.
615 */
616 if ( pThread->pfnThread != rtThreadPosixPriorityProxyThread
617 && rtThreadPosixPriorityProxyStart())
618 {
619 PRTREQ pReq;
620 int rc = RTReqQueueCall(g_hRTThreadPosixPriorityProxyQueue, &pReq, RT_INDEFINITE_WAIT,
621 (PFNRT)rtThreadNativeInternalCreate, 2, pThread, pNativeThread);
622 RTReqRelease(pReq);
623 return rc;
624 }
625
626 /*
627 * Fall back on creating it directly without regard to priority proxying.
628 */
629#endif
630 return rtThreadNativeInternalCreate(pThread, pNativeThread);
631}
632
633
634RTDECL(RTTHREAD) RTThreadSelf(void)
635{
636 PRTTHREADINT pThread = (PRTTHREADINT)pthread_getspecific(g_SelfKey);
637 /** @todo import alien threads? */
638 return pThread;
639}
640
641
642#ifdef RTTHREAD_POSIX_WITH_POKE
643RTDECL(int) RTThreadPoke(RTTHREAD hThread)
644{
645 AssertReturn(hThread != RTThreadSelf(), VERR_INVALID_PARAMETER);
646 PRTTHREADINT pThread = rtThreadGet(hThread);
647 AssertReturn(pThread, VERR_INVALID_HANDLE);
648
649 int rc;
650 if (g_iSigPokeThread != -1)
651 {
652 rc = pthread_kill((pthread_t)(uintptr_t)pThread->Core.Key, g_iSigPokeThread);
653 rc = RTErrConvertFromErrno(rc);
654 }
655 else
656 rc = VERR_NOT_SUPPORTED;
657
658 rtThreadRelease(pThread);
659 return rc;
660}
661#endif
662
663/** @todo move this into platform specific files. */
664RTR3DECL(int) RTThreadGetExecutionTimeMilli(uint64_t *pKernelTime, uint64_t *pUserTime)
665{
666#if defined(RT_OS_SOLARIS)
667 struct rusage ts;
668 int rc = getrusage(RUSAGE_LWP, &ts);
669 if (rc)
670 return RTErrConvertFromErrno(rc);
671
672 *pKernelTime = ts.ru_stime.tv_sec * 1000 + ts.ru_stime.tv_usec / 1000;
673 *pUserTime = ts.ru_utime.tv_sec * 1000 + ts.ru_utime.tv_usec / 1000;
674 return VINF_SUCCESS;
675
676#elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
677 /* on Linux, getrusage(RUSAGE_THREAD, ...) is available since 2.6.26 */
678 struct timespec ts;
679 int rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
680 if (rc)
681 return RTErrConvertFromErrno(rc);
682
683 *pKernelTime = 0;
684 *pUserTime = (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
685 return VINF_SUCCESS;
686
687#elif defined(RT_OS_DARWIN)
688 thread_basic_info ThreadInfo;
689 mach_msg_type_number_t Count = THREAD_BASIC_INFO_COUNT;
690 kern_return_t krc = thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)&ThreadInfo, &Count);
691 AssertReturn(krc == KERN_SUCCESS, RTErrConvertFromDarwinKern(krc));
692
693 *pKernelTime = ThreadInfo.system_time.seconds * 1000 + ThreadInfo.system_time.microseconds / 1000;
694 *pUserTime = ThreadInfo.user_time.seconds * 1000 + ThreadInfo.user_time.microseconds / 1000;
695
696 return VINF_SUCCESS;
697#elif defined(RT_OS_HAIKU)
698 thread_info ThreadInfo;
699 status_t status = get_thread_info(find_thread(NULL), &ThreadInfo);
700 AssertReturn(status == B_OK, RTErrConvertFromErrno(status));
701
702 *pKernelTime = ThreadInfo.kernel_time / 1000;
703 *pUserTime = ThreadInfo.user_time / 1000;
704
705 return VINF_SUCCESS;
706#else
707 return VERR_NOT_IMPLEMENTED;
708#endif
709}
710
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette