total CPU occupancy time problem...

Hi,
I made up a simple applicationthat read serial data from a port using an arinc board… nothing strnge until now…
the apps runs without problems but the system is veeeeery slow…
I analyze my system and i found that this program is using a cpu time very high…i see that other apps have a growing CPU occupancy time but in my case it is growing too fast…

here the result of two calls to sin

procnto                                 1     0     0     0     0     52002
devc-con                                2   60K   92K    4K  516K       229
slogger                              4099    8K   60K    4K  516K        29
pipe                                 4100   16K   72K   20K  912K        16
mqueue                               4101   12K   56K    4K  516K        19
pci-bios                             8198   40K   56K    4K  516K        29
devc-bluestorm                       8199   40K  112K   12K  780K        39
devc-eth_escc                        8200   32K   76K    8K  648K        27
devc_arinc                           8201    8K   60K  132K  644K        21
devc-par                             8202   44K   76K   12K  648K        21
devc-pty                             8203   44K   92K    4K  516K        40
io-net                              24589   64K  484K   84K 1041K       712
qconn                               28687   80K  140K   20K  912K      1950
inetd                               28688   36K   88K    8K  516K        13
devb-eide                           40974   52K   19M   72K  608K       165
nmea                                98323    4K   56K    8K  516K        19
nmea                                98324    4K   56K    8K  516K        23
arinc                               98325    4K  516K    8K  516K    245268
sh                                 110604  144K   60K    4K  516K        25
sh                                 122897  144K   60K    4K  516K        17
telnetd                            122898  108K   96K   12K  516K        18
sh                                 126998  144K   92K    8K  516K        16
sin                                131095   80K   76K    8K  516K         0

procnto                                 1     0     0     0     0     52011
devc-con                                2   60K   92K    4K  516K       229
slogger                              4099    8K   60K    4K  516K        29
pipe                                 4100   16K   72K   20K  912K        16
mqueue                               4101   12K   56K    4K  516K        19
pci-bios                             8198   40K   56K    4K  516K        29
devc-bluestorm                       8199   40K  112K   12K  780K        39
devc-eth_escc                        8200   32K   76K    8K  648K        27
devc_arinc                           8201    8K   60K  132K  644K        21
devc-par                             8202   44K   76K   12K  648K        21
devc-pty                             8203   44K   92K    4K  516K        40
io-net                              24589   64K  484K   84K 1041K       716
qconn                               28687   80K  140K   20K  912K      2034
inetd                               28688   36K   88K    8K  516K        13
devb-eide                           40974   52K   19M   72K  608K       165
nmea                                98323    4K   56K    8K  516K        19
nmea                                98324    4K   56K    8K  516K        23
arinc                               98325    4K  516K    8K  516K    256024
sh                                 110604  144K   60K    4K  516K        25
sh                                 122897  144K   60K    4K  516K        17
telnetd                            122898  108K   96K   12K  516K        18
sh                                 126998  144K   92K    8K  516K        16
sin                                139287   80K   76K    8K  516K         0

between the first and the second call I wait just 1 second…

now my question is: how can I reduce this time growth?

with other apps the problem is solved when i do a fread() because the process enter a reply-blocked state. in this case (with arinc) I can’t do a fread call because i must use API calls supplied with the board (i’ve just a library and a programmer guide), so the process is always in ready state, so not blocked…

I hope I’ve been clear enough to make any of you understand…

Hello,

as I understand it, the read call of your API is not blocking when there is no data, so your program is effectivly always READY. Two possibilities:

  1. Browse your API for a blocking mechanism: Either a flag to tell open or read function to block when no data available or a dedicated wait function (like select()).
  2. Polling, and going to sleep for n milliseconds if no data available, effectively yielding the CPU to other processes.

Perhaps you can give some more infos on the API so we find out more.

Regards,
Albrecht

you perfectly understand!
so, reading the user’s manual of the board I can’t find out a way to block the process…

theorically (??) there is a way:

when you want to read from the device, you can’t use a read, but API gives a AR_GETNEXT() function which is described as:

[i]this utility attempts to get data from an input channel. If none is there, it continues trying for up 1/4 second before stopping. It calls AR_GETWORD repeatedly, returning when it receives a response or times out.

The system clock is used to time out this function. For the CEI-x20 in 32 bit Windows, the Sleep() function is used to avoid tying up the processor while waiting for label to arrive.[/i]

now:
CEI-x20 is my type of board.
AR_GETWORD is a function that read just once at calls (if you want to read more data, you might insert it inside a while, for exemple…or just use AR_GETNEXT :smiley:)

i try to use sleep, usleep, combine it with sched_yield, some other crazy things, but the process is always on ready state…

I’m trying to attach the read function to an interrupt but I don’t know how good is it (similar to 2) )

Hello,

  1. sleep( n ) does block the calling thread for n seconds. No ifs, no buts. Try writing a simple program that calls sleep( 1 ) in an endless loop and watch the states in pidin. If that is not working your system is corrupt! Perhaps the API is silently creating some receiver thread on its own, and this thread is running mad. Try to identify the threads using pidin!

  2. It looks that the API comes from Windows world. Have you got the source code? How did you get QNX on that board at all? Do you have a Board Support Package (BSP) from somewhere? There should be a serial driver included that maps /dev/ser1 in the path name space and you can use POSIX read() - blocking or NON-blocking - at your leisure. Or is it a special piece of hardware?

  3. If the hardware asserts an interrupt when data is available then the ISR is definitely the spot where to put the AR_GETWORD() function. Or is this only a macro that expands to something crazy?

You see, it’s difficult to answer without any knowledge about the board. But we will find out.

Regards,
Albrecht

Don’t worry Alb, you are giving me a great hand!!
I know it is difficult (expecially for my chaotic english! - I’m sorry for that)

so…

  1. API doesn’t starts any thread…

  2. yes. i bought this board (that is a PC104 card, not an standard pc card). with the board they give me some packages precompiled for Windows, Dos and Linux Red Hat, and the source code of the api library… I must work on QNX (i’m doing it as work, they will pay me, but I’ve never seen a qnx system beforethat) so, I build this shared object which contain all the api calls for that board (not so difficult, except I spent a lot of time to find out the right memory mapping :smiley:)
    i thought that probabily there is something wrong with the API, or with the way the were compiled, but i verify that everything works ok…I mean, if I try to read from the device, it receive all labels with no sigle error…the problem is, that if I read from arinc device, I can’t read from any other standard serial device…(effectively it doesn’t work :smiley:)

  3. AR_GETWORD is a routine, not a macro…AR_GETNEXT is a routine too, based on AR_GETWORD(but is easy to use AR_GETNEXT instead of AR_GETWORD iside a while, with some if to verify if data are avaiable on channel, ecc…)

  4. (uhm…there is not a 4th question…) interrupts are enebled/disabled via HW except my kind of board (grrr)…to do this I need a API call to AR_INT_CONTROL. there is another api call that is AR_INT_SET that rceive as parameter the number of the board(not so important now) and assigned number of interrupts choose between 3,5,6,7 and 9 using as default 5…
    (in my system int5 is already assigned, so the only n/a is 9…

I hope there is some good informations…
thanks again…

Hi,

I don’t know what arinc device is or what labels are. Is arinc a hardware device? Are labels some kind of data packets? Remember, you have to be root and you have to have I/O privity (ThreadCtl(_NTO_TCL_IO, 0)) before you can make I/O to any hardware.

Regards,
Albrecht

ops, I’m sorry…

Arinc 429 is a serial protocol used for flight device comunications (airplanes, helicopters, etc…) I will not explain all characteristics and advantages (the most important is that arinc is better than rs422 because it can used to cover big distances with no signal dispersion)(I’m not sure it is good explaination - I’m sorry)

to interface my pc (in this case is a PC104, not a desk) i use this arinc board called CEI-420A by Condor Engineering…

labels are some kind of data packets (for more precion, the label is a part of the packet that identify the kind of the packet, and other bits are data, flags and stuff)…

I have both root and I/O privity…

For now I found some kind of solution:

In the main process I do all settings of the arinc board (such as bitrate, parity, internal wrap, etc…), so I start a thread with the looped read function and data conversion (I must attach time and data read from gps to the read message, but this is not a problem, everything work fine)…

if I do only this, situation is exactly the same…

so I enbled Interrupt on the board, and I’ve done:

while (1) {
            InterruptWait(0, NULL);
            . . . 
            // read, stuff and bla bla bla...
}

in this way the thread goes on INTR state but for now it is not able to receive any data (or probably i must set up in a better way the board to make it feel the interrupt)

however, thaks for your help until now…

Depending on how time critical your task is, you could create a signal event and use it with a timer to stop your READY whatever polling function. Then you go to sleep for a while, or use delay(), and then use the CPU-consuming routine again. This at least would give you some CPU time for other tasks, but of course also a maximum latency on receving the data equal to the time specified in the delay()… Very ugly, but if you don’t find another solution, this could help…

mmm very interesting thing…I will try it right now…
thanks…

Hi,

I refer to your code snippet with the InterruptWait() call. Remember that the thread that calls this function must be the one that calls InterruptAttachEvent(), otherwise it won’t work. After processing the interrupt, you must unmask it using InterruptUnmask() because the system masks the interrupt in the PIC prior to unblocking you.

I would try to avoid complicated polling schemes if at all possible.

Regards,
Albrecht

hi al,

I prefer choose the solution with interruptwait, so I’m working on it…
but reading the guide I learned that inside the ISR i can’t do kernel calls, so I wonder if I can do all the reading work (supplied by API)

…the fact is that I never worked with this… :frowning: