Changeset 54410 in vbox
- Timestamp:
- Feb 24, 2015 2:52:10 AM (10 years ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/Makefile.kmk
r54408 r54410 2002 2002 generic/mppresent-generic.cpp \ 2003 2003 generic/RTMpGetCoreCount-generic.cpp \ 2004 generic/RTMpOnPair-generic.cpp \2005 2004 nt/RTErrConvertFromNtStatus.cpp \ 2006 2005 r0drv/generic/threadctxhooks-r0drv-generic.cpp \ -
trunk/src/VBox/Runtime/r0drv/mp-r0drv.h
r53717 r54410 53 53 void *pvUser2; 54 54 RTCPUID idCpu; 55 RTCPUID idCpu2; 55 56 uint32_t volatile cHits; 56 57 #ifdef RT_OS_WINDOWS -
trunk/src/VBox/Runtime/r0drv/nt/mp-r0drv-nt.cpp
r53768 r54410 47 47 { 48 48 RT_NT_CPUID_SPECIFIC, 49 RT_NT_CPUID_PAIR, 49 50 RT_NT_CPUID_OTHERS, 50 51 RT_NT_CPUID_ALL … … 248 249 /** 249 250 * Wrapper between the native KIPI_BROADCAST_WORKER and IPRT's PFNRTMPWORKER for 251 * the RTMpOnPair case. 252 * 253 * @param uUserCtx The user context argument (PRTMPARGS). 254 */ 255 static ULONG_PTR __stdcall rtmpNtOnPairBroadcastIpiWrapper(ULONG_PTR uUserCtx) 256 { 257 PRTMPARGS pArgs = (PRTMPARGS)uUserCtx; 258 RTCPUID idCpu = KeGetCurrentProcessorNumber(); 259 if ( pArgs->idCpu == idCpu 260 || pArgs->idCpu2 == idCpu) 261 { 262 ASMAtomicIncU32(&pArgs->cHits); 263 pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2); 264 } 265 return 0; 266 } 267 268 269 /** 270 * Wrapper between the native KIPI_BROADCAST_WORKER and IPRT's PFNRTMPWORKER for 250 271 * the RTMpOnSpecific case. 251 272 * … … 268 289 * Internal worker for the RTMpOn* APIs using KeIpiGenericCall. 269 290 * 270 * @returns IPRT status code. 271 * @param pfnWorker The callback. 272 * @param pvUser1 User argument 1. 273 * @param pvUser2 User argument 2. 274 * @param enmCpuid What to do / is idCpu valid. 275 * @param idCpu Used if enmCpuid RT_NT_CPUID_SPECIFIC, otherwise ignored. 291 * @returns VINF_SUCCESS. 292 * @param pfnWorker The callback. 293 * @param pvUser1 User argument 1. 294 * @param pvUser2 User argument 2. 295 * @param idCpu First CPU to match, ultimately specific to the 296 * pfnNativeWrapper used. 297 * @param idCpu2 Second CPU to match, ultimately specific to the 298 * pfnNativeWrapper used. 299 * @param pcHits Where to return the number of this. Optional. 276 300 */ 277 301 static int rtMpCallUsingBroadcastIpi(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2, 278 PKIPI_BROADCAST_WORKER pfnNativeWrapper, RTCPUID idCpu) 302 PKIPI_BROADCAST_WORKER pfnNativeWrapper, RTCPUID idCpu, RTCPUID idCpu2, 303 uint32_t *pcHits) 279 304 { 280 305 RTMPARGS Args; … … 283 308 Args.pvUser2 = pvUser2; 284 309 Args.idCpu = idCpu; 310 Args.idCpu2 = idCpu2; 285 311 Args.cRefs = 0; 286 312 Args.cHits = 0; … … 288 314 AssertPtr(g_pfnrtKeIpiGenericCall); 289 315 g_pfnrtKeIpiGenericCall(pfnNativeWrapper, (uintptr_t)&Args); 290 291 if ( pfnNativeWrapper != rtmpNtOnSpecificBroadcastIpiWrapper 292 || Args.cHits > 0) 293 return VINF_SUCCESS; 294 return VERR_CPU_OFFLINE; 316 if (pcHits) 317 *pcHits = Args.cHits; 318 return VINF_SUCCESS; 295 319 } 296 320 … … 307 331 { 308 332 PRTMPARGS pArgs = (PRTMPARGS)DeferredContext; 333 309 334 ASMAtomicIncU32(&pArgs->cHits); 310 311 335 pArgs->pfnWorker(KeGetCurrentProcessorNumber(), pArgs->pvUser1, pArgs->pvUser2); 312 336 … … 323 347 * 324 348 * @returns IPRT status code. 325 * @param pfnWorker The callback. 326 * @param pvUser1 User argument 1. 327 * @param pvUser2 User argument 2. 328 * @param enmCpuid What to do / is idCpu valid. 329 * @param idCpu Used if enmCpuid RT_NT_CPUID_SPECIFIC, otherwise ignored. 330 */ 331 static int rtMpCallUsingDpcs(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2, RT_NT_CPUID enmCpuid, RTCPUID idCpu) 349 * @param pfnWorker The callback. 350 * @param pvUser1 User argument 1. 351 * @param pvUser2 User argument 2. 352 * @param enmCpuid What to do / is idCpu valid. 353 * @param idCpu Used if enmCpuid is RT_NT_CPUID_SPECIFIC or 354 * RT_NT_CPUID_PAIR, otherwise ignored. 355 * @param idCpu2 Used if enmCpuid is RT_NT_CPUID_PAIR, otherwise ignored. 356 * @param pcHits Where to return the number of this. Optional. 357 */ 358 static int rtMpCallUsingDpcs(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2, 359 RT_NT_CPUID enmCpuid, RTCPUID idCpu, RTCPUID idCpu2, uint32_t *pcHits) 332 360 { 333 361 PRTMPARGS pArgs; … … 361 389 pArgs->pvUser2 = pvUser2; 362 390 pArgs->idCpu = NIL_RTCPUID; 391 pArgs->idCpu2 = NIL_RTCPUID; 363 392 pArgs->cHits = 0; 364 393 pArgs->cRefs = 1; … … 371 400 KeSetImportanceDpc(&paExecCpuDpcs[0], HighImportance); 372 401 KeSetTargetProcessorDpc(&paExecCpuDpcs[0], (int)idCpu); 402 pArgs->idCpu = idCpu; 403 } 404 else if (enmCpuid == RT_NT_CPUID_SPECIFIC) 405 { 406 KeInitializeDpc(&paExecCpuDpcs[0], rtmpNtDPCWrapper, pArgs); 407 KeSetImportanceDpc(&paExecCpuDpcs[0], HighImportance); 408 KeSetTargetProcessorDpc(&paExecCpuDpcs[0], (int)idCpu); 409 pArgs->idCpu = idCpu; 410 411 KeInitializeDpc(&paExecCpuDpcs[1], rtmpNtDPCWrapper, pArgs); 412 KeSetImportanceDpc(&paExecCpuDpcs[1], HighImportance); 413 KeSetTargetProcessorDpc(&paExecCpuDpcs[1], (int)idCpu2); 414 pArgs->idCpu2 = idCpu2; 373 415 } 374 416 else … … 398 440 ASMAtomicIncS32(&pArgs->cRefs); 399 441 BOOLEAN ret = KeInsertQueueDpc(&paExecCpuDpcs[0], 0, 0); 442 Assert(ret); 443 } 444 else if (enmCpuid == RT_NT_CPUID_PAIR) 445 { 446 ASMAtomicIncS32(&pArgs->cRefs); 447 BOOLEAN ret = KeInsertQueueDpc(&paExecCpuDpcs[0], 0, 0); 448 Assert(ret); 449 450 ASMAtomicIncS32(&pArgs->cRefs); 451 ret = KeInsertQueueDpc(&paExecCpuDpcs[1], 0, 0); 400 452 Assert(ret); 401 453 } … … 428 480 g_pfnrtNtKeFlushQueuedDpcs(); 429 481 482 if (pcHits) 483 *pcHits = pArgs->cHits; 484 430 485 /* Dereference the argument structure. */ 431 486 int32_t cRefs = ASMAtomicDecS32(&pArgs->cRefs); … … 441 496 { 442 497 if (g_pfnrtKeIpiGenericCall) 443 return rtMpCallUsingBroadcastIpi(pfnWorker, pvUser1, pvUser2, rtmpNtOnAllBroadcastIpiWrapper, 0); 444 return rtMpCallUsingDpcs(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_ALL, 0); 498 return rtMpCallUsingBroadcastIpi(pfnWorker, pvUser1, pvUser2, rtmpNtOnAllBroadcastIpiWrapper, 499 NIL_RTCPUID, NIL_RTCPUID, NULL); 500 return rtMpCallUsingDpcs(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_ALL, NIL_RTCPUID, NIL_RTCPUID, NULL); 445 501 } 446 502 … … 449 505 { 450 506 if (g_pfnrtKeIpiGenericCall) 451 return rtMpCallUsingBroadcastIpi(pfnWorker, pvUser1, pvUser2, rtmpNtOnOthersBroadcastIpiWrapper, 0); 452 return rtMpCallUsingDpcs(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_OTHERS, 0); 453 } 507 return rtMpCallUsingBroadcastIpi(pfnWorker, pvUser1, pvUser2, rtmpNtOnOthersBroadcastIpiWrapper, 508 NIL_RTCPUID, NIL_RTCPUID, NULL); 509 return rtMpCallUsingDpcs(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_OTHERS, NIL_RTCPUID, NIL_RTCPUID, NULL); 510 } 511 512 513 RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) 514 { 515 int rc; 516 AssertReturn(idCpu1 != idCpu2, VERR_INVALID_PARAMETER); 517 AssertReturn(!(fFlags & RTMPON_F_VALID_MASK), VERR_INVALID_FLAGS); 518 if ((fFlags & RTMPON_F_CONCURRENT_EXEC) && !g_pfnrtKeIpiGenericCall) 519 return VERR_NOT_SUPPORTED; 520 521 /* 522 * Check that both CPUs are online before doing the broadcast call. 523 */ 524 if ( RTMpIsCpuOnline(idCpu1) 525 && RTMpIsCpuOnline(idCpu2)) 526 { 527 /* 528 * The broadcast IPI isn't quite as bad as it could have been, because 529 * it looks like windows doesn't synchronize CPUs on the way out, they 530 * seems to get back to normal work while the pair is still busy. 531 */ 532 uint32_t cHits = 0; 533 if (g_pfnrtKeIpiGenericCall) 534 rc = rtMpCallUsingBroadcastIpi(pfnWorker, pvUser1, pvUser2, rtmpNtOnPairBroadcastIpiWrapper, idCpu1, idCpu2, &cHits); 535 else 536 rc = rtMpCallUsingDpcs(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_PAIR, idCpu1, idCpu2, &cHits); 537 if (RT_SUCCESS(rc)) 538 { 539 Assert(cHits <= 2); 540 if (cHits == 2) 541 rc = VINF_SUCCESS; 542 else if (cHits == 1) 543 rc = VERR_NOT_ALL_CPUS_SHOWED; 544 else if (cHits == 0) 545 rc = VERR_CPU_OFFLINE; 546 else 547 rc = VERR_CPU_IPE_1; 548 } 549 } 550 /* 551 * A CPU must be present to be considered just offline. 552 */ 553 else if ( RTMpIsCpuPresent(idCpu1) 554 && RTMpIsCpuPresent(idCpu2)) 555 rc = VERR_CPU_OFFLINE; 556 else 557 rc = VERR_CPU_NOT_FOUND; 558 return rc; 559 } 560 561 562 RTDECL(bool) RTMpOnPairIsConcurrentExecSupported(void) 563 { 564 return RTMpOnAllIsConcurrentSafe(); 565 } 566 454 567 455 568 /** … … 503 616 * or if the current IRQL is unsuitable for KeWaitForSingleObject. 504 617 */ 618 int rc; 619 uint32_t cHits = 0; 505 620 if ( g_pfnrtKeIpiGenericCall 506 621 && ( RTMpGetOnlineCount() <= 2 507 622 || KeGetCurrentIrql() > APC_LEVEL) ) 508 return rtMpCallUsingBroadcastIpi(pfnWorker, pvUser1, pvUser2, rtmpNtOnSpecificBroadcastIpiWrapper, 0); 509 510 #if 0 /** @todo untested code. needs some tuning. */ 623 rc = rtMpCallUsingBroadcastIpi(pfnWorker, pvUser1, pvUser2, rtmpNtOnSpecificBroadcastIpiWrapper, 624 idCpu, NIL_RTCPUID, &cHits); 625 else 626 rc = rtMpCallUsingDpcs(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_SPECIFIC, idCpu, NIL_RTCPUID, &cHits); 627 if (RT_SUCCESS(rc)) 628 { 629 if (cHits == 1) 630 return VINF_SUCCESS; 631 rc = cHits == 0 ? VERR_CPU_OFFLINE : VERR_CPU_IPE_1; 632 } 633 return rc; 634 635 #if 0 /** @todo Untested code replacing the rtMpCallUsingDpcs caste. Needs some tuning too, I guess. */ 511 636 /* 512 637 * Initialize the argument package and the objects within it. … … 631 756 rtMpNtOnSpecificRelease(pArgs); 632 757 return rc; 633 634 #else635 return rtMpCallUsingDpcs(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_SPECIFIC, idCpu);636 758 #endif 637 759 }
Note:
See TracChangeset
for help on using the changeset viewer.