Changeset 6084 in vbox
- Timestamp:
- Dec 15, 2007 2:56:01 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/TMAll.cpp
r5999 r6084 1138 1138 * Processing. 1139 1139 */ 1140 switch (pTimer->enmState) 1141 { 1142 /* 1143 * Reschedule timer (in the active list). 1144 */ 1145 case TMTIMERSTATE_PENDING_RESCHEDULE: 1140 unsigned cRetries = 2; 1141 do 1142 { 1143 TMTIMERSTATE enmState = pTimer->enmState; 1144 switch (enmState) 1146 1145 { 1147 const PTMTIMER pPrev = TMTIMER_GET_PREV(pTimer); 1148 const PTMTIMER pNext = TMTIMER_GET_NEXT(pTimer); 1149 if (pPrev) 1150 TMTIMER_SET_NEXT(pPrev, pNext); 1151 else 1146 /* 1147 * Reschedule timer (in the active list). 1148 */ 1149 case TMTIMERSTATE_PENDING_RESCHEDULE: 1152 1150 { 1153 TMTIMER_SET_HEAD(pQueue, pNext); 1154 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX; 1151 if (RT_UNLIKELY(!tmTimerTry(pTimer, TMTIMERSTATE_PENDING_SCHEDULE, TMTIMERSTATE_PENDING_RESCHEDULE))) 1152 break; /* retry */ 1153 1154 const PTMTIMER pPrev = TMTIMER_GET_PREV(pTimer); 1155 const PTMTIMER pNext = TMTIMER_GET_NEXT(pTimer); 1156 if (pPrev) 1157 TMTIMER_SET_NEXT(pPrev, pNext); 1158 else 1159 { 1160 TMTIMER_SET_HEAD(pQueue, pNext); 1161 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX; 1162 } 1163 if (pNext) 1164 TMTIMER_SET_PREV(pNext, pPrev); 1165 pTimer->offNext = 0; 1166 pTimer->offPrev = 0; 1167 /* fall thru */ 1155 1168 } 1156 if (pNext) 1157 TMTIMER_SET_PREV(pNext, pPrev); 1158 pTimer->offNext = 0; 1159 pTimer->offPrev = 0; 1160 /* fall thru */ 1169 1170 /* 1171 * Schedule timer (insert into the active list). 1172 */ 1173 case TMTIMERSTATE_PENDING_SCHEDULE: 1174 { 1175 Assert(!pTimer->offNext); Assert(!pTimer->offPrev); 1176 if (RT_UNLIKELY(!tmTimerTry(pTimer, TMTIMERSTATE_ACTIVE, TMTIMERSTATE_PENDING_SCHEDULE))) 1177 break; /* retry */ 1178 1179 PTMTIMER pCur = TMTIMER_GET_HEAD(pQueue); 1180 if (pCur) 1181 { 1182 const uint64_t u64Expire = pTimer->u64Expire; 1183 for (;; pCur = TMTIMER_GET_NEXT(pCur)) 1184 { 1185 if (pCur->u64Expire > u64Expire) 1186 { 1187 const PTMTIMER pPrev = TMTIMER_GET_PREV(pCur); 1188 TMTIMER_SET_NEXT(pTimer, pCur); 1189 TMTIMER_SET_PREV(pTimer, pPrev); 1190 if (pPrev) 1191 TMTIMER_SET_NEXT(pPrev, pTimer); 1192 else 1193 { 1194 TMTIMER_SET_HEAD(pQueue, pTimer); 1195 pQueue->u64Expire = u64Expire; 1196 } 1197 TMTIMER_SET_PREV(pCur, pTimer); 1198 return; 1199 } 1200 if (!pCur->offNext) 1201 { 1202 TMTIMER_SET_NEXT(pCur, pTimer); 1203 TMTIMER_SET_PREV(pTimer, pCur); 1204 return; 1205 } 1206 } 1207 } 1208 else 1209 { 1210 TMTIMER_SET_HEAD(pQueue, pTimer); 1211 pQueue->u64Expire = pTimer->u64Expire; 1212 } 1213 return; 1214 } 1215 1216 /* 1217 * Stop the timer in active list. 1218 */ 1219 case TMTIMERSTATE_PENDING_STOP: 1220 { 1221 if (RT_UNLIKELY(!tmTimerTry(pTimer, TMTIMERSTATE_PENDING_STOP_SCHEDULE, TMTIMERSTATE_PENDING_STOP))) 1222 break; /* retry */ 1223 1224 const PTMTIMER pPrev = TMTIMER_GET_PREV(pTimer); 1225 const PTMTIMER pNext = TMTIMER_GET_NEXT(pTimer); 1226 if (pPrev) 1227 TMTIMER_SET_NEXT(pPrev, pNext); 1228 else 1229 { 1230 TMTIMER_SET_HEAD(pQueue, pNext); 1231 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX; 1232 } 1233 if (pNext) 1234 TMTIMER_SET_PREV(pNext, pPrev); 1235 pTimer->offNext = 0; 1236 pTimer->offPrev = 0; 1237 /* fall thru */ 1238 } 1239 1240 /* 1241 * Stop the timer (not on the active list). 1242 */ 1243 case TMTIMERSTATE_PENDING_STOP_SCHEDULE: 1244 Assert(!pTimer->offNext); Assert(!pTimer->offPrev); 1245 if (RT_UNLIKELY(!tmTimerTry(pTimer, TMTIMERSTATE_STOPPED, TMTIMERSTATE_PENDING_STOP_SCHEDULE))) 1246 break; 1247 return; 1248 1249 /* 1250 * Stop & destroy the timer. 1251 */ 1252 case TMTIMERSTATE_PENDING_STOP_DESTROY: 1253 { 1254 const PTMTIMER pPrev = TMTIMER_GET_PREV(pTimer); 1255 const PTMTIMER pNext = TMTIMER_GET_NEXT(pTimer); 1256 if (pPrev) 1257 TMTIMER_SET_NEXT(pPrev, pNext); 1258 else 1259 { 1260 TMTIMER_SET_HEAD(pQueue, pNext); 1261 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX; 1262 } 1263 if (pNext) 1264 TMTIMER_SET_PREV(pNext, pPrev); 1265 pTimer->offNext = 0; 1266 pTimer->offPrev = 0; 1267 /* fall thru */ 1268 } 1269 1270 /* 1271 * Destroy the timer. 1272 */ 1273 case TMTIMERSTATE_PENDING_DESTROY: 1274 { 1275 Assert(!pTimer->offNext); Assert(!pTimer->offPrev); 1276 PVM pVM = pTimer->CTXALLSUFF(pVM); 1277 const PTMTIMER pBigPrev = (PTMTIMER)(pTimer->pBigPrev ? MMHyperR3ToCC(pVM, pTimer->pBigPrev) : NULL); 1278 const PTMTIMER pBigNext = (PTMTIMER)(pTimer->pBigNext ? MMHyperR3ToCC(pVM, pTimer->pBigNext) : NULL); 1279 1280 /* unlink from created list */ 1281 if (pBigPrev) 1282 pBigPrev->pBigNext = pTimer->pBigNext; 1283 else 1284 pVM->tm.s.pCreated = pTimer->pBigNext; 1285 if (pBigNext) 1286 pBigNext->pBigPrev = pTimer->pBigPrev; 1287 pTimer->pBigNext = 0; 1288 pTimer->pBigPrev = 0; 1289 1290 /* free */ 1291 Log2(("TM: Inserting %p into the free list ahead of %p!\n", pTimer, pVM->tm.s.pFree)); 1292 pTimer->pBigNext = pVM->tm.s.pFree; 1293 pVM->tm.s.pFree = (PTMTIMERR3)MMHyperCCToR3(pVM, pTimer); 1294 TM_SET_STATE(pTimer, TMTIMERSTATE_FREE); 1295 return; 1296 } 1297 1298 /* 1299 * Postpone these until they get into the right state. 1300 */ 1301 case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE: 1302 case TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE: 1303 tmTimerLink(pQueue, pTimer); 1304 STAM_COUNTER_INC(&pTimer->CTXALLSUFF(pVM)->tm.s.CTXALLSUFF(StatPostponed)); 1305 return; 1306 1307 /* 1308 * None of these can be in the schedule. 1309 */ 1310 case TMTIMERSTATE_FREE: 1311 case TMTIMERSTATE_STOPPED: 1312 case TMTIMERSTATE_ACTIVE: 1313 case TMTIMERSTATE_EXPIRED: 1314 default: 1315 AssertMsgFailed(("Timer (%p) in the scheduling list has an invalid state %s (%d)!", 1316 pTimer, tmTimerState(pTimer->enmState), pTimer->enmState)); 1317 return; 1161 1318 } 1162 1163 /* 1164 * Schedule timer (insert into the active list). 1165 */ 1166 case TMTIMERSTATE_PENDING_SCHEDULE: 1167 { 1168 Assert(!pTimer->offNext); Assert(!pTimer->offPrev); 1169 TM_SET_STATE(pTimer, TMTIMERSTATE_ACTIVE); 1170 PTMTIMER pCur = TMTIMER_GET_HEAD(pQueue); 1171 if (pCur) 1172 { 1173 const uint64_t u64Expire = pTimer->u64Expire; 1174 for (;; pCur = TMTIMER_GET_NEXT(pCur)) 1175 { 1176 if (pCur->u64Expire > u64Expire) 1177 { 1178 const PTMTIMER pPrev = TMTIMER_GET_PREV(pCur); 1179 TMTIMER_SET_NEXT(pTimer, pCur); 1180 TMTIMER_SET_PREV(pTimer, pPrev); 1181 if (pPrev) 1182 TMTIMER_SET_NEXT(pPrev, pTimer); 1183 else 1184 { 1185 TMTIMER_SET_HEAD(pQueue, pTimer); 1186 pQueue->u64Expire = u64Expire; 1187 } 1188 TMTIMER_SET_PREV(pCur, pTimer); 1189 break; 1190 } 1191 else if (!pCur->offNext) 1192 { 1193 TMTIMER_SET_NEXT(pCur, pTimer); 1194 TMTIMER_SET_PREV(pTimer, pCur); 1195 break; 1196 } 1197 } 1198 } 1199 else 1200 { 1201 TMTIMER_SET_HEAD(pQueue, pTimer); 1202 pQueue->u64Expire = pTimer->u64Expire; 1203 } 1204 break; 1205 } 1206 1207 /* 1208 * Stop the timer in active list. 1209 */ 1210 case TMTIMERSTATE_PENDING_STOP: 1211 { 1212 const PTMTIMER pPrev = TMTIMER_GET_PREV(pTimer); 1213 const PTMTIMER pNext = TMTIMER_GET_NEXT(pTimer); 1214 if (pPrev) 1215 TMTIMER_SET_NEXT(pPrev, pNext); 1216 else 1217 { 1218 TMTIMER_SET_HEAD(pQueue, pNext); 1219 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX; 1220 } 1221 if (pNext) 1222 TMTIMER_SET_PREV(pNext, pPrev); 1223 pTimer->offNext = 0; 1224 pTimer->offPrev = 0; 1225 /* fall thru */ 1226 } 1227 1228 /* 1229 * Stop the timer (not on the active list). 1230 */ 1231 case TMTIMERSTATE_PENDING_STOP_SCHEDULE: 1232 Assert(!pTimer->offNext); Assert(!pTimer->offPrev); 1233 TM_SET_STATE(pTimer, TMTIMERSTATE_STOPPED); 1234 break; 1235 1236 /* 1237 * Stop & destroy the timer. 1238 */ 1239 case TMTIMERSTATE_PENDING_STOP_DESTROY: 1240 { 1241 const PTMTIMER pPrev = TMTIMER_GET_PREV(pTimer); 1242 const PTMTIMER pNext = TMTIMER_GET_NEXT(pTimer); 1243 if (pPrev) 1244 TMTIMER_SET_NEXT(pPrev, pNext); 1245 else 1246 { 1247 TMTIMER_SET_HEAD(pQueue, pNext); 1248 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX; 1249 } 1250 if (pNext) 1251 TMTIMER_SET_PREV(pNext, pPrev); 1252 pTimer->offNext = 0; 1253 pTimer->offPrev = 0; 1254 /* fall thru */ 1255 } 1256 1257 /* 1258 * Destroy the timer. 1259 */ 1260 case TMTIMERSTATE_PENDING_DESTROY: 1261 { 1262 Assert(!pTimer->offNext); Assert(!pTimer->offPrev); 1263 PVM pVM = pTimer->CTXALLSUFF(pVM); 1264 const PTMTIMER pBigPrev = (PTMTIMER)(pTimer->pBigPrev ? MMHyperR3ToCC(pVM, pTimer->pBigPrev) : NULL); 1265 const PTMTIMER pBigNext = (PTMTIMER)(pTimer->pBigNext ? MMHyperR3ToCC(pVM, pTimer->pBigNext) : NULL); 1266 1267 /* unlink from created list */ 1268 if (pBigPrev) 1269 pBigPrev->pBigNext = pTimer->pBigNext; 1270 else 1271 pVM->tm.s.pCreated = pTimer->pBigNext; 1272 if (pBigNext) 1273 pBigNext->pBigPrev = pTimer->pBigPrev; 1274 pTimer->pBigNext = 0; 1275 pTimer->pBigPrev = 0; 1276 1277 /* free */ 1278 Log2(("TM: Inserting %p into the free list ahead of %p!\n", pTimer, pVM->tm.s.pFree)); 1279 pTimer->pBigNext = pVM->tm.s.pFree; 1280 pVM->tm.s.pFree = (PTMTIMERR3)MMHyperCCToR3(pVM, pTimer); 1281 TM_SET_STATE(pTimer, TMTIMERSTATE_FREE); 1282 break; 1283 } 1284 1285 /* 1286 * Postpone these until they get into the right state. 1287 */ 1288 case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE: 1289 case TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE: 1290 tmTimerLink(pQueue, pTimer); 1291 STAM_COUNTER_INC(&pTimer->CTXALLSUFF(pVM)->tm.s.CTXALLSUFF(StatPostponed)); 1292 break; 1293 1294 /* 1295 * None of these can be in the schedule. 1296 */ 1297 case TMTIMERSTATE_FREE: 1298 case TMTIMERSTATE_STOPPED: 1299 case TMTIMERSTATE_ACTIVE: 1300 case TMTIMERSTATE_EXPIRED: 1301 AssertMsgFailed(("Timer (%p) in the scheduling list has an invalid state %s (%d)!", 1302 pTimer, tmTimerState(pTimer->enmState), pTimer->enmState)); 1303 break; 1304 } 1319 } while (cRetries-- > 0); 1305 1320 } 1306 1321
Note:
See TracChangeset
for help on using the changeset viewer.