I am working with RHEL 2.4.something and am having problems with scheduling POSIX threads. I want to have two simple threads trading the CPU back and forth as quickly as possible.
I need one of the threads to pause for 35 ms and the other to accurately detect when a 2 second timer goes off and otherwise be on duty continuously.
I want to avoid using usleep() because it is too coarse and is too indeterminant. I can ask for as little as 10 millisecs, since ticks runs at
100 Hz, but I never get anything close to that in reality. I can get 20 something millis with a great deal of variance and sometimes lose the CPU for as long as 185 millis, this approach is no good.Since sched_yield() never actually puts the threads to sleep, the overhead is significantly less. When I wrote my first test loops, I determined that I could run loops that would come back on task in about 25 microseconds with very little variation (I was delighted).
Then I tried putting some of the actual code in the loops and used gettimeofday to find the current time in seconds and microseconds so I could poll time in the loop to detect timeouts. When I tried any variation on the following loop. In the loop I check to see if the current time has exceeded a limit I calculated earlier. If the limit is exceeded, I give up the CPU so the other thread can do its thing, otherwise, I do some processing and repeat.
struct timeval t_now, t_end; // calculation of t_end not shown
while (1) // this is a control system, so the loop runs forever { gettimeofday(&t_now); if (!compare_time(t_now,t_end)) // implementation of compare_time not shown if( !sched_yield()) { printf("\nsched_yield fils with errno = %d", errno); exit(err_no); } else }
I got errno = 14 (invalid address) If I ignored the error condition I got a segmentation error.
If I coded loops that only called sched_yield() without checking the current time, no errors occurred.
Of course both threads implemented thise loop with some variations, so it occurred to me that maybe gettimeofday() was not reentrant? But I could find no information about it to determine one way or the other if this were the case. If I knew this to be the case, I could develop a workaround. I hacked around with this for hours yesterday and finally decided I needed to ask for some help!!!!
I am also using mutex exclusion, and so on. The whole loop works flawlessly when I let the two threads simply sleep for 20 or 35 ms. I just can't deal with the uncertainty of the timing. And I really don't want to get an embedded linux, because this project doesn't merit the effort.
Anyone ever run into this problem before?
- Frank