VirtualBox

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

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

IPRT: RTThreadPoke for posix.

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