VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win32/thread-win32.cpp@ 3672

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

InnoTek -> innotek: all the headers and comments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.3 KB
Line 
1/* $Id: thread-win32.cpp 2981 2007-06-01 16:01:28Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Threads, Win32.
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 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP RTLOGGROUP_THREAD
27#include <Windows.h>
28
29#include <errno.h>
30#include <process.h>
31
32#include <iprt/thread.h>
33#include <iprt/log.h>
34#include <iprt/assert.h>
35#include <iprt/alloc.h>
36#include <iprt/asm.h>
37#include <iprt/err.h>
38#include "internal/thread.h"
39
40
41/*******************************************************************************
42* Defined Constants And Macros *
43*******************************************************************************/
44/** The TLS index allocated for storing the RTTHREADINT pointer. */
45static DWORD g_dwSelfTLS = TLS_OUT_OF_INDEXES;
46
47
48/*******************************************************************************
49* Internal Functions *
50*******************************************************************************/
51static unsigned __stdcall rtThreadNativeMain(void *pvArgs);
52
53
54int rtThreadNativeInit(void)
55{
56 g_dwSelfTLS = TlsAlloc();
57 if (g_dwSelfTLS == TLS_OUT_OF_INDEXES)
58 return VERR_NO_TLS_FOR_SELF;
59 return VINF_SUCCESS;
60}
61
62
63void rtThreadNativeDetach(void)
64{
65 /*
66 * Deal with alien threads.
67 */
68 PRTTHREADINT pThread = (PRTTHREADINT)TlsGetValue(g_dwSelfTLS);
69 if ( pThread
70 && (pThread->fIntFlags & RTTHREADINT_FLAGS_ALIEN))
71 {
72 rtThreadTerminate(pThread, 0);
73 TlsSetValue(g_dwSelfTLS, NULL);
74 }
75}
76
77
78int rtThreadNativeAdopt(PRTTHREADINT pThread)
79{
80 if (!TlsSetValue(g_dwSelfTLS, pThread))
81 return VERR_FAILED_TO_SET_SELF_TLS;
82 return VINF_SUCCESS;
83}
84
85
86/**
87 * Wrapper which unpacks the param stuff and calls thread function.
88 */
89static unsigned __stdcall rtThreadNativeMain(void *pvArgs)
90{
91 DWORD dwThreadId = GetCurrentThreadId();
92 PRTTHREADINT pThread = (PRTTHREADINT)pvArgs;
93
94 if (!TlsSetValue(g_dwSelfTLS, pThread))
95 AssertReleaseMsgFailed(("failed to set self TLS. lasterr=%d thread '%s'\n", GetLastError(), pThread->szName));
96
97 int rc = rtThreadMain(pThread, dwThreadId, &pThread->szName[0]);
98
99 TlsSetValue(g_dwSelfTLS, NULL);
100 _endthreadex(rc);
101 return rc;
102}
103
104
105int rtThreadNativeCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread)
106{
107 AssertReturn(pThread->cbStack < ~(unsigned)0, VERR_INVALID_PARAMETER);
108
109 /*
110 * Create the thread.
111 */
112 pThread->hThread = (uintptr_t)INVALID_HANDLE_VALUE;
113 unsigned uThreadId = 0;
114 uintptr_t hThread = _beginthreadex(NULL, (unsigned)pThread->cbStack, rtThreadNativeMain, pThread, 0, &uThreadId);
115 if (hThread != 0 && hThread != ~0U)
116 {
117 pThread->hThread = hThread;
118 *pNativeThread = uThreadId;
119 return VINF_SUCCESS;
120 }
121 return RTErrConvertFromErrno(errno);
122}
123
124
125RTDECL(RTTHREAD) RTThreadSelf(void)
126{
127 PRTTHREADINT pThread = (PRTTHREADINT)TlsGetValue(g_dwSelfTLS);
128 /** @todo import alien threads ? */
129 return pThread;
130}
131
132
133RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
134{
135 return (RTNATIVETHREAD)GetCurrentThreadId();
136}
137
138
139RTR3DECL(int) RTThreadSleep(unsigned cMillies)
140{
141 LogFlow(("RTThreadSleep: cMillies=%d\n", cMillies));
142 Sleep(cMillies);
143 LogFlow(("RTThreadSleep: returning %Vrc (cMillies=%d)\n", VINF_SUCCESS, cMillies));
144 return VINF_SUCCESS;
145}
146
147
148RTR3DECL(bool) RTThreadYield(void)
149{
150 uint64_t u64TS = ASMReadTSC();
151 Sleep(0);
152 u64TS = ASMReadTSC() - u64TS;
153 bool fRc = u64TS > 1500;
154 LogFlow(("RTThreadYield: returning %d (%llu ticks)\n", fRc, u64TS));
155 return fRc;
156}
157
158
159#if 0 /* noone is using this ... */
160/**
161 * Returns the processor number the current thread was running on during this call
162 *
163 * @returns processor nr
164 */
165static int rtThreadGetCurrentProcessorNumber(void)
166{
167 static bool fInitialized = false;
168 static DWORD (WINAPI *pfnGetCurrentProcessorNumber)(void) = NULL;
169 if (!fInitialized)
170 {
171 HMODULE hmodKernel32 = GetModuleHandle("KERNEL32.DLL");
172 if (hmodKernel32)
173 pfnGetCurrentProcessorNumber = (DWORD (WINAPI*)(void))GetProcAddress(hmodKernel32, "GetCurrentProcessorNumber");
174 fInitialized = true;
175 }
176 if (pfnGetCurrentProcessorNumber)
177 return pfnGetCurrentProcessorNumber();
178 return -1;
179}
180#endif
181
182
183RTR3DECL(int) RTThreadSetAffinity(uint64_t u64Mask)
184{
185 Assert((DWORD_PTR)u64Mask == u64Mask || u64Mask == ~(uint64_t)0);
186 DWORD dwRet = SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR)u64Mask);
187 if (dwRet)
188 return VINF_SUCCESS;
189
190 int iLastError = GetLastError();
191 AssertMsgFailed(("SetThreadAffinityMask failed, LastError=%d\n", iLastError));
192 return RTErrConvertFromWin32(iLastError);
193}
194
195
196RTR3DECL(uint64_t) RTThreadGetAffinity(void)
197{
198 /*
199 * Haven't found no query api, but the set api returns the old mask, so let's use that.
200 */
201 DWORD_PTR dwIgnored;
202 DWORD_PTR dwProcAff = 0;
203 if (GetProcessAffinityMask(GetCurrentProcess(), &dwProcAff, &dwIgnored))
204 {
205 HANDLE hThread = GetCurrentThread();
206 DWORD dwRet = SetThreadAffinityMask(hThread, dwProcAff);
207 if (dwRet)
208 {
209 DWORD dwSet = SetThreadAffinityMask(hThread, dwRet);
210 Assert(dwSet == dwProcAff); NOREF(dwRet);
211 return dwRet;
212 }
213 }
214
215 int iLastError = GetLastError();
216 AssertMsgFailed(("SetThreadAffinityMask or GetProcessAffinityMask failed, LastError=%d\n", iLastError));
217 return RTErrConvertFromWin32(iLastError);
218}
219
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