VirtualBox

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

Last change on this file since 25802 was 25724, checked in by vboxsync, 15 years ago

iprt: Use RTMSINTERVAL for timeouts. Fixed missing timeout underflow checks in two RTFileAioCtxWait implementations.

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