Changeset 47352 in vbox for trunk/src/VBox
- Timestamp:
- Jul 23, 2013 4:19:20 PM (11 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r47199 r47352 369 369 { "RTThreadCtxHooksCreate", (void *)RTThreadCtxHooksCreate }, 370 370 { "RTThreadCtxHooksDeregister", (void *)RTThreadCtxHooksDeregister }, 371 { "RTThreadCtxHooksDestroy", (void *)RTThreadCtxHooksDestroy },372 371 { "RTThreadCtxHooksRegister", (void *)RTThreadCtxHooksRegister }, 372 { "RTThreadCtxHooksRelease", (void *)RTThreadCtxHooksRelease }, 373 { "RTThreadCtxHooksRetain", (void *)RTThreadCtxHooksRetain }, 373 374 { "RTThreadGetName", (void *)RTThreadGetName }, 374 375 { "RTThreadGetNative", (void *)RTThreadGetNative }, -
trunk/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp
r47201 r47352 42 42 43 43 44 RTDECL( void) RTThreadCtxHooksDestroy(RTTHREADCTX hThreadCtx)44 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx) 45 45 { 46 46 NOREF(hThreadCtx); 47 return UINT32_MAX; 47 48 } 48 RT_EXPORT_SYMBOL(RTThreadCtxHooksDestroy); 49 RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease); 50 51 52 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx) 53 { 54 NOREF(hThreadCtx); 55 return UINT32_MAX; 56 } 57 RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain); 49 58 50 59 -
trunk/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c
r47229 r47352 52 52 uint32_t volatile u32Magic; 53 53 /** The thread handle (owner) for which the context-hooks are registered. */ 54 RT THREADhOwner;54 RTNATIVETHREAD hOwner; 55 55 /** The preemption notifier object. */ 56 56 struct preempt_notifier hPreemptNotifier; … … 63 63 /** The thread-context operations. */ 64 64 struct preempt_ops hPreemptOps; 65 /** The reference count for this object. */ 66 uint32_t volatile cRefs; 65 67 } RTTHREADCTXINT, *PRTTHREADCTXINT; 66 68 … … 109 111 110 112 /** 111 * Worker function for RTThreadCtxHooks(Deregister| Destroy)().113 * Worker function for RTThreadCtxHooks(Deregister|Release)(). 112 114 * 113 115 * @param pThis Pointer to the internal thread-context object. … … 131 133 return VERR_NO_MEMORY; 132 134 pThis->u32Magic = RTTHREADCTXINT_MAGIC; 133 pThis->hOwner = RTThread Self();135 pThis->hOwner = RTThreadNativeSelf(); 134 136 pThis->fRegistered = false; 135 137 preempt_notifier_init(&pThis->hPreemptNotifier, &pThis->hPreemptOps); 138 pThis->cRefs = 1; 136 139 137 140 *phThreadCtx = pThis; … … 141 144 142 145 143 RTDECL( void) RTThreadCtxHooksDestroy(RTTHREADCTX hThreadCtx)146 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx) 144 147 { 145 148 /* 146 149 * Validate input. 147 150 */ 151 uint32_t cRefs; 152 PRTTHREADCTXINT pThis = hThreadCtx; 153 AssertPtr(pThis); 154 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 155 UINT32_MAX); 156 157 cRefs = ASMAtomicIncU32(&pThis->cRefs); 158 Assert(cRefs < UINT32_MAX / 2); 159 return cRefs; 160 } 161 RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain); 162 163 164 165 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx) 166 { 167 /* 168 * Validate input. 169 */ 170 uint32_t cRefs; 148 171 PRTTHREADCTXINT pThis = hThreadCtx; 149 172 if (pThis == NIL_RTTHREADCTX) 150 return ;151 AssertPtr(pThis); 152 AssertMsgReturn Void(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));153 Assert(pThis->hOwner == RTThreadSelf());173 return 0; 174 AssertPtr(pThis); 175 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 176 UINT32_MAX); 154 177 Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 155 178 156 /* 157 * If there's still a registered thread-context hook, deregister it now before destroying the object. 158 */ 159 if (pThis->fRegistered) 160 rtThreadCtxHooksDeregister(pThis); 161 162 /* 163 * Paranoia... but since these are ring-0 threads we can't be too careful. 164 */ 165 Assert(!pThis->fRegistered); 166 Assert(!pThis->hPreemptOps.sched_out); 167 Assert(!pThis->hPreemptOps.sched_in); 168 169 /* 170 * Destroy the object. 171 */ 172 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC); 173 RTMemFree(pThis); 174 } 175 RT_EXPORT_SYMBOL(RTThreadCtxHooksDestroy); 179 cRefs = ASMAtomicDecU32(&pThis->cRefs); 180 if (!cRefs) 181 { 182 /* 183 * If there's still a registered thread-context hook, deregister it now before destroying the object. 184 */ 185 if (pThis->fRegistered) 186 rtThreadCtxHooksDeregister(pThis); 187 188 /* 189 * Paranoia... but since these are ring-0 threads we can't be too careful. 190 */ 191 Assert(!pThis->fRegistered); 192 Assert(!pThis->hPreemptOps.sched_out); 193 Assert(!pThis->hPreemptOps.sched_in); 194 195 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC); 196 RTMemFree(pThis); 197 printk("freed pThis=%p\n", pThis); 198 } 199 else 200 Assert(cRefs < UINT32_MAX / 2); 201 202 return cRefs; 203 } 204 RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease); 176 205 177 206 … … 187 216 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 188 217 VERR_INVALID_HANDLE); 189 Assert(pThis->hOwner == RTThread Self());218 Assert(pThis->hOwner == RTThreadNativeSelf()); 190 219 Assert(!pThis->hPreemptOps.sched_out); 191 220 Assert(!pThis->hPreemptOps.sched_in); … … 217 246 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 218 247 VERR_INVALID_HANDLE); 219 Assert(pThis->hOwner == RTThread Self());248 Assert(pThis->hOwner == RTThreadNativeSelf()); 220 249 Assert(pThis->fRegistered); 221 250 … … 238 267 239 268 240 RTDECL( void) RTThreadCtxHooksDestroy(RTTHREADCTX hThreadCtx)269 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx) 241 270 { 242 271 NOREF(hThreadCtx); 243 } 244 RT_EXPORT_SYMBOL(RTThreadCtxHooksDestroy); 272 return UINT32_MAX; 273 } 274 RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain); 275 276 277 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx) 278 { 279 NOREF(hThreadCtx); 280 return UINT32_MAX; 281 } 282 RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease); 245 283 246 284 -
trunk/src/VBox/Runtime/r0drv/solaris/threadctxhooks-r0drv-solaris.c
r47302 r47352 51 51 uint32_t volatile u32Magic; 52 52 /** The thread handle (owner) for which the context-hooks are registered. */ 53 RT THREADhOwner;53 RTNATIVETHREAD hOwner; 54 54 /** Pointer to the registered thread-context hook. */ 55 55 PFNRTTHREADCTXHOOK pfnThreadCtxHook; … … 58 58 /** Whether this handle has any hooks registered or not. */ 59 59 bool fRegistered; 60 /** Number of references to this object. */ 61 uint32_t volatile cRefs; 60 62 } RTTHREADCTXINT, *PRTTHREADCTXINT; 61 63 64 65 /******************************************************************************* 66 * Defined Constants And Macros * 67 *******************************************************************************/ 68 /** Validates a thread-context hook handle and returns rc if not valid. */ 69 #define RTTHREADCTX_VALID_RETURN_RC(pThis, rc) \ 70 do { \ 71 AssertPtrReturn((pThis), (rc)); \ 72 AssertMsgReturn((pThis)->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", (pThis)->u32Magic, \ 73 (pThis)), (rc)); \ 74 AssertMsgReturn((pThis)->cRefs > 0, ("cRefs is 0! pThis=%p\n", (pThis)), (rc)); \ 75 } while (0) 62 76 63 77 … … 100 114 Assert(pThis->pfnThreadCtxHook); 101 115 pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser); 116 } 117 } 118 119 120 /** 121 * Hook function for the thread-free event. 122 * 123 * @param pvThreadCtxInt Opaque pointer to the internal thread-context 124 * object. 125 * @param fIsExec Whether this event is triggered due to exec(). 126 */ 127 static void rtThreadCtxHooksSolFree(void *pvThreadCtxInt, int fIsExec) 128 { 129 PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt; 130 AssertPtrReturnVoid(pThis); 131 AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis)); 132 133 uint32_t cRefs = ASMAtomicReadU32(&pThis->cRefs); 134 if (RT_UNLIKELY(!cRefs)) 135 { 136 /* Should never happen. */ 137 AssertMsgFailed(("rtThreadCtxHooksSolFree with cRefs=0 pThis=%p\n", pThis)); 138 return; 139 } 140 141 if (!ASMAtomicDecU32(&pThis->cRefs)) 142 { 143 Assert(!pThis->fRegistered); 144 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC); 145 RTMemFree(pThis); 102 146 } 103 147 } … … 113 157 return VERR_NO_MEMORY; 114 158 pThis->u32Magic = RTTHREADCTXINT_MAGIC; 115 pThis->hOwner = RTThread Self();159 pThis->hOwner = RTThreadNativeSelf(); 116 160 pThis->fRegistered = false; 161 pThis->cRefs = 2; /* One reference for the thread, one for the hook object. */ 117 162 118 163 /* … … 129 174 NULL, /* fork */ 130 175 NULL, /* lwp_create */ 131 NULL); /* free */176 rtThreadCtxHooksSolFree); 132 177 } 133 178 else … … 140 185 NULL, /* lwp_create */ 141 186 NULL, /* exit */ 142 NULL); /* free */187 rtThreadCtxHooksSolFree); 143 188 } 144 189 … … 148 193 149 194 150 RTDECL(void) RTThreadCtxHooksDestroy(RTTHREADCTX hThreadCtx) 151 { 152 /* 153 * Validate input. 154 */ 195 RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx) 196 { 197 PRTTHREADCTXINT pThis = hThreadCtx; 198 RTTHREADCTX_VALID_RETURN_RC(hThreadCtx, UINT32_MAX); 199 200 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); 201 Assert(cRefs < UINT32_MAX / 2); 202 return cRefs; 203 } 204 205 206 RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx) 207 { 155 208 PRTTHREADCTXINT pThis = hThreadCtx; 156 209 if (pThis == NIL_RTTHREADCTX) 157 return; 158 AssertPtr(pThis); 159 AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis)); 160 Assert(pThis->hOwner == RTThreadSelf()); 210 return 0; 211 212 RTTHREADCTX_VALID_RETURN_RC(hThreadCtx, UINT32_MAX); 161 213 Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 162 214 163 /* 164 * Deregister the hook. 165 */ 166 int rc; 167 if (g_frtSolOldThreadCtx) 168 { 169 rc = g_rtSolThreadCtx.Remove.pfnSol_removectx_old(curthread, 215 pThis->fRegistered = false; 216 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs); 217 218 if ( pThis->hOwner == RTThreadNativeSelf() 219 && cRefs == 1) 220 { 221 /* 222 * removectx() will invoke rtThreadCtxHooksSolFree() and there is no way to bypass it and still use 223 * rtThreadCtxHooksSolFree() at the same time. Hence the convulated reference counting. 224 * 225 * When this function is called from the owner thread and is the last reference, we call removectx() which 226 * will invoke rtThreadCtxHooksSolFree() with cRefs = 1 and that will then free the hook object. 227 * 228 * When the function is called from a different thread, we simply decrement the reference. Whenever the 229 * ring-0 thread dies, Solaris will call rtThreadCtxHooksSolFree() which will free the hook object. 230 */ 231 int rc; 232 if (g_frtSolOldThreadCtx) 233 { 234 rc = g_rtSolThreadCtx.Remove.pfnSol_removectx_old(curthread, 235 pThis, 236 rtThreadCtxHooksSolPreempting, 237 rtThreadCtxHooksSolResumed, 238 NULL, /* fork */ 239 NULL, /* lwp_create */ 240 rtThreadCtxHooksSolFree); 241 } 242 else 243 { 244 rc = g_rtSolThreadCtx.Remove.pfnSol_removectx(curthread, 170 245 pThis, 171 246 rtThreadCtxHooksSolPreempting, 172 247 rtThreadCtxHooksSolResumed, 173 NULL, /* fork */ 174 NULL, /* lwp_create */ 175 NULL); /* free */ 176 } 177 else 178 { 179 rc = g_rtSolThreadCtx.Remove.pfnSol_removectx(curthread, 180 pThis, 181 rtThreadCtxHooksSolPreempting, 182 rtThreadCtxHooksSolResumed, 183 NULL, /* fork */ 184 NULL, /* lwp_create */ 185 NULL, /* exit */ 186 NULL); /* free */ 187 } 188 AssertMsg(rc, ("removectx failed. rc=%d\n", rc)); 189 NOREF(rc); 190 191 /* 192 * Destroy the object. 193 */ 194 ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC); 195 RTMemFree(pThis); 248 NULL, /* fork */ 249 NULL, /* lwp_create */ 250 NULL, /* exit */ 251 rtThreadCtxHooksSolFree); 252 } 253 AssertMsg(rc, ("removectx failed. rc=%d\n", rc)); 254 NOREF(rc); 255 256 #ifdef VBOX_STRICT 257 cRefs = ASMAtomicReadU32(&pThis->cRefs); 258 Assert(!cRefs); 259 #endif 260 cRefs = 0; 261 } 262 263 return cRefs; 196 264 } 197 265 … … 208 276 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 209 277 VERR_INVALID_HANDLE); 210 Assert(pThis->hOwner == RTThread Self());278 Assert(pThis->hOwner == RTThreadNativeSelf()); 211 279 212 280 /* … … 232 300 AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), 233 301 VERR_INVALID_HANDLE); 234 Assert(pThis->hOwner == RTThread Self());302 Assert(pThis->hOwner == RTThreadNativeSelf()); 235 303 Assert(pThis->fRegistered); 236 304 -
trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemption.cpp
r47302 r47352 374 374 375 375 Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 376 RTThreadCtxHooksDestroy(hThreadCtx); 376 uint32_t cRefs = RTThreadCtxHooksRelease(hThreadCtx); 377 if (cRefs == UINT32_MAX) 378 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRelease returns invalid cRefs!"); 377 379 378 380 RTMemFree(pCtxData);
Note:
See TracChangeset
for help on using the changeset viewer.