Linux嵌入式实时操作系统开发与设计(十一)

附录A <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

中断延迟测试代码:

这是一个补丁(patch)文件,在我的Linux-2.2.12版本下编译通过。通过下面的命令粘贴到Linux源文件中:

# cd /usr/src/linux-2.2.12

# patch –p1 < /usr/src/linux-2.2.12/interrupt-latency-2.2.12-patch

粘贴完成后编译Linux内核:

# cd /usr/src/linux-2.2.12

# make config # 配置内核

# make dep

# make bzImage # 编译内核

# make modules # 编译模块

# make modules_install # 装载模块

# cp arch/i386/boot/bzImage /boot/interrupt-lattency

配置LILO,编辑/etc/lilo.conf,把下面几行添加进:

image=/boot/interrupt-latency

label=interrupt-lattency

read-only

root=/dev/hda1

重新装LILO

# /sbin/lilo

重启后在LILO提示符下输入:

LILO: interrupt-latency

则可以监控系统调用开/关中断的内核就起动完成,还需要运行一个用户空间程序(view.c, 见下面)用于输入命令和打印测试结果。

interrupt-latency-2.2.12-patch文件如下:

diff --exclude=version.h --exclude=config.h -Nru linux-2.2.12/arch/i386/kernel/Makefile linux-2.2.12-interrupt/arch/i386/kernel/Makefile

--- linux-2.2.12/arch/i386/kernel/Makefile Wed Jan 20 <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><time hour="10" minute="18"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; LETTER-SPACING: -0.4pt; mso-bidi-font-family: 'Times New Roman'">10:18:53</span></time> 1999

+++ linux-2.2.12-interrupt/arch/i386/kernel/Makefile Mon Mar 6 <time hour="11" minute="4"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; LETTER-SPACING: -0.4pt; mso-bidi-font-family: 'Times New Roman'">11:04:25</span></time> 2000

@@ -14,7 +14,9 @@

O_TARGET := kernel.o

O_OBJS := process.o signal.o entry.o traps.o irq.o vm86.o \

- ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o

+ ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o \

+ intr_blocking.o

+

OX_OBJS := i386_ksyms.o

MX_OBJS :=

diff --exclude=version.h --exclude=config.h -Nru linux-2.2.12/arch/i386/kernel/entry.S linux-2.2.12-interrupt/arch/i386/kernel/entry.S

--- linux-2.2.12/arch/i386/kernel/entry.S Fri Apr 30 <time hour="8" minute="13"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; LETTER-SPACING: -0.4pt; mso-bidi-font-family: 'Times New Roman'">08:13:37</span></time> 1999

+++ linux-2.2.12-interrupt/arch/i386/kernel/entry.S Mon Mar 6 <time hour="11" minute="5"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; LETTER-SPACING: -0.4pt; mso-bidi-font-family: 'Times New Roman'">11:05:10</span></time> 2000

@@ -96,6 +96,7 @@

movl %dx,%es;

#define RESTORE_ALL \

+ incl intrData; \

popl %ebx; \

popl %ecx; \

popl %edx; \

@@ -562,6 +563,8 @@

.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */

.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */

.long SYMBOL_NAME(sys_vfork) /* 190 */

+

+ .long SYMBOL_NAME(sys_get_intrData) /* 191 */

