我自己写一个中断的程序,可是我的中断线程里面只有一句话,
for( ; ; )
{
InterruptWait(NULL,NULL);
counter++;//这句话消耗的时间有时高达30us,太不可以思议了!?
}
可是这个语句里面的耗时却很大,有时有30+us ,如下图。
这个是我的system profiler information。
我的疑问:为什么这个一个简单的句子耗时需要那么多呢?还有就是线程Thread2的优先级已是255了,可是其READY时间依旧有20+us,是不是有点长了呢?感觉有点不可思议。请问各位大大了,这个具体是什么原因呢?
全部代码:
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <sys/neutrino.h>
#include <sys/resmgr.h>
#include <sys/stat.h>
#include <sys/syspage.h>
#define INTR_THREAD_PRIO 255
void *interrupt_thread (void *data);
struct sigevent intr_event;
int intr_id;
#define NUM_DATA_BYTES 1
unsigned int interrupt_num = 0;
long counter=0;
int main (void)
{
int i,runMask = 0x00000008;
struct _clockperiod *new;
struct timespec res;
if (ThreadCtl(_NTO_TCTL_RUNMASK, (void *)runMask) == -1)
printf("threadCtl failed.\n");
fprintf(stderr, "Using Interrupt %u\n", interrupt_num );
fflush(stdout);
new = (struct _clockperiod *)malloc(sizeof(struct _clockperiod));
new->nsec = 30000L;
new->fract = 0L;
ClockPeriod(CLOCK_REALTIME,new,NULL,0);
if ( clock_getres( CLOCK_REALTIME, &res) == -1 )
{
perror( "clock get resolution" );
return EXIT_FAILURE;
}
printf( "Clock resolution is %ld nanoseconds.\n",res.tv_nsec);
pthread_create (0, NULL, interrupt_thread, NULL);
// Now our main() thread just waits till we get killed
// pause();
sleep(5000);
return EXIT_SUCCESS;
}
const struct sigevent *interrupt_handler(void *event, int id)
{
// struct sigevent *return_event= (struct sigevent *) event;
return &intr_event;
}
void *interrupt_thread (void *notinuse)
{
struct sched_param param;
int runMask = 0x00000004;
if (ThreadCtl(_NTO_TCTL_RUNMASK, (void *)runMask) == -1)
printf("threadCtl failed.\n");
param.sched_priority = INTR_THREAD_PRIO;
if ( sched_setscheduler( 0, SCHED_FIFO, ¶m ) == -1 )
{
fprintf(stderr, "Unable to change priority: %s\n",
strerror(errno));
exit( EXIT_FAILURE );
}
printf("Interrupt Thread step 1.\n");
// We need I/O privileges so we can call InterruptAttach()
if (ThreadCtl (_NTO_TCTL_IO, 0) == -1)
{
fprintf(stderr, "Unable to get I/O privileges: %s\n",
strerror(errno));
exit( EXIT_FAILURE );
}
printf("Interrupt Thread step 2.\n");
// Set up a sigevent that will wake up InterruptWait()
SIGEV_INTR_INIT( &intr_event );
if ( interrupt_num == 0 )
{
interrupt_num = SYSPAGE_ENTRY (qtime)->intr;
}
intr_id = InterruptAttach (interrupt_num, interrupt_handler,NULL,0, _NTO_INTR_FLAGS_PROCESS);
if ( intr_id == -1 )
{
fprintf(stderr, "Unable to attach to irq %u: %s\n",
interrupt_num, strerror(errno));
exit( EXIT_FAILURE );
}
printf("Interrupt Thread step 3.\n");
for( ; ; )
{
InterruptWait(NULL,NULL);
counter++;
}
}
xtang1
3
你挂的是时钟中断。时钟中断被好几个程序共享着呢。虽然你的中断线程优先级很高,但是别的程序都是直接在中断模式下工作,最后才论到你。
pidin irq 可以看到还有哪些进程共享中断。
建议你试试别的中断源。
xtang,如你所说,确实是有多个进程占用时钟中断。
对于我们所使用的进程中断部分,照理说,真正计算的部分只有以下一个语句而已,如下:
counter++
在InterruptWait(NULL,NULL)状态下一直是阻塞状态,直至产生中断,会执行counter++
在System Profiler Info的信息来看,在这30us内没有被中断哈?线程一直占用着CPU,应该说CPU是一直执行着线程Thread2吧。我不明白的地方是counter++为何消耗30us呢?
PS.这个System Profiler的信息与上图虽然不是来自一个进程,但是它们的Code是一模一样的;
xtang1
5
我不知道你从哪里得出的结论,线程一直占用着CPU。线程,除非它的状态是RUNNING,它才会占着CPU,其它任何状态都没有占CPU。
我不记得“粉红色”代表线程的什么状态了,但应该不是RUNNING吧。
所以我不认为counter++消耗了30us。如果要看的话,你应该找Thread2从Interrupt Wait状态退出(意味着中断处理被调度到),到Thread2重新进入 Interrupt Wait状态之间的间隔,那个,才是counter++所消耗的时间。
你可以把Thread2 在你的绿色框里发生的事件都列出来,看看具体发生了什么事。
xtang, 你好,这个是Thread2的事件图,从图中看,应该是一直处于RUNING状态吧?
PS.我在另外一台双核的凌华的工控机上运行,没有出现上述的情况,可是我在一台8核的服务器上运行,就出现了上述的情况,这个让人很不解,说实在的,难道这个与处理器,还有主板有关?。
xtang1
7
嗯,看上去好象是在RUNNING。Thread2 当中的几根黑线是什么事件?
还有一个是我注意到你的Thread2有CPU绑定,先把这个绑定去除(Thread2可以任意CPU执行),还会是同样结果吗?
xtang,你好,Thread2当中的4根黑线是4个Interruptwait()的exit与enter ,照理应该不会有两个interruptwait 的enter哈?挺奇怪的,详细的信息如下图所示:
按照你说的,将CPU核绑定解除了,还是会出现这样的情况,只是黑线少了两条(应该分别是Interruptwait() exit 和 Interruptwait() enter),运行的时间依旧挺长,30us左右,当然,这个是少数情况如此,如下图所示:
xtang1
9
确实有点诡异。你要量的是interruptwait_exit 和 interruptwait_enter之间的时间。
比如 Evt#564353和Evt#564360,这个相当于931.381 - 931.376 = 0.005 (ms) 这个看上去还是挺靠谱的。而四根黑线的前两根,则是931.374 - 931.349 = 0.025 (ms) 则大了5倍。不太确信是什么原因。从Event ID来看,这两个事件中间还有约10个事件发生,你可以查一下time line,看看这些有没有关连性。
你的中断源的频率有多高?你的线程优先级足够高,唯一可以挡住你的线程的,就是内核无法正常退出(因为中断进入太快,或是别的原因)。
如果你的任务对于中断响应要求比较高的话,你应该试试用 interruptAttach() 直接挂 ISR,应该会更精确一点。
xtang:
确实有点诡异。你要量的是interruptwait_exit 和 interruptwait_enter之间的时间。
比如 Evt#564353和Evt#564360,这个相当于931.381 - 931.376 = 0.005 (ms) 这个看上去还是挺靠谱的。而四根黑线的前两根,则是931.374 - 931.349 = 0.025 (ms) 则大了5倍。不太确信是什么原因。从Event ID来看,这两个事件中间还有约10个事件发生,你可以查一下time line,看看这些有没有关连性。
你的中断源的频率有多高?你的线程优先级足够高,唯一可以挡住你的线程的,就是内核无法正常退出(因为中断进入太快,或是别的原因)。
如果你的任务对于中断响应要求比较高的话,你应该试试用 interruptAttach() 直接挂 ISR,应该会更精确一点。
xtang,你好,我查看了确实有7个事件发生,其实1个为线程级别,6个是Interrupt0x0产生的(照理说从Ev#564342到EV#564352之间应该是9个,你说会不会有数据在log的时候丢失呢?应该不会吧,嘿嘿?),分别是调用内核的情况。其中Interrupt0x0下有三种Handler entry与exit,只有InterruptISR*是我产生的,其余的均是系统产生的,如下图:
如果把ISR挂在InterrupAttach()那么如果ISR花的时间比较长的话(用于计算之类),占用着内核,是否会导致其他的进程无法获取内核?对于其他的进程调度产生影响吧?
我的中断源的周期是30us一次。其实xtang,你说的很对,线程级别已是足够高了,可是导致内核的无法正常退出,应该是我这个程序的主要原因。对于这种问题,一般如何避免呢?因为是系统的调用,不好处理哈。
xtang1
11
啊,你这个是x86吧。
中断0在x86里是时钟中断,你的程序是线程中断,当kernel退出 (InterruptWait() exit) ,进入到线程处理中时,中断0可以打断你的处理,经过三个程序处理后,才会回到你的线程。所以当中有一个长停顿。
如果你不需要网络,可以把那两个占用中断0的进程杀掉,(slay io-pkt-v4-hc qconn)应该情况会好转。
如果你需要io-pkt-h4-vc, 那你只有自己改ISR,你的中断优先级应该高于中断0,它就无法打断你的处理了。
ISR时间过长,确实会影响系统。但是如果你的中断处理确实需要高速响应,那是无法回避的。常用的方法是用ISR,在ISR里处理time critical的事情,然后再激发一个外部线程,来进行不是time critical,但需要大量CPU时间的计算。
xtang:
啊,你这个是x86吧。
中断0在x86里是时钟中断,你的程序是线程中断,当kernel退出 (InterruptWait() exit) ,进入到线程处理中时,中断0可以打断你的处理,经过三个程序处理后,才会回到你的线程。所以当中有一个长停顿。
如果你不需要网络,可以把那两个占用中断0的进程杀掉,(slay io-pkt-v4-hc qconn)应该情况会好转。
如果你需要io-pkt-h4-vc, 那你只有自己改ISR,你的中断优先级应该高于中断0,它就无法打断你的处理了。
ISR时间过长,确实会影响系统。但是如果你的中断处理确实需要高速响应,那是无法回避的。常用的方法是用ISR,在ISR里处理time critical的事情,然后再激发一个外部线程,来进行不是time critical,但需要大量CPU时间的计算。
恩,倒也是哈。谢谢xtang哈,对于这个时候理解比以前透彻多了。