Linux embedded real-time operating system development and design (eleven)

xiaoxiao2021-03-06  103

Appendix A

Interrupt delay test code:

This is a patch file, compiling under my Linux-2.2.12 version. Paste it into the Linux source file by the following command:

# cd /usr/src/linux-2.2.12

# patch -p1

Compile the Linux kernel after the paste is completed:

# cd /usr/src/linux-2.2.12

# Make config # Configure the kernel

# Make Dep

# Make Bzimage # Compile the kernel

# MAKE MODULES # Compilation Module

# Make Modules_Install # loading module

# CP Arch / i386 / boot / bzimage / boot / interrupt-lattency

Configure LILO, edit /etc/lilo.conf, add the following lines to:

Image = / boot / interrupt-latency

Label = interrupt-lattency

Read-only

Root = / dev / hda1

Re-decorate LILO:

# / sbin / lilo

Enter the LILO prompt after restart:

INTERRUPT-LATENCY

The kernel that can monitor the system call open / off interrupt is completed, and you need to run a user spatial program (see.c, see below) for entering commands and printing test results.

The interrupt-latency-2.2.12-patch file is as follows:

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

10:18:53

1999

Linux-2.2.12-Interrupt / Arch / I386 / KERNEL / MAKEFILE MON Mar 6

11:04:25

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

08:13:37

1999

Linux-2.2.12-Interrupt / Arch / I386 / KERNEL / ENTRY.S MON Mar 6

11: 05: 102000

@@ -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

22:57:25

1999

Linux-2.2.12-Interrupt / Arch / I386 / KERNEL / Head.s Mon Mar 6

11:14:26

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

16:00:00

1969

Linux-2.2.12-Interrupt / Arch / I386 / KERNEL / INTR_BLOCKING.C MON Mar 6

11:41:50

2000

@@ -0, 0 1,322 @@

# include

/ **** Platform **** /

# Define Readclock (low) /

__ASM__ __Volatile__ ("RDTSC": "= a" (low): "EDX")

/ **** configure **** /

# define num_log_entry 4

# define INTR_IENABLE 0x200

/ **** Data structure **** / struct intertata {

/ * 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 ceertheng @ /

Unsigned Rangelow;

Unsigned rangehigh;

/ * Count the total number interrupts and intrs in inn * /

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 clean cout.

* /

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 (INTDATA.LOGFLAG == 0) || (INTRDATA.PANICFLAG! = 0) {

Return

}

/ * Do nothing We Had if clear 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;

INTRSTARTFILINE = LINENO;

ReadClock (intrstartcount);

}

/ * Strategy:

* We do a count online

