VirtualBox

source: vbox/trunk/include/iprt/req.h@ 39654

Last change on this file since 39654 was 39632, checked in by vboxsync, 13 years ago

Most of the reqpool code is there now. The testcase didn't turn up any bad bugs yet, so there must be some pretty bad stuff hiding in there. according to the rules...

  • Property eol-style set to native
  • Property svn:eol-style set to native
File size: 19.0 KB
Line 
1/** @file
2 * IPRT - Request Queue & Pool.
3 */
4
5/*
6 * Copyright (C) 2006-2011 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef ___iprt_req_h
27#define ___iprt_req_h
28
29#include <iprt/cdefs.h>
30#include <iprt/types.h>
31
32#include <iprt/stdarg.h>
33
34RT_C_DECLS_BEGIN
35
36/** @defgroup grp_rt_req RTReq - Request Queue & Pool.
37 * @ingroup grp_rt
38 * @{
39 */
40
41/** Request queue handle. */
42typedef struct RTREQQUEUEINT *RTREQQUEUE;
43/** Pointer to a request queue handle. */
44typedef RTREQQUEUE *PRTREQQUEUE;
45/** NIL request queue handle. */
46#define NIL_RTREQQUEUE ((RTREQQUEUE)0)
47
48/** Request thread pool handle. */
49typedef struct RTREQPOOLINT *RTREQPOOL;
50/** Poiner to a request thread pool handle. */
51typedef RTREQPOOL *PRTREQPOOL;
52/** NIL request pool handle. */
53#define NIL_RTREQPOOL ((RTREQPOOL)0)
54
55
56/**
57 * Request type.
58 */
59typedef enum RTREQTYPE
60{
61 /** Invalid request. */
62 RTREQTYPE_INVALID = 0,
63 /** RT: Internal. */
64 RTREQTYPE_INTERNAL,
65 /** Maximum request type (exclusive). Used for validation. */
66 RTREQTYPE_MAX
67} RTREQTYPE;
68
69/**
70 * Request flags.
71 */
72typedef enum RTREQFLAGS
73{
74 /** The request returns a iprt status code. */
75 RTREQFLAGS_IPRT_STATUS = 0,
76 /** The request is a void request and have no status code. */
77 RTREQFLAGS_VOID = 1,
78 /** Return type mask. */
79 RTREQFLAGS_RETURN_MASK = 1,
80 /** Caller does not wait on the packet, Queue process thread will free it. */
81 RTREQFLAGS_NO_WAIT = 2
82} RTREQFLAGS;
83
84
85/** A request packet. */
86typedef struct RTREQ RTREQ;
87/** Pointer to an RT request packet. */
88typedef RTREQ *PRTREQ;
89/** Nil request handle. */
90#define NIL_RTREQ ((PRTREQ)0)
91
92
93#ifdef IN_RING3
94
95/**
96 * Create a request packet queue
97 *
98 * @returns iprt status code.
99 * @param phQueue Where to store the request queue handle.
100 */
101RTDECL(int) RTReqQueueCreate(PRTREQQUEUE phQueue);
102
103/**
104 * Destroy a request packet queue
105 *
106 * @returns iprt status code.
107 * @param hQueue The request queue.
108 */
109RTDECL(int) RTReqQueueDestroy(RTREQQUEUE hQueue);
110
111/**
112 * Process one or more request packets
113 *
114 * @returns iprt status code.
115 * @returns VERR_TIMEOUT if cMillies was reached without the packet being added.
116 *
117 * @param hQueue The request queue.
118 * @param cMillies Number of milliseconds to wait for a pending request.
119 * Use RT_INDEFINITE_WAIT to only wait till one is added.
120 */
121RTDECL(int) RTReqQueueProcess(RTREQQUEUE hQueue, RTMSINTERVAL cMillies);
122
123/**
124 * Allocate and queue a call request.
125 *
126 * If it's desired to poll on the completion of the request set cMillies
127 * to 0 and use RTReqWait() to check for completion. In the other case
128 * use RT_INDEFINITE_WAIT.
129 * The returned request packet must be freed using RTReqRelease().
130 *
131 * @returns iprt statuscode.
132 * Will not return VERR_INTERRUPTED.
133 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
134 *
135 * @param hQueue The request queue.
136 * @param ppReq Where to store the pointer to the request.
137 * This will be NULL or a valid request pointer not matter what happens.
138 * @param cMillies Number of milliseconds to wait for the request to
139 * be completed. Use RT_INDEFINITE_WAIT to only
140 * wait till it's completed.
141 * @param pfnFunction Pointer to the function to call.
142 * @param cArgs Number of arguments following in the ellipsis.
143 * @param ... Function arguments.
144 *
145 * @remarks See remarks on RTReqQueueCallV.
146 */
147RTDECL(int) RTReqQueueCall(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, PFNRT pfnFunction, unsigned cArgs, ...);
148
149/**
150 * Allocate and queue a call request to a void function.
151 *
152 * If it's desired to poll on the completion of the request set cMillies
153 * to 0 and use RTReqWait() to check for completion. In the other case
154 * use RT_INDEFINITE_WAIT.
155 * The returned request packet must be freed using RTReqRelease().
156 *
157 * @returns iprt status code.
158 * Will not return VERR_INTERRUPTED.
159 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
160 *
161 * @param hQueue The request queue.
162 * @param ppReq Where to store the pointer to the request.
163 * This will be NULL or a valid request pointer not matter what happens.
164 * @param cMillies Number of milliseconds to wait for the request to
165 * be completed. Use RT_INDEFINITE_WAIT to only
166 * wait till it's completed.
167 * @param pfnFunction Pointer to the function to call.
168 * @param cArgs Number of arguments following in the ellipsis.
169 * @param ... Function arguments.
170 *
171 * @remarks See remarks on RTReqQueueCallV.
172 */
173RTDECL(int) RTReqQueueCallVoid(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, PFNRT pfnFunction, unsigned cArgs, ...);
174
175/**
176 * Allocate and queue a call request to a void function.
177 *
178 * If it's desired to poll on the completion of the request set cMillies
179 * to 0 and use RTReqWait() to check for completion. In the other case
180 * use RT_INDEFINITE_WAIT.
181 * The returned request packet must be freed using RTReqRelease().
182 *
183 * @returns iprt status code.
184 * Will not return VERR_INTERRUPTED.
185 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
186 *
187 * @param hQueue The request queue.
188 * @param ppReq Where to store the pointer to the request.
189 * This will be NULL or a valid request pointer not matter what happens, unless fFlags
190 * contains RTREQFLAGS_NO_WAIT when it will be optional and always NULL.
191 * @param cMillies Number of milliseconds to wait for the request to
192 * be completed. Use RT_INDEFINITE_WAIT to only
193 * wait till it's completed.
194 * @param fFlags A combination of the RTREQFLAGS values.
195 * @param pfnFunction Pointer to the function to call.
196 * @param cArgs Number of arguments following in the ellipsis.
197 * @param ... Function arguments.
198 *
199 * @remarks See remarks on RTReqQueueCallV.
200 */
201RTDECL(int) RTReqQueueCallEx(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
202
203/**
204 * Allocate and queue a call request.
205 *
206 * If it's desired to poll on the completion of the request set cMillies
207 * to 0 and use RTReqWait() to check for completion. In the other case
208 * use RT_INDEFINITE_WAIT.
209 * The returned request packet must be freed using RTReqRelease().
210 *
211 * @returns iprt status code.
212 * Will not return VERR_INTERRUPTED.
213 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
214 *
215 * @param hQueue The request queue.
216 * @param ppReq Where to store the pointer to the request.
217 * This will be NULL or a valid request pointer not matter what happens, unless fFlags
218 * contains RTREQFLAGS_NO_WAIT when it will be optional and always NULL.
219 * @param cMillies Number of milliseconds to wait for the request to
220 * be completed. Use RT_INDEFINITE_WAIT to only
221 * wait till it's completed.
222 * @param fFlags A combination of the RTREQFLAGS values.
223 * @param pfnFunction Pointer to the function to call.
224 * @param cArgs Number of arguments following in the ellipsis.
225 * @param Args Variable argument vector.
226 *
227 * @remarks Caveats:
228 * - Do not pass anything which is larger than an uintptr_t.
229 * - 64-bit integers are larger than uintptr_t on 32-bit hosts.
230 * Pass integers > 32-bit by reference (pointers).
231 * - Don't use NULL since it should be the integer 0 in C++ and may
232 * therefore end up with garbage in the bits 63:32 on 64-bit
233 * hosts because 'int' is 32-bit.
234 * Use (void *)NULL or (uintptr_t)0 instead of NULL.
235 */
236RTDECL(int) RTReqQueueCallV(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args);
237
238/**
239 * Checks if the queue is busy or not.
240 *
241 * The caller is responsible for dealing with any concurrent submitts.
242 *
243 * @returns true if busy, false if idle.
244 * @param hQueue The queue.
245 */
246RTDECL(bool) RTReqQueueIsBusy(RTREQQUEUE hQueue);
247
248/**
249 * Allocates a request packet.
250 *
251 * The caller allocates a request packet, fills in the request data
252 * union and queues the request.
253 *
254 * @returns iprt status code.
255 *
256 * @param hQueue The request queue.
257 * @param enmType Package type.
258 * @param phReq Where to store the handle to the new request.
259 */
260RTDECL(int) RTReqQueueAlloc(RTREQQUEUE hQueue, RTREQTYPE enmType, PRTREQ *phReq);
261
262
263/**
264 * Creates a request thread pool.
265 *
266 * The core configuration is given as parameters, finer pool tuning can be
267 * achieved via RTReqPoolSetCfgVar.
268 *
269 * @returns IPRT status code.
270 * @param cMaxThreads The maximum number of worker threads.
271 * UINT32_MAX is an alias for the highest
272 * allowed thread count.
273 * @param cMsMinIdle The number of milliseconds a worker
274 * thread needs to be idle before it is
275 * considered for shutdown. The value
276 * RT_INDEFINITE_WAIT disables automatic
277 * idle thread shutdown.
278 * @param cThreadsPushBackThreshold At which worker thread count the push
279 * back should kick in.
280 * @param cMsMaxPushBack The max number of milliseconds to push
281 * back a submitter. UINT32_MAX is an
282 * alias for the highest allowed push back.
283 * @param pszName The pool name. Keep it short as it is
284 * used for naming worker threads.
285 * @param phPool Where to return the pool handle.
286 */
287RTDECL(int) RTReqPoolCreate(uint32_t cMaxThreads, RTMSINTERVAL cMsMinIdle,
288 uint32_t cThreadsPushBackThreshold, uint32_t cMsMaxPushBack,
289 const char *pszName, PRTREQPOOL phPool);
290
291/**
292 * Retainsa reference to a request thread pool.
293 *
294 * @returns The new reference count, UINT32_MAX on invalid handle (asserted).
295 * @param hPool The request thread pool handle.
296 */
297RTDECL(uint32_t) RTReqPoolRetain(RTREQPOOL hPool);
298
299/**
300 * Releases a reference to the request thread pool.
301 *
302 * When the reference count reaches zero, the request will be pooled for reuse.
303 *
304 * @returns The new reference count, UINT32_MAX on invalid handle (asserted).
305 * @param hPool The request thread pool handle.
306 */
307RTDECL(uint32_t) RTReqPoolRelease(RTREQPOOL hPool);
308
309/**
310 * Request thread pool configuration variable.
311 */
312typedef enum RTREQPOOLCFGVAR
313{
314 /** Invalid zero value. */
315 RTREQPOOLCFGVAR_INVALID = 0,
316 /** The desired RTTHREADTYPE of the worker threads. */
317 RTREQPOOLCFGVAR_THREAD_TYPE,
318 /** The minimum number of threads to keep handy once spawned. */
319 RTREQPOOLCFGVAR_MIN_THREADS,
320 /** The maximum number of thread to start. */
321 RTREQPOOLCFGVAR_MAX_THREADS,
322 /** The minimum number of milliseconds a worker thread needs to be idle
323 * before we consider shutting it down. The other shutdown criteria
324 * being set by RTREQPOOLCFGVAR_MIN_THREADS. The value
325 * RT_INDEFINITE_WAIT can be used to disable shutting down idle threads. */
326 RTREQPOOLCFGVAR_MS_MIN_IDLE,
327 /** The sleep period, in milliseoncds, to employ when idling. The value
328 * RT_INDEFINITE_WAIT can be used to disable shutting down idle threads. */
329 RTREQPOOLCFGVAR_MS_IDLE_SLEEP,
330 /** The number of threads at which to start pushing back. The value
331 * UINT64_MAX is an alias for the current upper thread count limit, i.e.
332 * disabling push back. The value 0 (zero) is an alias for the current
333 * lower thread count, a good value to start pushing back at. The value
334 * must otherwise be within */
335 RTREQPOOLCFGVAR_PUSH_BACK_THRESHOLD,
336 /** The minimum push back time in milliseconds. */
337 RTREQPOOLCFGVAR_PUSH_BACK_MIN_MS,
338 /** The maximum push back time in milliseconds. */
339 RTREQPOOLCFGVAR_PUSH_BACK_MAX_MS,
340 /** The maximum number of free requests to keep handy for recycling. */
341 RTREQPOOLCFGVAR_MAX_FREE_REQUESTS,
342 /** The end of the range of valid config variables. */
343 RTREQPOOLCFGVAR_END,
344 /** Blow the type up to 32-bits. */
345 RTREQPOOLCFGVAR_32BIT_HACK = 0x7fffffff
346} RTREQPOOLCFGVAR;
347
348
349/**
350 * Sets a config variable for a request thread pool.
351 *
352 * @returns IPRT status code.
353 * @param hPool The pool handle.
354 * @param enmVar The variable to set.
355 * @param uValue The new value.
356 */
357RTDECL(int) RTReqPoolSetCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar, uint64_t uValue);
358
359/**
360 * Gets a config variable for a request thread pool.
361 *
362 * @returns The value, UINT64_MAX on invalid parameters.
363 * @param hPool The pool handle.
364 * @param enmVar The variable to query.
365 */
366RTDECL(uint64_t) RTReqPoolGetCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar);
367
368/**
369 * Request thread pool statistics value names.
370 */
371typedef enum RTREQPOOLSTAT
372{
373 /** The invalid zero value, as per tradition. */
374 RTREQPOOLSTAT_INVALID = 0,
375 /** The current number of worker threads. */
376 RTREQPOOLSTAT_THREADS,
377 /** The number of threads that have been created. */
378 RTREQPOOLSTAT_THREADS_CREATED,
379 /** The total number of requests that have been processed. */
380 RTREQPOOLSTAT_REQUESTS_PROCESSED,
381 /** The total number of requests that have been submitted. */
382 RTREQPOOLSTAT_REQUESTS_SUBMITTED,
383 /** the current number of pending (waiting) requests. */
384 RTREQPOOLSTAT_REQUESTS_PENDING,
385 /** The current number of active (executing) requests. */
386 RTREQPOOLSTAT_REQUESTS_ACTIVE,
387 /** The current number of free (recycled) requests. */
388 RTREQPOOLSTAT_REQUESTS_FREE,
389 /** Total time the requests took to process. */
390 RTREQPOOLSTAT_NS_TOTAL_REQ_PROCESSING,
391 /** Total time the requests had to wait in the queue before being
392 * scheduled. */
393 RTREQPOOLSTAT_NS_TOTAL_REQ_QUEUED,
394 /** Average time the requests took to process. */
395 RTREQPOOLSTAT_NS_AVERAGE_REQ_PROCESSING,
396 /** Average time the requests had to wait in the queue before being
397 * scheduled. */
398 RTREQPOOLSTAT_NS_AVERAGE_REQ_QUEUED,
399 /** The end of the valid statistics value names. */
400 RTREQPOOLSTAT_END,
401 /** Blow the type up to 32-bit. */
402 RTREQPOOLSTAT_32BIT_HACK = 0x7fffffff
403} RTREQPOOLSTAT;
404
405/**
406 * Read a statistics value from the request thread pool.
407 *
408 * @returns The value, UINT64_MAX if an invalid parameter was given.
409 * @param hPool The request thread pool handle.
410 * @param enmStat The statistics value to get.
411 */
412RTDECL(uint64_t) RTReqPoolGetStat(RTREQPOOL hPool, RTREQPOOLSTAT enmStat);
413
414/**
415 * Allocates a request packet.
416 *
417 * This is mostly for internal use, please use the convenience methods.
418 *
419 * @returns iprt status code.
420 *
421 * @param hPool The request thread pool handle.
422 * @param enmType Package type.
423 * @param phReq Where to store the handle to the new request.
424 */
425RTDECL(int) RTReqPoolAlloc(RTREQPOOL hPool, RTREQTYPE enmType, PRTREQ *phReq);
426
427RTDECL(int) RTReqPoolCallEx( RTREQPOOL hPool, RTMSINTERVAL cMillies, PRTREQ *phReq, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
428RTDECL(int) RTReqPoolCallExV(RTREQPOOL hPool, RTMSINTERVAL cMillies, PRTREQ *phReq, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list va);
429
430RTDECL(int) RTReqPoolCallWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...);
431RTDECL(int) RTReqPoolCallNoWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...);
432
433RTDECL(int) RTReqPoolCallVoidWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...);
434RTDECL(int) RTReqPoolCallVoidNoWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...);
435
436
437/**
438 * Retainsa reference to a request.
439 *
440 * @returns The new reference count, UINT32_MAX on invalid handle (asserted).
441 * @param hReq The request handle.
442 */
443RTDECL(uint32_t) RTReqRetain(PRTREQ hReq);
444
445/**
446 * Releases a reference to the request.
447 *
448 * When the reference count reaches zero, the request will be pooled for reuse.
449 *
450 * @returns The new reference count, UINT32_MAX on invalid handle (asserted).
451 * @param hReq Package to release.
452 */
453RTDECL(uint32_t) RTReqRelease(PRTREQ hReq);
454
455/**
456 * Queue a request.
457 *
458 * The quest must be allocated using RTReqQueueAlloc() or RTReqPoolAlloc() and
459 * contain all the required data.
460 *
461 * If it's desired to poll on the completion of the request set cMillies
462 * to 0 and use RTReqWait() to check for completion. In the other case
463 * use RT_INDEFINITE_WAIT.
464 *
465 * @returns iprt status code.
466 * Will not return VERR_INTERRUPTED.
467 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
468 *
469 * @param pReq The request to queue.
470 * @param cMillies Number of milliseconds to wait for the request to
471 * be completed. Use RT_INDEFINITE_WAIT to only
472 * wait till it's completed.
473 */
474RTDECL(int) RTReqSubmit(PRTREQ pReq, RTMSINTERVAL cMillies);
475
476
477/**
478 * Wait for a request to be completed.
479 *
480 * @returns iprt status code.
481 * Will not return VERR_INTERRUPTED.
482 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
483 *
484 * @param pReq The request to wait for.
485 * @param cMillies Number of milliseconds to wait.
486 * Use RT_INDEFINITE_WAIT to only wait till it's completed.
487 */
488RTDECL(int) RTReqWait(PRTREQ pReq, RTMSINTERVAL cMillies);
489
490/**
491 * Get the status of the request.
492 *
493 * @returns Status code in the IPRT tradition.
494 *
495 * @param pReq The request.
496 */
497RTDECL(int) RTReqGetStatus(PRTREQ pReq);
498
499#endif /* IN_RING3 */
500
501
502/** @} */
503
504RT_C_DECLS_END
505
506#endif
507
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