blob: 3e47307d1de6e7e78f62675f34edd19fee896da9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
/* $Id$ */
/** @file
* VirtualBox API client session watcher
*/
/*
* Copyright (C) 2013-2016 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#ifndef ____H_CLIENTWATCHER
#define ____H_CLIENTWATCHER
#include <list>
#include <VBox/com/ptr.h>
#include <VBox/com/AutoLock.h>
#include "VirtualBoxImpl.h"
#if defined(RT_OS_WINDOWS)
# define CWUPDATEREQARG NULL
# define CWUPDATEREQTYPE HANDLE
# define CW_MAX_CLIENTS _16K /**< Max number of clients we can watch (windows). */
# ifndef DEBUG /* The debug version triggers worker thread code much much earlier. */
# define CW_MAX_CLIENTS_PER_THREAD 63 /**< Max clients per watcher thread (windows). */
# else
# define CW_MAX_CLIENTS_PER_THREAD 3 /**< Max clients per watcher thread (windows). */
# endif
# define CW_MAX_HANDLES_PER_THREAD (CW_MAX_CLIENTS_PER_THREAD + 1) /**< Max handles per thread. */
#elif defined(RT_OS_OS2)
# define CWUPDATEREQARG NIL_RTSEMEVENT
# define CWUPDATEREQTYPE RTSEMEVENT
#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
# define CWUPDATEREQARG NIL_RTSEMEVENT
# define CWUPDATEREQTYPE RTSEMEVENT
#else
# error "Port me!"
#endif
/**
* Class which checks for API clients which have crashed/exited, and takes
* the necessary cleanup actions. Singleton.
*/
class VirtualBox::ClientWatcher
{
public:
/**
* Constructor which creates a usable instance
*
* @param pVirtualBox Reference to VirtualBox object
*/
ClientWatcher(const ComObjPtr<VirtualBox> &pVirtualBox);
/**
* Default destructor. Cleans everything up.
*/
~ClientWatcher();
bool isReady();
void update();
void addProcess(RTPROCESS pid);
private:
/**
* Default constructor. Don't use, will not create a sensible instance.
*/
ClientWatcher();
static DECLCALLBACK(int) worker(RTTHREAD hThreadSelf, void *pvUser);
uint32_t reapProcesses(void);
VirtualBox *mVirtualBox;
RTTHREAD mThread;
CWUPDATEREQTYPE mUpdateReq;
util::RWLockHandle mLock;
typedef std::list<RTPROCESS> ProcessList;
ProcessList mProcesses;
#if defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
uint8_t mUpdateAdaptCtr;
#endif
#ifdef RT_OS_WINDOWS
/** Indicate a real update request is pending.
* To avoid race conditions this must be set before mUpdateReq is signalled and
* read after resetting mUpdateReq. */
volatile bool mfUpdateReq;
/** Set when the worker threads are supposed to shut down. */
volatile bool mfTerminate;
/** Number of active subworkers.
* When decremented to 0, subworker zero is signalled. */
uint32_t volatile mcActiveSubworkers;
/** Number of valid handles in mahWaitHandles. */
uint32_t mcWaitHandles;
/** The wait interval (usually INFINITE). */
uint32_t mcMsWait;
/** Per subworker data. Subworker 0 is the main worker and does not have a
* pReq pointer since. */
struct PerSubworker
{
/** The wait result. */
DWORD dwWait;
/** The subworker index. */
uint32_t iSubworker;
/** The subworker thread handle. */
RTTHREAD hThread;
/** Self pointer (for worker thread). */
VirtualBox::ClientWatcher *pSelf;
} maSubworkers[(CW_MAX_CLIENTS + CW_MAX_CLIENTS_PER_THREAD - 1) / CW_MAX_CLIENTS_PER_THREAD];
/** Wait handle array. The mUpdateReq manual reset event handle is inserted
* every 64 entries, first entry being 0. */
HANDLE mahWaitHandles[CW_MAX_CLIENTS + (CW_MAX_CLIENTS + CW_MAX_CLIENTS_PER_THREAD - 1) / CW_MAX_CLIENTS_PER_THREAD];
void subworkerWait(VirtualBox::ClientWatcher::PerSubworker *pSubworker, uint32_t cMsWait);
static DECLCALLBACK(int) subworkerThread(RTTHREAD hThreadSelf, void *pvUser);
void winResetHandleArray(uint32_t cProcHandles);
#endif
};
#endif /* !____H_CLIENTWATCHER */
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
|