VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxService/VBoxServicePageSharing.cpp@ 30064

Last change on this file since 30064 was 30037, checked in by vboxsync, 15 years ago

Redundant logging

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.8 KB
Line 
1/* $Id: VBoxServicePageSharing.cpp 30037 2010-06-04 13:36:41Z vboxsync $ */
2/** @file
3 * VBoxService - Guest page sharing.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <iprt/assert.h>
23#include <iprt/avl.h>
24#include <iprt/asm.h>
25#include <iprt/mem.h>
26#include <iprt/stream.h>
27#include <iprt/file.h>
28#include <iprt/string.h>
29#include <iprt/semaphore.h>
30#include <iprt/system.h>
31#include <iprt/thread.h>
32#include <iprt/time.h>
33#include <VBox/VBoxGuestLib.h>
34#include "VBoxServiceInternal.h"
35#include "VBoxServiceUtils.h"
36
37
38/*******************************************************************************
39* Global Variables *
40*******************************************************************************/
41
42/** The semaphore we're blocking on. */
43static RTSEMEVENTMULTI g_PageSharingEvent = NIL_RTSEMEVENTMULTI;
44
45#if defined(RT_OS_WINDOWS) && !defined(TARGET_NT4)
46#include <tlhelp32.h>
47#include <psapi.h>
48#include <winternl.h>
49
50typedef struct
51{
52 AVLPVNODECORE Core;
53 HMODULE hModule;
54 char szFileVersion[16];
55 MODULEENTRY32 Info;
56} KNOWN_MODULE, *PKNOWN_MODULE;
57
58#define SystemModuleInformation 11
59
60typedef struct _RTL_PROCESS_MODULE_INFORMATION
61{
62 ULONG Section;
63 PVOID MappedBase;
64 PVOID ImageBase;
65 ULONG ImageSize;
66 ULONG Flags;
67 USHORT LoadOrderIndex;
68 USHORT InitOrderIndex;
69 USHORT LoadCount;
70 USHORT OffsetToFileName;
71 CHAR FullPathName[256];
72} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
73
74typedef struct _RTL_PROCESS_MODULES
75{
76 ULONG NumberOfModules;
77 RTL_PROCESS_MODULE_INFORMATION Modules[1];
78} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
79
80typedef NTSTATUS (WINAPI *PFNZWQUERYSYSTEMINFORMATION)(ULONG, PVOID, ULONG, PULONG);
81static PFNZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
82static HMODULE hNtdll = 0;
83
84
85static DECLCALLBACK(int) VBoxServicePageSharingEmptyTreeCallback(PAVLPVNODECORE pNode, void *);
86
87static PAVLPVNODECORE pKnownModuleTree = NULL;
88
89/**
90 * Registers a new module with the VMM
91 * @param pModule Module ptr
92 * @param fValidateMemory Validate/touch memory pages or not
93 */
94void VBoxServicePageSharingRegisterModule(PKNOWN_MODULE pModule, bool fValidateMemory)
95{
96 VMMDEVSHAREDREGIONDESC aRegions[VMMDEVSHAREDREGIONDESC_MAX];
97 DWORD dwModuleSize = pModule->Info.modBaseSize;
98 BYTE *pBaseAddress = pModule->Info.modBaseAddr;
99 DWORD cbVersionSize, dummy;
100 BYTE *pVersionInfo;
101
102 VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule\n");
103
104 cbVersionSize = GetFileVersionInfoSize(pModule->Info.szExePath, &dummy);
105 if (!cbVersionSize)
106 {
107 VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: GetFileVersionInfoSize failed with %d\n", GetLastError());
108 return;
109 }
110 pVersionInfo = (BYTE *)RTMemAlloc(cbVersionSize);
111 if (!pVersionInfo)
112 return;
113
114 if (!GetFileVersionInfo(pModule->Info.szExePath, 0, cbVersionSize, pVersionInfo))
115 {
116 VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: GetFileVersionInfo failed with %d\n", GetLastError());
117 goto end;
118 }
119
120 /* Fetch default code page. */
121 struct LANGANDCODEPAGE {
122 WORD wLanguage;
123 WORD wCodePage;
124 } *lpTranslate;
125
126 UINT cbTranslate;
127 BOOL ret = VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"), (LPVOID *)&lpTranslate, &cbTranslate);
128 if ( !ret
129 || cbTranslate < 4)
130 {
131 VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: VerQueryValue failed with %d (cb=%d)\n", GetLastError(), cbTranslate);
132 goto end;
133 }
134
135 unsigned i;
136 UINT cbFileVersion;
137 char *lpszFileVersion;
138 unsigned cTranslationBlocks = cbTranslate/sizeof(struct LANGANDCODEPAGE);
139
140 for(i = 0; i < cTranslationBlocks; i++)
141 {
142 /* Fetch file version string. */
143 char szFileVersionLocation[256];
144
145 sprintf(szFileVersionLocation, TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"), lpTranslate[i].wLanguage, lpTranslate[i].wCodePage);
146 ret = VerQueryValue(pVersionInfo, szFileVersionLocation, (LPVOID *)&lpszFileVersion, &cbFileVersion);
147 if (ret)
148 break;
149 }
150 if (i == cTranslationBlocks)
151 {
152 VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: no file version found!\n");
153 goto end;
154 }
155
156 _snprintf(pModule->szFileVersion, sizeof(pModule->szFileVersion), "%s", lpszFileVersion);
157 pModule->szFileVersion[RT_ELEMENTS(pModule->szFileVersion) - 1] = 0;
158
159 unsigned idxRegion = 0;
160
161 if (fValidateMemory)
162 {
163 do
164 {
165 MEMORY_BASIC_INFORMATION MemInfo;
166
167 SIZE_T ret = VirtualQuery(pBaseAddress, &MemInfo, sizeof(MemInfo));
168 Assert(ret);
169 if (!ret)
170 {
171 VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: VirtualQueryEx failed with %d\n", GetLastError());
172 break;
173 }
174
175 if ( MemInfo.State == MEM_COMMIT
176 && MemInfo.Type == MEM_IMAGE)
177 {
178 switch (MemInfo.Protect)
179 {
180 case PAGE_EXECUTE:
181 case PAGE_EXECUTE_READ:
182 case PAGE_READONLY:
183 {
184 char *pRegion = (char *)MemInfo.BaseAddress;
185
186 /* Skip the first region as it only contains the image file header. */
187 if (pRegion != (char *)pModule->Info.modBaseAddr)
188 {
189 /* Touch all pages. */
190 while (pRegion < (char *)MemInfo.BaseAddress + MemInfo.RegionSize)
191 {
192 /* Try to trick the optimizer to leave the page touching code in place. */
193 ASMProbeReadByte(pRegion);
194 pRegion += PAGE_SIZE;
195 }
196 }
197#ifdef RT_ARCH_X86
198 aRegions[idxRegion].GCRegionAddr = (RTGCPTR32)MemInfo.BaseAddress;
199#else
200 aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)MemInfo.BaseAddress;
201#endif
202 aRegions[idxRegion].cbRegion = MemInfo.RegionSize;
203 idxRegion++;
204
205 break;
206 }
207
208 default:
209 break; /* ignore */
210 }
211 }
212
213 pBaseAddress = (BYTE *)MemInfo.BaseAddress + MemInfo.RegionSize;
214 if (dwModuleSize > MemInfo.RegionSize)
215 {
216 dwModuleSize -= MemInfo.RegionSize;
217 }
218 else
219 {
220 dwModuleSize = 0;
221 break;
222 }
223
224 if (idxRegion >= RT_ELEMENTS(aRegions))
225 break; /* out of room */
226 }
227 while (dwModuleSize);
228 }
229 else
230 {
231 /* We can't probe kernel memory ranges, so pretend it's one big region. */
232#ifdef RT_ARCH_X86
233 aRegions[idxRegion].GCRegionAddr = (RTGCPTR32)pBaseAddress;
234#else
235 aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)pBaseAddress;
236#endif
237 aRegions[idxRegion].cbRegion = dwModuleSize;
238 idxRegion++;
239 }
240 VBoxServiceVerbose(3, "VbglR3RegisterSharedModule %s %s base=%p size=%x cregions=%d\n", pModule->Info.szModule, pModule->szFileVersion, pModule->Info.modBaseAddr, pModule->Info.modBaseSize, idxRegion);
241#ifdef RT_ARCH_X86
242 int rc = VbglR3RegisterSharedModule(pModule->Info.szModule, pModule->szFileVersion, (RTGCPTR32)pModule->Info.modBaseAddr,
243 pModule->Info.modBaseSize, idxRegion, aRegions);
244#else
245 int rc = VbglR3RegisterSharedModule(pModule->Info.szModule, pModule->szFileVersion, (RTGCPTR64)pModule->Info.modBaseAddr,
246 pModule->Info.modBaseSize, idxRegion, aRegions);
247#endif
248
249// AssertRC(rc);
250 if (RT_FAILURE(rc))
251 VBoxServiceVerbose(3, "VbglR3RegisterSharedModule failed with %d\n", rc);
252
253end:
254 RTMemFree(pVersionInfo);
255 return;
256}
257
258/**
259 * Inspect all loaded modules for the specified process
260 * @param dwProcessId Process id
261 */
262void VBoxServicePageSharingInspectModules(DWORD dwProcessId, PAVLPVNODECORE *ppNewTree)
263{
264 HANDLE hProcess, hSnapshot;
265
266 /* Get a list of all the modules in this process. */
267 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
268 FALSE /* no child process handle inheritance */, dwProcessId);
269 if (hProcess == NULL)
270 {
271 VBoxServiceVerbose(3, "VBoxServicePageSharingInspectModules: OpenProcess %x failed with %d\n", dwProcessId, GetLastError());
272 return;
273 }
274
275 hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
276 if (hSnapshot == INVALID_HANDLE_VALUE)
277 {
278 VBoxServiceVerbose(3, "VBoxServicePageSharingInspectModules: CreateToolhelp32Snapshot failed with %d\n", GetLastError());
279 CloseHandle(hProcess);
280 return;
281 }
282
283 VBoxServiceVerbose(3, "VBoxServicePageSharingInspectModules\n");
284
285 MODULEENTRY32 ModuleInfo;
286 BOOL bRet;
287
288 ModuleInfo.dwSize = sizeof(ModuleInfo);
289 bRet = Module32First(hSnapshot, &ModuleInfo);
290 do
291 {
292 /** todo when changing this make sure VBoxService.exe is excluded! */
293 char *pszDot = strrchr(ModuleInfo.szModule, '.');
294 if ( pszDot
295 && (pszDot[1] == 'e' || pszDot[1] == 'E'))
296 continue; /* ignore executables for now. */
297
298 /* Found it before? */
299 PAVLPVNODECORE pRec = RTAvlPVGet(ppNewTree, ModuleInfo.modBaseAddr);
300 if (!pRec)
301 {
302 pRec = RTAvlPVRemove(&pKnownModuleTree, ModuleInfo.modBaseAddr);
303 if (!pRec)
304 {
305 /* New module; register it. */
306 PKNOWN_MODULE pModule = (PKNOWN_MODULE)RTMemAllocZ(sizeof(*pModule));
307 Assert(pModule);
308 if (!pModule)
309 break;
310
311 pModule->Info = ModuleInfo;
312 pModule->Core.Key = ModuleInfo.modBaseAddr;
313 pModule->hModule = LoadLibraryEx(ModuleInfo.szExePath, 0, DONT_RESOLVE_DLL_REFERENCES);
314 if (pModule->hModule)
315 VBoxServicePageSharingRegisterModule(pModule, true /* validate pages */);
316
317 VBoxServiceVerbose(3, "\n\n MODULE NAME: %s", ModuleInfo.szModule );
318 VBoxServiceVerbose(3, "\n executable = %s", ModuleInfo.szExePath );
319 VBoxServiceVerbose(3, "\n process ID = 0x%08X", ModuleInfo.th32ProcessID );
320 VBoxServiceVerbose(3, "\n base address = 0x%08X", (DWORD) ModuleInfo.modBaseAddr );
321 VBoxServiceVerbose(3, "\n base size = %d", ModuleInfo.modBaseSize );
322
323 pRec = &pModule->Core;
324 }
325 bool ret = RTAvlPVInsert(ppNewTree, pRec);
326 Assert(ret); NOREF(ret);
327 }
328 }
329 while (Module32Next(hSnapshot, &ModuleInfo));
330
331 CloseHandle(hSnapshot);
332 CloseHandle(hProcess);
333}
334
335/**
336 * Inspect all running processes for executables and dlls that might be worth sharing
337 * with other VMs.
338 *
339 */
340void VBoxServicePageSharingInspectGuest()
341{
342 HANDLE hSnapshot;
343 PAVLPVNODECORE pNewTree = NULL;
344 DWORD dwProcessId = GetCurrentProcessId();
345
346 VBoxServiceVerbose(3, "VBoxServicePageSharingInspectGuest\n");
347
348 hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
349 if (hSnapshot == INVALID_HANDLE_VALUE)
350 {
351 VBoxServiceVerbose(3, "CreateToolhelp32Snapshot failed with %d\n", GetLastError());
352 return;
353 }
354
355 /* Check loaded modules for all running processes. */
356 PROCESSENTRY32 ProcessInfo;
357
358 ProcessInfo.dwSize = sizeof(ProcessInfo);
359 Process32First(hSnapshot, &ProcessInfo);
360
361 do
362 {
363 /* Skip our own process. */
364 if (ProcessInfo.th32ProcessID != dwProcessId)
365 VBoxServicePageSharingInspectModules(ProcessInfo.th32ProcessID, &pNewTree);
366 }
367 while (Process32Next(hSnapshot, &ProcessInfo));
368
369 CloseHandle(hSnapshot);
370
371 /* Check all loaded kernel modules. */
372 if (ZwQuerySystemInformation)
373 {
374 ULONG cbBuffer = 0;
375 PVOID pBuffer = NULL;
376 PRTL_PROCESS_MODULES pSystemModules;
377
378 NTSTATUS ret = ZwQuerySystemInformation(SystemModuleInformation, (PVOID)&cbBuffer, 0, &cbBuffer);
379 if (!cbBuffer)
380 {
381 VBoxServiceVerbose(1, "ZwQuerySystemInformation returned length 0\n");
382 goto skipkernelmodules;
383 }
384
385 pBuffer = RTMemAllocZ(cbBuffer);
386 if (!pBuffer)
387 goto skipkernelmodules;
388
389 ret = ZwQuerySystemInformation(SystemModuleInformation, pBuffer, cbBuffer, &cbBuffer);
390 if (ret != STATUS_SUCCESS)
391 {
392 VBoxServiceVerbose(1, "ZwQuerySystemInformation returned %x (1)\n", ret);
393 goto skipkernelmodules;
394 }
395
396 pSystemModules = (PRTL_PROCESS_MODULES)pBuffer;
397 for (unsigned i = 0; i < pSystemModules->NumberOfModules; i++)
398 {
399 VBoxServiceVerbose(4, "\n\n KERNEL MODULE NAME: %s", pSystemModules->Modules[i].FullPathName[pSystemModules->Modules[i].OffsetToFileName] );
400 VBoxServiceVerbose(4, "\n executable = %s", pSystemModules->Modules[i].FullPathName );
401 VBoxServiceVerbose(4, "\n flags = 0x%08X\n", pSystemModules->Modules[i].Flags);
402
403 /* User-mode modules seem to have no flags set; skip them as we detected them above. */
404 if (pSystemModules->Modules[i].Flags == 0)
405 continue;
406
407 /* Found it before? */
408 PAVLPVNODECORE pRec = RTAvlPVGet(&pNewTree, pSystemModules->Modules[i].ImageBase);
409 if (!pRec)
410 {
411 pRec = RTAvlPVRemove(&pKnownModuleTree, pSystemModules->Modules[i].ImageBase);
412 if (!pRec)
413 {
414 /* New module; register it. */
415 char szFullFilePath[512];
416 PKNOWN_MODULE pModule = (PKNOWN_MODULE)RTMemAllocZ(sizeof(*pModule));
417 Assert(pModule);
418 if (!pModule)
419 break;
420
421 strcpy(pModule->Info.szModule, &pSystemModules->Modules[i].FullPathName[pSystemModules->Modules[i].OffsetToFileName]);
422 GetSystemDirectoryA(szFullFilePath, sizeof(szFullFilePath));
423
424 /* skip \Systemroot\system32 */
425 char *lpPath = strchr(&pSystemModules->Modules[i].FullPathName[1], '\\');
426 if (!lpPath)
427 {
428 /* Seen just file names in XP; try to locate the file in the system32 and system32\drivers directories. */
429 strcat(szFullFilePath, "\\");
430 strcat(szFullFilePath, pSystemModules->Modules[i].FullPathName);
431 VBoxServiceVerbose(3, "Unexpected kernel module name try %s\n", szFullFilePath);
432 if (RTFileExists(szFullFilePath) == false)
433 {
434 GetSystemDirectoryA(szFullFilePath, sizeof(szFullFilePath));
435 strcat(szFullFilePath, "\\drivers\\");
436 strcat(szFullFilePath, pSystemModules->Modules[i].FullPathName);
437 VBoxServiceVerbose(3, "Unexpected kernel module name try %s\n", szFullFilePath);
438 if (RTFileExists(szFullFilePath) == false)
439 {
440 VBoxServiceVerbose(1, "Unexpected kernel module name %s\n", pSystemModules->Modules[i].FullPathName);
441 RTMemFree(pModule);
442 continue;
443 }
444 }
445 }
446 else
447 {
448 lpPath = strchr(lpPath+1, '\\');
449 if (!lpPath)
450 {
451 VBoxServiceVerbose(1, "Unexpected kernel module name %s (2)\n", pSystemModules->Modules[i].FullPathName);
452 RTMemFree(pModule);
453 continue;
454 }
455
456 strcat(szFullFilePath, lpPath);
457 }
458
459 strcpy(pModule->Info.szExePath, szFullFilePath);
460 pModule->Info.modBaseAddr = (BYTE *)pSystemModules->Modules[i].ImageBase;
461 pModule->Info.modBaseSize = pSystemModules->Modules[i].ImageSize;
462
463 pModule->Core.Key = pSystemModules->Modules[i].ImageBase;
464 VBoxServicePageSharingRegisterModule(pModule, false /* don't check memory pages */);
465
466 VBoxServiceVerbose(3, "\n\n KERNEL MODULE NAME: %s", pModule->Info.szModule );
467 VBoxServiceVerbose(3, "\n executable = %s", pModule->Info.szExePath );
468 VBoxServiceVerbose(3, "\n base address = 0x%08X", (DWORD) pModule->Info.modBaseAddr );
469 VBoxServiceVerbose(3, "\n flags = 0x%08X", pSystemModules->Modules[i].Flags);
470 VBoxServiceVerbose(3, "\n base size = %d", pModule->Info.modBaseSize );
471
472 pRec = &pModule->Core;
473 }
474 bool ret = RTAvlPVInsert(&pNewTree, pRec);
475 Assert(ret); NOREF(ret);
476 }
477 }
478skipkernelmodules:
479 if (pBuffer)
480 RTMemFree(pBuffer);
481 }
482
483 /* Delete leftover modules in the old tree. */
484 RTAvlPVDestroy(&pKnownModuleTree, VBoxServicePageSharingEmptyTreeCallback, NULL);
485
486 /* Check all registered modules. */
487 VbglR3CheckSharedModules();
488
489 /* Activate new module tree. */
490 pKnownModuleTree = pNewTree;
491}
492
493/**
494 * RTAvlPVDestroy callback.
495 */
496static DECLCALLBACK(int) VBoxServicePageSharingEmptyTreeCallback(PAVLPVNODECORE pNode, void *)
497{
498 PKNOWN_MODULE pModule = (PKNOWN_MODULE)pNode;
499
500 VBoxServiceVerbose(3, "VBoxServicePageSharingEmptyTreeCallback %s %s\n", pModule->Info.szModule, pModule->szFileVersion);
501
502 /* Defererence module in the hypervisor. */
503 int rc = VbglR3UnregisterSharedModule(pModule->Info.szModule, pModule->szFileVersion, (RTGCPTR64)pModule->Info.modBaseAddr, pModule->Info.modBaseSize);
504 AssertRC(rc);
505
506 if (pModule->hModule)
507 FreeLibrary(pModule->hModule);
508 RTMemFree(pNode);
509 return 0;
510}
511
512
513#elif TARGET_NT4
514void VBoxServicePageSharingInspectGuest()
515{
516 /* not implemented */
517}
518#else
519void VBoxServicePageSharingInspectGuest()
520{
521 /* @todo other platforms */
522}
523#endif
524
525/** @copydoc VBOXSERVICE::pfnPreInit */
526static DECLCALLBACK(int) VBoxServicePageSharingPreInit(void)
527{
528 return VINF_SUCCESS;
529}
530
531
532/** @copydoc VBOXSERVICE::pfnOption */
533static DECLCALLBACK(int) VBoxServicePageSharingOption(const char **ppszShort, int argc, char **argv, int *pi)
534{
535 NOREF(ppszShort);
536 NOREF(argc);
537 NOREF(argv);
538 NOREF(pi);
539 return VINF_SUCCESS;
540}
541
542
543/** @copydoc VBOXSERVICE::pfnInit */
544static DECLCALLBACK(int) VBoxServicePageSharingInit(void)
545{
546 VBoxServiceVerbose(3, "VBoxServicePageSharingInit\n");
547
548 int rc = RTSemEventMultiCreate(&g_PageSharingEvent);
549 AssertRCReturn(rc, rc);
550
551#if defined(RT_OS_WINDOWS) && !defined(TARGET_NT4)
552 hNtdll = LoadLibrary("ntdll.dll");
553
554 if (hNtdll)
555 ZwQuerySystemInformation = (PFNZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll, "ZwQuerySystemInformation");
556#endif
557
558 /* @todo report system name and version */
559 /* Never fail here. */
560 return VINF_SUCCESS;
561}
562
563/** @copydoc VBOXSERVICE::pfnWorker */
564DECLCALLBACK(int) VBoxServicePageSharingWorker(bool volatile *pfShutdown)
565{
566 /*
567 * Tell the control thread that it can continue
568 * spawning services.
569 */
570 RTThreadUserSignal(RTThreadSelf());
571
572 /*
573 * Block here first for a minute as using DONT_RESOLVE_DLL_REFERENCES is kind of risky; other code that uses LoadLibrary on a dll loaded like this
574 * before will end up crashing the process as the dll's init routine was never called.
575 *
576 * We have to use this feature as we can't simply execute all init code in our service process.
577 *
578 */
579 int rc = RTSemEventMultiWait(g_PageSharingEvent, 60000);
580 if (*pfShutdown)
581 goto end;
582
583 if (rc != VERR_TIMEOUT && RT_FAILURE(rc))
584 {
585 VBoxServiceError("RTSemEventMultiWait failed; rc=%Rrc\n", rc);
586 goto end;
587 }
588
589 /*
590 * Now enter the loop retrieving runtime data continuously.
591 */
592 for (;;)
593 {
594 VBoxServiceVerbose(3, "VBoxServicePageSharingWorker: enabled=%d\n", VbglR3PageSharingIsEnabled());
595
596 if (VbglR3PageSharingIsEnabled())
597 VBoxServicePageSharingInspectGuest();
598
599 /*
600 * Block for a minute.
601 *
602 * The event semaphore takes care of ignoring interruptions and it
603 * allows us to implement service wakeup later.
604 */
605 if (*pfShutdown)
606 break;
607 rc = RTSemEventMultiWait(g_PageSharingEvent, 60000);
608 if (*pfShutdown)
609 break;
610 if (rc != VERR_TIMEOUT && RT_FAILURE(rc))
611 {
612 VBoxServiceError("RTSemEventMultiWait failed; rc=%Rrc\n", rc);
613 break;
614 }
615 }
616
617end:
618 RTSemEventMultiDestroy(g_PageSharingEvent);
619 g_PageSharingEvent = NIL_RTSEMEVENTMULTI;
620
621 VBoxServiceVerbose(3, "VBoxServicePageSharingWorker: finished thread\n");
622 return 0;
623}
624
625/** @copydoc VBOXSERVICE::pfnTerm */
626static DECLCALLBACK(void) VBoxServicePageSharingTerm(void)
627{
628 VBoxServiceVerbose(3, "VBoxServicePageSharingTerm\n");
629
630#if defined(RT_OS_WINDOWS) && !defined(TARGET_NT4)
631 if (hNtdll)
632 FreeLibrary(hNtdll);
633#endif
634 return;
635}
636
637
638/** @copydoc VBOXSERVICE::pfnStop */
639static DECLCALLBACK(void) VBoxServicePageSharingStop(void)
640{
641 RTSemEventMultiSignal(g_PageSharingEvent);
642}
643
644
645/**
646 * The 'pagesharing' service description.
647 */
648VBOXSERVICE g_PageSharing =
649{
650 /* pszName. */
651 "pagesharing",
652 /* pszDescription. */
653 "Page Sharing",
654 /* pszUsage. */
655 NULL,
656 /* pszOptions. */
657 NULL,
658 /* methods */
659 VBoxServicePageSharingPreInit,
660 VBoxServicePageSharingOption,
661 VBoxServicePageSharingInit,
662 VBoxServicePageSharingWorker,
663 VBoxServicePageSharingStop,
664 VBoxServicePageSharingTerm
665};
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette