VirtualBox

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

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

rebranding: IPRT files again.

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