APIs for Custom Synchronization
While the
Intel Inspector
supports a significant portion of the Windows* OS and POSIX* APIs, it is often useful to define your own synchronization constructs. Any specially built constructs that you create are not normally tracked by the
Intel Inspector
; however, the
Intel Inspector
supports synchronization APIs to help you gather semantic information related to your custom synchronization constructs.
Synchronization constructs may generally be modeled as a series of signals. One thread, or many threads, may wait for a signal from another group of threads before proceeding with some action. Synchronization APIs track when a thread begins waiting for a signal and when the signal occurs.
Using User-Defined Synchronization APIs in Your Code
Use This in C/C++ Code
| Use This in Fortran Code
| To Do This
|
---|---|---|
|
| Tell the
Intel Inspector that the code received a signal on the specified synchronization object.
|
|
| Tell the
Intel Inspector that the code is about to send a signal on the specified synchronization object.
|
|
| Tell the
Intel Inspector that the synchronization object will not be used again, so the
Intel Inspector can dispose of bookkeeping information associated with this object.
|
The
addr
parameter is simply a value that uniquely identifies the synchronization object to be modeled. Unique values allow the
Intel Inspector
to track distinct custom synchronization objects. To use the same custom object to protect access in different parts of your code, use the same
addr
parameter around each.
Since each custom synchronization construct may involve any number of synchronization objects, each synchronization object must be triggered off a unique memory handle, which the synchronization APIs will use to track the object. You can track any number of synchronization objects at one time using synchronization APIs, as long as each object uses a unique memory pointer. You can think of this as modeling objects similar to the
WaitForMultipleObjects
function in the Windows* OS API. You can create more complex synchronization constructs from a group of synchronization objects.
API Usage Tips
Follow these guidelines to properly insert synchronization APIs within your code:
- Insert anacquiredAPI immediatelyafteryour code stops waiting for a synchronization object.
- Insert areleasingAPI immediatelybeforethe code signals that it no longer holds a synchronization object.
If you place the synchronization APIs improperly, the
Intel Inspector
may report threading problems where there are none or fail to detect real threading problems.
Usage Example: User-Defined Synchronized Critical Section
The following code snippets show how to create a critical section construct that can be tracked with synchronization APIs:
C/C++ Example
| Fortran Example
|
---|---|
|
|
Note the following when looking at this simple critical section example:
- TheacquiredAPI is placed immediately after the code obtains the user lock.
- ThereleasingAPI is placed before the code releases the user lock. This ensures another thread does not call theacquiredAPI before theIntel Inspectorrealizes this thread has released the lock.
Usage Example: User-Level Synchronized Barrier
Higher-level constructs, such as barriers, are also easy to model using synchronization APIs. The following code snippets show how to create a barrier construct that can be tracked using synchronization APIs:
C/C++ Example
| Fortran Example
|
---|---|
|
|
Note the following when looking at this example:
- There are two synchronization objects in this barrier code. Thecounterobject is used to do a gather-like signaling from all the threads to the final thread indicating that each thread has entered the barrier. Once the last thread hits the barrier, it uses theteamflagobject to signal all the other threads that they may proceed.
- As each thread enters the barrier, it calls thereleasingAPI to tell theIntel Inspectorit is about to signal the last thread by incrementingcounter.
- The last thread to enter the barrier calls theacquiredAPI to tell theIntel Inspectorit was successfully signaled by all the other threads.
- The last thread to enter the barrier then calls thereleasingAPI to tell theIntel Inspectorit is going to signal the barrier completion to all the other threads by settingteamflag.
- Finally, before leaving the barrier, each thread calls theacquiredAPI to tell theIntel Inspectorit successfully received the end-of-barrier signal.