- Timestamp:
- Nov 17, 2009 9:33:54 PM (15 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VM.cpp
r24730 r24738 811 811 STAM_REG(pVM, &pUVM->vm.s.StatReqFree, STAMTYPE_COUNTER, "/VM/Req/Free", STAMUNIT_OCCURENCES, "Number of VMR3ReqFree calls."); 812 812 STAM_REG(pVM, &pUVM->vm.s.StatReqFreeOverflow, STAMTYPE_COUNTER, "/VM/Req/FreeOverflow", STAMUNIT_OCCURENCES, "Number of times the request was actually freed."); 813 STAM_REG(pVM, &pUVM->vm.s.StatReqProcessed, STAMTYPE_COUNTER, "/VM/Req/Processed", STAMUNIT_OCCURENCES, "Number of processed requests (any queue)."); 814 STAM_REG(pVM, &pUVM->vm.s.StatReqMoreThan1, STAMTYPE_COUNTER, "/VM/Req/MoreThan1", STAMUNIT_OCCURENCES, "Number of times there are more than one request on the queue when processing it."); 815 STAM_REG(pVM, &pUVM->vm.s.StatReqPushBackRaces, STAMTYPE_COUNTER, "/VM/Req/PushBackRaces", STAMUNIT_OCCURENCES, "Number of push back races."); 813 816 814 817 rc = CPUMR3Init(pVM); -
trunk/src/VBox/VMM/VMInternal.h
r24508 r24738 198 198 /** Number of times the request was actually freed. */ 199 199 STAMCOUNTER StatReqFreeOverflow; 200 /** Number of requests served. */ 201 STAMCOUNTER StatReqProcessed; 202 /** Number of times there are more than one request and the others needed to be 203 * pushed back onto the list. */ 204 STAMCOUNTER StatReqMoreThan1; 205 /** Number of times we've raced someone when pushing the other requests back 206 * onto the list. */ 207 STAMCOUNTER StatReqPushBackRaces; 200 208 #endif 201 209 -
trunk/src/VBox/VMM/VMReq.cpp
r24467 r24738 983 983 984 984 /** 985 * VMR3ReqProcessU helper that handles cases where there are more than one 986 * pending request. 987 * 988 * @returns The oldest request. 989 * @param pUVM Pointer to the user mode VM structure 990 * @param idDstCpu VMCPUID_ANY or virtual CPU ID. 991 * @param pReqList The list of requests. 992 * @param ppvReqs Pointer to the list head. 993 */ 994 static PVMREQ vmR3ReqProcessUTooManyHelper(PUVM pUVM, VMCPUID idDstCpu, PVMREQ pReqList, void * volatile *ppvReqs) 995 { 996 STAM_COUNTER_INC(&pUVM->vm.s.StatReqMoreThan1); 997 /* Chop off the last one (pReq). */ 998 PVMREQ pPrev; 999 PVMREQ pReqRet = pReqList; 1000 do 1001 { 1002 pPrev = pReqRet; 1003 pReqRet = pReqRet->pNext; 1004 } while (pReqRet->pNext); 1005 ASMAtomicWritePtr((void * volatile *)&pPrev->pNext, NULL); 1006 1007 /* Push the others back onto the list (end of it). */ 1008 Log2(("VMR3ReqProcess: Pushing back %p %p...\n", pReqList, pReqList->pNext)); 1009 if (RT_UNLIKELY(!ASMAtomicCmpXchgPtr(ppvReqs, pReqList, NULL))) 1010 { 1011 STAM_COUNTER_INC(&pUVM->vm.s.StatReqPushBackRaces); 1012 do 1013 { 1014 ASMNopPause(); 1015 PVMREQ pReqList2 = (PVMREQ)ASMAtomicXchgPtr(ppvReqs, NULL); 1016 if (pReqList2) 1017 { 1018 PVMREQ pLast = pReqList2; 1019 while (pLast->pNext) 1020 pLast = pLast->pNext; 1021 ASMAtomicWritePtr((void * volatile *)&pLast->pNext, pReqList); 1022 pReqList = pReqList2; 1023 } 1024 } while (!ASMAtomicCmpXchgPtr(ppvReqs, pReqList, NULL)); 1025 } 1026 1027 if (RT_LIKELY(pUVM->pVM)) 1028 { 1029 if (idDstCpu == VMCPUID_ANY) 1030 VM_FF_SET(pUVM->pVM, VM_FF_REQUEST); 1031 else 1032 VMCPU_FF_SET(&pUVM->pVM->aCpus[idDstCpu], VMCPU_FF_REQUEST); 1033 } 1034 1035 return pReqRet; 1036 } 1037 1038 1039 /** 985 1040 * Process pending request(s). 986 1041 * … … 996 1051 * 997 1052 * @note SMP safe (multiple EMTs trying to satisfy VM_FF_REQUESTs). 1053 * 1054 * @remarks This was made reentrant for 998 1055 */ 999 1056 VMMR3DECL(int) VMR3ReqProcessU(PUVM pUVM, VMCPUID idDstCpu) … … 1011 1068 { 1012 1069 /* 1013 * Get pending requests. 1070 * Get the pending requests. 1071 * If there are more than one request, unlink the oldest and put the 1072 * rest back so that we're reentrant. 1014 1073 */ 1015 void * volatile *pp Reqs;1074 void * volatile *ppvReqs; 1016 1075 if (idDstCpu == VMCPUID_ANY) 1017 1076 { 1018 pp Reqs = (void * volatile *)&pUVM->vm.s.pReqs;1077 ppvReqs = (void * volatile *)&pUVM->vm.s.pReqs; 1019 1078 if (RT_LIKELY(pUVM->pVM)) 1020 1079 VM_FF_CLEAR(pUVM->pVM, VM_FF_REQUEST); … … 1024 1083 Assert(idDstCpu < pUVM->cCpus); 1025 1084 Assert(pUVM->aCpus[idDstCpu].vm.s.NativeThreadEMT == RTThreadNativeSelf()); 1026 pp Reqs = (void * volatile *)&pUVM->aCpus[idDstCpu].vm.s.pReqs;1085 ppvReqs = (void * volatile *)&pUVM->aCpus[idDstCpu].vm.s.pReqs; 1027 1086 if (RT_LIKELY(pUVM->pVM)) 1028 1087 VMCPU_FF_CLEAR(&pUVM->pVM->aCpus[idDstCpu], VMCPU_FF_REQUEST); 1029 1088 } 1030 PVMREQ pReqs = (PVMREQ)ASMAtomicXchgPtr(ppReqs, NULL); 1031 if (!pReqs) 1089 1090 PVMREQ pReq = (PVMREQ)ASMAtomicXchgPtr(ppvReqs, NULL); 1091 if (!pReq) 1032 1092 break; 1093 if (RT_UNLIKELY(pReq->pNext)) 1094 pReq = vmR3ReqProcessUTooManyHelper(pUVM, idDstCpu, pReq, ppvReqs); 1033 1095 1034 1096 /* 1035 * Reverse the list to process it in FIFO order. 1097 * Process the request. 1098 * Note! The status code handling here extremely important and yet very 1099 * fragile. 1036 1100 */ 1037 PVMREQ pReq = pReqs; 1038 if (pReq->pNext) 1039 Log2(("VMR3ReqProcess: 2+ requests: %p %p %p\n", pReq, pReq->pNext, pReq->pNext->pNext)); 1040 pReqs = NULL; 1041 while (pReq) 1042 { 1043 Assert(pReq->enmState == VMREQSTATE_QUEUED); 1044 Assert(pReq->pUVM == pUVM); 1045 PVMREQ pCur = pReq; 1046 pReq = pReq->pNext; 1047 pCur->pNext = pReqs; 1048 pReqs = pCur; 1049 } 1050 1051 1052 /* 1053 * Process the requests. 1054 * 1055 * Since this is a FF worker certain rules applies to the 1056 * status codes. See the EM section in VBox/err.h and EM.cpp for details. 1057 */ 1058 while (pReqs) 1059 { 1060 /* Unchain the first request and advance the list. */ 1061 pReq = pReqs; 1062 pReqs = pReqs->pNext; 1063 pReq->pNext = NULL; 1064 1065 /* Process the request */ 1066 int rc2 = vmR3ReqProcessOneU(pUVM, pReq); 1067 1068 /* 1069 * The status code handling extremely important yet very fragile. Should probably 1070 * look for a better way of communicating status changes to EM... 1071 */ 1072 if ( rc2 >= VINF_EM_FIRST 1073 && rc2 <= VINF_EM_LAST 1074 && ( rc == VINF_SUCCESS 1075 || rc2 < rc) ) 1076 rc = rc2; 1077 /** @todo may have to abort processing to propagate EM scheduling status codes 1078 * up to the caller... See the ugly hacks after VMMR3EmtRendezvousFF 1079 * and VMR3ReqProcessU in EM.cpp. */ 1080 } 1101 STAM_COUNTER_INC(&pUVM->vm.s.StatReqProcessed); 1102 int rc2 = vmR3ReqProcessOneU(pUVM, pReq); 1103 if ( rc2 >= VINF_EM_FIRST 1104 && rc2 <= VINF_EM_LAST 1105 && ( rc == VINF_SUCCESS 1106 || rc2 < rc) ) 1107 rc = rc2; 1108 /** @todo may have to abort processing to propagate EM scheduling status codes 1109 * up to the caller... See the ugly hacks after VMMR3EmtRendezvousFF 1110 * and VMR3ReqProcessU in EM.cpp. */ 1081 1111 } 1082 1112 … … 1096 1126 static int vmR3ReqProcessOneU(PUVM pUVM, PVMREQ pReq) 1097 1127 { 1098 LogFlow(("vmR3ReqProcessOne : pReq=%p type=%d fFlags=%#x\n", pReq, pReq->enmType, pReq->fFlags));1128 LogFlow(("vmR3ReqProcessOneU: pReq=%p type=%d fFlags=%#x\n", pReq, pReq->enmType, pReq->fFlags)); 1099 1129 1100 1130 /* … … 1210 1240 { 1211 1241 /* Free the packet, nobody is waiting. */ 1212 LogFlow(("vmR3ReqProcessOne : Completed request %p: rcReq=%Rrc rcRet=%Rrc - freeing it\n",1242 LogFlow(("vmR3ReqProcessOneU: Completed request %p: rcReq=%Rrc rcRet=%Rrc - freeing it\n", 1213 1243 pReq, rcReq, rcRet)); 1214 1244 VMR3ReqFree(pReq); … … 1217 1247 { 1218 1248 /* Notify the waiter and him free up the packet. */ 1219 LogFlow(("vmR3ReqProcessOne : Completed request %p: rcReq=%Rrc rcRet=%Rrc - notifying waiting thread\n",1249 LogFlow(("vmR3ReqProcessOneU: Completed request %p: rcReq=%Rrc rcRet=%Rrc - notifying waiting thread\n", 1220 1250 pReq, rcReq, rcRet)); 1221 1251 ASMAtomicXchgSize(&pReq->fEventSemClear, false);
Note:
See TracChangeset
for help on using the changeset viewer.