- Timestamp:
- Sep 14, 2009 6:36:15 AM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 52265
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmapi.h
r22915 r22986 167 167 #define VMSETRTERR_FLAGS_NO_WAIT RT_BIT_32(2) 168 168 /** @} */ 169 170 171 /**172 * VM reset callback.173 *174 * @returns VBox status code.175 * @param pDevInst Device instance of the device which registered the callback.176 * @param pvUser User argument.177 */178 typedef DECLCALLBACK(int) FNVMATRESET(PPDMDEVINS pDevInst, void *pvUser);179 /** VM reset callback. */180 typedef FNVMATRESET *PFNVMATRESET;181 182 /**183 * VM reset internal callback.184 *185 * @returns VBox status code.186 * @param pVM The VM which is begin reset.187 * @param pvUser User argument.188 */189 typedef DECLCALLBACK(int) FNVMATRESETINT(PVM pVM, void *pvUser);190 /** VM reset internal callback. */191 typedef FNVMATRESETINT *PFNVMATRESETINT;192 193 /**194 * VM reset external callback.195 *196 * @param pvUser User argument.197 */198 typedef DECLCALLBACK(void) FNVMATRESETEXT(void *pvUser);199 /** VM reset external callback. */200 typedef FNVMATRESETEXT *PFNVMATRESETEXT;201 202 169 203 170 /** … … 387 354 VMMR3DECL(int) VMR3AtDtorRegister(PFNVMATDTOR pfnAtDtor, void *pvUser); 388 355 VMMR3DECL(int) VMR3AtDtorDeregister(PFNVMATDTOR pfnAtDtor); 389 VMMR3DECL(int) VMR3AtResetRegister(PVM pVM, PPDMDEVINS pDevInst, PFNVMATRESET pfnCallback, void *pvUser, const char *pszDesc);390 VMMR3DECL(int) VMR3AtResetRegisterInternal(PVM pVM, PFNVMATRESETINT pfnCallback, void *pvUser, const char *pszDesc);391 VMMR3DECL(int) VMR3AtResetRegisterExternal(PVM pVM, PFNVMATRESETEXT pfnCallback, void *pvUser, const char *pszDesc);392 VMMR3DECL(int) VMR3AtResetDeregister(PVM pVM, PPDMDEVINS pDevInst, PFNVMATRESET pfnCallback);393 VMMR3DECL(int) VMR3AtResetDeregisterInternal(PVM pVM, PFNVMATRESETINT pfnCallback);394 VMMR3DECL(int) VMR3AtResetDeregisterExternal(PVM pVM, PFNVMATRESETEXT pfnCallback);395 356 VMMR3DECL(int) VMR3AtStateRegister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser); 396 357 VMMR3DECL(int) VMR3AtStateDeregister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser); -
trunk/src/VBox/VMM/VM.cpp
r22980 r22986 32 32 * In hindsight this component is a big design mistake, all this stuff really 33 33 * belongs in the VMM component. It just seemed like a kind of ok idea at a 34 * time when the VMM bit was a bit vague. 'VM' also happend to be the name of35 * the per-VM instance structure (see vm.h), so it kind of made sense. However36 * as it turned out, VMM(.cpp) is almost empty all it provides in ring-3 is some37 * minor functionally and some "routing" services.34 * time when the VMM bit was a kind of vague. 'VM' also happend to be the name 35 * of the per-VM instance structure (see vm.h), so it kind of made sense. 36 * However as it turned out, VMM(.cpp) is almost empty all it provides in ring-3 37 * is some minor functionally and some "routing" services. 38 38 * 39 39 * Fixing this is just a matter of some more or less straight forward 40 * refactoring, the question is just when someone will get to it. 40 * refactoring, the question is just when someone will get to it. Moving the EMT 41 * would be a good start. 41 42 * 42 43 */ … … 141 142 static void vmR3DestroyUVM(PUVM pUVM, uint32_t cMilliesEMTWait); 142 143 static void vmR3AtDtor(PVM pVM); 143 static int vmR3AtResetU(PUVM pUVM);144 144 static DECLCALLBACK(int) vmR3Reset(PVM pVM); 145 static DECLCALLBACK(int) vmR3AtStateRegisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser);146 145 static DECLCALLBACK(int) vmR3AtStateDeregisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser); 147 146 static DECLCALLBACK(int) vmR3AtErrorRegisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser); … … 433 432 AssertCompile(sizeof(pUVM->vm.s) <= sizeof(pUVM->vm.padding)); 434 433 435 pUVM->vm.s.ppAtResetNext = &pUVM->vm.s.pAtReset;436 434 pUVM->vm.s.ppAtStateNext = &pUVM->vm.s.pAtState; 437 435 pUVM->vm.s.ppAtErrorNext = &pUVM->vm.s.pAtError; … … 2380 2378 SELMR3Reset(pVM); 2381 2379 TRPMR3Reset(pVM); 2382 vmR3AtResetU(pVM->pUVM);2383 2380 REMR3Reset(pVM); 2384 2381 IOMR3Reset(pVM); … … 2404 2401 2405 2402 return VINF_EM_RESET; 2406 }2407 2408 2409 /**2410 * Walks the list of at VM reset callbacks and calls them2411 *2412 * @returns VBox status code.2413 * Any failure is fatal.2414 * @param pUVM Pointe to the user mode VM structure.2415 */2416 static int vmR3AtResetU(PUVM pUVM)2417 {2418 RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);2419 2420 /*2421 * Walk the list and call them all.2422 */2423 for (PVMATRESET pCur = pUVM->vm.s.pAtReset; pCur; pCur = pCur->pNext)2424 {2425 /* do the call */2426 int rc = VINF_SUCCESS;2427 switch (pCur->enmType)2428 {2429 case VMATRESETTYPE_DEV:2430 rc = pCur->u.Dev.pfnCallback(pCur->u.Dev.pDevIns, pCur->pvUser);2431 break;2432 case VMATRESETTYPE_INTERNAL:2433 rc = pCur->u.Internal.pfnCallback(pUVM->pVM, pCur->pvUser);2434 break;2435 case VMATRESETTYPE_EXTERNAL:2436 pCur->u.External.pfnCallback(pCur->pvUser);2437 break;2438 default:2439 AssertMsgFailed(("Invalid at-reset type %d!\n", pCur->enmType));2440 RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);2441 return VERR_INTERNAL_ERROR;2442 }2443 if (RT_FAILURE(rc))2444 {2445 AssertMsgFailed(("At-reset handler %s failed with rc=%d\n", pCur->pszDesc, rc));2446 RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);2447 return rc;2448 }2449 }2450 2451 RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);2452 return VINF_SUCCESS;2453 }2454 2455 2456 /**2457 * Internal registration function2458 */2459 static int vmr3AtResetRegisterU(PUVM pUVM, void *pvUser, const char *pszDesc, PVMATRESET *ppNew)2460 {2461 /*2462 * Allocate restration structure.2463 */2464 PVMATRESET pNew = (PVMATRESET)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew));2465 if (pNew)2466 {2467 /* fill data. */2468 pNew->pszDesc = pszDesc;2469 pNew->pvUser = pvUser;2470 2471 /* insert */2472 RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);2473 pNew->pNext = *pUVM->vm.s.ppAtResetNext;2474 *pUVM->vm.s.ppAtResetNext = pNew;2475 pUVM->vm.s.ppAtResetNext = &pNew->pNext;2476 RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);2477 2478 *ppNew = pNew;2479 return VINF_SUCCESS;2480 }2481 return VERR_NO_MEMORY;2482 }2483 2484 2485 /**2486 * Registers an at VM reset callback.2487 *2488 * @returns VBox status code.2489 * @param pVM The VM.2490 * @param pDevInst Device instance.2491 * @param pfnCallback Callback function.2492 * @param pvUser User argument.2493 * @param pszDesc Description (optional).2494 */2495 VMMR3DECL(int) VMR3AtResetRegister(PVM pVM, PPDMDEVINS pDevInst, PFNVMATRESET pfnCallback, void *pvUser, const char *pszDesc)2496 {2497 /*2498 * Validate.2499 */2500 if (!pDevInst)2501 {2502 AssertMsgFailed(("pDevIns is NULL!\n"));2503 return VERR_INVALID_PARAMETER;2504 }2505 2506 /*2507 * Create the new entry.2508 */2509 PVMATRESET pNew;2510 int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew);2511 if (RT_SUCCESS(rc))2512 {2513 /*2514 * Fill in type data.2515 */2516 pNew->enmType = VMATRESETTYPE_DEV;2517 pNew->u.Dev.pfnCallback = pfnCallback;2518 pNew->u.Dev.pDevIns = pDevInst;2519 }2520 2521 return rc;2522 }2523 2524 2525 /**2526 * Registers an at VM reset internal callback.2527 *2528 * @returns VBox status code.2529 * @param pVM The VM.2530 * @param pfnCallback Callback function.2531 * @param pvUser User argument.2532 * @param pszDesc Description (optional).2533 */2534 VMMR3DECL(int) VMR3AtResetRegisterInternal(PVM pVM, PFNVMATRESETINT pfnCallback, void *pvUser, const char *pszDesc)2535 {2536 /*2537 * Validate.2538 */2539 if (!pfnCallback)2540 {2541 AssertMsgFailed(("pfnCallback is NULL!\n"));2542 return VERR_INVALID_PARAMETER;2543 }2544 2545 /*2546 * Create the new entry.2547 */2548 PVMATRESET pNew;2549 int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew);2550 if (RT_SUCCESS(rc))2551 {2552 /*2553 * Fill in type data.2554 */2555 pNew->enmType = VMATRESETTYPE_INTERNAL;2556 pNew->u.Internal.pfnCallback = pfnCallback;2557 }2558 2559 return rc;2560 }2561 2562 2563 /**2564 * Registers an at VM reset external callback.2565 *2566 * @returns VBox status code.2567 * @param pVM The VM.2568 * @param pfnCallback Callback function.2569 * @param pvUser User argument.2570 * @param pszDesc Description (optional).2571 */2572 VMMR3DECL(int) VMR3AtResetRegisterExternal(PVM pVM, PFNVMATRESETEXT pfnCallback, void *pvUser, const char *pszDesc)2573 {2574 /*2575 * Validate.2576 */2577 if (!pfnCallback)2578 {2579 AssertMsgFailed(("pfnCallback is NULL!\n"));2580 return VERR_INVALID_PARAMETER;2581 }2582 2583 /*2584 * Create the new entry.2585 */2586 PVMATRESET pNew;2587 int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew);2588 if (RT_SUCCESS(rc))2589 {2590 /*2591 * Fill in type data.2592 */2593 pNew->enmType = VMATRESETTYPE_EXTERNAL;2594 pNew->u.External.pfnCallback = pfnCallback;2595 }2596 2597 return rc;2598 }2599 2600 2601 /**2602 * Unlinks and frees a callback.2603 *2604 * @returns Pointer to the next callback structure.2605 * @param pUVM Pointer to the user mode VM structure.2606 * @param pCur The one to free.2607 * @param pPrev The one before pCur.2608 */2609 static PVMATRESET vmr3AtResetFreeU(PUVM pUVM, PVMATRESET pCur, PVMATRESET pPrev)2610 {2611 /*2612 * Unlink it.2613 */2614 PVMATRESET pNext = pCur->pNext;2615 if (pPrev)2616 {2617 pPrev->pNext = pNext;2618 if (!pNext)2619 pUVM->vm.s.ppAtResetNext = &pPrev->pNext;2620 }2621 else2622 {2623 pUVM->vm.s.pAtReset = pNext;2624 if (!pNext)2625 pUVM->vm.s.ppAtResetNext = &pUVM->vm.s.pAtReset;2626 }2627 2628 /*2629 * Free it.2630 */2631 MMR3HeapFree(pCur);2632 2633 return pNext;2634 }2635 2636 2637 /**2638 * Deregisters an at VM reset callback.2639 *2640 * @returns VBox status code.2641 * @param pVM The VM.2642 * @param pDevIns Device instance.2643 * @param pfnCallback Callback function.2644 */2645 VMMR3DECL(int) VMR3AtResetDeregister(PVM pVM, PPDMDEVINS pDevIns, PFNVMATRESET pfnCallback)2646 {2647 PUVM pUVM = pVM->pUVM;2648 RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);2649 2650 int rc = VERR_VM_ATRESET_NOT_FOUND;2651 PVMATRESET pPrev = NULL;2652 PVMATRESET pCur = pUVM->vm.s.pAtReset;2653 while (pCur)2654 {2655 if ( pCur->enmType == VMATRESETTYPE_DEV2656 && pCur->u.Dev.pDevIns == pDevIns2657 && ( !pfnCallback2658 || pCur->u.Dev.pfnCallback == pfnCallback))2659 {2660 pCur = vmr3AtResetFreeU(pUVM, pCur, pPrev);2661 rc = VINF_SUCCESS;2662 }2663 else2664 {2665 pPrev = pCur;2666 pCur = pCur->pNext;2667 }2668 }2669 2670 RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);2671 AssertRC(rc);2672 return rc;2673 }2674 2675 2676 /**2677 * Deregisters an at VM reset internal callback.2678 *2679 * @returns VBox status code.2680 * @param pVM The VM.2681 * @param pfnCallback Callback function.2682 */2683 VMMR3DECL(int) VMR3AtResetDeregisterInternal(PVM pVM, PFNVMATRESETINT pfnCallback)2684 {2685 PUVM pUVM = pVM->pUVM;2686 RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);2687 2688 int rc = VERR_VM_ATRESET_NOT_FOUND;2689 PVMATRESET pPrev = NULL;2690 PVMATRESET pCur = pUVM->vm.s.pAtReset;2691 while (pCur)2692 {2693 if ( pCur->enmType == VMATRESETTYPE_INTERNAL2694 && pCur->u.Internal.pfnCallback == pfnCallback)2695 {2696 pCur = vmr3AtResetFreeU(pUVM, pCur, pPrev);2697 rc = VINF_SUCCESS;2698 }2699 else2700 {2701 pPrev = pCur;2702 pCur = pCur->pNext;2703 }2704 }2705 2706 RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);2707 AssertRC(rc);2708 return rc;2709 }2710 2711 2712 /**2713 * Deregisters an at VM reset external callback.2714 *2715 * @returns VBox status code.2716 * @param pVM The VM.2717 * @param pfnCallback Callback function.2718 */2719 VMMR3DECL(int) VMR3AtResetDeregisterExternal(PVM pVM, PFNVMATRESETEXT pfnCallback)2720 {2721 PUVM pUVM = pVM->pUVM;2722 RTCritSectEnter(&pUVM->vm.s.AtStateCritSect);2723 2724 int rc = VERR_VM_ATRESET_NOT_FOUND;2725 PVMATRESET pPrev = NULL;2726 PVMATRESET pCur = pUVM->vm.s.pAtReset;2727 while (pCur)2728 {2729 if ( pCur->enmType == VMATRESETTYPE_INTERNAL2730 && pCur->u.External.pfnCallback == pfnCallback)2731 {2732 pCur = vmr3AtResetFreeU(pUVM, pCur, pPrev);2733 rc = VINF_SUCCESS;2734 }2735 else2736 {2737 pPrev = pCur;2738 pCur = pCur->pNext;2739 }2740 }2741 2742 RTCritSectLeave(&pUVM->vm.s.AtStateCritSect);2743 AssertRC(rc);2744 return rc;2745 2403 } 2746 2404 … … 3002 2660 * Validate input. 3003 2661 */ 3004 if (!pfnAtState) 3005 { 3006 AssertMsgFailed(("callback is required\n")); 3007 return VERR_INVALID_PARAMETER; 3008 } 3009 3010 /* 3011 * Make sure we're in EMT (to avoid the locking). 3012 */ 3013 PVMREQ pReq; 3014 int rc = VMR3ReqCall(pVM, VMCPUID_ANY, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtStateRegisterU, 3, pVM->pUVM, pfnAtState, pvUser); 3015 if (RT_FAILURE(rc)) 3016 return rc; 3017 rc = pReq->iStatus; 3018 VMR3ReqFree(pReq); 3019 3020 LogFlow(("VMR3AtStateRegister: returns %Rrc\n", rc)); 3021 return rc; 3022 } 3023 3024 3025 /** 3026 * Registers a VM state change callback. 3027 * 3028 * @returns VBox status code. 3029 * @param pUVM Pointer to the user mode VM structure. 3030 * @param pfnAtState Pointer to callback. 3031 * @param pvUser User argument. 3032 * @thread EMT 3033 */ 3034 static DECLCALLBACK(int) vmR3AtStateRegisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser) 3035 { 2662 AssertPtrReturn(pfnAtState, VERR_INVALID_PARAMETER); 2663 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 2664 3036 2665 /* 3037 2666 * Allocate a new record. 3038 2667 */ 3039 2668 PUVM pUVM = pVM->pUVM; 3040 2669 PVMATSTATE pNew = (PVMATSTATE)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew)); 3041 2670 if (!pNew) … … 3066 2695 * @thread Any. 3067 2696 */ 3068 VMMR3DECL(int) 2697 VMMR3DECL(int) VMR3AtStateDeregister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser) 3069 2698 { 3070 2699 LogFlow(("VMR3AtStateDeregister: pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser)); … … 3073 2702 * Validate input. 3074 2703 */ 3075 if (!pfnAtState) 3076 { 3077 AssertMsgFailed(("callback is required\n")); 3078 return VERR_INVALID_PARAMETER; 3079 } 3080 3081 /* 3082 * Make sure we're in EMT (to avoid the logging). 3083 */ 3084 PVMREQ pReq; 3085 int rc = VMR3ReqCall(pVM, VMCPUID_ANY, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtStateDeregisterU, 3, pVM->pUVM, pfnAtState, pvUser); 3086 if (RT_FAILURE(rc)) 3087 return rc; 3088 rc = pReq->iStatus; 3089 VMR3ReqFree(pReq); 3090 3091 LogFlow(("VMR3AtStateDeregister: returns %Rrc\n", rc)); 3092 return rc; 3093 } 3094 3095 3096 /** 3097 * Deregisters a VM state change callback. 3098 * 3099 * @returns VBox status code. 3100 * @param pUVM Pointer to the user mode VM structure. 3101 * @param pfnAtState Pointer to callback. 3102 * @param pvUser User argument. 3103 * @thread EMT 3104 */ 3105 static DECLCALLBACK(int) vmR3AtStateDeregisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser) 3106 { 3107 LogFlow(("vmR3AtStateDeregisterU: pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser)); 2704 AssertPtrReturn(pfnAtState, VERR_INVALID_PARAMETER); 2705 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 2706 2707 PUVM pUVM = pVM->pUVM; 3108 2708 RTCritSectEnter(&pUVM->vm.s.AtStateCritSect); 3109 2709 -
trunk/src/VBox/VMM/VMInternal.h
r22980 r22986 36 36 * @{ 37 37 */ 38 39 40 /**41 * At-reset callback type.42 */43 typedef enum VMATRESETTYPE44 {45 /** Device callback. */46 VMATRESETTYPE_DEV = 1,47 /** Internal callback . */48 VMATRESETTYPE_INTERNAL,49 /** External callback. */50 VMATRESETTYPE_EXTERNAL51 } VMATRESETTYPE;52 53 54 /** Pointer to at-reset callback. */55 typedef struct VMATRESET *PVMATRESET;56 57 /**58 * At reset callback.59 */60 typedef struct VMATRESET61 {62 /** Pointer to the next one in the list. */63 PVMATRESET pNext;64 /** Callback type. */65 VMATRESETTYPE enmType;66 /** User argument for the callback. */67 void *pvUser;68 /** Description. */69 const char *pszDesc;70 /** Type specific data. */71 union72 {73 /** VMATRESETTYPE_DEV. */74 struct75 {76 /** Callback. */77 PFNVMATRESET pfnCallback;78 /** Device instance. */79 PPDMDEVINS pDevIns;80 } Dev;81 82 /** VMATRESETTYPE_INTERNAL. */83 struct84 {85 /** Callback. */86 PFNVMATRESETINT pfnCallback;87 } Internal;88 89 /** VMATRESETTYPE_EXTERNAL. */90 struct91 {92 /** Callback. */93 PFNVMATRESETEXT pfnCallback;94 } External;95 } u;96 } VMATRESET;97 38 98 39 … … 270 211 bool fEMTDoesTheCleanup; 271 212 272 /** Critical section for pAt Reset and pAtState. */213 /** Critical section for pAtState. */ 273 214 RTCRITSECT AtStateCritSect; 274 275 /** List of registered reset callbacks. */276 PVMATRESET pAtReset;277 /** List of registered reset callbacks. */278 PVMATRESET *ppAtResetNext;279 280 215 /** List of registered state change callbacks. */ 281 216 PVMATSTATE pAtState;
Note:
See TracChangeset
for help on using the changeset viewer.