/*

* NOTE!! This doesn't have to be exact - we just have

diff --exclude=version.h --exclude=config.h -Nru linux-2.2.12/arch/i386/kernel/head.S linux-2.2.12-interrupt/arch/i386/kernel/head.S

--- linux-2.2.12/arch/i386/kernel/head.S Thu Jan 14 <time hour="22" minute="57"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; LETTER-SPACING: -0.4pt; mso-bidi-font-family: 'Times New Roman'">22:57:25</span></time> 1999

+++ linux-2.2.12-interrupt/arch/i386/kernel/head.S Mon Mar 6 <time hour="11" minute="14"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; LETTER-SPACING: -0.4pt; mso-bidi-font-family: 'Times New Roman'">11:14:26</span></time> 2000

@@ -316,6 +316,7 @@

movl %ax,%es

pushl $int_msg

call SYMBOL_NAME(printk)

+ incl intrData

popl %eax

popl %ds

popl %es

diff --exclude=version.h --exclude=config.h -Nru linux-2.2.12/arch/i386/kernel/intr_blocking.c linux-2.2.12-interrupt/arch/i386/kernel/intr_blocking.c

--- linux-2.2.12/arch/i386/kernel/intr_blocking.c Wed Dec 31 <time hour="16" minute="0"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; LETTER-SPACING: -0.4pt; mso-bidi-font-family: 'Times New Roman'">16:00:00</span></time> 1969

+++ linux-2.2.12-interrupt/arch/i386/kernel/intr_blocking.c Mon Mar 6 <time hour="11" minute="41"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; LETTER-SPACING: -0.4pt; mso-bidi-font-family: 'Times New Roman'">11:41:50</span></time> 2000

@@ -0,0 +1,322 @@

+#include <asm/system.h>

+

+

+/**** platform ****/

+#define readclock(low) \

+ __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")

+

+/**** configure ****/

+#define NUM_LOG_ENTRY 4

+#define INTR_IENABLE 0x200

+

+/**** data structure ****/

+struct IntrData {

+ /* count interrupt and iret */

+ int breakCount;

+

+ /* the test name */

+ const char * testName;

+

+ /* flag to control logging */

+ unsigned logFlag; /* 0 - no logging; 1 - logging */

+

+ /* panic flag - set to 1 if something is realy wrong */

+ unsigned panicFlag;

+

+ /* for synchro between start and end */

+ unsigned syncFlag;

+

+ /* we only log interrupts within certain range */

+ unsigned rangeLow;

+ unsigned rangeHigh;

+

+ /* count the total number interrupts and intrs in range*/

+ unsigned numIntrs;

+ unsigned numInRangeIntrs;

+

+

+ /* error accounting */

+ unsigned skipSti;

+ unsigned skipCli;

+ unsigned syncStiError;

+ unsigned syncCliError;

+ unsigned stiBreakError;

+ unsigned restoreSti;

+ unsigned restoreCli;

+

+ struct {

+ /* worst blocking time */

+ unsigned blockingTime;

+

+ const char * startFileName;

+ unsigned startFileLine;

+ unsigned startCount;

+

+ const char *endFileName;

+ unsigned endFileLine;

+ unsigned endCount;

+ } count[NUM_LOG_ENTRY];

+};

+

+struct IntrData intrData = {

+ 0,

+ "interrupt latency test (4 distinctive entries)",

+ 0,

+ 0,

+ 0,

+

+ 1,

+ 0xffffffff,

+

+ 0,

+ 0,

+

+ 0,

+ 0,

+ 0,

+ 0,

+ 0,

+ 0,

+ 0

+};

+

+

+/**** functions ****/

+#if 0

+void intr_check_int(int x)

+{

+

+ unsigned flag;

+ __intr_save_flags(flag);

+

+ if ((flag & INTR_IENABLE) != 0) {

+ switch(x) {

+ case 0 :

+ intrData.count[0].blockingTime ++;

+ break;

+ case 1 :

+ intrData.count[0].startFileLine ++;

+ break;

+ case 2 :

+ intrData.count[0].startCount ++;

+ break;

+ case 3 :

+ intrData.count[0].endFileLine ++;

+ break;

+ case 4 :

+ intrData.count[0].endCount ++;

+ break;

+ default :

+ intrData.count[0].startFileName = "Wrong check number";

+ break;

+ }

+ } else {

+ switch(x) {

+ case 0 :

+ intrData.count[1].blockingTime ++;

+ break;

+ case 1 :

+ intrData.count[1].startFileLine ++;

+ break;

+ case 2 :

+ intrData.count[1].startCount ++;

+ break;

+ case 3 :

+ intrData.count[1].endFileLine ++;

+ break;

+ case 4 :

+ intrData.count[1].endCount ++;

+ break;

+ default :

+ intrData.count[1].startFileName = "Wrong check number";

+ break;

+ }

+ }

+}

