Changeset 47199 in vbox
- Timestamp:
- Jul 16, 2013 3:45:42 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 87306
- Location:
- trunk
- Files:
-
- 2 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/mangling.h
r46639 r47199 1592 1592 # define RTThreadCreateF RT_MANGLER(RTThreadCreateF) 1593 1593 # define RTThreadCreateV RT_MANGLER(RTThreadCreateV) 1594 # define RTThreadCtxHooksCreate RT_MANGLER(RTThreadCtxHooksCreate) /* r0drv */ 1595 # define RTThreadCtxHooksDeregister RT_MANGLER(RTThreadCtxHooksDeregister) /* r0drv */ 1596 # define RTThreadCtxHooksDestroy RT_MANGLER(RTThreadCtxHooksDestroy) /* r0drv */ 1597 # define RTThreadCtxHooksRegister RT_MANGLER(RTThreadCtxHooksRegister) /* r0drv */ 1594 1598 # define RTThreadFromNative RT_MANGLER(RTThreadFromNative) 1595 1599 # define RTThreadGetAffinity RT_MANGLER(RTThreadGetAffinity) -
trunk/include/iprt/thread.h
r43363 r47199 580 580 RTDECL(bool) RTThreadIsInInterrupt(RTTHREAD hThread); 581 581 582 583 /** 584 * Thread-context events. 585 */ 586 typedef enum RTTHREADCTXEVENT 587 { 588 /** This thread is about to be preempted. */ 589 RTTHREADCTXEVENT_PREEMPTING = 0, 590 /** This thread has just been resumed. */ 591 RTTHREADCTXEVENT_RESUMED, 592 /** The usual 32-bit size hack. */ 593 RTTHREADCTXEVENT_32BIT_HACK = 0x7fffffff 594 } RTTHREADCTXEVENT; 595 596 /** 597 * Thread-context hook. 598 * 599 * @returns IPRT status code. 600 * @param enmEvent The thread-context event. 601 * @param pvUser User argument. 602 * 603 * @remarks This function may be called under different contexts, i.e. with 604 * different locks held, with/without preemption disabled depending on 605 * the event in @a enmEvent. 606 */ 607 typedef DECLCALLBACK(void) FNRTTHREADCTXHOOK(RTTHREADCTXEVENT enmEvent, void *pvUser); 608 /** Pointer to a thread-context hook. */ 609 typedef FNRTTHREADCTXHOOK *PFNRTTHREADCTXHOOK; 610 611 /** 612 * Create a handle for a thread-context hook. 613 * 614 * This must be called once per-thread before using RTThreadCtxHooksRegister(). 615 * 616 * @returns IPRT status code. 617 * @param phThreadCtx Where to store the thread-context handle. 618 */ 619 RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx); 620 621 /** 622 * Destroy a thread-context hook handle for the current thread. 623 * 624 * This will deregister any thread-context hooks registered under this handle if 625 * required. 626 * 627 * @param phThreadCtx Pointer to the thread-context handle. 628 */ 629 RTDECL(void) RTThreadCtxHooksDestroy(RTTHREADCTX hThreadCtx); 630 631 /** 632 * Registers a thread-context hook for the current thread to receive 633 * notifications for all supported thread-context events. 634 * 635 * @returns IPRT status code. 636 * @param phThreadCtx Poinner to the thread-context handle. 637 * @param pfnThreadHook Pointer to a thread-context hook (a callback) 638 * for all thread-context events. 639 * @param pvUser User argument (optional, can be NULL). 640 */ 641 RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadHook, void *pvUser); 642 643 /** 644 * Deregisters a thread-context hook for the current thread. 645 * 646 * @returns IPRT status code. 647 * @param phThreadCtx Pointer to the thread-context handle. 648 */ 649 RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx); 650 582 651 # endif /* IN_RING0 */ 583 652 -
trunk/include/iprt/types.h
r46688 r47199 1825 1825 #define NIL_RTTHREAD 0 1826 1826 1827 /** Thread-context handle.*/ 1828 typedef R0PTRTYPE(struct RTTHREADCTXINT *) RTTHREADCTX; 1829 /** Pointer to thread handle. */ 1830 typedef RTTHREADCTX *PRTTHREADCTX; 1831 /** Nil thread-context handle. */ 1832 #define NIL_RTTHREADCTX 0 1833 1827 1834 /** A TLS index. */ 1828 1835 typedef RTHCINTPTR RTTLS; -
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r46889 r47199 367 367 { "RTStrPrintfV", (void *)RTStrPrintfV }, 368 368 { "RTThreadCreate", (void *)RTThreadCreate }, 369 { "RTThreadCtxHooksCreate", (void *)RTThreadCtxHooksCreate }, 370 { "RTThreadCtxHooksDeregister", (void *)RTThreadCtxHooksDeregister }, 371 { "RTThreadCtxHooksDestroy", (void *)RTThreadCtxHooksDestroy }, 372 { "RTThreadCtxHooksRegister", (void *)RTThreadCtxHooksRegister }, 369 373 { "RTThreadGetName", (void *)RTThreadGetName }, 370 374 { "RTThreadGetNative", (void *)RTThreadGetNative }, -
trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv
r43389 r47199 194 194 ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/semspinmutex-r0drv-generic.c=>r0drv/generic/semspinmutex-r0drv-generic.c \ 195 195 ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/mpnotification-r0drv-generic.cpp=>r0drv/generic/mpnotification-r0drv-generic.c \ 196 ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp=>r0drv/generic/threadctxhooks-r0drv-generic.c \ 196 197 ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/RTMpIsCpuWorkPending-r0drv-generic.cpp=>r0drv/generic/RTMpIsCpuWorkPending-r0drv-generic.c \ 197 198 ${PATH_ROOT}/src/VBox/Runtime/r0drv/memobj-r0drv.cpp=>r0drv/memobj-r0drv.c \ -
trunk/src/VBox/HostDrivers/Support/linux/Makefile
r46646 r47199 95 95 r0drv/linux/thread-r0drv-linux.o \ 96 96 r0drv/linux/thread2-r0drv-linux.o \ 97 r0drv/linux/threadctxhooks-r0drv-linux.o \ 97 98 r0drv/linux/time-r0drv-linux.o \ 98 99 r0drv/linux/timer-r0drv-linux.o \ -
trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv
r46646 r47199 186 186 ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/thread-r0drv-linux.c=>r0drv/linux/thread-r0drv-linux.c \ 187 187 ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c=>r0drv/linux/thread2-r0drv-linux.c \ 188 ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c=>r0drv/linux/threadctxhooks-r0drv-linux.c \ 188 189 ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c=>r0drv/linux/time-r0drv-linux.c \ 189 190 ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c=>r0drv/linux/timer-r0drv-linux.c \ -
trunk/src/VBox/Runtime/Makefile.kmk
r47126 r47199 1737 1737 r0drv/linux/thread-r0drv-linux.c \ 1738 1738 r0drv/linux/thread2-r0drv-linux.c \ 1739 r0drv/linux/threadctxhooks-r0drv-linux.c \ 1739 1740 r0drv/linux/time-r0drv-linux.c \ 1740 1741 r0drv/linux/timer-r0drv-linux.c \ … … 1759 1760 generic/RTMpGetCoreCount-generic.cpp \ 1760 1761 nt/RTErrConvertFromNtStatus.cpp \ 1762 r0drv/generic/threadctxhooks-r0drv-generic.cpp \ 1761 1763 r0drv/memobj-r0drv.cpp \ 1762 1764 r0drv/mpnotification-r0drv.c \ … … 1798 1800 generic/timer-generic.cpp \ 1799 1801 r0drv/generic/mpnotification-r0drv-generic.cpp \ 1802 r0drv/generic/threadctxhooks-r0drv-generic.cpp \ 1800 1803 r0drv/darwin/alloc-r0drv-darwin.cpp \ 1801 1804 r0drv/darwin/assert-r0drv-darwin.cpp \ … … 1857 1860 r0drv/generic/RTMpOn-r0drv-generic.cpp \ 1858 1861 r0drv/generic/mpnotification-r0drv-generic.cpp \ 1862 r0drv/generic/threadctxhooks-r0drv-generic.cpp \ 1859 1863 r0drv/memobj-r0drv.cpp \ 1860 1864 r0drv/powernotification-r0drv.c \ … … 1894 1898 r0drv/generic/RTMpIsCpuWorkPending-r0drv-generic.cpp \ 1895 1899 r0drv/generic/mpnotification-r0drv-generic.cpp \ 1900 r0drv/generic/threadctxhooks-r0drv-generic.cpp \ 1896 1901 r0drv/freebsd/alloc-r0drv-freebsd.c \ 1897 1902 r0drv/freebsd/assert-r0drv-freebsd.c \ … … 1924 1929 r0drv/mpnotification-r0drv.c \ 1925 1930 r0drv/powernotification-r0drv.c \ 1931 r0drv/generic/threadctxhooks-r0drv-generic.cpp \ 1926 1932 r0drv/solaris/RTLogWriteDebugger-r0drv-solaris.c \ 1927 1933 r0drv/solaris/RTMpPokeCpu-r0drv-solaris.c \ … … 1957 1963 r0drv/generic/RTMpIsCpuWorkPending-r0drv-generic.cpp \ 1958 1964 r0drv/generic/mpnotification-r0drv-generic.cpp \ 1965 r0drv/generic/threadctxhooks-r0drv-generic.cpp \ 1959 1966 r0drv/haiku/alloc-r0drv-haiku.c \ 1960 1967 r0drv/haiku/assert-r0drv-haiku.c \ -
trunk/src/VBox/Runtime/include/internal/magics.h
r46567 r47199 191 191 /** RTTESTINT::u32Magic value. (Daniel Kehlmann) */ 192 192 #define RTTESTINT_MAGIC UINT32_C(0x19750113) 193 /** RTTHREADCTXINT::u32Magic value. (Dennis MacAlistair Ritchie) */ 194 #define RTTHREADCTXINT_MAGIC UINT32_C(0x19410909) 193 195 /** RTTHREADINT::u32Magic value. (Gilbert Keith Chesterton) */ 194 196 #define RTTHREADINT_MAGIC UINT32_C(0x18740529) -
trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
r44867 r47199 125 125 #include <asm/div64.h> 126 126 127 /* For thread-context hooks. */ 128 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_PREEMPT_NOTIFIERS) 129 # include <linux/preempt.h> 130 #endif 131 127 132 /* for workqueue / task queues. */ 128 133 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41) -
trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemption.cpp
r45541 r47199 32 32 #include <iprt/asm-amd64-x86.h> 33 33 #include <iprt/err.h> 34 #include <iprt/mem.h> 34 35 #include <iprt/time.h> 35 36 #include <iprt/string.h> … … 37 38 #include "tstR0ThreadPreemption.h" 38 39 40 41 #define TSTRTR0THREADCTXDATA_MAGIC 0xc01a50da 42 43 /** 44 * Thread-context hook data. 45 */ 46 typedef struct TSTRTR0THREADCTXDATA 47 { 48 uint32_t volatile u32Magic; 49 RTCPUID uSourceCpuId; 50 RTTHREADCTX hThreadCtx; 51 52 /* For RTTHREADCTXEVENT_PREEMPTING. */ 53 bool fPreemptingSuccess; 54 volatile bool fPreemptingInvoked; 55 56 /* For RTTHREADCTXEVENT_RESUMED. */ 57 bool fResumedSuccess; 58 volatile bool fResumedInvoked; 59 60 char achResult[512]; 61 } TSTRTR0THREADCTXDATA, *PTSTRTR0THREADCTXDATA; 62 63 64 /** 65 * Thread-context hook function. 66 * 67 * @param enmEvent The thread-context event. 68 * @param pvUser Pointer to the user argument. 69 */ 70 static void tstR0ThreadCtxHook(RTTHREADCTXEVENT enmEvent, void *pvUser) 71 { 72 PTSTRTR0THREADCTXDATA pData = (PTSTRTR0THREADCTXDATA)pvUser; 73 AssertPtrReturnVoid(pData); 74 75 if (pData->u32Magic != TSTRTR0THREADCTXDATA_MAGIC) 76 { 77 RTStrPrintf(pData->achResult, sizeof(pData->achResult), "!tstR0ThreadCtxHook: Invalid magic."); 78 return; 79 } 80 81 switch (enmEvent) 82 { 83 case RTTHREADCTXEVENT_PREEMPTING: 84 { 85 ASMAtomicWriteBool(&pData->fPreemptingInvoked, true); 86 87 /* We've already been called once, we now might very well be on another CPU. Nothing to do here. */ 88 if (pData->fPreemptingSuccess) 89 return; 90 91 if (RTThreadPreemptIsEnabled(NIL_RTTHREAD)) 92 { 93 RTStrPrintf(pData->achResult, sizeof(pData->achResult), 94 "!tstR0ThreadCtxHook[RTTHREADCTXEVENT_PREEMPTING]: Called with preemption enabled"); 95 break; 96 } 97 98 RTCPUID uCurrentCpuId = RTMpCpuId(); 99 if (pData->uSourceCpuId != uCurrentCpuId) 100 { 101 RTStrPrintf(pData->achResult, sizeof(pData->achResult), 102 "!tstR0ThreadCtxHook[RTTHREADCTXEVENT_PREEMPTING]: migrated uSourceCpuId=%RU32 uCurrentCpuId=%RU32", 103 pData->uSourceCpuId, uCurrentCpuId); 104 break; 105 } 106 107 pData->fPreemptingSuccess = true; 108 break; 109 } 110 111 case RTTHREADCTXEVENT_RESUMED: 112 { 113 ASMAtomicWriteBool(&pData->fResumedInvoked, true); 114 115 /* We've already been called once successfully, nothing more to do. */ 116 if (ASMAtomicReadBool(&pData->fResumedSuccess)) 117 return; 118 119 if (!pData->fPreemptingSuccess) 120 { 121 RTStrPrintf(pData->achResult, sizeof(pData->achResult), 122 "!tstR0ThreadCtxHook[RTTHREADCTXEVENT_RESUMED]: Called before preempting callback was invoked."); 123 } 124 125 ASMAtomicWriteBool(&pData->fResumedSuccess, true); 126 break; 127 } 128 129 default: 130 AssertMsgFailed(("Invalid event %#x\n", enmEvent)); 131 break; 132 } 133 } 39 134 40 135 … … 179 274 } 180 275 276 case TSTR0THREADPREEMPTION_CTXHOOKS: 277 { 278 if (!RTThreadPreemptIsEnabled(NIL_RTTHREAD)) 279 { 280 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksCreate must be called with preemption enabled"); 281 break; 282 } 283 284 RTTHREADCTX hThreadCtx; 285 int rc = RTThreadCtxHooksCreate(&hThreadCtx); 286 if (RT_FAILURE(rc)) 287 { 288 if (rc == VERR_NOT_SUPPORTED) 289 RTStrPrintf(pszErr, cchErr, "RTThreadCtxHooksCreate returns VERR_NOT_SUPPORTED"); 290 else 291 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksCreate returns %Rrc", rc); 292 break; 293 } 294 295 PTSTRTR0THREADCTXDATA pCtxData = (PTSTRTR0THREADCTXDATA)RTMemAlloc(sizeof(*pCtxData)); 296 AssertReturn(pCtxData, VERR_NO_MEMORY); 297 pCtxData->u32Magic = TSTRTR0THREADCTXDATA_MAGIC; 298 pCtxData->hThreadCtx = hThreadCtx; 299 pCtxData->fPreemptingSuccess = false; 300 pCtxData->fPreemptingInvoked = false; 301 pCtxData->fResumedInvoked = false; 302 pCtxData->fResumedSuccess = false; 303 RT_ZERO(pCtxData->achResult); 304 305 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; 306 RTThreadPreemptDisable(&PreemptState); 307 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 308 309 pCtxData->uSourceCpuId = RTMpCpuId(); 310 311 rc = RTThreadCtxHooksRegister(hThreadCtx, &tstR0ThreadCtxHook, pCtxData); 312 if (RT_FAILURE(rc)) 313 { 314 RTMemFree(pCtxData); 315 RTStrPrintf(pszErr, cchErr, "!RTThreadCtxHooksRegister returns %Rrc", rc); 316 break; 317 } 318 319 RTThreadPreemptRestore(&PreemptState); 320 321 /* Check if the preempting callback has/will been invoked. */ 322 const uint32_t cMsTimeout = 8000; 323 const uint32_t cMsSleepGranularity = 50; 324 uint32_t cMsSlept = 0; 325 for (;;) 326 { 327 RTThreadPreemptDisable(&PreemptState); 328 const RTCPUID uCurrentCpuId = RTMpCpuId(); 329 RTThreadPreemptRestore(&PreemptState); 330 331 if ( pCtxData->uSourceCpuId != uCurrentCpuId 332 || cMsSlept >= cMsTimeout) 333 { 334 break; 335 } 336 337 RTThreadSleep(cMsSleepGranularity); 338 cMsSlept += cMsSleepGranularity; 339 } 340 341 if (!ASMAtomicReadBool(&pCtxData->fPreemptingInvoked)) 342 { 343 RTStrPrintf(pszErr, cchErr, "!tstR0ThreadCtxHooks[RTTHREADCTXEVENT_PREEMPTING] not invoked after ca. %u ms", 344 cMsSlept); 345 } 346 else if (!pCtxData->fPreemptingSuccess) 347 RTStrCopy(pszErr, cchErr, pCtxData->achResult); 348 else 349 { 350 /* Preempting callback succeeded, now check if the resumed callback has/will been invoked. */ 351 cMsSlept = 0; 352 for (;;) 353 { 354 if ( ASMAtomicReadBool(&pCtxData->fResumedInvoked) 355 || cMsSlept >= cMsTimeout) 356 { 357 break; 358 } 359 360 RTThreadSleep(cMsSleepGranularity); 361 cMsSlept += cMsSleepGranularity; 362 } 363 364 if (!ASMAtomicReadBool(&pCtxData->fResumedInvoked)) 365 { 366 RTStrPrintf(pszErr, cchErr, "!tstR0ThreadCtxHooks[RTTHREADCTXEVENT_RESUMED] not invoked after ca. %u ms", 367 cMsSlept); 368 } 369 else if (!pCtxData->fResumedSuccess) 370 RTStrCopy(pszErr, cchErr, pCtxData->achResult); 371 } 372 373 RTThreadCtxHooksDeregister(hThreadCtx); 374 RTThreadCtxHooksDestroy(hThreadCtx); 375 RTMemFree(pCtxData); 376 break; 377 } 378 181 379 default: 182 380 RTStrPrintf(pszErr, cchErr, "!Unknown test #%d", uOperation); -
trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemption.h
r45538 r47199 39 39 TSTR0THREADPREMEPTION_IS_TRUSTY, 40 40 TSTR0THREADPREMEPTION_IS_PENDING, 41 TSTR0THREADPREMEPTION_NESTED 41 TSTR0THREADPREMEPTION_NESTED, 42 TSTR0THREADPREEMPTION_CTXHOOKS 42 43 } TSTR0THREADPREMEPTION; 43 44 -
trunk/src/VBox/Runtime/testcase/tstR0ThreadPreemptionDriver.cpp
r46326 r47199 245 245 RTTestIPrintf(RTTESTLVL_ALWAYS, "%s", Req.szMsg); 246 246 247 248 /* 249 * Test thread-context hooks. 250 */ 251 RTTestSub(hTest, "RTThreadCtxHooks"); 252 Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; 253 Req.Hdr.cbReq = sizeof(Req); 254 Req.szMsg[0] = '\0'; 255 RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, 256 TSTR0THREADPREEMPTION_CTXHOOKS, 0, &Req.Hdr), VINF_SUCCESS); 257 if (RT_FAILURE(rc)) 258 return RTTestSummaryAndDestroy(hTest); 259 if (Req.szMsg[0] == '!') 260 RTTestIFailed("%s", &Req.szMsg[1]); 261 else if (Req.szMsg[0]) 262 RTTestIPrintf(RTTESTLVL_ALWAYS, "%s", Req.szMsg); 263 247 264 /* 248 265 * Done.
Note:
See TracChangeset
for help on using the changeset viewer.