If there are at least 4 threads racing on the same address, it can happen that one of the readers may observe another matching reader in other_info. To avoid locking up, we have to consume 'other_info' regardless, but skip the report. See the added comment for more details.
Unified · Split
| @@ -422,6 +422,44 @@ retry: · 421 unmodified lines | |||
| 422 | return false; | 422 | return false; |
| 423 | } | 423 | } |
| 424 | 424 | ||
| 425 | access_type |= other_info.access_type; | ||
| 426 | if ((access_type & KCSAN_ACCESS_WRITE) == 0) { | ||
| 427 | /* | ||
| 428 | * While the address matches, this is not the other_info | ||
| 429 | * from the thread that consumed our watchpoint, since | ||
| 430 | * neither this nor the access in other_info is a write. | ||
| 431 | * It is invalid to continue with the report, since we | ||
| 432 | * only have information about reads. | ||
| 433 | * | ||
| 434 | * This can happen due to concurrent races on the same | ||
| 435 | * address, with at least 4 threads. To avoid locking up | ||
| 436 | * other_info and all other threads, we have to consume | ||
| 437 | * it regardless. | ||
| 438 | * | ||
| 439 | * A concrete case to illustrate why we might lock up if | ||
| 440 | * we do not consume other_info: | ||
| 441 | * | ||
| 442 | * We have 4 threads, all accessing the same address | ||
| 443 | * (or matching address ranges). Assume the following | ||
| 444 | * watcher and watchpoint consumer pairs: | ||
| 445 | * write1-read1, read2-write2. The first to populate | ||
| 446 | * other_info is write2, however, write1 consumes it, | ||
| 447 | * resulting in a report of write1-write2. This report | ||
| 448 | * is valid, however, now read1 populates other_info; | ||
| 449 | * read2-read1 is an invalid conflict, yet, no other | ||
| 450 | * conflicting access is left. Therefore, we must | ||
| 451 | * consume read1's other_info. | ||
| 452 | * | ||
| 453 | * Since this case is assumed to be rare, it is | ||
| 454 | * reasonable to omit this report: one of the other | ||
| 455 | * reports includes information about the same shared | ||
| 456 | * data, and at this point the likelihood that we | ||
| 457 | * re-report the same race again is high. | ||
| 458 | */ | ||
| 459 | release_report(flags, KCSAN_REPORT_RACE_SIGNAL); | ||
| 460 | return false; | ||
| 461 | } | ||
| 462 | |||
| 425 | /* | 463 | /* |
| 426 | * Matching & usable access in other_info: keep other_info_lock | 464 | * Matching & usable access in other_info: keep other_info_lock |
| 427 | * locked, as this thread consumes it to print the full report; | 465 | * locked, as this thread consumes it to print the full report; |