summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/include/HGCMThread.h
blob: d547fed43eecef2946211a2fe64bdea3b5c6e6e6 (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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/* $Id: HGCMThread.h $ */
/** @file
 * HGCMThread - Host-Guest Communication Manager worker threads header.
 */

/*
 * Copyright (C) 2006-2022 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * SPDX-License-Identifier: GPL-3.0-only
 */

#ifndef MAIN_INCLUDED_HGCMThread_h
#define MAIN_INCLUDED_HGCMThread_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#include <VBox/types.h>

#include "HGCMObjects.h"

/* Forward declaration of the worker thread class. */
class HGCMThread;

/** A handle for HGCM message. */
typedef uint32_t HGCMMSGHANDLE;

/* Forward declaration of message core class. */
class HGCMMsgCore;

/** @todo comment */

typedef HGCMMsgCore *FNHGCMNEWMSGALLOC(uint32_t u32MsgId);
typedef FNHGCMNEWMSGALLOC *PFNHGCMNEWMSGALLOC;

/** Function that is called after message processing by worker thread,
 *  or if an error occurred during message handling after successfully
 *  posting (hgcmMsgPost) the message to worker thread.
 *
 * @param result    Return code either from the service which actually processed the message
 *                  or from HGCM.
 * @param pMsgCore  Pointer to just processed message.
 *
 * @return Restricted set of VBox status codes when guest call message:
 * @retval VINF_SUCCESS on success
 * @retval VERR_CANCELLED if the request was cancelled.
 * @retval VERR_ALREADY_RESET if the VM is resetting.
 * @retval VERR_NOT_AVAILABLE if HGCM has been disconnected from the VMMDev
 *         (shouldn't happen).
 */
typedef DECLCALLBACKTYPE(int, FNHGCMMSGCALLBACK,(int32_t result, HGCMMsgCore *pMsgCore));
/** Pointer to a message completeion callback function. */
typedef FNHGCMMSGCALLBACK *PFNHGCMMSGCALLBACK;


/** HGCM core message. */
class HGCMMsgCore : public HGCMReferencedObject
{
    private:
        friend class HGCMThread;

        /** Version of message header. */
        uint32_t m_u32Version;

        /** Message number/identifier. */
        uint32_t m_u32Msg;

        /** Thread the message belongs to, referenced by the message. */
        HGCMThread *m_pThread;

        /** Callback function pointer. */
        PFNHGCMMSGCALLBACK m_pfnCallback;

        /** Next element in a message queue. */
        HGCMMsgCore *m_pNext;
        /** Previous element in a message queue.
         *  @todo seems not necessary. */
        HGCMMsgCore *m_pPrev;

        /** Various internal flags. */
        uint32_t m_fu32Flags;

        /** Result code for a Send */
        int32_t m_rcSend;

    protected:
        void InitializeCore(uint32_t u32MsgId, HGCMThread *pThread);

        virtual ~HGCMMsgCore();

    public:
        HGCMMsgCore() : HGCMReferencedObject(HGCMOBJ_MSG) {};

        uint32_t MsgId(void) { return m_u32Msg; };

        HGCMThread *Thread(void) { return m_pThread; };

        /** Initialize message after it was allocated. */
        virtual void Initialize(void) {};

        /** Uninitialize message. */
        virtual void Uninitialize(void) {};
};


/** HGCM worker thread function.
 *
 *  @param pThread       The HGCM thread instance.
 *  @param pvUser        User specified thread parameter.
 */
typedef DECLCALLBACKTYPE(void, FNHGCMTHREAD,(HGCMThread *pThread, void *pvUser));
typedef FNHGCMTHREAD *PFNHGCMTHREAD;


/**
 * Thread API.
 * Based on thread handles. Internals of a thread are not exposed to users.
 */

/** Initialize threads.
 *
 * @return VBox status code.
 */
int hgcmThreadInit(void);
void hgcmThreadUninit(void);


/** Create a HGCM worker thread.
 *
 * @param ppThread          Where to return the pointer to the worker thread.
 * @param pszThreadName     Name of the thread, needed by runtime.
 * @param pfnThread         The worker thread function.
 * @param pvUser            A pointer passed to worker thread.
 * @param pszStatsSubDir    The "sub-directory" under "/HGCM/" where thread
 *                          statistics should be registered.  The caller,
 *                          HGCMService, will deregister them.  NULL if no stats.
 * @param pUVM              The user mode VM handle to register statistics with.
 *                          NULL if no stats.
 * @param pVMM              The VMM vtable for statistics registration. NULL if
 *                          no stats.
 *
 * @return VBox status code.
 */
int hgcmThreadCreate(HGCMThread **ppThread, const char *pszThreadName, PFNHGCMTHREAD pfnThread, void *pvUser,
                     const char *pszStatsSubDir, PUVM pUVM, PCVMMR3VTABLE pVMM);

/** Wait for termination of a HGCM worker thread.
 *
 * @param pThread       The HGCM thread.  The passed in reference is always
 *                      consumed.
 *
 * @return VBox status code.
 */
int hgcmThreadWait(HGCMThread *pThread);

/** Allocate a message to be posted to HGCM worker thread.
 *
 * @param pThread       The HGCM worker thread.
 * @param ppHandle      Where to store the pointer to the new message.
 * @param u32MsgId      Message identifier.
 * @param pfnNewMessage New message allocation callback.
 *
 * @return VBox status code.
 */
int hgcmMsgAlloc(HGCMThread *pThread, HGCMMsgCore **ppHandle, uint32_t u32MsgId, PFNHGCMNEWMSGALLOC pfnNewMessage);

/** Post a message to HGCM worker thread.
 *
 * @param pMsg          The message.  Reference will be consumed!
 * @param pfnCallback   Message completion callback.
 *
 * @return VBox status code.
 * @retval VINF_HGCM_ASYNC_EXECUTE on success.
 *
 * @thread any
 */
int hgcmMsgPost(HGCMMsgCore *pMsg, PFNHGCMMSGCALLBACK pfnCallback);

/** Send a message to HGCM worker thread.
 *
 *  The function will return after message is processed by thread.
 *
 * @param pMsg          The message.  Reference will be consumed!
 *
 * @return VBox status code.
 *
 * @thread any
 */
int hgcmMsgSend(HGCMMsgCore *pMsg);


/* Wait for and get a message.
 *
 * @param pThread       The HGCM worker thread.
 * @param ppMsg         Where to store returned message pointer.
 *
 * @return VBox status code.
 *
 * @thread worker thread
 */
int hgcmMsgGet(HGCMThread *pThread, HGCMMsgCore **ppMsg);


/** Worker thread has processed a message previously obtained with hgcmMsgGet.
 *
 * @param pMsg          Processed message pointer.
 * @param result        Result code, VBox status code.
 *
 * @return Restricted set of VBox status codes when guest call message:
 * @retval VINF_SUCCESS on success
 * @retval VERR_CANCELLED if the request was cancelled.
 * @retval VERR_ALREADY_RESET if the VM is resetting.
 * @retval VERR_NOT_AVAILABLE if HGCM has been disconnected from the VMMDev
 *         (shouldn't happen).
 *
 * @thread worker thread
 */
int hgcmMsgComplete(HGCMMsgCore *pMsg, int32_t result);


#endif /* !MAIN_INCLUDED_HGCMThread_h */