* 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 (INTDATA.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 (INTDATA.SYNCFLAG! = 1) {

INTRDATA.SYNCSTIROR ;

__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 = 0xffffffffff;

Unsigned lowestindex;

Unsigned SameIndex = 0xffffffffff;

INTRDATA.NUMINRANGEINTRS ;

/ * Check if we need to log this event * /

For (i = 0; 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 number area is the first chars in

* Both File Names Are Same, We consider it is the same

* Entry. * /

SameIndex = i;

}

}

IF (SameIndex == 0xfffffffff) {

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 (INTDATA.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

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

21:28:12

1999

Linux-2.2.12-Interrupt / include / ASM-I386 / System.h Mon Mar 6

11:08:02

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": / * 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": / * 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

/ *

The user spatial program View.c is as follows:

#include

#include

#include

#include

#include

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

#define Num_Log_ENTRY 4

#define clock_frequency 266 / * cycles per microsecond * /

#define syscall_number 191

/ ****************** * End of config ************** /

#define cmd_exit 0 # Define cmd_display 1

#define cmd_start 2

#define cmd_stop 3

#define cmd_continue 4

#define cmd_set_Range 5

#define cmd_last 6

Struct intertata {

/ * 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 ceertheng @ /

UNSIGNED RANGELOW;

UNSIGNED RANGEHIGH;

/ * Count the total number interrupts and intrs in inn * /

UNSIGNED NUMINTRS;

UNSIGNED NUMINRANGEINTRS;

/ * Error Accounting * /

UNSIGNED SKIPSTI;

UNSIGNED SKIPCLI;

UNSIGNED SYNCSTIROR;

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];

}

UNSIGNED PDATA;

Struct intrdata data;

INT KMEM;

Char BUF [81];

Unsigned int Getint (const char * prompt)

{

Unsigned Int i;

Printf ("% s", prompt);

Scanf ("% D", & i);

Return I;

}

Unsigned int getHex (const char * prompt)

{

Unsigned Int i;

Printf ("% s", prompt);

Scanf ("% x", & i);

Return I;

}

Unsigned getcommand ()

{

For (;;) {

UNSIGNED CMD;

Printf ("/ n");

Printf ("Command Menu / N");

Printf ("============== / n"); Printf ("0-EXIT 1-Display 2-start logging 3-stop logging 4-payging / n");

Printf ("5-SET RANGE / N");

Printf ("/ n");

Printf ("Your Choice:");

Scanf ("% u", & cmd);

IF ((cmd> = 0) && (cmd

Return CMD;

} else {

Printf ("INVALID Choice !!!!! / N / N");

}

}

}

Unsigned getkMemint (unsigned offset)

{

OFF_T Seekerror;

SSIZE_T SIZE;

Unsigned Num = 0;

Assert ((Offset & 3) == 0);

Seekerror = lseek (kmem, offset, seek_set);

Assert (seekerror! = (OFF_T) -1);

Size = Read (KMEM, & Num, SizeOf (NUM);

Assert (sizeof (num) == 4);

assert (size == 4);

Return Num;

}

Char * getkMemString (unsigned offset)

{

OFF_T Seekerror;

SSIZE_T SIZE;

BUF [80] = 0;

BUF [0] = 0;

IF (Offset == 0) Return BUF;

Seekerror = lseek (kmem, offset, seek_set);

Assert (seekerror! = (OFF_T) -1);

Size = read (KMEM, BUF, 80);

Assert (size == 80);

Return BUF;

}

Void getkmemblock (unsigned offset, void * buf, unsigned bufsize)

{

OFF_T Seekerror;

SSIZE_T SIZE;

Seekerror = lseek (kmem, offset, seek_set);

Assert (seekerror! = (OFF_T) -1);

Size = Read (KMEM, BUF, BUFSIZE);

Assert (size == buffsize);

}

Void SetKMemBlock (unsigned offset, void * buf, unsigned bufsize)

{

OFF_T Seekerror;

SSIZE_T SIZE;

Seekerror = lseek (kmem, offset, seek_set);

Assert (seekerror! = (OFF_T) -1);

Size = Write (KMEM, BUF, BUFSIZE);

Assert (size == buffsize);

}

Void setkMemint (unsigned offset, unsigned x)

{

OFF_T Seekerror;

SSIZE_T SIZE;

Seekerror = lseek (kmem, offset, seek_set);

Assert (seekerror! = (OFF_T) -1); size = write (kmem, & x, sizeof (x));

askERT (size == sizeof (x));

}

Void Display ()

{

UNSIGNED I;

GetKMemBlock (PDATA, & DATA, SIZEOF (DATA);

Printf ("% s: / n", getkMemString ((unsigned) data.testname);

Printf ("BreakCount:% D / N", DATA.BREAKCOUNT);

Printf ("Logflag:% D / N", Data.logflag;

Printf ("PanicFlag:% D / N", Data.PanicFlag;

Printf ("SyncFlag:% D / N", DATA.SyncFlag;

Printf ("Range: [% U):% u (0x% x)] / N",

Data.rangelow, Data.Rangelow,

Data.Rangehigh, Data.Rangehigh

Printf ("NUMINTRS:% U / N", DATA.NUMINTRS;

Printf ("NUMINRANGEINTS:% U / N", DATA.NUMINRANGEINTRS

Printf ("Skipsti SkipCli Syncsti SyncCli Stibreak Reststi RESTCLI / N");

Printf ("% D / T% D / T% D / T% D / T% D / T% D / T% D / T / N",

Data.skipsti,

Data.skipCli,

Data.syncstierror,

Data.syncClierror,

Data.stibreakerror,

Data.restoSti,

Data.restoreCli);

For (i = 0; i

Printf ("Log Entry:% D / N", I);

Printf ("/ TBLOCKINGTIME:% U (% U US) / N",

Data.count [i] .blockingtime,

Data.count [i] .bockingTime / clock_frequency);

Printf ("/ tstartfilename:% s / n",

GetkMemString ((unsigned) Data.count [i] .startfilename);

Printf ("/ tstartfileline:% u / n", data.count [i] .startfileline);

Printf ("/ tstartcount:% u / n", data.count [i] .startcount);

Printf ("/ TENDFILENAME:% S / N",

GetkMemString ((unsigned) Data.count [i] .endfilename);

Printf ("/ TENDFILINE:% u / n", data.count [i] .endfileline);

Printf ("/ tendcount:% u / n", data.count [i] .endcount);

}

Printf ("/ n");

}

Void startlogging () {

UNSIGNED I;

/ * init first * /

Data.breakcount = 0;

DATA.LOGFLAG = 0;

Data.panicflag = 0;

Data.syncflag = 0;

Data.numIntrs = 0;

Data.numinRangeInTRS = 0;

DATA.SKIPSTI =

Data.skipCli =

Data.syncstierror =

Data.syncClierRor =

Data.stibreakerror =

Data.Restoresti =

Data.RestoreCli = 0;

For (i = 0; i

Data.count [i] .blockingTime = 0;

Data.count [i] .StartFileName = 0;

Data.count [i] .StartFileLine = 0;

Data.count [i] .startcount = 0;

Data.count [i] .endfilename = 0;

Data.count [i] .endfileline = 0;

Data.count [i] .endcount = 0;

}

SetKMemBlock (PDATA, & DATA, SIZEOF (DATA);

/ * Turn the logging flag * /

SetKMEMINT (PDATA & DATA.LOGFLAG - & DATA), 1);

}

void endlogging ()

{

/ * Turn the logging flag * /

SetKMEMINT (PDATA & data.logflag - (unsigned) & data), 0);

}

Void Continueloggin ()

{

/ * Turn the logging flag * /

SetKMEMINT (PDATA & DATA.LOGFLAG - & DATA), 1);

}

Void setRange ()

{

Data.rangelow = GetInt ("INPUT LOWER Bound (Decimal):");

Printf ("/ TLOWER BOUND IS% U (0x% x) / n", DATA.RANGELOW, DATA.RANGELOW);

Data.Rangehigh = GetInt ("INPUT UPPER Bound (Decimal):");

Printf ("/ Tupper Bound IS% U (0x% x) / N", DATA.RANGEHIGH, DATA.RANGEHIGH);

SetKMEMINT (PDATA & DATA.RANGELOW - & DATA),

Data.rangelow;

SetKMEMINT (PDATA & DATA.RANGEHIGH - & DATA),

Data.RangehiGH;

}

Main ()

{

Unsigned int CMD;

unsigned long offset;

KMEM = Open ("/ dev / kmem", o_rdwr);

Assert (kmem> 0);

IF (Syscall_Number, & PDATA)! = 0) {

Printf ("Failed to Get Jsundata Address Through Syscall 191! / N");

PDATA = GetHex ("INPUT ManNually The Address of Jsundata:");

}

GetKMemBlock (PDATA, & DATA, SIZEOF (DATA);

For (;;) {

CMD = getcommand ();

Switch (cmd) {

Case cmd_display:

DISPLAY ();

Break;

Case cmd_start:

StartLogging ();

Break;

Case cmd_stop:

ENDLOGGING ();

Break;

Case cmd_continue:

Continueloggin ();

Break;

Case cmd_set_range:

SetRANge ();

Break;

Case cmd_exit:

Close (KMEM);

Return;

DEFAULT:

Assert (0 == 1);

}

}

}

Appendix B

Context switching test program lat_ctx.c:

/ *

* LAT_CTX.C - Context Switch Timer

*

* usage: lat_ctx [-s size] #procs [#procs ....]

*

* Copyright (c) 1994 Larry McVoy. Distributed Under The FSF GPL with

* Additional Restriction That Results May Published Only IF

* (1) The Benchmark IS unmodified, and

* (2) The Version in The Sccsid Below Is Included in The Report.

* Support for this development by Sun Microsystems is gratefully Acknowledged.

* /

Char * id = "$ ID $ / n";

#include "bench.h"

#if Defined (SGI) && Defined (PIN)

#include

#include

Int ncpus;

#ENDIF

#define maxProc 2048

#define chunk (4 << 10)

#define Trips 5

#ifndef max

#define max (a, b) ((a)> (b)? (a): (b))

#ENDIF

INT process_size, * data; / * size & pointer to an array what big * /

INT PIDS [MAXPROC];

INT P [MAXPROC] [2];

Double PIPE_COST (INT P [】 [2], int procs);

INT CTX (int procs, int nprocs);

Int Sumit (int);

Void Killem (INT Procs);

Void DOIT (int P [MaxProc] [2], int RD, int WR);

INT CREATE_PIPES (INT P [], int procs;

INT CREATE_DAEMONS (int P [], int PIDS [], int procs; int

Main (int AC, char ** av)

{

INT I, MAX_PROCS;

Double Overhead = 0;

IF (AC <2) {

USAGE: Printf ("Usage:% s [-s kbytes] processes [Processes ...] / N",

AV [0]);

Exit (1);

}

/ *

* NEED 4 BYTE INTS.

* /

IF (SIZEOF (int)! = 4) {

FPRINTF (stderr, "fix sumit () in ctx.c./n");

Exit (1);

}

/ *

* If The specified a context size, get it.

* /

IF (! Strcmp (AV [1], "-s")) {

IF (AC <4) {

Goto usage;

}

Process_size = ATOI (AV [2]) * 1024;

IF (Process_Size> 0) {

Data = (int *) Calloc (1, Max (Process_Size, Chunk);

Bencho (SUMIT (CHUNK), SUMIT (0), 0);

Overhead = gettime ();

Overhead / = GET_N ();

Overhead * = process_size;

Overhead / = chunk;

}

AC - = 2;

AV = 2;

}

#if Defined (SGI) && Defined (PIN)

NCPUS = SYSMP (MP_nprocs);

SYSMP (MP_MUSTRUN, 0);

#ENDIF

For (Max_Procs = ATOI (AV [1]), i = 1; i

INT procs = atoi (AV [i]);

IF (MAX_PROCS

}

Max_Procs = Create_pipes (p, max_procs);

Overhead = PIPE_COST (p, max_procs);

Max_Procs = CREATE_DAEMONS (P, PIDS, MAX_PROCS);

FPRINTF (stderr, "/ n /" size =% DK OVR =%. 2F / n ", process_size / 1024, overhead);

For (i = 1; i

Double Time;

INT procs = atoi (AV [i]);

IF (Procs> Max_Procs) Continue;

Bench (CTX (Procs, Max_Procs), 0);

Time = USECS_SPENT ();

Time / = GET_N ();

TIME / = procs;

Time / = trips;

Time - = Overhead;

FPRINTF (stderr, "% D% .2f / n", procs, time);

}

/ *

* Close The Pipes and kill the children.

* /

Killem (MAX_PROCS);

For (i = 0; i

Close (p [i] [1]);

IF (i> 0) {

Wait (0);

}

}

Return (0);

}

int

CTX (int procs, int nprocs)

{

Int msg;

INT I;

Int sum;

/ *

* Main Process - All Others Should Be Ready To Roll, Time The

* loop.

* /

For (i = 0; i

IF (Write (P [NPROCS - PROCS] [1], & MSG, SIZEOF (MSG))! =

SizeOf (MSG)) {

PERROR ("Read / Write on Pipe");

Exit (1);

}

IF (read (p [nprocs-1] [0], & msg, sizeof (msg))! = sizeof (msg)) {

PERROR ("Read / Write on Pipe");

Exit (1);

}

SUM = SUMIT (Process_Size);

}

Return (SUM);

}

Void

Killem (int procs)

{

INT I;

For (i = 1; i

IF (PIDS [i]> 0) {

Kill (PIDS [I], SIGTERM;

}

}

}

Void

DOIT (int P [】 [2], int RD, INT WR)

{

INT MSG, SUM = 0 / * LINT * /

Signal (SIGTERM, SIG_DFL);

IF (data) Bzero ((void *) data, process_size);

For (;;) {

IF (read (p [rd], & msg, sizeof (msg))! = SizeOf (msg)) {

PERROR ("Read / Write on Pipe");

Break;

}

SUM = SUMIT (Process_Size);

IF (Write (P [P [WR], & MSG, SIZEOF (MSG))! = SizeOf (MSG)) {

PERROR ("Read / Write on Pipe");

Break;

}

}

USE_INT (SUM);

Exit (1);

}

int

DOIT_COST (int P [】 [2], int procs

{

Static Int K;

INT msg = 1;

INT I;

For (i = 0; i

IF (WRITE (P [K] [1], & MSG, SIZEOF (MSG))! = SizeOf (MSG)) {

PERROR ("Read / Write on Pipe");

Exit (1);

}

IF (read (p [k] [0], & msg, sizeof (msg))! = sizeof (msg)) {

PERROR ("Read / Write on Pipe");

Exit (1);

}

IF ( k == procs) {

K = 0;

}

}

Return (MSG);

}

/ *

* The cost return is the cost of going through one pipe overca.

* No Memory Costs Are Included Here, This Is Different Than Lmbench1. * /

Double

PIPE_COST (int P [】 [2], int procs)

{

Double Result;

/ *

* Measure the overhead of passing a byte arround the ring.

* /

Bench (DOIT_COST (P, Procs), 0);

Result = USECS_SPENT ();

Result / = GET_N ();

Result / = trips;

Return Result;

}

int

Create_daemons (int P [】 [2], int pids [], int procs

{

INT I;

Int msg;

/ *

* Use the pipes as a ring, and fork off a bunch of processes

* to pass the byte through their part of the ring.

*

* Do The Sum in Each Process And Get Time Before Moving ON.

* /

Signal (SIGTERM, SIG_IGN);

For (i = 1; i

Switch (PIDS [i] = fork ()) {

Case -1: / * could Not fork, Out of Processes? * /

procs = i;

Break;

Case 0: / * child * /

#if Defined (SGI) && Defined (PIN)

SYSMP (MP_MUSTRUN, I% NCPUS);

#ENDIF

DOIT (P, I-1, I);

/ * NotReached * /

Default: / * parent * /

;

}

}

/ *

* Go ONCE AROUND THE LOOP To Make Sure That Everyone Is Ready and

* to get the token in the pipeline.

* /

IF (Write (P [0] [1], & MSG, SIZEOF (MSG))! = SizeOf (MSG) ||

Read (p [procs-1], & msg, sizeof (msg))! = SizeOf (MSG)) {

PERROR ("Write / Read / Write on Pipe);

Exit (1);

}

IF (data) Bzero ((void *) data, process_size);

Return procs;

}

int

Create_pipes (int P [】 [2], int procs

{

INT I;

/ *

* Get a bunch of pipes.

* /

Morefds ();

For (i = 0; i

IF (Pipe (P [I]) == -1) {

Return I;

}

}

Return procs;

}

/ *

* Bring hoWMUCH DATA INTO The Cache, Assuming That The smallest cache

* LINE IS 16 bytes.

* /

int

SUMIT (int howmuch)

{

INT DONE, SUM = 0;

Register int * D = data;

#if 0

#define a sum = d [0] D [4] D [8] D [12] D [16] D [20] D [24] D [28] / D [32] D [36] D [40] D [44] D [48] D [52] D [56] D [60] /

D [64] D [68] D [72] D [76] D [80] D [84] D [88] D [92] /

D [96] D [100] D [104] D [108] D [112] D [116] D [120] D [124]; /

D = 128;

#define twokb a a a a a a

#ELSE

#define a sum = d [0] D [1] D [2] D [3] D [4] D [5] D [6] D [7] D [8] D [9] /

D [10] D [11] D [12] D [13] D [14] D [15] D [16] D [17] D [18] D [19] /

D [20] D [21] D [22] D [25] D [26] D [27] D [28] D [29] /

D [30] D [31] D [32] D [33] D [34] D [35] D [36] D [37] D [38] D [39] /

D [40] D [41] D [42] D [43] D [44] D [45] D [46] D [47] D [48] D [49] /

D [50] D [51] D [52] D [53] D [54] D [55] D [56] D [57] D [58] D [59] /

D [60] D [61] D [62] D [63] D [64] D [65] D [66] D [67] D [68] D [69] /

D [70] D [71] D [72] D [73] D [74] D [75] D [76] D [77] D [78] D [79] /

D [80] D [81] D [82] D [83] D [84] D [85] D [86] D [87] D [88] D [89] /

D [90] D [91] D [92] D [93] D [94] D [95] D [96] D [97] D [98] D [99] /

D [100] D [101] D [102] D [103] D [104] /

D [105] D [106] D [107] D [108] D [109] /

D [110] D [111] D [112] D [113] D [114] /

D [115] D [116] D [117] D [118] D [119] /

D [120] D [121] D [122] D [123] D [124] D [125] D [126] D [127]; / D = 128; / * INTS; BYTES == 512 * /

#define twokb a a a a a a

#ENDIF

For (DONE = 0; DONE

Twokb

}

Return (SUM);

}

/ * Bench.h * /

#ifndef _bench_h

#define _bench_h

#ifdef Win32

#include

Typedef unsigned char bool_t;

#ENDIF

#include

#include

#include

#ifndef Win32

#include

#ENDIF

#include

#include

#include

#include

#ifndef Win32

#include

#ENDIF

#include

#ifndef Win32

#include

#ENDIF

#include

#ifndef Win32

#include

#include

#include

#include

#include

#include

#define portmap

#include

#ENDIF

#ifndef Have_uint

Typedef unsigned int uint

#ENDIF

#ifdef Have_UINT64_T

Typedef uint64_t uint64;

#ELSE

TYPEDEF UNSIGNED Long Long uint64;

#ENDIF

#define no_portmapper / * Needs to be up here, lib_ *. h look at it * /

#include "stats.h"

#include "Timing.h"

#include "lib_tcp.h"

#include "lib_udp.h"

#include "lib_unix.h"

#ifdef debug

# Define debug (x) fprintf x

#ELSE

# Define debug (x)

#ENDIF

#ifdef no_portmapper

#define TCP_SELECT-31233

#define tcp_xact -31234

#define TCP_Control -31235

#define tcp_data -31236 # Define TCP_CONNECT -31237

#define udp_xact -31238

#define udp_data -31239

#ELSE

#define tcp_select (u_long) 404038 / * xxx - unregistered * /

#define tcp_xact (u_long) 404039 / * xxx - unregistered * /

#define tcp_control (u_long) 404040 / * xxx - unregistered * /

#define TCP_DATA (U_LONG) 404041 / * XXX - Unregistered * /

#define TCP_CONNECT (U_LONG) 404042 / * xxx - unregistered * /

#define udp_xact (u_long) 404032 / * xxx - unregistered * /

#define udp_data (u_long) 404033 / * xxx - unregistered * /

#define VERS (U_LONG) 1

#ENDIF

#define unix_control "/tmp/lmbench.ctl"

#define unix_data "/tmp/lmbench.data"

#define unix_lat "/tmp/lmbench.lat"

/ *

* Socket Send / Recv Buffer Optimizations

* /

#define sockopt_read 0x0001

#define sockopt_write 0x0002

#define sockopt_rdwr 0x0003

#define sockopt_pid 0x0004

#define sockopt_reuse 0x0008

#define sockopt_none 0

#ifndef sockbuf

#define sockbuf (1024 * 1024)

#ENDIF

#ifndef XFERSIZE

#define XFERSIZE (64 * 1024) / * All Bandwidth I / O SHOULD USE * /

#ENDIF

#if defined (Sys5) || Defined (Win32)

#define Bzero (B, LEN) MEMSET (B, 0, LEN)

#define bcopy (S, D, L) Memcpy (D, S, L)

#define rindex (s, c) Strrchr (s, c)

#ENDIF

#define gettime usecs_spent

#define streq! Strcmp

#define ulong unsigned long

#ifdef use_rand

#define SRAND48 SRAND

#define Drand48 () (Double) RAND () / (double) Rand_max)

#ENDIF

#ifdef use_random

#define SRAND48 SRAND

#define Drand48 () (Double) RAND () / (double) Rand_max)

#ENDIF

#ifdef Win32

#include

#define getpid _getpid

INT getTimeOfDay (struct timeval * tv, struct timezone * tz); # endif

#define smallest_line 32 / * Smallst Cache Line Size * /

#define Time_Open2Close

#define Go_Away Signal (SIGALRM, EXIT); ALARM (60 * 60);

#define real_short 50000

#define Short 1000000

#define Medium 2000000

#define longer 7500000 / * for networking data transfer * /

#define enough real_short

#define Tries 11

Typedef struct {

Int n;

UINT64 U [Tries];

UINT64 N [Tries];

} result_t;

Void insertinit (Result_t * r);

Void insertsort (uint64, uint64, result_t *);

Void save_median ();

Void save_minimum ();

Void Save_Results (Result_t * R);

Void get_results; result_t * r);

#define bencho (loop_body, overhead_body, enough) {/

INT __I, __N; /

Double __oh; /

Result_t __overhead, __r; /

Insertinit (& __ overhead); InsertInit (& __ R); /

__N = (Enough == 0 || GET_ENOUGH (Enough) <= 100000)? Tries: 1; /

IF (Enough

FOR (__i = 0; __i <__n; __ i) {/

Bench1 (Overhead_Body, Enough; /

IF (getTime ()> 0) /

INSERTSORT (GetTime (), get_n (), & __ overhead); /

Bench1 (Loop_Body, Enough; /

IF (getTime ()> 0) /

INSERTSORT (GetTime (), get_n (), & __ r); /

} /

FOR (__i = 0; __i <__r.n; __ i) {/

__oh = __OverHead.u [__ i] / (double) __ overhead.n [__ i]; /

__r.u [__ i] - = (uint64) ((double) __ r.N [__ i] * __oh); /

} / Save_results (& __ r); /

}

#define Bench (loop_body, enough) {/

Long __i, __n; /

Result_t __r; /

Insertinit (& __ r); /

__N = (Enough == 0 || GET_ENOUGH (Enough) <= 100000)? Tries: 1; /

IF (Enough

FOR (__i = 0; __i <__n; __ i) {/

Bench1 (Loop_Body, Enough; /

IF (getTime ()> 0) /

INSERTSORT (GetTime (), get_n (), & __ r); /

} /

Save_Results (& __ r); /

}

#define beench1 (loop_body, enough) {/

Double __Usecs; /

Bench_inner (loop_body, enough); /

__Usecs = getTime (); /

__Usecs - = t_overhead () GET_N () * l_overhead (); /

Settime (__ usecs> = 0.? (uint64) __ @ecs: 0.); /

}

#define bench_inner (loop_body, enough) {/

Static u_long __Item = 1; /

INT __ENOUGH = GET_ENUGH (Enough); /

u_long __n; /

Double __Result = 0 .; /

/

While (__ result <0.95 * __enough) {/

Start (0); /

For (__n = __Ipect); __n> 0; __n--) {/

LOOP_BODY; /

} /

__RESULT = STOP (0, 0); /

IF (__Result <0.99 * __enough /

|| __Result> 1.2 * __enough) {/

IF (__Result> 150.) {/ double tmp = __Items / __RESULT; /

TMP * = 1.1 * __enough; /

__Item = (U_LONG) (TMP 1); /

} else {/

IF (__Iterations> (u_long) 1 << 27) {/

__RESULT = 0 .; /

Break; /

} /

__IpectInces << = 3; /

} /

} /

} / * while * / /

Save_n ((uint64) __ ipiography; settime ((uint64) __ result); /

}

/ *

* Generated from msg.x which is includD here:

Program XACT_PROG {

Version XACT_VERS {

charr

RPC_XACT (CHAR) = 1;

} = 1;

= 3970;

* Please do not edit this file.

* IT WAS generated using rpcgen.

* /

#include

#define XACT_PROG ((u_long) 404040)

#define XACT_VERS ((U_LONG) 1)

#define rpc_xact (u_long) 1)

#define rpc_exit (u_long) 2)

EXTERN CHAR * RPC_XACT_1 ();

EXTERN CHAR * Client_rpc_xact_1 ();

#ENDIF / * _BENCH_H * /

转载请注明原文地址:https://www.9cbs.com/read-125462.html

New Post(0)