请问各位大大,我这个中断线程耗时太多,是什么缘故呢?

我自己写一个中断的程序,可是我的中断线程里面只有一句话,

 for( ; ; )
 {
        InterruptWait(NULL,NULL);
        counter++;//这句话消耗的时间有时高达30us,太不可以思议了!?
 }

可是这个语句里面的耗时却很大,有时有30+us :frowning: ,如下图。
这个是我的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, &param ) == -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++;
 }
}

不懂,帮你顶顶,引起高手注意

你挂的是时钟中断。时钟中断被好几个程序共享着呢。虽然你的中断线程优先级很高,但是别的程序都是直接在中断模式下工作,最后才论到你。

pidin irq 可以看到还有哪些进程共享中断。

建议你试试别的中断源。

xtang,如你所说,确实是有多个进程占用时钟中断。
对于我们所使用的进程中断部分,照理说,真正计算的部分只有以下一个语句而已,如下:

counter++

在InterruptWait(NULL,NULL)状态下一直是阻塞状态,直至产生中断,会执行counter++
在System Profiler Info的信息来看,在这30us内没有被中断哈?线程一直占用着CPU,应该说CPU是一直执行着线程Thread2吧。我不明白的地方是counter++为何消耗30us呢?
PS.这个System Profiler的信息与上图虽然不是来自一个进程,但是它们的Code是一模一样的;

我不知道你从哪里得出的结论,线程一直占用着CPU。线程,除非它的状态是RUNNING,它才会占着CPU,其它任何状态都没有占CPU。

我不记得“粉红色”代表线程的什么状态了,但应该不是RUNNING吧。

所以我不认为counter++消耗了30us。如果要看的话,你应该找Thread2从Interrupt Wait状态退出(意味着中断处理被调度到),到Thread2重新进入 Interrupt Wait状态之间的间隔,那个,才是counter++所消耗的时间。

你可以把Thread2 在你的绿色框里发生的事件都列出来,看看具体发生了什么事。

xtang, 你好,这个是Thread2的事件图,从图中看,应该是一直处于RUNING状态吧?
PS.我在另外一台双核的凌华的工控机上运行,没有出现上述的情况,可是我在一台8核的服务器上运行,就出现了上述的情况,这个让人很不解,说实在的,难道这个与处理器,还有主板有关?。

嗯,看上去好象是在RUNNING。Thread2 当中的几根黑线是什么事件?

还有一个是我注意到你的Thread2有CPU绑定,先把这个绑定去除(Thread2可以任意CPU执行),还会是同样结果吗?

xtang,你好,Thread2当中的4根黑线是4个Interruptwait()的exit与enter ,照理应该不会有两个interruptwait 的enter哈?挺奇怪的,详细的信息如下图所示:

按照你说的,将CPU核绑定解除了,还是会出现这样的情况,只是黑线少了两条(应该分别是Interruptwait() exit 和 Interruptwait() enter),运行的时间依旧挺长,30us左右,当然,这个是少数情况如此,如下图所示:

确实有点诡异。你要量的是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,你说的很对,线程级别已是足够高了,可是导致内核的无法正常退出,应该是我这个程序的主要原因。对于这种问题,一般如何避免呢?因为是系统的调用,不好处理哈。

啊,你这个是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哈,对于这个时候理解比以前透彻多了。 :smiley: