Chapter 8 NI-488.2 Programming Techniques
NI-488.2 User Manual 8-10 ni.com
Assume that a process has two separate threads that make NI-488.2 calls,
thread 1 and thread 2. Just as thread 1 is about to examine one of the
NI-488.2 globals, it gets preempted and thread 2 is allowed to run. Thread 2
proceeds to make several NI-488.2 calls that automatically update the
NI-488.2 globals. Later, when thread 1 is allowed to run, the NI-488.2
global that it is ready to examine is no longer in a known state and its value
is no longer reliable.
The previous example illustrates a well-known multithreading problem.
It is unsafe to access process-global variables from multiple threads of
execution. You can avoid this problem in two ways:
• Use synchronization to protect access to process-global variables.
• Do not use process-global variables.
If you choose to implement the synchronization solution, you must ensure
that the code making NI-488.2 calls and examining the NI-488.2 globals
modified by a NI-488.2 call is protected by a synchronization primitive.
For example, each thread might acquire a semaphore before making a
NI-488.2 call and then release the semaphore after examining the NI-488.2
globals modified by the call. For more information about the use of
synchronization primitives, refer to your operating system documentation
about synchronization objects supported by your operating system.
If you choose not to use process-global variables, you can access per-thread
copies of the NI-488.2 global variables using a special set of NI-488.2 calls.
Whenever a thread makes an NI-488.2 call, the driver keeps a private copy
of the NI-488.2 globals for that thread. The following code shows the set of
functions you can use to access these per-thread NI-488.2 global variables:
int ThreadIbsta();// return thread-specific ibsta
int ThreadIberr();// return thread-specific iberr
int ThreadIbcnt();// return thread-specific ibcnt
long ThreadIbcntl();// return thread-specific ibcntl
In your application, instead of accessing the per-process NI-488.2 globals,
substitute a call to get the corresponding per-thread NI-488.2 global.
For example, the following line of code,
if (ibsta & ERR)
could be replaced by
if (ThreadIbsta() & ERR)