VirtualBox

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

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

Biggest check-in ever. New source code headers for all (C) innotek files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.1 KB
Line 
1/* $Id: thread-posix.cpp 4071 2007-08-07 17:07:59Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Threads, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP RTLOGGROUP_THREAD
23#include <errno.h>
24#include <pthread.h>
25#include <signal.h>
26#if defined(RT_OS_SOLARIS)
27# include <sched.h>
28#endif
29
30#include <iprt/thread.h>
31#include <iprt/log.h>
32#include <iprt/assert.h>
33#include <iprt/asm.h>
34#include <iprt/err.h>
35#include "internal/thread.h"
36
37
38/*******************************************************************************
39* Header Files *
40*******************************************************************************/
41/** The pthread key in which we store the pointer to our own PRTTHREAD structure. */
42static pthread_key_t g_SelfKey;
43
44
45/*******************************************************************************
46* Internal Functions *
47*******************************************************************************/
48static void *rtThreadNativeMain(void *pvArgs);
49static void rtThreadKeyDestruct(void *pvValue);
50
51
52int rtThreadNativeInit(void)
53{
54 /*
55 * Allocate the TLS (key in posix terms) where we store the pointer to
56 * a threads RTTHREADINT structure.
57 */
58
59 int rc = pthread_key_create(&g_SelfKey, rtThreadKeyDestruct);
60 if (!rc)
61 return VINF_SUCCESS;
62 return VERR_NO_TLS_FOR_SELF;
63}
64
65
66/**
67 * Destructor called when a thread terminates.
68 * @param pvValue The key value. PRTTHREAD in our case.
69 */
70static void rtThreadKeyDestruct(void *pvValue)
71{
72 /*
73 * Deal with alien threads.
74 */
75 PRTTHREADINT pThread = (PRTTHREADINT)pvValue;
76 if (pThread->fIntFlags & RTTHREADINT_FLAGS_ALIEN)
77 {
78 pthread_setspecific(g_SelfKey, pThread);
79 rtThreadTerminate(pThread, 0);
80 pthread_setspecific(g_SelfKey, NULL);
81 }
82}
83
84
85/**
86 * Adopts a thread, this is called immediately after allocating the
87 * thread structure.
88 *
89 * @param pThread Pointer to the thread structure.
90 */
91int rtThreadNativeAdopt(PRTTHREADINT pThread)
92{
93 /*
94 * Block SIGALRM - required for timer-posix.cpp.
95 * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling.
96 * It will not help much if someone creates threads directly using pthread_create. :/
97 */
98 sigset_t SigSet;
99 sigemptyset(&SigSet);
100 sigaddset(&SigSet, SIGALRM);
101 sigprocmask(SIG_BLOCK, &SigSet, NULL);
102
103 int rc = pthread_setspecific(g_SelfKey, pThread);
104 if (!rc)
105 return VINF_SUCCESS;
106 return VERR_FAILED_TO_SET_SELF_TLS;
107}
108
109
110/**
111 * Wrapper which unpacks the params and calls thread function.
112 */
113static void *rtThreadNativeMain(void *pvArgs)
114{
115 PRTTHREADINT pThread = (PRTTHREADINT)pvArgs;
116
117 /*
118 * Block SIGALRM - required for timer-posix.cpp.
119 * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling.
120 * It will not help much if someone creates threads directly using pthread_create. :/
121 */
122 sigset_t SigSet;
123 sigemptyset(&SigSet);
124 sigaddset(&SigSet, SIGALRM);
125 sigprocmask(SIG_BLOCK, &SigSet, NULL);
126
127 int rc = pthread_setspecific(g_SelfKey, pThread);
128 AssertReleaseMsg(!rc, ("failed to set self TLS. rc=%d thread '%s'\n", rc, pThread->szName));
129
130 /*
131 * Call common main.
132 */
133 pthread_t Self = pthread_self();
134 Assert((uintptr_t)Self == (RTNATIVETHREAD)Self && (uintptr_t)Self != NIL_RTNATIVETHREAD);
135 rc = rtThreadMain(pThread, (uintptr_t)Self, &pThread->szName[0]);
136
137 pthread_setspecific(g_SelfKey, NULL);
138 pthread_exit((void *)rc);
139 return (void *)rc;
140}
141
142
143int rtThreadNativeCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread)
144{
145 /*
146 * Set the default stack size.
147 */
148 if (!pThread->cbStack)
149 pThread->cbStack = 512*1024;
150
151 /*
152 * Setup thread attributes.
153 */
154 pthread_attr_t ThreadAttr;
155 int rc = pthread_attr_init(&ThreadAttr);
156 if (!rc)
157 {
158 rc = pthread_attr_setdetachstate(&ThreadAttr, PTHREAD_CREATE_DETACHED);
159 if (!rc)
160 {
161 rc = pthread_attr_setstacksize(&ThreadAttr, pThread->cbStack);
162 if (!rc)
163 {
164 /*
165 * Create the thread.
166 */
167 pthread_t ThreadId;
168 rc = pthread_create(&ThreadId, &ThreadAttr, rtThreadNativeMain, pThread);
169 if (!rc)
170 {
171 *pNativeThread = (uintptr_t)ThreadId;
172 return VINF_SUCCESS;
173 }
174 }
175 }
176 pthread_attr_destroy(&ThreadAttr);
177 }
178 return RTErrConvertFromErrno(rc);
179}
180
181
182RTDECL(RTTHREAD) RTThreadSelf(void)
183{
184 PRTTHREADINT pThread = (PRTTHREADINT)pthread_getspecific(g_SelfKey);
185 /** @todo import alien threads? */
186 return pThread;
187}
188
189
190RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
191{
192 return (RTNATIVETHREAD)pthread_self();
193}
194
195
196RTDECL(int) RTThreadSleep(unsigned cMillies)
197{
198 LogFlow(("RTThreadSleep: cMillies=%d\n", cMillies));
199 if (!cMillies)
200 {
201 /* pthread_yield() isn't part of SuS, thus this fun. */
202#ifdef RT_OS_DARWIN
203 pthread_yield_np();
204#elif defined(RT_OS_FREEBSD) /* void pthread_yield */
205 pthread_yield();
206#elif defined(RT_OS_SOLARIS)
207 sched_yield();
208#else
209 if (!pthread_yield())
210#endif
211 {
212 LogFlow(("RTThreadSleep: returning %Vrc (cMillies=%d)\n", VINF_SUCCESS, cMillies));
213 return VINF_SUCCESS;
214 }
215 }
216 else
217 {
218 struct timespec ts;
219 struct timespec tsrem = {0,0};
220
221 ts.tv_nsec = (cMillies % 1000) * 1000000;
222 ts.tv_sec = cMillies / 1000;
223 if (!nanosleep(&ts, &tsrem))
224 {
225 LogFlow(("RTThreadSleep: returning %Vrc (cMillies=%d)\n", VINF_SUCCESS, cMillies));
226 return VINF_SUCCESS;
227 }
228 }
229
230 int rc = RTErrConvertFromErrno(errno);
231 LogFlow(("RTThreadSleep: returning %Vrc (cMillies=%d)\n", rc, cMillies));
232 return rc;
233}
234
235
236RTDECL(bool) RTThreadYield(void)
237{
238 uint64_t u64TS = ASMReadTSC();
239#ifdef RT_OS_DARWIN
240 pthread_yield_np();
241#elif defined(RT_OS_SOLARIS)
242 sched_yield();
243#else
244 pthread_yield();
245#endif
246 u64TS = ASMReadTSC() - u64TS;
247 bool fRc = u64TS > 1500;
248 LogFlow(("RTThreadYield: returning %d (%llu ticks)\n", fRc, u64TS));
249 return fRc;
250}
251
252
253RTR3DECL(uint64_t) RTThreadGetAffinity(void)
254{
255 return 1;
256}
257
258
259RTR3DECL(int) RTThreadSetAffinity(uint64_t u64Mask)
260{
261 if (u64Mask != 1)
262 return VERR_INVALID_PARAMETER;
263 return VINF_SUCCESS;
264}
265
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