-
Notifications
You must be signed in to change notification settings - Fork 87
HB-relationship involving thread creations while mutexes are held #1913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements the second part of happens-before (HB) relationship analysis for thread creations while mutexes are held. It introduces two new analyses (MustlockHistory and DescendantLockset) that work together to detect race conditions by establishing happens-before relationships between thread operations based on mutex locking patterns.
Changes:
- Added
MustlockHistoryanalysis to track which threads have locked specific mutexes - Added
DescendantLocksetanalysis to compute descendant locksets and determine happens-before relationships - Extended
CreationLocksetanalysis with query support for integration with the new analyses - Added 20 comprehensive test cases covering both race-free and racing scenarios
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
src/analyses/mustlockHistory.ml |
New analysis tracking mutex lock history per thread |
src/analyses/descendantLockset.ml |
New analysis computing descendant locksets and HB relationships |
src/analyses/creationLockset.ml |
Added CreationLockset query support |
src/domains/queries.ml |
Added CreationLockset and MustlockHistory query types with supporting domains |
src/goblint_lib.ml |
Exported the two new analysis modules |
tests/regression/53-races-mhp/40-45-*.c |
Race-free test cases validating correct HB detection |
tests/regression/53-races-mhp/50-59-*.c |
Racing test cases validating race detection |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
tests/regression/53-races-mhp/45-dl_multiple_mutexes_racefree.c
Outdated
Show resolved
Hide resolved
… of descendant lockset analysis
|
Random thought: What do your analyses do for recursive mutexes? Are they sound in these cases? |
|
Thanks for bringing this up, those would never have crossed my mind. I think the analyses remain sound, but get less precise. The only relevant thing changing here coming to my mind is the fact that after an unlock, we can't assume anymore that the mutex is now unlocked. As unlock statements have been places in our analyses, where we assume things to just break, but not start/keep working, this wouldn't be an issue. |
👍 Could you add tests here and maybe also include some tests for your first analysis (potentially in a separate PR)? |
second part of #1805. The first half was implemented in #1865.
closes #1805.
Summary
Simplest case: After creating$t_1$ in $t_0$ with mutex $l$ held, succeeding statements until maybe unlocking in $t_0$ must happen before everything after definitely locking $l$ in $t_1$ .
generalizations:
Examples
In the following examples,
Amust happen beforeB.Simple example
graph TB; subgraph t1; E["lock(l);"]-->F; F["unlock(l);"]-->G; G((B)) end; subgraph t0; A["lock(l);"]-->B; B["create(t1);"]-->C; C((A))-->D; D["unlock(l);"]; end; B-.->EBin a descendant ofgraph TB; subgraph t2; H((B)) end; subgraph t1; E["lock(l);"]-->F; F["create(t2);"] end; subgraph t0; A["lock(l);"]-->B; B["create(t1);"]-->C; C((A))-->D; D["unlock(l);"]; end; B-.->E F-.->HAin a descendant ofHere, it is important that no unlock happens in$t_0$ before $t_2$ is joined into $t_0$ .
graph TB; subgraph t1; E["lock(l);"]-->I; I["unlock(l);"]-->F; F((B)); end; subgraph t2; H((A)) end; subgraph t0; A["lock(l);"]-->B; B["create(t1);"]-->C; C["create(t2);"]-->D; D["join(t2);"]-->G; G["unlock(l);"] end; B-.->E C-.->H H-.->DAnalyses
Descendant Locksets$\mathcal{DL}$
MapBotTransfer functions
Mustlock History$\mathcal{LH}$
MapTopTransfer functions
Global Descendant Locksets$\mathcal{DL}_g$
MapBotMapBotContributions
create(t1)Happens-Before rules
Statement$\mathcal{LH}_ 2, \mathcal T_2$ must happen after $\mathcal{DL}_ 1,\mathcal{DL}_ {g1}, \mathcal{LH}_ 1, \mathcal T_1$ , if:
$\exists \mathcal T_2\mapsto L_a\in\mathcal{DL}_ 1, l_ {LH}\mapsto T_ {LH}\in \mathcal{LH}_ 1, t_ {LH}\in T_ {LH}:$
$l_{LH}\in L_a\land\mathcal T_1\in \mathcal A\ t_{LH}\land(t_{LH}\in\mathcal A\ \mathcal T_2\lor t_{LH}=\mathcal T_2)$
s2withs1withAdditionally, we check if the condition above holds for any$t_1\mapsto DL_1\in\mathcal{DL}_g\ \mathcal T_1$ replacing $t_1$ with $\mathcal T_1$ and $DL_1$ with $\mathcal{DL}_1$