JavaScript is not currently enabled, but is required for full CodeSonar manual search and browse functionality.
If you are viewing this file in your hub's Web GUI, enable JavaScript in your browser: you will also need it for GUI functionality.
If you opened this file directly from disk, your browser may be directly suppressing JavaScript functionality: certain browsers perform this suppression on local files (but not files delivered by web servers) for security reasons.
| CodeSonar® 9.2p0 | CONFIDENTIAL | CodeSecure Inc |
One of the critical components of data race detection is the identification of thread entry points: the procedures or methods that start executing in newly-created threads. If CodeSonar cannot identify all the thread entry points in a project, it will generally not be able to detect all locations where a data race can occur.
Signal handler entry points are also identified: signal handlers are essentially treated as a special kind of thread.
The functions that CodeSonar will treat as thread entry points can be divided into four categories:
CodeSonar always treats the following program entry functions as thread entry points:
There are two relevant configuration parameters.
CodeSonar ships with library models that allow it to recognize a large number of thread entry point functions. A call to one of these functions will trigger a Thread Entry Point warning (when that class is enabled). Some examples are listed in the following table
| Thread entry point functions include... | |
|---|---|
| Apache Portable Runtime (APR) | apr_thread_create() |
| ARINC 653 | CREATE_PROCESS() |
| CMX-RTX | K_Task_Create() |
| FreeRTOS | xTaskCreate() |
| libc | g_thread_create() |
| Linux Kernel | kernel_thread() |
| Mac OS X | kernel_thread_start() |
| Win32/MFC | AfxBeginThread() |
| Netscape Portable Runtime (NSPR) | PR_CreateThread() |
| Qt | QThread::start() |
| ThreadX | _tx_thread_create() |
| uC/OS-III | OSTaskCreate() |
| VxWorks | taskInit() |
| Win32 | CreateThread() |
| wxWidgets | wxThread::Create() |
CodeSonar ships with library models that allow it to identify functions such as libc signal() as signal handler entry points. A call to one of these functions will trigger a Signal Handler Entry Point warning (when that class is enabled).
If you are authoring a model for a function that specifies a thread entry point or signal handler entry point, it is usually best to have the model call the already-modeled function that is most similar. This will ensure that CodeSonar correctly treats the function as specifying an entry point, and includes it in the appropriate checks.
If no existing model is appropriate, write your model using the extension functions provided. In particular, your model should call one of the following functions.
| csonar_thread_create() | Indicates a thread entry point. |
|---|---|
| csonar_sighand_create() | Indicates a signal handler entry point. It can also be useful for modeling interrupts. |
See the function documentation for annotated examples.
CodeSonar will identify thread entry points if the Data Race warning class is enabled.
The two most likely causes of a failure in entry point discovery are time limits and library modeling issues. If you suspect that CodeSonar has not discovered all the thread entry points in your project:
Alternatively, enable warning class Thread Entry Point, so that CodeSonar issues a warning at every identified thread entry point.
For example, the following simple program has two thread entry points: main() and entry_f().
#include <pthread.h>
int x;
void *entry_f( void *a ){
x = 5;
return a;
}
int main( int argc, char** argv ){
pthread_t t;
pthread_create( &t, NULL, entry_f, NULL );
x = 4;
return argc;
}
CodeSonar identifies both entry points:
The relevant part of the analysis log looks (something) like the following.
[...]
Thread entry points:
Thread entry point: entry_f
lockset map: 0x7fffec1b1318
[MAK_READ:global_locks #locks: 0 #path_dags: 1 ls:{ }]
[MAK_WRITE:x #locks: 0 #path_dags: 1 ls:{ }]
[MAK_WRITE:global_locks-&next #locks: 0 #path_dags: 1 ls:{ }]
Thread entry point: main
lockset map: 0x7ffff7efcbb0
[MAK_WRITE:x #locks: 0 #path_dags: 1 ls:{ }]
[...]
Enabling data race detection increases the amount of information that the CodeSonar analysis must gather and store. This can cause various steps in the analysis process to take more time. In some cases, they can take so long that analysis time limits expire, causing CodeSonar to drop data that is needed to identify thread entry points properly. To maintain high precision and ensure that thread entry points are discovered, you may need to increase some of these time limits.
The time limits that are most important to thread entry point discovery are governed by configuration file parameters:
To determine whether time limit expiration is affecting thread entry point discovery for your project:
If CodeSonar did not discover any thread entry points (or only main()), there is probably a library modeling issue.
A critical element of thread discovery is identifying thread creation procedures, including understanding how their arguments are used to specify a thread starting point. This requires that library models be provided for thread creation procedures. If a model for your thread creation procedure is not shipped with CodeSonar, you will need to create a model or directly modify your code.
It is relatively common for large code bases to include their own thread entry point wrappers. These wrappers make it hard for CodeSonar to identify true thread entry points, and are themselves candidates for modeling.
Here is a small example:
/* Code Excerpt 1: User code with wrappers. */ /* underlying API function: real_thread_create() * thread creation wrapper: thread_create_wrapper() * thread entry point: user_thread_entry_point() * thread entry wrapper: thread_entry_wrapper() typedef struct{ function_pointer f; data_pointer d; } thread_entry_closure; void thread_entry_wrapper( thread_entry_closure *c ){ /* ... additional thread setup code */ c->f( c->d ); /* ... additional thread teardown code */ } void thread_create_wrapper( function_pointer fp, data_pointer dp ) { thread_entry_closure c = { fp, dp }; real_thread_create( thread_entry_wrapper, &c ); } void user_thread_entry_point( data_pointer d ){ /* ... code that runs in a separate thread */ } void other_user_code( void ){ thread_create_wrapper( user_thread_entry_point, xyz ); }
To handle this kind of code, you need to inform CodeSonar that
You can do this either by creating a library model for thread_create_wrapper(), or by directly modifying the source code:
/* Code Excerpt 2: Direct source modification for Code Excerpt 1. */ #ifdef __CODESONAR__ #include <stdlib.h> #include "csonar.h" #endif void thread_create_wrapper( function_pointer fp, data_pointer dp ) { #ifdef __CODESONAR__ csonar_thread_create( *((csonar_thread_entry_fn_t*)&fp), dp ); #endif thread_entry_closure c = { fp, dp }; real_thread_create( thread_entry_wrapper, &c ); }
To report problems with this documentation, please visit https://support.codesecure.com/.