win-pvdrivers

view xenpci/xenpci_highsync.c @ 1063:fe04dbceb0b2

Tidy up highsync code. Remove KdPrint calls.
author James Harper <james.harper@bendigoit.com.au>
date Thu Oct 03 18:10:21 2013 +1000 (2013-10-03)
parents 1ee7940af105
children 27bd2a5a4704
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenpci.h"
22 /* Not really necessary but keeps PREfast happy */
23 #if (VER_PRODUCTBUILD >= 7600)
24 static KDEFERRED_ROUTINE XenPci_HighSyncCallFunction0;
25 static KDEFERRED_ROUTINE XenPci_HighSyncCallFunctionN;
26 #endif
28 /*
29 we need these intrinsics as even going to HIGH_LEVEL doesn't ensure that interrupts are completely disabled
30 */
31 #pragma intrinsic(_disable)
32 #pragma intrinsic(_enable)
34 struct {
35 volatile ULONG do_spin;
36 volatile LONG nr_procs_at_dispatch_level;
37 volatile LONG nr_spinning_at_sync_level;
38 KDPC dpcs[MAX_VIRT_CPUS];
39 KEVENT highsync_complete_event;
40 KIRQL sync_level;
41 PXENPCI_HIGHSYNC_FUNCTION function0;
42 PXENPCI_HIGHSYNC_FUNCTION functionN;
43 PVOID context;
44 } typedef highsync_info_t;
46 static VOID
47 XenPci_HighSyncCallFunction0(PRKDPC Dpc, PVOID Context, PVOID SystemArgument1, PVOID SystemArgument2) {
48 highsync_info_t *highsync_info = Context;
49 ULONG ActiveProcessorCount;
50 KIRQL old_irql;
52 UNREFERENCED_PARAMETER(Dpc);
53 UNREFERENCED_PARAMETER(SystemArgument1);
54 UNREFERENCED_PARAMETER(SystemArgument2);
56 FUNCTION_ENTER();
57 #if (NTDDI_VERSION >= NTDDI_WINXP)
58 ActiveProcessorCount = (ULONG)KeNumberProcessors;
59 #else
60 ActiveProcessorCount = (ULONG)*KeNumberProcessors;
61 #endif
62 InterlockedIncrement(&highsync_info->nr_procs_at_dispatch_level);
63 if (highsync_info->sync_level > DISPATCH_LEVEL) {
64 while (highsync_info->nr_procs_at_dispatch_level < (LONG)ActiveProcessorCount) {
65 KeStallExecutionProcessor(1);
66 KeMemoryBarrier();
67 }
68 }
69 _disable(); //__asm cli;
70 KeRaiseIrql(highsync_info->sync_level, &old_irql);
71 while (highsync_info->nr_spinning_at_sync_level < (LONG)ActiveProcessorCount - 1) {
72 KeStallExecutionProcessor(1);
73 KeMemoryBarrier();
74 }
75 highsync_info->function0(highsync_info->context);
76 KeLowerIrql(old_irql);
77 _enable(); //__asm sti;
78 highsync_info->do_spin = FALSE;
79 KeMemoryBarrier();
80 /* wait for all the other processors to complete spinning, just in case it matters */
81 while (highsync_info->nr_spinning_at_sync_level) {
82 KeStallExecutionProcessor(1);
83 KeMemoryBarrier();
84 }
85 InterlockedDecrement(&highsync_info->nr_procs_at_dispatch_level);
86 /* wait until nr_procs_at_dispatch_level drops to 0 indicating that nothing else requires highsync_info */
87 while (highsync_info->nr_procs_at_dispatch_level) {
88 KeStallExecutionProcessor(1);
89 KeMemoryBarrier();
90 }
91 KeSetEvent(&highsync_info->highsync_complete_event, IO_NO_INCREMENT, FALSE);
93 FUNCTION_EXIT();
94 }
96 static VOID
97 XenPci_HighSyncCallFunctionN(PRKDPC Dpc, PVOID Context, PVOID SystemArgument1, PVOID SystemArgument2) {
98 highsync_info_t *highsync_info = Context;
99 ULONG ActiveProcessorCount;
100 KIRQL old_irql;
102 UNREFERENCED_PARAMETER(Dpc);
103 UNREFERENCED_PARAMETER(SystemArgument1);
104 UNREFERENCED_PARAMETER(SystemArgument2);
106 FUNCTION_ENTER();
107 FUNCTION_MSG("(CPU = %d)\n", KeGetCurrentProcessorNumber());
109 FUNCTION_MSG("CPU %d spinning...\n", KeGetCurrentProcessorNumber());
110 InterlockedIncrement(&highsync_info->nr_procs_at_dispatch_level);
111 if (highsync_info->sync_level > DISPATCH_LEVEL) {
112 #if (NTDDI_VERSION >= NTDDI_WINXP)
113 ActiveProcessorCount = (ULONG)KeNumberProcessors;
114 #else
115 ActiveProcessorCount = (ULONG)*KeNumberProcessors;
116 #endif
117 while (highsync_info->nr_procs_at_dispatch_level < (LONG)ActiveProcessorCount) {
118 KeStallExecutionProcessor(1);
119 KeMemoryBarrier();
120 }
121 }
122 _disable(); //__asm cli;
123 KeRaiseIrql(highsync_info->sync_level, &old_irql);
124 InterlockedIncrement(&highsync_info->nr_spinning_at_sync_level);
125 while(highsync_info->do_spin) {
126 KeStallExecutionProcessor(1);
127 KeMemoryBarrier();
128 }
129 highsync_info->functionN(highsync_info->context);
130 KeLowerIrql(old_irql);
131 _enable(); //__asm sti;
132 InterlockedDecrement(&highsync_info->nr_spinning_at_sync_level);
133 InterlockedDecrement(&highsync_info->nr_procs_at_dispatch_level);
134 FUNCTION_EXIT();
135 return;
136 }
138 VOID
139 XenPci_HighSync(PXENPCI_HIGHSYNC_FUNCTION function0, PXENPCI_HIGHSYNC_FUNCTION functionN, PVOID context) {
140 ULONG ActiveProcessorCount;
141 ULONG i;
142 highsync_info_t *highsync_info;
143 KIRQL old_irql;
145 UNREFERENCED_PARAMETER(context);
146 FUNCTION_ENTER();
148 highsync_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(highsync_info_t), XENPCI_POOL_TAG);
149 RtlZeroMemory(highsync_info, sizeof(highsync_info_t));
150 KeInitializeEvent(&highsync_info->highsync_complete_event, SynchronizationEvent, FALSE);
151 highsync_info->function0 = function0;
152 highsync_info->functionN = functionN;
153 highsync_info->context = context;
154 highsync_info->sync_level = HIGH_LEVEL;
156 #if (NTDDI_VERSION >= NTDDI_WINXP)
157 ActiveProcessorCount = (ULONG)KeNumberProcessors;
158 #else
159 ActiveProcessorCount = (ULONG)*KeNumberProcessors;
160 #endif
162 /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */
163 KeRaiseIrql(highsync_info->sync_level, &old_irql);
165 highsync_info->do_spin = TRUE;
166 for (i = 0; i < ActiveProcessorCount; i++) {
167 if (i == 0)
168 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunction0, highsync_info);
169 else
170 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunctionN, highsync_info);
171 KeSetTargetProcessorDpc(&highsync_info->dpcs[i], (CCHAR)i);
172 KeSetImportanceDpc(&highsync_info->dpcs[i], HighImportance);
173 FUNCTION_MSG("queuing Dpc for CPU %d\n", i);
174 KeInsertQueueDpc(&highsync_info->dpcs[i], NULL, NULL);
175 }
176 FUNCTION_MSG("All Dpc's queued\n");
178 KeMemoryBarrier();
179 KeLowerIrql(old_irql);
181 FUNCTION_MSG("Waiting for highsync_complete_event\n");
182 KeWaitForSingleObject(&highsync_info->highsync_complete_event, Executive, KernelMode, FALSE, NULL);
183 #if (NTDDI_VERSION >= NTDDI_WINXP)
184 KeFlushQueuedDpcs();
185 #else
186 {
187 /* just wait 1 second until all DPC's finish - not ideal but it's only for W2K */
188 LARGE_INTEGER interval;
189 interval.QuadPart = -1 * 1000 * 1000 * 10; /* 1 second */
190 KeDelayExecutionThread(KernelMode, FALSE, &interval);
191 }
192 #endif
193 ExFreePoolWithTag(highsync_info, XENPCI_POOL_TAG);
194 FUNCTION_EXIT();
195 }