VirtualBox

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

Last change on this file since 13660 was 13660, checked in by vboxsync, 17 years ago

IPRT: RTThreadPoke update - don't use signal but sigaction (more well defined interface), make sure SIGUSR2 isn't masked on the threads and that it's interruptable (i.e. can interrupt sys calls).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.6 KB
Line 
1/* $Id: thread-posix.cpp 13660 2008-10-29 15:46:17Z vboxsync $ */
2/** @file
3 * IPRT - Threads, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#define LOG_GROUP RTLOGGROUP_THREAD
36#include <errno.h>
37#include <pthread.h>
38#include <signal.h>
39#if defined(RT_OS_SOLARIS)
40# include <sched.h>
41#endif
42
43#include <iprt/thread.h>
44#include <iprt/log.h>
45#include <iprt/assert.h>
46#include <iprt/asm.h>
47#include <iprt/err.h>
48#include <iprt/string.h>
49#include "internal/thread.h"
50
51
52/*******************************************************************************
53* Defined Constants And Macros *
54*******************************************************************************/
55/** The signal we're using for RTThreadPoke. */
56#define RTTHREAD_POSIX_POKE_SIG SIGUSR2
57
58
59/*******************************************************************************
60* Global Variables *
61*******************************************************************************/
62/** The pthread key in which we store the pointer to our own PRTTHREAD structure. */
63static pthread_key_t g_SelfKey;
64
65
66/*******************************************************************************
67* Internal Functions *
68*******************************************************************************/
69static void *rtThreadNativeMain(void *pvArgs);
70static void rtThreadKeyDestruct(void *pvValue);
71static void rtThreadPosixPokeSignal(int iSignal);
72
73int rtThreadNativeInit(void)
74{
75 /*
76 * Allocate the TLS (key in posix terms) where we store the pointer to
77 * a threads RTTHREADINT structure.
78 */
79 int rc = pthread_key_create(&g_SelfKey, rtThreadKeyDestruct);
80 if (rc)
81 return VERR_NO_TLS_FOR_SELF;
82
83 /*
84 * Register the dummy signal handler for RTThreadPoke.
85 * (Assert may explode here, but at least we'll notice.)
86 */
87 struct sigaction SigAct;
88 memset(&SigAct, '\0', sizeof(SigAct));
89 SigAct.sa_handler = rtThreadPosixPokeSignal;
90 sigfillset(&SigAct.sa_mask);
91 SigAct.sa_flags = 0;
92
93 struct sigaction SigActOld;
94 if (!sigaction(RTTHREAD_POSIX_POKE_SIG, &SigAct, &SigActOld))
95 Assert(SigActOld.sa_handler == SIG_DFL);
96 else
97 {
98 rc = RTErrConvertFromErrno(errno);
99 AssertMsgFailed(("rc=%Rrc errno=%d\n", rc, errno));
100 pthread_key_delete(g_SelfKey);
101 g_SelfKey = 0;
102 }
103 return rc;
104}
105
106
107/**
108 * Destructor called when a thread terminates.
109 * @param pvValue The key value. PRTTHREAD in our case.
110 */
111static void rtThreadKeyDestruct(void *pvValue)
112{
113 /*
114 * Deal with alien threads.
115 */
116 PRTTHREADINT pThread = (PRTTHREADINT)pvValue;
117 if (pThread->fIntFlags & RTTHREADINT_FLAGS_ALIEN)
118 {
119 pthread_setspecific(g_SelfKey, pThread);
120 rtThreadTerminate(pThread, 0);
121 pthread_setspecific(g_SelfKey, NULL);
122 }
123}
124
125
126/**
127 * Dummy signal handler for the poke signal.
128 *
129 * @param iSignal The signal number.
130 */
131static void rtThreadPosixPokeSignal(int iSignal)
132{
133 Assert(iSignal == RTTHREAD_POSIX_POKE_SIG);
134 NOREF(iSignal);
135}
136
137
138/**
139 * Adopts a thread, this is called immediately after allocating the
140 * thread structure.
141 *
142 * @param pThread Pointer to the thread structure.
143 */
144int rtThreadNativeAdopt(PRTTHREADINT pThread)
145{
146 /*
147 * Block SIGALRM - required for timer-posix.cpp.
148 * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling.
149 * It will not help much if someone creates threads directly using pthread_create. :/
150 */
151 sigset_t SigSet;
152 sigemptyset(&SigSet);
153 sigaddset(&SigSet, SIGALRM);
154 sigdelset(&SigSet, RTTHREAD_POSIX_POKE_SIG);
155 sigprocmask(SIG_BLOCK, &SigSet, NULL);
156 siginterrupt(RTTHREAD_POSIX_POKE_SIG, 1);
157
158 int rc = pthread_setspecific(g_SelfKey, pThread);
159 if (!rc)
160 return VINF_SUCCESS;
161 return VERR_FAILED_TO_SET_SELF_TLS;
162}
163
164
165/**
166 * Wrapper which unpacks the params and calls thread function.
167 */
168static void *rtThreadNativeMain(void *pvArgs)
169{
170 PRTTHREADINT pThread = (PRTTHREADINT)pvArgs;
171
172 /*
173 * Block SIGALRM - required for timer-posix.cpp.
174 * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling.
175 * It will not help much if someone creates threads directly using pthread_create. :/
176 */
177 sigset_t SigSet;
178 sigemptyset(&SigSet);
179 sigaddset(&SigSet, SIGALRM);
180 sigdelset(&SigSet, RTTHREAD_POSIX_POKE_SIG);
181 sigprocmask(SIG_BLOCK, &SigSet, NULL);
182 siginterrupt(RTTHREAD_POSIX_POKE_SIG, 1);
183
184 int rc = pthread_setspecific(g_SelfKey, pThread);
185 AssertReleaseMsg(!rc, ("failed to set self TLS. rc=%d thread '%s'\n", rc, pThread->szName));
186
187 /*
188 * Call common main.
189 */
190 pthread_t Self = pthread_self();
191 Assert((uintptr_t)Self == (RTNATIVETHREAD)Self && (uintptr_t)Self != NIL_RTNATIVETHREAD);
192 rc = rtThreadMain(pThread, (uintptr_t)Self, &pThread->szName[0]);
193
194 pthread_setspecific(g_SelfKey, NULL);
195 pthread_exit((void *)rc);
196 return (void *)rc;
197}
198
199
200int rtThreadNativeCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread)
201{
202 /*
203 * Set the default stack size.
204 */
205 if (!pThread->cbStack)
206 pThread->cbStack = 512*1024;
207
208 /*
209 * Setup thread attributes.
210 */
211 pthread_attr_t ThreadAttr;
212 int rc = pthread_attr_init(&ThreadAttr);
213 if (!rc)
214 {
215 rc = pthread_attr_setdetachstate(&ThreadAttr, PTHREAD_CREATE_DETACHED);
216 if (!rc)
217 {
218 rc = pthread_attr_setstacksize(&ThreadAttr, pThread->cbStack);
219 if (!rc)
220 {
221 /*
222 * Create the thread.
223 */
224 pthread_t ThreadId;
225 rc = pthread_create(&ThreadId, &ThreadAttr, rtThreadNativeMain, pThread);
226 if (!rc)
227 {
228 *pNativeThread = (uintptr_t)ThreadId;
229 return VINF_SUCCESS;
230 }
231 }
232 }
233 pthread_attr_destroy(&ThreadAttr);
234 }
235 return RTErrConvertFromErrno(rc);
236}
237
238
239RTDECL(RTTHREAD) RTThreadSelf(void)
240{
241 PRTTHREADINT pThread = (PRTTHREADINT)pthread_getspecific(g_SelfKey);
242 /** @todo import alien threads? */
243 return pThread;
244}
245
246
247RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
248{
249 return (RTNATIVETHREAD)pthread_self();
250}
251
252
253RTDECL(int) RTThreadSleep(unsigned cMillies)
254{
255 LogFlow(("RTThreadSleep: cMillies=%d\n", cMillies));
256 if (!cMillies)
257 {
258 /* pthread_yield() isn't part of SuS, thus this fun. */
259#ifdef RT_OS_DARWIN
260 pthread_yield_np();
261#elif defined(RT_OS_FREEBSD) /* void pthread_yield */
262 pthread_yield();
263#elif defined(RT_OS_SOLARIS)
264 sched_yield();
265#else
266 if (!pthread_yield())
267#endif
268 {
269 LogFlow(("RTThreadSleep: returning %Vrc (cMillies=%d)\n", VINF_SUCCESS, cMillies));
270 return VINF_SUCCESS;
271 }
272 }
273 else
274 {
275 struct timespec ts;
276 struct timespec tsrem = {0,0};
277
278 ts.tv_nsec = (cMillies % 1000) * 1000000;
279 ts.tv_sec = cMillies / 1000;
280 if (!nanosleep(&ts, &tsrem))
281 {
282 LogFlow(("RTThreadSleep: returning %Vrc (cMillies=%d)\n", VINF_SUCCESS, cMillies));
283 return VINF_SUCCESS;
284 }
285 }
286
287 int rc = RTErrConvertFromErrno(errno);
288 LogFlow(("RTThreadSleep: returning %Vrc (cMillies=%d)\n", rc, cMillies));
289 return rc;
290}
291
292
293RTDECL(bool) RTThreadYield(void)
294{
295 uint64_t u64TS = ASMReadTSC();
296#ifdef RT_OS_DARWIN
297 pthread_yield_np();
298#elif defined(RT_OS_SOLARIS)
299 sched_yield();
300#else
301 pthread_yield();
302#endif
303 u64TS = ASMReadTSC() - u64TS;
304 bool fRc = u64TS > 1500;
305 LogFlow(("RTThreadYield: returning %d (%llu ticks)\n", fRc, u64TS));
306 return fRc;
307}
308
309
310RTR3DECL(uint64_t) RTThreadGetAffinity(void)
311{
312 return 1;
313}
314
315
316RTR3DECL(int) RTThreadSetAffinity(uint64_t u64Mask)
317{
318 if (u64Mask != 1)
319 return VERR_INVALID_PARAMETER;
320 return VINF_SUCCESS;
321}
322
323
324RTDECL(int) RTThreadPoke(RTTHREAD hThread)
325{
326 AssertReturn(hThread != RTThreadSelf(), VERR_INVALID_PARAMETER);
327 PRTTHREADINT pThread = rtThreadGet(hThread);
328 AssertReturn(pThread, VERR_INVALID_HANDLE);
329
330 int rc = pthread_kill((pthread_t)(uintptr_t)pThread->Core.Key, RTTHREAD_POSIX_POKE_SIG);
331
332 rtThreadRelease(pThread);
333 return RTErrConvertFromErrno(rc);
334}
Note: See TracBrowser for help on using the repository browser.

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