+

+#endif

+

+

+static inline void intr_SetPanic(unsigned x, const char *fname, unsigned l)

+{

+ if (intrData.panicFlag != 0) {

+ /* double error; impossible */

+ intrData.panicFlag = 99;

+ return;

+ }

+ intrData.panicFlag = x;

+ intrData.count[0].startFileName = fname;

+ intrData.count[0].startFileLine = l;

+}

+

+static const char *intrStartFileName;

+static unsigned intrStartFileLine;

+static unsigned intrStartCount;

+

+/* strategy :

+ * if it is true "cli", i.e., clearing the IF, we remember

+ * everything, and clear breakCount.

+ */

+void intr_cli(const char *fname, unsigned lineno)

+{

+ unsigned flag;

+ __intr_save_flags(flag);

+

+ __intr_cli();

+

+ /* if we are not logging or we have an error, do nothing */

+ if ((intrData.logFlag == 0) || ( intrData.panicFlag != 0)) {

+ return;

+ }

+

+ /* do nothing we had IF cleared before we call this function */

+ if ((flag & INTR_IENABLE) == 0) {

+ intrData.skipCli ++;

+ return;

+ }

+

+ /* debug */

+ if (intrData.syncFlag == 1) {

+ intrData.syncCliError ++;

+ }

+ intrData.syncFlag = 1;

+

+ intrData.breakCount = 0;

+

+ /* Read the Time Stamp Counter */

+ intrStartFileName = fname;

+ intrStartFileLine = lineno;

+ readclock(intrStartCount);

+}

+

+

+/* strategy:

+ * we do a count only if

+ * 1. syncFlag is 1 (a valid cli() was called)

+ * 2. breakCount is 0 (no iret is called between cli() and this sti()

+ */

+void intr_sti(const char *fname, unsigned lineno)

+{

+ unsigned flag;

+ unsigned endCount;

+ unsigned diff;

+ int i;

+

+ __intr_save_flags(flag);

+

+ /* if we are not logging or we have an error, do nothing */

+ if ((intrData.logFlag == 0) || ( intrData.panicFlag != 0)) {

+ __intr_sti();

+ return;

+ }

+

+

+ /* check if this is a real sti() */

+ if ((flag & INTR_IENABLE) != 0) {

+ intrData.skipSti ++;

+ __intr_sti();

+ return;

+ }

+

+ /* check 1*/

+ if (intrData.syncFlag != 1) {

+ intrData.syncStiError ++;

+ __intr_sti();

+ return;

+ }

+

+ /* check 2 */

+ if (intrData.breakCount != 0) {

+ intrData.stiBreakError ++;

+ __intr_sti();

+ return;

+ }

+

+ /* read count again */

+ readclock(endCount);

+

+ intrData.syncFlag = 0;

+

+ diff = endCount - intrStartCount;

+

+ if ((diff >= intrData.rangeLow) && (diff <= intrData.rangeHigh)) {

+ unsigned lowest=0xffffffff;

+ unsigned lowestIndex;

+ unsigned sameIndex = 0xffffffff;

+

+ intrData.numInRangeIntrs++;

+

+ /* check if we need to log this event */

+ for (i=0; i< NUM_LOG_ENTRY; i++) {

+

+ if (lowest > intrData.count[i].blockingTime) {

+ lowest = intrData.count[i].blockingTime;

+ lowestIndex = i;

+ }

+

+ if ( (lineno == intrData.count[i].endFileLine) &&

+ (intrStartFileLine == intrData.count[i].startFileLine) &&

+ (fname[0] == intrData.count[i].endFileName[0]) &&

+ (intrStartFileName[0] == intrData.count[i].startFileName[0]) ) {

+ /* if the line numbers are same, the first chars in

+ * both file names are same, we consider it is the same

+ * entry. */

+ sameIndex = i;

+ }

+ }

+

+ if (sameIndex == 0xffffffff) {

+ i = lowestIndex;

+ } else {

+ i = sameIndex;

+ }

+

+ if (diff > intrData.count[i].blockingTime) {

+ intrData.count[i].blockingTime = diff;

+ intrData.count[i].endFileName = fname;

+ intrData.count[i].endFileLine = lineno;

+ intrData.count[i].endCount = endCount;

+ intrData.count[i].startFileName = intrStartFileName;

+ intrData.count[i].startFileLine = intrStartFileLine;

+ intrData.count[i].startCount = intrStartCount;

+ }

+ }

+

+ intrData.numIntrs++;

+ __intr_sti();

+}

