Concurrency checks for Multi-threaded and Multi-core Code
CodeSonar catches complex concurrency-related defects in multi-threaded and multi-core code, like data race, deadlocks and incorrect use of synchronization techniques.
Detect Data Races
Data races cause a disproportionate number of concurrency-related bugs, that are detected extremely effective by CodeSonar. A data race can be caused by
1. Multiple threads of execution access a shared piece of data.
2. One thread that changes the value of the data.
3. An access that is not separated by explicit synchronization.
Data races can leave a system in an inconsistent state, which can remain undetected and only show up in unusual cases with curious symptoms.
Because of the huge number of possible execution the detection and debugging of data races, and concurrency problems in general, cause difficulties for traditional testing methods.
As can be seen from the figure above, there are six possible interleavings of two threads with two instructions each. With three instructions each, there are twenty possible interleavings. Due to the variety of combinations, it is infeasible to test every interleaving in real-world systems. The diagnosis of data races proves to be rather difficult, because the defect occurs only under certain interleavings. Data races are sensitive to traditional tools like debuggers, which affect timing and can make the bug disappear temporarily.
In contrast to traditional tools CodeSonar detects data races by focusing on the causes, not the symptoms. The tool examines the code and creates an abstract model of what locks are held by what threads. It considers automatically possible interleavings, examines patterns of access to shared memory locations, and finds situations in which code is susceptible to problematic interleavings. As soon as CodeSonar identifies a data race, the tool issues a data race warning that includes supporting information.
Contrary to the widespread assumption that some types of data races are harmless, they can cause damage during execution. This is because optimizing compilers reorder instructions.
Deadlock means a situation in which two or more threads prevent each other from making progress by each holding a look needed by another. The most common approach to avoiding deadlock is to ensure a partial ordering to the resources. This way was proposed by Dijkstra in 1965 as a solution to the Dining Philosophers Problem
. Large code base make it difficult to tell through manual inspection if the software follows this rule. The automated analysis of CodeSonar issues a warning if the same locks can be acquired in different orders by different threads.
Moreover the tool provides a nested locks check, to avoid this dangerous defects. This check triggers a warning whenever a thread tries to obtain two or more locks. Depending on the requirements the nested lock check can be enable or disabled.
In a deadlock, both threads are completely stuck, both unable to carry out its operations or get to the point where it can release its lock.