Changeset 36839 in vbox
- Timestamp:
- Apr 25, 2011 5:29:21 PM (14 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/Performance.h
r36527 r36839 145 145 ~CollectorGuest(); 146 146 147 bool isUnregistered() { return mUnregistered; }; 147 148 bool isEnabled() { return mEnabled; }; 148 149 bool isValid() { return mValid; }; 149 150 void invalidateStats() { mValid = false; }; 151 void unregister() { mUnregistered = true; }; 150 152 int updateStats(); 151 153 int enable(); … … 168 170 169 171 private: 172 bool mUnregistered; 170 173 bool mEnabled; 171 174 bool mValid; … … 194 197 public: 195 198 CollectorGuestManager() : mVMMStatsProvider(NULL) {}; 199 ~CollectorGuestManager() { Assert(mGuests.size() == 0); }; 196 200 void registerGuest(CollectorGuest* pGuest); 197 201 void unregisterGuest(CollectorGuest* pGuest); 198 202 CollectorGuest *getVMMStatsProvider() { return mVMMStatsProvider; }; 199 203 void preCollect(CollectorHints& hints, uint64_t iTick); 204 void destroyUnregistered(); 200 205 private: 201 206 CollectorGuestList mGuests; … … 234 239 public: 235 240 BaseMetric(CollectorHAL *hal, const char *name, ComPtr<IUnknown> object) 236 : mPeriod(0), mLength(0), mHAL(hal), mName(name), mObject(object), mLastSampleTaken(0), mEnabled(false) {}; 241 : mPeriod(0), mLength(0), mHAL(hal), mName(name), mObject(object), 242 mLastSampleTaken(0), mEnabled(false), mUnregistered(false) {}; 237 243 virtual ~BaseMetric() {}; 238 244 … … 249 255 void enable() { mEnabled = true; }; 250 256 void disable() { mEnabled = false; }; 251 257 void unregister() { mUnregistered = true; }; 258 259 bool isUnregistered() { return mUnregistered; }; 252 260 bool isEnabled() { return mEnabled; }; 253 261 ULONG getPeriod() { return mPeriod; }; … … 265 273 uint64_t mLastSampleTaken; 266 274 bool mEnabled; 275 bool mUnregistered; 267 276 }; 268 277 -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r36727 r36839 10562 10562 { 10563 10563 mParent->performanceCollector()->unregisterGuest(mCollectorGuest); 10564 delete mCollectorGuest;10564 // delete mCollectorGuest; => CollectorGuestManager::destroyUnregistered() 10565 10565 mCollectorGuest = NULL; 10566 10566 } 10567 #if 0 10567 10568 // Trigger async cleanup tasks, avoid doing things here which are not 10568 10569 // vital to be done immediately and maybe need more locks. This calls 10569 10570 // Machine::unregisterMetrics(). 10570 10571 mParent->onMachineUninit(mPeer); 10572 #else 10573 /* 10574 * It is safe to call Machine::unregisterMetrics() here because 10575 * PerformanceCollector::samplerCallback no longer accesses guest methods 10576 * holding the lock. 10577 */ 10578 unregisterMetrics(mParent->performanceCollector(), mPeer); 10579 #endif 10571 10580 10572 10581 if (aReason == Uninit::Abnormal) -
trunk/src/VBox/Main/src-server/Performance.cpp
r36527 r36839 110 110 111 111 CollectorGuest::CollectorGuest(Machine *machine, RTPROCESS process) : 112 m Enabled(false), mValid(false), mMachine(machine), mProcess(process),112 mUnregistered(false), mEnabled(false), mValid(false), mMachine(machine), mProcess(process), 113 113 mCpuUser(0), mCpuKernel(0), mCpuIdle(0), 114 114 mMemTotal(0), mMemFree(0), mMemBalloon(0), mMemShared(0), mMemCache(0), mPageTotal(0), … … 202 202 void CollectorGuestManager::preCollect(CollectorHints& hints, uint64_t /* iTick */) 203 203 { 204 /* 205 * Since we are running without a lock the value of mVMMStatsProvider 206 * can change at any moment. In the worst case we won't collect any data. 207 */ 204 208 CollectorGuestList::iterator it; 205 209 … … 211 215 this, __PRETTY_FUNCTION__, *it, (*it)->getProcess(), 212 216 hints.isGuestStatsCollected((*it)->getProcess())?"y":"n")); 217 if ((*it)->isUnregistered()) 218 continue; 213 219 if ( (hints.isHostRamVmmCollected() && *it == mVMMStatsProvider) 214 220 || hints.isGuestStatsCollected((*it)->getProcess())) … … 252 258 LogAleksey(("{%p} " LOG_FN_FMT ": About to unregister guest=%p provider=%p\n", 253 259 this, __PRETTY_FUNCTION__, pGuest, mVMMStatsProvider)); 254 mGuests.remove(pGuest); 255 LogAleksey(("{%p} " LOG_FN_FMT ": Number of guests after remove is %d\n", 256 this, __PRETTY_FUNCTION__, mGuests.size())); 260 //mGuests.remove(pGuest); => destroyUnregistered() 261 pGuest->unregister(); 257 262 if (pGuest == mVMMStatsProvider) 258 263 { 259 264 /* This was our VMM stats provider, it is time to re-elect */ 260 if (mGuests.empty()) 261 { 262 /* Nobody can provide VMM stats */ 263 mVMMStatsProvider = NULL; 264 } 265 else 266 { 267 /* First let's look for a guest already collecting stats */ 268 CollectorGuestList::iterator it; 269 270 for (it = mGuests.begin(); it != mGuests.end(); it++) 271 if ((*it)->isEnabled()) 272 { 273 /* Found one, elect it */ 274 mVMMStatsProvider = *it; 275 LogAleksey(("{%p} " LOG_FN_FMT ": LEAVE new provider=%p\n", 276 this, __PRETTY_FUNCTION__, mVMMStatsProvider)); 277 return; 278 } 279 280 /* Nobody collects stats, take the first one */ 281 mVMMStatsProvider = mGuests.front(); 265 CollectorGuestList::iterator it; 266 /* Assume that nobody can provide VMM stats */ 267 mVMMStatsProvider = NULL; 268 269 for (it = mGuests.begin(); it != mGuests.end(); it++) 270 { 271 /* Skip unregistered as they are about to be destroyed */ 272 if ((*it)->isUnregistered()) 273 continue; 274 275 if ((*it)->isEnabled()) 276 { 277 /* Found the guest already collecting stats, elect it */ 278 mVMMStatsProvider = *it; 279 break; 280 } 281 else if (!mVMMStatsProvider) 282 { 283 /* If nobody collects stats, take the first registered */ 284 mVMMStatsProvider = *it; 285 } 282 286 } 283 287 } … … 286 290 } 287 291 292 void CollectorGuestManager::destroyUnregistered() 293 { 294 CollectorGuestList::iterator it; 295 296 for (it = mGuests.begin(); it != mGuests.end();) 297 if ((*it)->isUnregistered()) 298 { 299 delete *it; 300 it = mGuests.erase(it); 301 LogAleksey(("{%p} " LOG_FN_FMT ": Number of guests after erasing unregistered is %d\n", 302 this, __PRETTY_FUNCTION__, mGuests.size())); 303 } 304 else 305 ++it; 306 } 288 307 289 308 #endif /* !VBOX_COLLECTOR_TEST_CASE */ -
trunk/src/VBox/Main/src-server/PerformanceImpl.cpp
r36128 r36839 16 16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 17 17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 18 */ 19 20 /* 21 * Rules of engagement: 22 * 1) All performance objects must be destroyed by PerformanceCollector only! 23 * 2) All public methods of PerformanceCollector must be protected with 24 * read or write lock. 25 * 3) samplerCallback only uses the write lock during the third phase 26 * which pulls data into SubMetric objects. This is where object destruction 27 * and all list modifications are done. The pre-collection phases are 28 * run without any locks which is only possible because: 29 * 4) Public methods of PerformanceCollector as well as pre-collection methods 30 cannot modify lists or destroy objects, and: 31 * 5) Pre-collection methods cannot modify metric data. 18 32 */ 19 33 … … 200 214 mMagic = 0; 201 215 216 /* Destroy unregistered metrics */ 217 BaseMetricList::iterator it; 218 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end();) 219 if ((*it)->isUnregistered()) 220 { 221 delete *it; 222 it = m.baseMetrics.erase(it); 223 } 224 else 225 ++it; 226 Assert(m.baseMetrics.size() == 0); 227 /* 228 * Now when we have destroyed all base metrics that could 229 * try to pull data from unregistered CollectorGuest objects 230 * it is safe to destroy them as well. 231 */ 232 m.gm->destroyUnregistered(); 233 202 234 /* Destroy resource usage sampler */ 203 235 int vrc = RTTimerLRDestroy (m.sampler); … … 534 566 535 567 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 536 LogAleksey(("{%p} " LOG_FN_FMT ": before remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size()));568 int n = 0; 537 569 BaseMetricList::iterator it; 538 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); )570 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it) 539 571 if ((*it)->associatedWith(aObject)) 540 572 { 541 delete *it;542 it = m.baseMetrics.erase(it);573 (*it)->unregister(); 574 ++n; 543 575 } 544 else 545 ++it; 546 LogAleksey(("{%p} " LOG_FN_FMT ": after remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size())); 576 LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p, marked %d metrics\n", 577 this, __PRETTY_FUNCTION__, (void *)aObject, n)); 547 578 //LogFlowThisFuncLeave(); 548 579 } … … 640 671 { 641 672 Log4(("{%p} " LOG_FN_FMT ": ENTER\n", this, __PRETTY_FUNCTION__)); 642 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);673 /* No locking until stage 3!*/ 643 674 644 675 pm::CollectorHints hints; … … 665 696 m.gm->preCollect(hints, iTick); 666 697 698 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 699 /* 700 * Before we can collect data we need to go through both lists 701 * again to see if any base metrics are marked as unregistered. 702 * Those should be destroyed now. 703 */ 704 LogAleksey(("{%p} " LOG_FN_FMT ": before remove_if: toBeCollected.size()=%d\n", this, __PRETTY_FUNCTION__, toBeCollected.size())); 705 toBeCollected.remove_if(std::mem_fun(&pm::BaseMetric::isUnregistered)); 706 LogAleksey(("{%p} " LOG_FN_FMT ": after remove_if: toBeCollected.size()=%d\n", this, __PRETTY_FUNCTION__, toBeCollected.size())); 707 LogAleksey(("{%p} " LOG_FN_FMT ": before remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size())); 708 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end();) 709 if ((*it)->isUnregistered()) 710 { 711 delete *it; 712 it = m.baseMetrics.erase(it); 713 } 714 else 715 ++it; 716 LogAleksey(("{%p} " LOG_FN_FMT ": after remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size())); 717 /* 718 * Now when we have destroyed all base metrics that could 719 * try to pull data from unregistered CollectorGuest objects 720 * it is safe to destroy them as well. 721 */ 722 m.gm->destroyUnregistered(); 723 667 724 /* Finally, collect the data */ 668 725 std::for_each (toBeCollected.begin(), toBeCollected.end(),
Note:
See TracChangeset
for help on using the changeset viewer.