VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/nt/thread-r0drv-nt.cpp@ 70334

Last change on this file since 70334 was 70334, checked in by vboxsync, 7 years ago

iprt: Moved ZwYieldExecution prototype to iprt/nt/nt.h.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 5.8 KB
Line 
1/* $Id: thread-r0drv-nt.cpp 70334 2017-12-24 14:36:37Z vboxsync $ */
2/** @file
3 * IPRT - Threads, Ring-0 Driver, NT.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
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
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "the-nt-kernel.h"
32#include "internal/iprt.h"
33#include <iprt/thread.h>
34
35#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
36# include <iprt/asm-amd64-x86.h>
37#endif
38#include <iprt/assert.h>
39#include <iprt/err.h>
40#include <iprt/mp.h>
41#include "internal-r0drv-nt.h"
42
43
44
45RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
46{
47 return (RTNATIVETHREAD)PsGetCurrentThread();
48}
49
50
51static int rtR0ThreadNtSleepCommon(RTMSINTERVAL cMillies)
52{
53 LARGE_INTEGER Interval;
54 Interval.QuadPart = -(int64_t)cMillies * 10000;
55 NTSTATUS rcNt = KeDelayExecutionThread(KernelMode, TRUE, &Interval);
56 switch (rcNt)
57 {
58 case STATUS_SUCCESS:
59 return VINF_SUCCESS;
60 case STATUS_ALERTED:
61 case STATUS_USER_APC:
62 return VERR_INTERRUPTED;
63 default:
64 return RTErrConvertFromNtStatus(rcNt);
65 }
66}
67
68
69RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies)
70{
71 return rtR0ThreadNtSleepCommon(cMillies);
72}
73
74
75RTDECL(bool) RTThreadYield(void)
76{
77 return ZwYieldExecution() != STATUS_NO_YIELD_PERFORMED;
78}
79
80
81RTDECL(bool) RTThreadPreemptIsEnabled(RTTHREAD hThread)
82{
83 Assert(hThread == NIL_RTTHREAD); RT_NOREF1(hThread);
84 KIRQL Irql = KeGetCurrentIrql();
85 if (Irql > APC_LEVEL)
86 return false;
87 if (!ASMIntAreEnabled())
88 return false;
89 return true;
90}
91
92
93RTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread)
94{
95 Assert(hThread == NIL_RTTHREAD); RT_NOREF1(hThread);
96
97 /*
98 * Read the globals and check if they are useful.
99 */
100/** @todo Should we check KPRCB.InterruptRequest and KPRCB.DpcInterruptRequested (older kernels). */
101 uint32_t const offQuantumEnd = g_offrtNtPbQuantumEnd;
102 uint32_t const cbQuantumEnd = g_cbrtNtPbQuantumEnd;
103 uint32_t const offDpcQueueDepth = g_offrtNtPbDpcQueueDepth;
104 if (!offQuantumEnd && !cbQuantumEnd && !offDpcQueueDepth)
105 return false;
106 Assert((offQuantumEnd && cbQuantumEnd) || (!offQuantumEnd && !cbQuantumEnd));
107
108 /*
109 * Disable interrupts so we won't be messed around.
110 */
111 bool fPending;
112 RTCCUINTREG fSavedFlags = ASMIntDisableFlags();
113
114#ifdef RT_ARCH_X86
115 PKPCR pPcr = (PKPCR)__readfsdword(RT_OFFSETOF(KPCR,SelfPcr));
116 uint8_t *pbPrcb = (uint8_t *)pPcr->Prcb;
117
118#elif defined(RT_ARCH_AMD64)
119 /* HACK ALERT! The offset is from windbg/vista64. */
120 PKPCR pPcr = (PKPCR)__readgsqword(RT_OFFSETOF(KPCR,Self));
121 uint8_t *pbPrcb = (uint8_t *)pPcr->CurrentPrcb;
122
123#else
124# error "port me"
125#endif
126
127 /* Check QuantumEnd. */
128 if (cbQuantumEnd == 1)
129 {
130 uint8_t volatile *pbQuantumEnd = (uint8_t volatile *)(pbPrcb + offQuantumEnd);
131 fPending = *pbQuantumEnd == TRUE;
132 }
133 else if (cbQuantumEnd == sizeof(uint32_t))
134 {
135 uint32_t volatile *pu32QuantumEnd = (uint32_t volatile *)(pbPrcb + offQuantumEnd);
136 fPending = *pu32QuantumEnd != 0;
137 }
138 else
139 fPending = false;
140
141 /* Check DpcQueueDepth. */
142 if ( !fPending
143 && offDpcQueueDepth)
144 {
145 uint32_t volatile *pu32DpcQueueDepth = (uint32_t volatile *)(pbPrcb + offDpcQueueDepth);
146 fPending = *pu32DpcQueueDepth > 0;
147 }
148
149 ASMSetFlags(fSavedFlags);
150 return fPending;
151}
152
153
154RTDECL(bool) RTThreadPreemptIsPendingTrusty(void)
155{
156#if 0 /** @todo RTThreadPreemptIsPending isn't good enough on w7 and possibly elsewhere. */
157 /* RTThreadPreemptIsPending is only reliable if we've got both offsets and size. */
158 return g_offrtNtPbQuantumEnd != 0
159 && g_cbrtNtPbQuantumEnd != 0
160 && g_offrtNtPbDpcQueueDepth != 0;
161#else
162 return false;
163#endif
164}
165
166
167RTDECL(bool) RTThreadPreemptIsPossible(void)
168{
169 /* yes, kernel preemption is possible. */
170 return true;
171}
172
173
174RTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState)
175{
176 AssertPtr(pState);
177 Assert(pState->uchOldIrql == 255);
178 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
179
180 KeRaiseIrql(DISPATCH_LEVEL, &pState->uchOldIrql);
181 RT_ASSERT_PREEMPT_CPUID_DISABLE(pState);
182}
183
184
185RTDECL(void) RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState)
186{
187 AssertPtr(pState);
188
189 RT_ASSERT_PREEMPT_CPUID_RESTORE(pState);
190 KeLowerIrql(pState->uchOldIrql);
191 pState->uchOldIrql = 255;
192}
193
194
195RTDECL(bool) RTThreadIsInInterrupt(RTTHREAD hThread)
196{
197 Assert(hThread == NIL_RTTHREAD); NOREF(hThread);
198
199 KIRQL CurIrql = KeGetCurrentIrql();
200 return CurIrql > PASSIVE_LEVEL; /** @todo Is there a more correct way? */
201}
202
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