Changeset 39004 in vbox for trunk/src/VBox/Runtime/r0drv/linux
- Timestamp:
- Oct 17, 2011 2:12:14 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 74405
- Location:
- trunk/src/VBox/Runtime/r0drv/linux
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/linux/initterm-r0drv-linux.c
r36555 r39004 5 5 6 6 /* 7 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 37 37 38 38 /******************************************************************************* 39 * Global Variables * 40 *******************************************************************************/ 41 /** The IPRT work queue. */ 42 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41) 43 static struct workqueue_struct *g_prtR0LnxWorkQueue; 44 #else 45 static DECLARE_TASK_QUEUE(g_rtR0LnxWorkQueue); 46 #endif 47 48 49 /******************************************************************************* 39 50 * Internal Functions * 40 51 *******************************************************************************/ … … 45 56 46 57 58 /** 59 * Pushes an item onto the IPRT work queue. 60 * 61 * @param pWork The work item. 62 * @param pfnWorker The callback function. It will be called back 63 * with @a pWork as argument. 64 */ 65 DECLHIDDEN(void) rtR0LnxWorkqueuePush(RTR0LNXWORKQUEUEITEM *pWork, void (*pfnWorker)(RTR0LNXWORKQUEUEITEM *)) 66 { 67 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41) 68 INIT_WORK(pWork, pfnWorker); 69 queue_work(g_prtR0LnxWorkQueue, pWork); 70 #else 71 INIT_TQUEUE(pWork, pfnWorker, pWork); 72 queue_task(pWork, &g_rtR0LnxWorkQueue); 73 #endif 74 } 75 76 77 /** 78 * Flushes all items in the IPRT work queue. 79 * 80 * @remarks This is mostly for 2.4.x compatability. Must not be called from 81 * atomic contexts or with unncessary locks held. 82 */ 83 DECLHIDDEN(void) rtR0LnxWorkqueueFlush(void) 84 { 85 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41) 86 flush_workqueue(g_prtR0LnxWorkQueue); 87 #else 88 run_task_queue(&g_rtR0LnxWorkQueue); 89 #endif 90 } 91 92 47 93 DECLHIDDEN(int) rtR0InitNative(void) 48 94 { 95 g_prtR0LnxWorkQueue = create_workqueue("iprt"); 96 if (!g_prtR0LnxWorkQueue) 97 return VERR_NO_MEMORY; 98 49 99 return VINF_SUCCESS; 50 100 } … … 53 103 DECLHIDDEN(void) rtR0TermNative(void) 54 104 { 105 rtR0LnxWorkqueueFlush(); 106 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41) 107 destroy_workqueue(g_prtR0LnxWorkQueue); 108 g_prtR0LnxWorkQueue = NULL; 109 #endif 110 55 111 #ifdef RT_ARCH_AMD64 56 112 rtR0MemExecCleanup(); -
trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
r36233 r39004 5 5 6 6 /* 7 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 119 119 #include <asm/div64.h> 120 120 121 /* for workqueue / task queues. */ 122 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41) 123 # include <linux/workqueue.h> 124 #else 125 # include <linux/tqueue.h> 126 #endif 127 121 128 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 122 129 # include <linux/kthread.h> … … 368 375 #endif 369 376 370 #endif 377 /* 378 * Workqueue stuff, see initterm-r0drv-linux.c. 379 */ 380 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41) 381 typedef struct work_struct RTR0LNXWORKQUEUEITEM; 382 #else 383 typedef struct tq_struct RTR0LNXWORKQUEUEITEM; 384 #endif 385 DECLHIDDEN(void) rtR0LnxWorkqueuePush(RTR0LNXWORKQUEUEITEM *pWork, void (*pfnWorker)(RTR0LNXWORKQUEUEITEM *)); 386 DECLHIDDEN(void) rtR0LnxWorkqueueFlush(void); 387 388 389 #endif -
trunk/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c
r33603 r39004 5 5 6 6 /* 7 * Copyright (C) 2006-201 0Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 175 175 /** The change interval spinlock for standard timers only. */ 176 176 spinlock_t ChgIntLock; 177 /** Workqueue item for delayed destruction. */ 178 RTR0LNXWORKQUEUEITEM DtorWorkqueueItem; 177 179 /** Sub-timers. 178 180 * Normally there is just one, but for RTTIMER_FLAGS_CPU_ALL this will contain … … 386 388 #ifdef RTTIMER_LINUX_WITH_HRTIMER 387 389 if (fHighRes) 388 hrtimer_cancel(&pSubTimer->u.Hr.LnxTimer); 390 { 391 /* There is no equivalent to del_timer in the hrtimer API, 392 hrtimer_cancel() == del_timer_sync(). Just like the WARN_ON in 393 del_timer_sync() asserts, waiting for a timer callback to complete 394 is deadlock prone, so don't do it. */ 395 int rc = hrtimer_try_to_cancel(&pSubTimer->u.Hr.LnxTimer); 396 if (rc < 0) 397 { 398 hrtimer_start(&pSubTimer->u.Hr.LnxTimer, ktime_set(KTIME_SEC_MAX, 0), HRTIMER_MODE_ABS); 399 hrtimer_try_to_cancel(&pSubTimer->u.Hr.LnxTimer); 400 } 401 } 389 402 else 390 403 #endif 391 { 392 if (timer_pending(&pSubTimer->u.Std.LnxTimer)) 393 del_timer_sync(&pSubTimer->u.Std.LnxTimer); 394 } 404 del_timer(&pSubTimer->u.Std.LnxTimer); 395 405 396 406 rtTimerLnxSetState(&pSubTimer->enmState, RTTIMERLNXSTATE_STOPPED); … … 405 415 static void rtTimerLnxDestroyIt(PRTTIMER pTimer) 406 416 { 407 RTSPINLOCK hSpinlock = pTimer->hSpinlock; 417 RTSPINLOCK hSpinlock = pTimer->hSpinlock; 418 RTCPUID iCpu; 408 419 Assert(pTimer->fSuspended); 409 420 RTTIMERLNX_LOG(("destroyit %p\n", pTimer)); … … 423 434 424 435 /* 425 * Uninitialize the structure and free the associated resources. 426 * The spinlock goes last. 436 * Invalidate the handle. 427 437 */ 428 438 ASMAtomicWriteU32(&pTimer->u32Magic, ~RTTIMER_MAGIC); 439 440 /* 441 * Make sure all timers have stopped executing since we're stopping them in 442 * an asynchronous manner up in rtTimerLnxStopSubTimer. 443 */ 444 iCpu = pTimer->cCpus; 445 while (iCpu-- > 0) 446 { 447 #ifdef RTTIMER_LINUX_WITH_HRTIMER 448 if (pTimer->fHighRes) 449 hrtimer_cancel(&pTimer->aSubTimers[iCpu].u.Hr.LnxTimer); 450 else 451 #endif 452 del_timer_sync(&pTimer->aSubTimers[iCpu].u.Std.LnxTimer); 453 } 454 455 /* 456 * Finally, free the resources. 457 */ 429 458 RTMemFreeEx(pTimer, RT_OFFSETOF(RTTIMER, aSubTimers[pTimer->cCpus])); 430 459 if (hSpinlock != NIL_RTSPINLOCK) 431 460 RTSpinlockDestroy(hSpinlock); 461 } 462 463 464 /** 465 * Workqueue callback (no DECLCALLBACK!) for deferred destruction. 466 * 467 * @param pWork Pointer to the DtorWorkqueueItem member of our timer 468 * structure. 469 */ 470 static void rtTimerLnxDestroyDeferred(RTR0LNXWORKQUEUEITEM *pWork) 471 { 472 PRTTIMER pTimer = RT_FROM_MEMBER(pWork, RTTIMER, DtorWorkqueueItem); 473 rtTimerLnxDestroyIt(pTimer); 432 474 } 433 475 … … 464 506 } 465 507 466 rtTimerLnxDestroyIt(pTimer); 508 /* 509 * Destroying a timer from the callback is unsafe since the callout code 510 * might be touching the timer structure upon return (hrtimer does!). So, 511 * we have to defer the actual destruction to the IRPT workqueue. 512 */ 513 rtR0LnxWorkqueuePush(&pTimer->DtorWorkqueueItem, rtTimerLnxDestroyDeferred); 467 514 } 468 515 … … 933 980 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 934 981 RTCPUID iCpu; 982 RTTIMERLNXSTATE enmState; 935 983 936 984 … … 944 992 for (iCpu = 0; iCpu < pTimer->cCpus; iCpu++) 945 993 { 946 RTTIMERLNXSTATE enmState;947 994 for (;;) 948 995 { … … 978 1025 /* 979 1026 * Do the actual stopping. Fortunately, this doesn't require any IPIs. 980 * Unfortunately it cannot be done synchronously from within the spinlock, 981 * because we might end up in an active waiting for a handler to complete. 1027 * Unfortunately it cannot be done synchronously. 982 1028 */ 983 1029 for (iCpu = 0; iCpu < pTimer->cCpus; iCpu++) … … 1419 1465 int rc; 1420 1466 1467 rtR0LnxWorkqueueFlush(); /* for 2.4 */ 1421 1468 *ppTimer = NULL; 1422 1469
Note:
See TracChangeset
for help on using the changeset viewer.