VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c@ 47206

Last change on this file since 47206 was 47206, checked in by vboxsync, 11 years ago

IPRT: Kernel thread-context hooks, Solaris implementation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.3 KB
Line 
1/* $Id: threadctxhooks-r0drv-linux.c 47206 2013-07-17 10:17:13Z vboxsync $ */
2/** @file
3 * IPRT - Thread-Context Hook, Ring-0 Driver, Linux.
4 */
5
6/*
7 * Copyright (C) 2013 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include "the-linux-kernel.h"
32#include "internal/iprt.h"
33
34#include <iprt/mem.h>
35#include <iprt/assert.h>
36#include <iprt/thread.h>
37#include <iprt/err.h>
38#include <iprt/asm.h>
39#include "internal/thread.h"
40
41#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_PREEMPT_NOTIFIERS)
42
43/*******************************************************************************
44* Structures and Typedefs *
45*******************************************************************************/
46/**
47 * The internal thread-context object.
48 */
49typedef struct RTTHREADCTXINT
50{
51 /** Magic value (RTTHREADCTXINT_MAGIC). */
52 uint32_t volatile u32Magic;
53 /** The thread handle (owner) for which the context-hooks are registered. */
54 RTTHREAD hOwner;
55 /** The preemption notifier object. */
56 struct preempt_notifier hPreemptNotifier;
57 /** Whether this handle has any hooks registered or not. */
58 bool fRegistered;
59 /** Pointer to the registered thread-context hook. */
60 PFNRTTHREADCTXHOOK pfnThreadCtxHook;
61 /** User argument passed to the thread-context hook. */
62 void *pvUser;
63 /** The thread-context operations. */
64 struct preempt_ops hPreemptOps;
65} RTTHREADCTXINT, *PRTTHREADCTXINT;
66
67
68/**
69 * Hook function for the thread-preempting event.
70 *
71 * @param pPreemptNotifier Pointer to the preempt_notifier struct.
72 * @param pNext Pointer to the task that is preempting the
73 * current thread.
74 *
75 * @remarks Called with the rq (runqueue) lock held and with preemption
76 * disabled!
77 */
78static void rtThreadCtxHooksLnxSchedOut(struct preempt_notifier *pPreemptNotifier, struct task_struct *pNext)
79{
80 PRTTHREADCTXINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier);
81 AssertPtr(pThis);
82 AssertPtr(pThis->pfnThreadCtxHook);
83 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
84
85 pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_PREEMPTING, pThis->pvUser);
86}
87
88
89/**
90 * Hook function for the thread-resumed event.
91 *
92 * @param pPreemptNotifier Pointer to the preempt_notifier struct.
93 * @param iCpu The CPU this thread is scheduled on.
94 *
95 * @remarks Called without holding the rq (runqueue) lock and with preemption
96 * enabled!
97 */
98static void rtThreadCtxHooksLnxSchedIn(struct preempt_notifier *pPreemptNotifier, int iCpu)
99{
100 PRTTHREADCTXINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier);
101 AssertPtr(pThis);
102 AssertPtr(pThis->pfnThreadCtxHook);
103
104 pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser);
105}
106
107
108/**
109 * Worker function for RTThreadCtxHooks(Deregister|Destroy)().
110 *
111 * @param pThis Pointer to the internal thread-context object.
112 */
113DECLINLINE(void) rtThreadCtxHooksDeregister(PRTTHREADCTXINT pThis)
114{
115 preempt_notifier_unregister(&pThis->hPreemptNotifier);
116 pThis->hPreemptOps.sched_out = NULL;
117 pThis->hPreemptOps.sched_in = NULL;
118 pThis->fRegistered = false;
119}
120
121
122RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
123{
124 PRTTHREADCTXINT pThis;
125 Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
126
127 pThis = (PRTTHREADCTXINT)RTMemAllocZ(sizeof(*pThis));
128 if (RT_UNLIKELY(!pThis))
129 return VERR_NO_MEMORY;
130 pThis->u32Magic = RTTHREADCTXINT_MAGIC;
131 pThis->hOwner = RTThreadSelf();
132 pThis->fRegistered = false;
133 preempt_notifier_init(&pThis->hPreemptNotifier, &pThis->hPreemptOps);
134
135 *phThreadCtx = pThis;
136 return VINF_SUCCESS;
137}
138RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate);
139
140
141RTDECL(void) RTThreadCtxHooksDestroy(RTTHREADCTX hThreadCtx)
142{
143 /*
144 * Validate input.
145 */
146 PRTTHREADCTXINT pThis = hThreadCtx;
147 if (pThis == NIL_RTTHREADCTX)
148 return;
149 AssertPtr(pThis);
150 AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
151 Assert(pThis->hOwner == RTThreadSelf());
152 Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));
153
154 /*
155 * If there's still a registered thread-context hook, deregister it now before destroying the object.
156 */
157 if (pThis->fRegistered)
158 rtThreadCtxHooksDeregister(pThis);
159
160 /*
161 * Paranoia... but since these are ring-0 threads we can't be too careful.
162 */
163 Assert(!pThis->fRegistered);
164 Assert(!pThis->hPreemptOps.sched_out);
165 Assert(!pThis->hPreemptOps.sched_in);
166
167 /*
168 * Destroy the object.
169 */
170 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
171 RTMemFree(pThis);
172}
173RT_EXPORT_SYMBOL(RTThreadCtxHooksDestroy);
174
175
176RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
177{
178 /*
179 * Validate input.
180 */
181 PRTTHREADCTXINT pThis = hThreadCtx;
182 if (pThis == NIL_RTTHREADCTX)
183 return VINF_SUCCESS;
184 AssertPtr(pThis);
185 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
186 VERR_INVALID_HANDLE);
187 Assert(pThis->hOwner == RTThreadSelf());
188 Assert(!pThis->hPreemptOps.sched_out);
189 Assert(!pThis->hPreemptOps.sched_in);
190
191 /*
192 * Register the callback.
193 */
194 pThis->hPreemptOps.sched_out = rtThreadCtxHooksLnxSchedOut;
195 pThis->hPreemptOps.sched_in = rtThreadCtxHooksLnxSchedIn;
196 pThis->pvUser = pvUser;
197 pThis->pfnThreadCtxHook = pfnThreadCtxHook;
198 pThis->fRegistered = true;
199 preempt_notifier_register(&pThis->hPreemptNotifier);
200
201 return VINF_SUCCESS;
202}
203RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister);
204
205
206RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
207{
208 /*
209 * Validate input.
210 */
211 PRTTHREADCTXINT pThis = hThreadCtx;
212 if (pThis == NIL_RTTHREADCTX)
213 return VINF_SUCCESS;
214 AssertPtr(pThis);
215 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
216 VERR_INVALID_HANDLE);
217 Assert(pThis->hOwner == RTThreadSelf());
218 Assert(pThis->fRegistered);
219
220 /*
221 * Deregister the callback.
222 */
223 rtThreadCtxHooksDeregister(pThis);
224 return VINF_SUCCESS;
225}
226RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister);
227
228#else /* Not supported / Not needed */
229
230RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx)
231{
232 NOREF(phThreadCtx);
233 return VERR_NOT_SUPPORTED;
234}
235RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate);
236
237
238RTDECL(void) RTThreadCtxHooksDestroy(RTTHREADCTX hThreadCtx)
239{
240 NOREF(hThreadCtx);
241}
242RT_EXPORT_SYMBOL(RTThreadCtxHooksDestroy);
243
244
245RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
246{
247 NOREF(hThreadCtx);
248 NOREF(pfnThreadCtxHook);
249 NOREF(pvUser);
250 return VERR_NOT_SUPPORTED;
251}
252RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister);
253
254
255RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx)
256{
257 NOREF(hThreadCtx);
258 return VERR_NOT_SUPPORTED;
259}
260RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister);
261
262#endif /* Not supported / Not needed */
263
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