Changeset 98095 in vbox
- Timestamp:
- Jan 16, 2023 3:17:49 PM (23 months ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/ConsoleImpl.h
r98091 r98095 810 810 typedef struct LEDSET *PLEDSET; 811 811 PPDMLED volatile *i_getLedSet(uint32_t iLedSet); 812 void i_setLedType(DeviceType_T *penmSubTypeEntry, DeviceType_T enmNewType); 813 HRESULT i_refreshLedTypeArrays(AutoReadLock *pReadLock); 812 814 uint32_t i_allocateDriverLeds(uint32_t cLeds, uint32_t fTypes, DeviceType_T **ppSubTypes); 813 void i_attachStatusDriver(PCFGMNODE pCtlInst, DeviceType_T enmType );815 void i_attachStatusDriver(PCFGMNODE pCtlInst, DeviceType_T enmType, uint32_t cLeds = 1); 814 816 void i_attachStatusDriver(PCFGMNODE pCtlInst, uint32_t fTypes, uint32_t cLeds, DeviceType_T **ppaSubTypes, 815 817 Console::MediumAttachmentMap *pmapMediumAttachments, … … 1068 1070 /** @name LEDs and their management 1069 1071 * @{ */ 1070 /** Read/write lock separating LED allocations (write) from queries (read). */ 1072 /** Read/write lock separating LED allocations and per-type data construction 1073 * (write) from queries (read). */ 1071 1074 RWLockHandle mLedLock; 1075 /** LED configuration generation. This is increased whenever a new set is 1076 * allocated or a sub-device type changes. */ 1077 uint32_t muLedGen; 1078 /** The LED configuration generation which maLedTypes was constructed for. */ 1079 uint32_t muLedTypeGen; 1072 1080 /** Number of LED sets in use in maLedSets. */ 1073 1081 uint32_t mcLedSets; … … 1085 1093 DeviceType_T *paSubTypes; 1086 1094 } maLedSets[32]; 1095 /** LEDs data organized by DeviceType_T. 1096 * This is reconstructed by Console::i_refreshLedTypeArrays() when 1097 * Console::getDeviceActivity is called and mLedTypeGen doesn't match 1098 * muLedGen. */ 1099 struct 1100 { 1101 /** Number of possibly valid entries in pappLeds. */ 1102 uint32_t cLeds; 1103 /** Number of allocated entries. */ 1104 uint32_t cAllocated; 1105 /** Array of pointer to LEDSET::papLed entries. 1106 * The indirection is due to Console::i_drvStatus_UnitChanged() only knowing 1107 * about the LEDSET::papLeds. */ 1108 PPDMLED volatile **pappLeds; 1109 } maLedTypes[DeviceType_End]; 1087 1110 /** @} */ 1088 1111 -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r98091 r98095 428 428 , mBusMgr(NULL) 429 429 , mLedLock(LOCKCLASS_LISTOFOTHEROBJECTS /* must be higher than LOCKCLASS_OTHEROBJECT */) 430 , muLedGen(0) 431 , muLedTypeGen(0) 432 , mcLedSets(0) 430 433 , m_pKeyStore(NULL) 431 434 , mpIfSecKey(NULL) … … 438 441 , mpCryptoIf(NULL) 439 442 { 443 RT_ZERO(maLedSets); 444 RT_ZERO(maLedTypes); 440 445 } 441 446 … … 446 451 { 447 452 LogFlowThisFunc(("\n")); 448 449 mcLedSets = 0;450 RT_ZERO(maLedSets);451 453 452 454 MYVMM2USERMETHODS *pVmm2UserMethods = (MYVMM2USERMETHODS *)RTMemAllocZ(sizeof(*mpVmm2UserMethods) + sizeof(Console *)); … … 881 883 882 884 /* Release memory held by the LED sets (no need to take lock). */ 885 for (size_t idxType = 0; idxType < RT_ELEMENTS(maLedTypes); idxType++) 886 { 887 maLedTypes[idxType].cLeds = 0; 888 maLedTypes[idxType].cAllocated = 0; 889 RTMemFree(maLedTypes[idxType].pappLeds); 890 maLedTypes[idxType].pappLeds = NULL; 891 } 883 892 for (size_t idxSet = 0; idxSet < mcLedSets; idxSet++) 884 893 { 894 maLedSets[idxSet].cLeds = 0; 885 895 RTMemFree((void *)maLedSets[idxSet].papLeds); 886 896 maLedSets[idxSet].papLeds = NULL; … … 2815 2825 } 2816 2826 2827 /** 2828 * Refreshes the maLedTypes and muLedTypeGen members. 2829 */ 2830 HRESULT Console::i_refreshLedTypeArrays(AutoReadLock *pReadLock) 2831 { 2832 pReadLock->release(); 2833 AutoWriteLock alock(mLedLock COMMA_LOCKVAL_SRC_POS); 2834 2835 /* 2836 * Check that the refresh was already done by someone else while we 2837 * acquired the write lock. 2838 */ 2839 if (muLedTypeGen != muLedGen) 2840 { 2841 /* 2842 * Reset the data. 2843 */ 2844 for (size_t idxType = 0; idxType < RT_ELEMENTS(maLedTypes); idxType++) 2845 maLedTypes[idxType].cLeds = 0; 2846 2847 /* 2848 * Rebuild the data. 2849 */ 2850 for (uint32_t idxSet = 0; idxSet < mcLedSets; idxSet++) 2851 { 2852 PLEDSET const pLS = &maLedSets[idxSet]; 2853 uint32_t const cLeds = pLS->cLeds; 2854 PPDMLED volatile * const papSrcLeds = pLS->papLeds; 2855 DeviceType_T * const paSubTypes = pLS->paSubTypes; 2856 for (uint32_t idxLed = 0; idxLed < cLeds; idxLed++) 2857 { 2858 /** @todo If we make Console::i_drvStatus_UnitChanged() modify the generation 2859 * too, we could skip NULL entries here and make it a bit more compact. 2860 * OTOH, most unused LED entires have a paSubTypes of DeviceType_Null. */ 2861 DeviceType_T enmType = paSubTypes ? paSubTypes[idxLed] : (DeviceType_T)(ASMBitFirstSetU32(pLS->fTypes) - 1); 2862 if (enmType > DeviceType_Null && enmType < DeviceType_End) 2863 { 2864 uint32_t const idxLedType = maLedTypes[enmType].cLeds; 2865 if (idxLedType >= maLedTypes[enmType].cAllocated) 2866 { 2867 void *pvNew = RTMemRealloc(maLedTypes[enmType].pappLeds, 2868 sizeof(maLedTypes[0].pappLeds[0]) * (idxLedType + 16)); 2869 if (!pvNew) 2870 return E_OUTOFMEMORY; 2871 maLedTypes[enmType].pappLeds = (PPDMLED volatile **)pvNew; 2872 maLedTypes[enmType].cAllocated = idxLedType + 16; 2873 } 2874 maLedTypes[enmType].pappLeds[idxLedType] = &papSrcLeds[idxLed]; 2875 maLedTypes[enmType].cLeds = idxLedType + 1; 2876 } 2877 } 2878 } 2879 muLedTypeGen = muLedGen; 2880 } 2881 2882 /* 2883 * We have to release the write lock before re-acquiring the read-lock. 2884 * 2885 * This means there is a theoretical race here, however we ASSUME that 2886 * LED sets are never removed and therefore we will be just fine 2887 * accessing slightly dated per-type data. 2888 */ 2889 alock.release(); 2890 pReadLock->acquire(); 2891 return S_OK; 2892 } 2893 2817 2894 /** read the value of a LED. */ 2818 2895 DECLINLINE(uint32_t) readAndClearLed(PPDMLED pLed) … … 2828 2905 { 2829 2906 /* 2830 * Make a roadmap of which DeviceType_T LED types are wanted: 2907 * Make a roadmap of which DeviceType_T LED types are wanted. 2908 * 2909 * Note! This approach means we'll return the same values in aActivity for 2910 * duplicate aType entries. 2831 2911 */ 2832 uint32_t f Wanted= 0;2912 uint32_t fRequestedTypes = 0; 2833 2913 AssertCompile(DeviceType_End <= 32); 2834 2914 … … 2836 2916 { 2837 2917 DeviceType_T const enmType = aType[iType]; 2918 AssertCompile((unsigned)DeviceType_Null == 0 /* first */); 2838 2919 AssertReturn(enmType > DeviceType_Null && enmType < DeviceType_End, 2839 2920 setError(E_INVALIDARG, tr("Invalid DeviceType for getDeviceActivity in entry #%u: %d"), iType, enmType)); 2840 fWanted |= RT_BIT_32((unsigned)enmType); 2841 } 2842 2843 /* Resize the result vector before making changes (may throw, paranoia). */ 2921 fRequestedTypes |= RT_BIT_32((unsigned)enmType); 2922 } 2923 2924 /* 2925 * Resize the result vector before making changes (may throw, paranoia). 2926 */ 2844 2927 aActivity.resize(aType.size()); 2845 2928 2846 2929 /* 2847 * Collect all the LEDs in a single sweep through all drivers' sets: 2848 * 2849 * Because this method can be called by the frontend and others while the 2850 * VM is being constructed, we use a dedicated lock to prevent stumbling 2851 * into the allocator. 2930 * Accumulate the per-type data for all the requested types. 2931 * We will lazily refresh the per-type data collection here when needed. 2852 2932 */ 2853 2933 PDMLEDCORE aLEDs[DeviceType_End] = { {0} }; … … 2855 2935 { 2856 2936 AutoReadLock alock(mLedLock COMMA_LOCKVAL_SRC_POS); 2857 uint32_t idxSet = mcLedSets; 2858 while (idxSet-- > 0) 2859 { 2860 /* Look inside this driver's set of LEDs and check if the types mask overlap with the request: */ 2861 PLEDSET pLS = &maLedSets[idxSet]; 2862 if (pLS->fTypes & fWanted) 2937 if (RT_LIKELY(muLedGen == muLedTypeGen)) 2938 { /* likely */ } 2939 else 2940 { 2941 HRESULT hrc = i_refreshLedTypeArrays(&alock); 2942 if (FAILED(hrc)) 2943 return hrc; 2944 } 2945 2946 AssertCompile((unsigned)DeviceType_Null == 0 /* we skip this one */); 2947 for (uint32_t idxType = 1; idxType < RT_ELEMENTS(maLedTypes); idxType++) 2948 if (fRequestedTypes & RT_BIT_32(idxType)) 2863 2949 { 2864 uint32_t const cLeds = pLS->cLeds; 2865 PPDMLED volatile * const papSrcLeds = pLS->papLeds; 2866 2867 /* Multi-type drivers (e.g. SCSI) have a subtype array which must be matched. */ 2868 DeviceType_T const *paSubTypes = pLS->paSubTypes; 2869 if (paSubTypes) 2870 for (uint32_t idxLed = 0; idxLed < cLeds; idxLed++) 2871 { 2872 DeviceType_T const enmType = paSubTypes[idxLed]; 2873 Assert((unsigned)enmType < (unsigned)DeviceType_End); 2874 if (fWanted & RT_BIT_32((unsigned)enmType)) 2875 aLEDs[enmType].u32 |= readAndClearLed(papSrcLeds[idxLed]); 2876 } 2877 /* Single-type drivers (e.g. floppy) have the type in ->enmType */ 2878 else 2879 { 2880 uint32_t const idxType = ASMBitFirstSetU32(pLS->fTypes) - 1; 2881 for (uint32_t idxLed = 0; idxLed < cLeds; idxLed++) 2882 aLEDs[idxType].u32 |= readAndClearLed(papSrcLeds[idxLed]); 2883 } 2950 uint32_t const cLeds = maLedTypes[idxType].cLeds; 2951 PPDMLED volatile ** const pappSrcLeds = maLedTypes[idxType].pappLeds; 2952 for (size_t iLed = 0; iLed < cLeds; iLed++) 2953 aLEDs[idxType].u32 |= readAndClearLed(*pappSrcLeds[iLed]); 2884 2954 } 2885 }2886 2955 } 2887 2956 -
trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
r98091 r98095 657 657 658 658 /** 659 * Updates the device type for a LED. 660 * 661 * @param penmSubTypeEntry The sub-type entry to update. 662 * @param enmNewType The new type. 663 */ 664 void Console::i_setLedType(DeviceType_T *penmSubTypeEntry, DeviceType_T enmNewType) 665 { 666 /* 667 * ASSUMES no race conditions here wrt concurrent type updating. 668 */ 669 if (*penmSubTypeEntry != enmNewType) 670 { 671 *penmSubTypeEntry = enmNewType; 672 ASMAtomicIncU32(&muLedGen); 673 } 674 } 675 676 677 /** 659 678 * Allocate a set of LEDs. 660 679 * … … 738 757 * @throws ConfigError and std::bad_alloc. 739 758 */ 740 void Console::i_attachStatusDriver(PCFGMNODE pCtlInst, DeviceType_T enmType )759 void Console::i_attachStatusDriver(PCFGMNODE pCtlInst, DeviceType_T enmType, uint32_t cLeds /*= 1*/) 741 760 { 742 761 Assert(enmType > DeviceType_Null && enmType < DeviceType_End); 743 i_attachStatusDriver(pCtlInst, RT_BIT_32(enmType), 1, NULL, NULL, NULL, 0);762 i_attachStatusDriver(pCtlInst, RT_BIT_32(enmType), cLeds, NULL, NULL, NULL, 0); 744 763 } 745 764 … … 2184 2203 * Attach the status driver. 2185 2204 */ 2186 i_attachStatusDriver(pInst, RT_BIT_32(DeviceType_USB), 2, NULL, NULL, NULL, 0);2205 i_attachStatusDriver(pInst, DeviceType_USB, 2); 2187 2206 } 2188 2207 } /* for every USB controller. */ … … 2485 2504 2486 2505 /* Attach the status driver */ 2487 i_attachStatusDriver(pCtlInst, DeviceType_Floppy, 2, NULL,2488 &mapMediumAttachments, pszCtrlDev, ulInstance);2506 i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_Floppy), 2507 2, NULL, &mapMediumAttachments, pszCtrlDev, ulInstance); 2489 2508 break; 2490 2509 } … … 5097 5116 5098 5117 if (paLedDevType) 5099 paLedDevType[uLUN] = enmType;5118 i_setLedType(&paLedDevType[uLUN], enmType); 5100 5119 5101 5120 /* Dump the changed LUN if possible, dump the complete device otherwise */
Note:
See TracChangeset
for help on using the changeset viewer.