vbox的更動 61774 路徑 trunk/src/VBox/Main
- 時間撮記:
- 2016-6-20 下午09:45:58 (8 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Main/src-all/EventImpl.cpp
r60765 r61774 598 598 private: 599 599 ComPtr<IEventListener> mListener; 600 BOOL 600 BOOL const mActive; 601 601 EventSource *mOwner; 602 602 603 603 RTSEMEVENT mQEvent; 604 int32_t volatile m WaitCnt;604 int32_t volatile mQEventBusyCnt; 605 605 RTCRITSECT mcsQLock; 606 606 PassiveQueue mQueue; … … 749 749 BOOL aActive, 750 750 EventSource *aOwner) : 751 mActive(aActive), mOwner(aOwner), m WaitCnt(0), mRefCnt(0)751 mActive(aActive), mOwner(aOwner), mQEventBusyCnt(0), mRefCnt(0) 752 752 { 753 753 mListener = aListener; … … 859 859 uint64_t sinceRead = RTTimeMilliTS() - mLastRead; 860 860 size_t queueSize = mQueue.size(); 861 if ( (queueSize > 1000) || ((queueSize > 500) && (sinceRead > 60 * 1000)))861 if (queueSize > 1000 || (queueSize > 500 && sinceRead > 60 * 1000)) 862 862 { 863 863 ::RTCritSectLeave(&mcsQLock); … … 866 866 867 867 868 RTSEMEVENT hEvt = mQEvent; 868 869 if (queueSize != 0 && mQueue.back() == aEvent) 869 870 /* if same event is being pushed multiple times - it's reusable event and 870 871 we don't really need multiple instances of it in the queue */ 871 (void)aEvent; 872 else 872 hEvt = NIL_RTSEMEVENT; 873 else if (hEvt != NIL_RTSEMEVENT) /* don't bother queuing after shutdown */ 874 { 873 875 mQueue.push_back(aEvent); 876 ASMAtomicIncS32(&mQEventBusyCnt); 877 } 874 878 875 879 ::RTCritSectLeave(&mcsQLock); 876 880 877 // notify waiters 878 ::RTSemEventSignal(mQEvent); 881 // notify waiters unless we've been shut down. 882 if (hEvt != NIL_RTSEMEVENT) 883 { 884 ::RTSemEventSignal(hEvt); 885 ASMAtomicDecS32(&mQEventBusyCnt); 886 } 879 887 880 888 return S_OK; … … 895 903 mLastRead = RTTimeMilliTS(); 896 904 905 /* 906 * If waiting both desired and necessary, then try grab the event 907 * semaphore and mark it busy. If it's NIL we've been shut down already. 908 */ 909 if (aTimeout != 0 && mQueue.empty()) 910 { 911 RTSEMEVENT hEvt = mQEvent; 912 if (hEvt != NIL_RTSEMEVENT) 913 { 914 ASMAtomicIncS32(&mQEventBusyCnt); 915 ::RTCritSectLeave(&mcsQLock); 916 917 // release lock while waiting, listener will not go away due to above holder 918 aAlock.release(); 919 920 ::RTSemEventWait(hEvt, aTimeout); 921 ASMAtomicDecS32(&mQEventBusyCnt); 922 923 // reacquire lock 924 aAlock.acquire(); 925 ::RTCritSectEnter(&mcsQLock); 926 } 927 } 928 897 929 if (mQueue.empty()) 898 {899 ::RTCritSectLeave(&mcsQLock);900 // Speed up common case901 if (aTimeout == 0)902 {903 *aEvent = NULL;904 return S_OK;905 }906 // release lock while waiting, listener will not go away due to above holder907 aAlock.release();908 909 // In order to safely shutdown, count all waiting threads here.910 ASMAtomicIncS32(&mWaitCnt);911 ::RTSemEventWait(mQEvent, aTimeout);912 ASMAtomicDecS32(&mWaitCnt);913 914 // reacquire lock915 aAlock.acquire();916 ::RTCritSectEnter(&mcsQLock);917 }918 if (mQueue.empty())919 {920 930 *aEvent = NULL; 921 }922 931 else 923 932 { … … 925 934 mQueue.pop_front(); 926 935 } 936 927 937 ::RTCritSectLeave(&mcsQLock); 928 938 return S_OK; … … 945 955 if (mQEvent != NIL_RTSEMEVENT) 946 956 { 947 RTSEMEVENT tmp = mQEvent; 957 /* Grab the event semaphore. Must do this while owning the CS or we'll 958 be racing user wanting to use the handle. */ 959 ::RTCritSectEnter(&mcsQLock); 960 RTSEMEVENT hEvt = mQEvent; 948 961 mQEvent = NIL_RTSEMEVENT; 949 950 /* On Darwin it is known that RTSemEventDestroy() returns 0 while 951 * corresponding thread remains to be blocked after that. In order to prevent 952 * undesireble freeze on shutdown, this workaround is used. */ 953 Log(("Wait for %d waiters to release.\n", ASMAtomicReadS32(&mWaitCnt))); 954 while (ASMAtomicReadS32(&mWaitCnt) > 0) 955 { 956 ::RTSemEventSignal(tmp); 957 958 /* Are we already done? */ 959 if (ASMAtomicReadS32(&mWaitCnt) == 0) 960 break; 961 962 RTThreadSleep(10); 963 } 964 Log(("All waiters just released the lock.\n")); 965 966 ::RTSemEventDestroy(tmp); 962 ::RTCritSectLeave(&mcsQLock); 963 964 /* 965 * Signal waiters and wait for them and any other signallers to stop using the sempahore. 966 * 967 * Note! RTSemEventDestroy does not necessarily guarantee that waiting threads are 968 * out of RTSemEventWait or even woken up when it returns. Darwin is (or was?) 969 * an example of this, the result was undesirable freezes on shutdown. 970 */ 971 int32_t cBusy = ASMAtomicReadS32(&mQEventBusyCnt); 972 if (cBusy > 0) 973 { 974 Log(("Wait for %d waiters+signalers to release.\n", cBusy)); 975 while (cBusy-- > 0) 976 ::RTSemEventSignal(hEvt); 977 978 for (uint32_t cLoops = 0;; cLoops++) 979 { 980 RTThreadSleep(RT_MIN(8, cLoops)); 981 if (ASMAtomicReadS32(&mQEventBusyCnt) <= 0) 982 break; 983 ::RTSemEventSignal(hEvt); /* (Technically unnecessary, but just in case.) */ 984 } 985 Log(("All waiters+signalers just released the lock.\n")); 986 } 987 988 ::RTSemEventDestroy(hEvt); 967 989 } 968 990 }
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器