+

+

+void intr_restore_flags(const char *fname, unsigned lineno, unsigned x)

+{

+ unsigned flag;

+

+ /* if we are not logging or we have an error, do nothing */

+ if ((intrData.logFlag == 0) || ( intrData.panicFlag != 0)) {

+ __intr_restore_flags(x);

+ return;

+ }

+

+ __intr_save_flags(flag);

+

+ if (((flag & INTR_IENABLE) == 0) &&

+ ((x & INTR_IENABLE) != 0) ) {

+ intrData.restoreSti ++;

+ intr_sti(fname, lineno);

+ }

+

+ if ( ((flag & INTR_IENABLE) != 0) &&

+ ((x & INTR_IENABLE) == 0) ) {

+ intrData.restoreCli ++;

+ intr_cli(fname, lineno);

+ }

+

+ __intr_restore_flags(x);

+}

+

+#include <asm/uaccess.h>

+

+asmlinkage int sys_get_intrData(void ** ptr)

+{

+ return put_user(&intrData, ptr);

+}

diff --exclude=version.h --exclude=config.h -Nru linux-2.2.12/include/asm-i386/system.h linux-2.2.12-interrupt/include/asm-i386/system.h

--- linux-2.2.12/include/asm-i386/system.h Mon Oct 11 <time hour="21" minute="28"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; LETTER-SPACING: -0.4pt; mso-bidi-font-family: 'Times New Roman'">21:28:12</span></time> 1999

+++ linux-2.2.12-interrupt/include/asm-i386/system.h Mon Mar 6 <time hour="11" minute="8"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; LETTER-SPACING: -0.4pt; mso-bidi-font-family: 'Times New Roman'">11:08:02</span></time> 2000

@@ -174,13 +174,33 @@

#define wmb() __asm__ __volatile__ ("": : :"memory")

/* interrupt control.. */

+#if 0

#define __sti() __asm__ __volatile__ ("sti": : :"memory")

#define __cli() __asm__ __volatile__ ("cli": : :"memory")

#define __save_flags(x) \

__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")

#define __restore_flags(x) \

__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")

+#endif

+#define __intr_sti() __asm__ __volatile__ ("sti": : :"memory")

+#define __intr_cli() __asm__ __volatile__ ("cli": : :"memory")

+#define __intr_save_flags(x) \

+__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")

+#define __intr_restore_flags(x) \

+__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")

+

+/* jsun */

+extern void intr_cli(const char *, unsigned);

+extern void intr_sti(const char *, unsigned);

+extern void intr_restore_flags(const char *, unsigned, unsigned);

+extern void intr_sync_flag(const char *, unsigned lineno);

+

+#define __cli() intr_cli(__FILE__, __LINE__)

+#define __sti() intr_sti(__FILE__, __LINE__)

+#define __save_flags(x) \

+__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")

+#define __restore_flags(x) intr_restore_flags(__FILE__, __LINE__, x)

#ifdef __SMP__

@@ -197,9 +217,8 @@

#define cli() __cli()

#define sti() __sti()

-#define save_flags(x) __save_flags(x)

+#define save_flags(x) __save_flags(x)

#define restore_flags(x) __restore_flags(x)

-

#endif

/*

用户空间程序view.c如下:

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

#include <fcntl.h>

#include <assert.h>

/****************** CONFIG ****************/

#define<span sty

你可能感兴趣的:(C++,c,linux,嵌入式,Office)