LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

When does thread switch occur in CVI TS code modules?

Hi all

 

I am developing an TestStand/CVI application and am running into a wierd problem (using TS 3.1, CVI 7.x ) and hoping for some insight..

 

I have a teststand sequence that launches 4 parallel subsequence threads, each of which is supposed to take a measurement from a BERT.   There are 4 BERTS in the test system, and each subsequence is supposed to communicate with a specific BERT

 

The attached JPG shows the top level sequence that launches the threads (there is a rendezvous in the setup that is not shown) and the "Single CH BErt Test" is the multi threaded code.

 

The CVI code for "measure true BER" looks something like this (not all the code is shown below)

 

->See TSFunction.txt attachment

 

 

Each of the BERT instrument functions is IVI based and has an IVI_Lock and IVI_unlock around all functions that perform instrument IO....

 

Now the interesting part.   I run the code and get timeouts and bus errors and notice from the SPY capture that the Viprintf commands that  the BERT_ReadErrors function is not completing before another thread trys to run it..... 

 

The attached excel spread sheet illustrates.  The calls to the 4 BERT's are color coded and row 109 is the first call to BERT_ReadErrors (color coded in yellow in the excel spreadsheet.    Why does the thread switch occur in row 112 of the excel file?  It results in a problem when I try to read from the bus in row 116....

 

 

The code for BERT_ReadErrors is shown below

 

-> See BErtcode.txt

 

 

 

 

 

 

 

 

Download All
0 Kudos
Message 1 of 6
(4,147 Views)

Hello tmaxprt,

 

Thank you for making use of the National Instruments discussion forums for this excellent question!  The scheduling of threads is managed by the operating system rather than the environment.  As such, there are many variables, both within and also outside of CVI and TestStand, that could come into play when trying to determine why a certain thread takes over for what otherwise seems to be a continuous stream of execution within one thread. 

 

However, you are able to manage this behavior to some extent by recognizing critical sections of your code that you desire to run sequentially within a given thread and then blocking other threads from executing during this window.  Introducing a thread management resource (e.g. a lock, a mutex, a semaphore, etc.) will allow you to exercise this extent of control.  As such, if you truly believe that the switch from one thread to another is responsible for the error you are encountering, you may be able to actively affect a change in this behavior.

 

On this note, can you describe why you believe that the thread switching causes the error you receive?  Your code is extensive, and I was not immediately able to extract the reasoning for this conclusion by perusing the context of the code alone.  Also, I noticed that the line of code executed which generates an error passes a different parameter than its sibling threads do in the very same line.  The line in question passes 0x0DC9C608, while the three other threads pass "CUR".  For the same reasons above, I am not sure of the significance of either of these parameters as they pertain to the viRead function, but the fact that they are different stands out.  Can you shed any light on the purpose of either of these parameters and the effect they have on this function?

 

Thanks,

0 Kudos
Message 2 of 6
(4,106 Views)

I was under the impression that IVI_Lock and ivi_Unlock would create the mutex around the code and prevent a thread switch.?  If that is the case there should be no sweitch between row 111 to row 115....?

 

I suspect the thread switch results in the error as i am able to execute the BERT_ReadError function on each BERT individually.  

 

From the SPY trace, it appears that the ViPrintf on ROW 111 (viPrintf (0x0CD0B7A8, "led_stat?") thread ID 00000B34 is getting swtiched out by another viprintf from thread 0x00000CC4.   Then , each thread actually sends out the formatted string to the corresponding BERT (row 113 and 114).

 

However, I suspect that the fromatted write on row 113 is not actually getting transferred correctly. since the corresponding read (row 116) is timing out.  That suggests the instrument never saw the command.

 

 

 

 

0 Kudos
Message 3 of 6
(4,100 Views)

The IVI_Unlock appears to be called in the custom error handling portion of your code.  Along this line of thought, the only apparent reason that these other threads are able to execute at this point is that the original thread (Thread ID: 0x00000454) generates an error in the lines of code that follow the call to viPrintf and its associated call to Formatted viWrite.  You may be able to debug where this error occurs more easliy as you have access to the entire code and presumably its execution.  Also, I will reiterate that I think it is very important to determine why 0x0DC9C608 is being passed instead of "CUR" in the call to viRead (116).  This may actually be related to the error discussed above (which results in IVI_Unlock) as I see that this parameter is the variable cMessageBufer and is used in several string compares and/or subsequent viRead calls in the thread.  I look forward to hearing back from you with what you find out about the error that is being generated and why the two different parameters are being passed!

0 Kudos
Message 4 of 6
(4,085 Views)

There are 5 threads running here:

 

Main thread : 0x000009A4

 4 BERT threads (the other thread ID's)

 

I believe it is fairly standard to call Ivi_Unlock in the Error handling section of driver functions (every NI driver I've looked does it that way), so i dont think that is the issue.  Besides there was no error until the Read on Row 116.  

 

Also, with the ViRead, I suspect NI SPY shows the address of the buffer (as opposed to its contents) when there is nothing in it.  In any case, it still does not make sense why the ViWrite in row 113 (thread 0x00000B34) is interrupted by a viPrintf from thread 0x00000404

 

 

0 Kudos
Message 5 of 6
(4,067 Views)

tmaxprt,

 

Identifying the location of IVI_Unlock in the error handler was an attempt to answer your initial question about why other threads are being able to execute when a certain thread should be holding a lock and preventing this.  Based on what I can tell, the thread that is supposed to be holding a lock (Thread ID: 0x00000454) encounters an error somewhere, calls the custom error handler, and thereby releases the lock, allowing other threads to obtain the lock and begin to execute.

 

Regarding the parameter that I was hoping to get more information about, if NI Spy shows the address of the buffer instead of its contents, it should behave the very same way in the other calls as well.  As this is not the case, we need to figure out why the calls are different.  In any event, whether the parameter is supposed to be the address or the actual value, we need to determine the reason for the discrepancy. 

 

I would be curious to see if you could compare the values of cMessageBufer just before and just after the viRead calls for each of the threads as well as which line of code triggers the error handler and its associated lock release to address the first issue of the thread forfeiting its control.

 

Thanks always,

0 Kudos
Message 6 of 6
(4,063 Views)