VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/os2/thread-os2.cpp@ 103795

Last change on this file since 103795 was 99901, checked in by vboxsync, 19 months ago

IPRT: Cleaned up RTThreadGetExecutionTimeMilli and associated testcase.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 8.2 KB
Line 
1/* $Id: thread-os2.cpp 99901 2023-05-22 14:15:10Z vboxsync $ */
2/** @file
3 * IPRT - Threads, OS/2.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_THREAD
42#define INCL_BASE
43#include <os2.h>
44#undef RT_MAX
45
46#include <errno.h>
47#include <process.h>
48#include <stdlib.h>
49#include <signal.h>
50#include <InnoTekLIBC/FastInfoBlocks.h>
51#include <InnoTekLIBC/thread.h>
52
53#include <iprt/thread.h>
54#include <iprt/log.h>
55#include <iprt/assert.h>
56#include <iprt/alloc.h>
57#include <iprt/asm-amd64-x86.h>
58#include <iprt/cpuset.h>
59#include <iprt/string.h>
60#include <iprt/err.h>
61#include "internal/thread.h"
62
63
64/*********************************************************************************************************************************
65* Global Variables *
66*********************************************************************************************************************************/
67/** Pointer to thread local memory which points to the current thread. */
68static PRTTHREADINT *g_ppCurThread;
69
70
71/*********************************************************************************************************************************
72* Internal Functions *
73*********************************************************************************************************************************/
74static void rtThreadNativeMain(void *pvArgs);
75
76
77DECLHIDDEN(int) rtThreadNativeInit(void)
78{
79 /*
80 * Allocate thread local memory.
81 */
82 PULONG pul;
83 int rc = DosAllocThreadLocalMemory(1, &pul);
84 if (rc)
85 return VERR_NO_TLS_FOR_SELF;
86 g_ppCurThread = (PRTTHREADINT *)(void *)pul;
87 return VINF_SUCCESS;
88}
89
90
91static void rtThreadOs2BlockSigAlarm(void)
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
104
105DECLHIDDEN(void) rtThreadNativeReInitObtrusive(void)
106{
107 rtThreadOs2BlockSigAlarm();
108}
109
110
111DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
112{
113
114 *g_ppCurThread = pThread;
115 return VINF_SUCCESS;
116}
117
118
119DECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread)
120{
121 if (pThread == *g_ppCurThread)
122 *g_ppCurThread = NULL;
123}
124
125
126/**
127 * Wrapper which unpacks the params and calls thread function.
128 */
129static void rtThreadNativeMain(void *pvArgs)
130{
131 rtThreadOs2BlockSigAlarm();
132
133 /*
134 * Call common main.
135 */
136 PRTTHREADINT pThread = (PRTTHREADINT)pvArgs;
137 *g_ppCurThread = pThread;
138
139#ifdef fibGetTidPid
140 rtThreadMain(pThread, fibGetTidPid(), &pThread->szName[0]);
141#else
142 rtThreadMain(pThread, _gettid(), &pThread->szName[0]);
143#endif
144
145 *g_ppCurThread = NULL;
146 _endthread();
147}
148
149
150DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread)
151{
152 /*
153 * Default stack size.
154 */
155 if (!pThread->cbStack)
156 pThread->cbStack = 512*1024;
157
158 /*
159 * Create the thread.
160 */
161 int iThreadId = _beginthread(rtThreadNativeMain, NULL, pThread->cbStack, pThread);
162 if (iThreadId > 0)
163 {
164#ifdef fibGetTidPid
165 *pNativeThread = iThreadId | (fibGetPid() << 16);
166#else
167 *pNativeThread = iThreadId;
168#endif
169 return VINF_SUCCESS;
170 }
171 return RTErrConvertFromErrno(errno);
172}
173
174
175RTDECL(RTTHREAD) RTThreadSelf(void)
176{
177 PRTTHREADINT pThread = *g_ppCurThread;
178 if (pThread)
179 return (RTTHREAD)pThread;
180 /** @todo import alien threads? */
181 return NULL;
182}
183
184
185RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
186{
187#ifdef fibGetTidPid
188 return fibGetTidPid();
189#else
190 return _gettid();
191#endif
192}
193
194
195RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies)
196{
197 LogFlow(("RTThreadSleep: cMillies=%d\n", cMillies));
198 DosSleep(cMillies);
199 LogFlow(("RTThreadSleep: returning (cMillies=%d)\n", cMillies));
200 return VINF_SUCCESS;
201}
202
203
204RTDECL(int) RTThreadSleepNoLog(RTMSINTERVAL cMillies)
205{
206 DosSleep(cMillies);
207 return VINF_SUCCESS;
208}
209
210
211RTDECL(bool) RTThreadYield(void)
212{
213 uint64_t u64TS = ASMReadTSC();
214 DosSleep(0);
215 u64TS = ASMReadTSC() - u64TS;
216 bool fRc = u64TS > 1750;
217 LogFlow(("RTThreadYield: returning %d (%llu ticks)\n", fRc, u64TS));
218 return fRc;
219}
220
221
222RTR3DECL(int) RTThreadGetAffinity(PRTCPUSET pCpuSet)
223{
224 union
225 {
226 uint64_t u64;
227 MPAFFINITY mpaff;
228 } u;
229
230 APIRET rc = DosQueryThreadAffinity(AFNTY_THREAD, &u.mpaff);
231 if (!rc)
232 {
233 RTCpuSetFromU64(pCpuSet, u.u64);
234 return VINF_SUCCESS;
235 }
236 return RTErrConvertFromOS2(rc);
237}
238
239
240RTR3DECL(int) RTThreadSetAffinity(PCRTCPUSET pCpuSet)
241{
242 union
243 {
244 uint64_t u64;
245 MPAFFINITY mpaff;
246 } u;
247 u.u64 = pCpuSet ? RTCpuSetToU64(pCpuSet) : UINT64_MAX;
248 int rc = DosSetThreadAffinity(&u.mpaff);
249 if (!rc)
250 return VINF_SUCCESS;
251 return RTErrConvertFromOS2(rc);
252}
253
254
255RTR3DECL(RTTLS) RTTlsAlloc(void)
256{
257 AssertCompile(NIL_RTTLS == -1);
258 return __libc_TLSAlloc();
259}
260
261
262RTR3DECL(int) RTTlsAllocEx(PRTTLS piTls, PFNRTTLSDTOR pfnDestructor)
263{
264 int rc;
265 int iTls = __libc_TLSAlloc();
266 if (iTls != -1)
267 {
268 if ( !pfnDestructor
269 || __libc_TLSDestructor(iTls, (void (*)(void *, int, unsigned))pfnDestructor, 0) != -1)
270 {
271 *piTls = iTls;
272 return VINF_SUCCESS;
273 }
274
275 rc = RTErrConvertFromErrno(errno);
276 __libc_TLSFree(iTls);
277 }
278 else
279 rc = RTErrConvertFromErrno(errno);
280
281 *piTls = NIL_RTTLS;
282 return rc;
283}
284
285
286RTR3DECL(int) RTTlsFree(RTTLS iTls)
287{
288 if (iTls == NIL_RTTLS)
289 return VINF_SUCCESS;
290 if (__libc_TLSFree(iTls) != -1)
291 return VINF_SUCCESS;
292 return RTErrConvertFromErrno(errno);
293}
294
295
296RTR3DECL(void *) RTTlsGet(RTTLS iTls)
297{
298 return __libc_TLSGet(iTls);
299}
300
301
302RTR3DECL(int) RTTlsGetEx(RTTLS iTls, void **ppvValue)
303{
304 int rc = VINF_SUCCESS;
305 void *pv = __libc_TLSGet(iTls);
306 if (RT_UNLIKELY(!pv))
307 {
308 errno = 0;
309 pv = __libc_TLSGet(iTls);
310 if (!pv && errno)
311 rc = RTErrConvertFromErrno(errno);
312 }
313
314 *ppvValue = pv;
315 return rc;
316}
317
318
319RTR3DECL(int) RTTlsSet(RTTLS iTls, void *pvValue)
320{
321 if (__libc_TLSSet(iTls, pvValue) != -1)
322 return VINF_SUCCESS;
323 return RTErrConvertFromErrno(errno);
324}
325
326
327RTR3DECL(int) RTThreadGetExecutionTimeMilli(uint64_t *pcMsKernelTime, uint64_t *pcMsUserTime)
328{
329 RT_NOREF(pcMsKernelTime, pcMsUserTime);
330 return VERR_NOT_IMPLEMENTED;
331}
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