性能优化测试工具

1. unixbench 系统微性能

UNIXBENCH也是linux、unix测试系统基准性能的经典工具,UNIXBENCH测试包含了系统调用、读写、进程、2D、3D、管道、运算、C库等系统基准性能,它的优点在于提供了对系统性能的一种评价体系,为系统评分,如此方便对系统作对比测试;但UNIXBENCH在网络性能测试欠缺。

1.1 实验数据

首先需要安装

wget http://soft.vpser.net/test/unixbench/unixbench-5.1.2.tar.gz
tar zxvf unixbench-5.1.2.tar.gz
cd unixbench-5.1.2

然后修改一个地方

vim Makefile

修改为

$(PROGDIR)/ubgears: $(SRCDIR)/ubgears.c
	$(CC) -o $(PROGDIR)/ubgears ${CFLAGS} ${OPTON} $(SRCDIR)/ubgears.c -lm $(GL_LIBS)

然后再make编译一下

make

接下来就可以执行啦

./Run
wanglei@wanglei-PC:~/unixbench/unixbench-5.1.2$ ./Run
make all
make[1]: 进入目录“/home/wanglei/unixbench/unixbench-5.1.2”
Checking distribution of files
./pgms  exists
./src  exists
./testdir  exists
./tmp  exists
./results  exists
make[1]: 离开目录“/home/wanglei/unixbench/unixbench-5.1.2”
sh: 1: 3dinfo: not found

   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.2                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   December 22, 2007                  johantheghost at yahoo period com

Wide character in print at ./Run line 1510.
Wide character in printf at ./Run line 1541.

#测试字符串处理能力(没有浮点操作)
1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

#测试浮点数操作的速度和效率
1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

#测试考察每秒钟可以执行的 execl 系统调用的次数
1 x Execl Throughput  1 2 3

#测试从一个文件向另外一个文件传输数据的速率。
1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

#测试一秒钟内一个进程可以向一个管道写 512 字节数据然后再读回的次数
1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

#测试两个进程(每秒钟)通过一个管道交换一个不断增长的整数的次数
1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

#测试每秒钟一个进程可以创建子进程然后收回子进程的次数(子进程一定立即退出)
1 x Process Creation  1 2 3

#测试进入和离开操作系统内核的代价,即一次系统调用的代价
1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

#测试一秒钟内一个进程可以并发地开始一个shell脚本的n个拷贝的次数(n 一般取值 1,2,4,8)
1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3
Wide character in printf at ./Run line 1483.

12 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

12 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

12 x Execl Throughput  1 2 3

12 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

12 x File Copy 256 bufsize 500 maxblocks  1 2 3

12 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

12 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

12 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

12 x Process Creation  1 2 3

12 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

12 x Shell Scripts (1 concurrent)  1 2 3

12 x Shell Scripts (8 concurrent)  1 2 3
Wide character in printf at ./Run line 1483.

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.2)

   System: wanglei-PC: GNU/Linux
   OS: GNU/Linux -- 5.4.18-35-generic -- #21-KYLINOS SMP Tue Jul 20 13:33:58 UTC 2021
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 1: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 2: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 3: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 4: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 5: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 6: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 7: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 8: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 9: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 10: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 11: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6400.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   11:07:45 up  2:21,  1 user,  load average: 0.52, 0.50, 0.32; runlevel 5

------------------------------------------------------------------------
Benchmark Run: 二 1123 2021 11:07:45 - 11:36:17
12 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       53955535.7 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     8393.0 MWIPS (9.9 s, 7 samples)
Execl Throughput                               4957.7 lps   (29.3 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        706473.5 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          193748.6 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1873394.0 KBps  (30.0 s, 2 samples)
Pipe Throughput                             1102969.5 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 250067.1 lps   (10.0 s, 7 samples)
Process Creation                              15296.1 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                  12389.0 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   6230.8 lpm   (60.0 s, 2 samples)
System Call Overhead                         607934.3 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   53955535.7   4623.4
Double-Precision Whetstone                       55.0       8393.0   1526.0
Execl Throughput                                 43.0       4957.7   1153.0
File Copy 1024 bufsize 2000 maxblocks          3960.0     706473.5   1784.0
File Copy 256 bufsize 500 maxblocks            1655.0     193748.6   1170.7
File Copy 4096 bufsize 8000 maxblocks          5800.0    1873394.0   3230.0
Pipe Throughput                               12440.0    1102969.5    886.6
Pipe-based Context Switching                   4000.0     250067.1    625.2
Process Creation                                126.0      15296.1   1214.0
Shell Scripts (1 concurrent)                     42.4      12389.0   2921.9
Shell Scripts (8 concurrent)                      6.0       6230.8  10384.7
System Call Overhead                          15000.0     607934.3    405.3
                                                                   ========
System Benchmarks Index Score                                        1665.1

------------------------------------------------------------------------
Benchmark Run: 二 1123 2021 11:36:17 - 12:04:48
12 CPUs in system; running 12 parallel copies of tests

Dhrystone 2 using register variables      363650755.8 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                    85771.9 MWIPS (10.3 s, 7 samples)
Execl Throughput                              28408.8 lps   (29.6 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks       1275181.4 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          358031.0 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       4410923.4 KBps  (30.0 s, 2 samples)
Pipe Throughput                             7980067.2 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                1807449.0 lps   (10.0 s, 7 samples)
Process Creation                              95125.1 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                  60549.2 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   7614.8 lpm   (60.0 s, 2 samples)
System Call Overhead                        4087239.8 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0  363650755.8  31161.2
Double-Precision Whetstone                       55.0      85771.9  15594.9
Execl Throughput                                 43.0      28408.8   6606.7
File Copy 1024 bufsize 2000 maxblocks          3960.0    1275181.4   3220.2
File Copy 256 bufsize 500 maxblocks            1655.0     358031.0   2163.3
File Copy 4096 bufsize 8000 maxblocks          5800.0    4410923.4   7605.0
Pipe Throughput                               12440.0    7980067.2   6414.8
Pipe-based Context Switching                   4000.0    1807449.0   4518.6
Process Creation                                126.0      95125.1   7549.6
Shell Scripts (1 concurrent)                     42.4      60549.2  14280.5
Shell Scripts (8 concurrent)                      6.0       7614.8  12691.3
System Call Overhead                          15000.0    4087239.8   2724.8
                                                                   ========
System Benchmarks Index Score                                        7167.5

默认测试完成后测试结果会存放在results目录

wanglei@wanglei-PC:~/unixbench/unixbench-5.1.2/results$ ls
wanglei-PC-2021-11-23-01       wanglei-PC-2021-11-23-01.log
wanglei-PC-2021-11-23-01.html

在OpenEular的机器上

遇到了X11/Xlib.h 和 GL/gl.h:没有那个文件或目录

安装一下缺少的文件

yum install libX* --skip-broken
yum install mesa-libGL-devel mesa-libGLU-devel

测试出来的性能

[root@localhost unixbench-5.1.2]# ./Run 
make all
make[1]: Entering directory '/home/kevin/unixbench-5.1.2'
Checking distribution of files
./pgms  exists
./src  exists
./testdir  exists
./tmp  exists
./results  exists
make[1]: Leaving directory '/home/kevin/unixbench-5.1.2'
sh: 3dinfo: command not found

   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.2                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   December 22, 2007                  johantheghost at yahoo period com

Wide character in print at ./Run line 1510.
Wide character in printf at ./Run line 1541.

1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3
Wide character in printf at ./Run line 1483.

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.2)

   System: localhost.localdomain: GNU/Linux
   OS: GNU/Linux -- 4.19.90-2106.3.0.0095.oe1.x86_64 -- #1 SMP Wed Jun 23 15:18:59 UTC 2021
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: QEMU Virtual CPU version 2.5+ (6384.0 bogomips)
          x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   10:58:16 up 20 min,  1 user,  load average: 0.11, 0.11, 0.07; runlevel 3

------------------------------------------------------------------------
Benchmark Run: 三 1124 2021 10:58:16 - 11:26:16
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       59529711.0 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     8005.9 MWIPS (9.2 s, 7 samples)
Execl Throughput                               5962.1 lps   (29.9 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        573321.5 KBps  (30.0 s, 2 samples)
=> File Copy 256 bufsize 500 maxblocks          135742.4 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1838405.3 KBps  (30.0 s, 2 samples)
=> Pipe Throughput                              804986.8 lps   (10.0 s, 7 samples)
=> Pipe-based Context Switching                 221877.9 lps   (10.0 s, 7 samples)
Process Creation                              14708.9 lps   (30.0 s, 2 samples)
=> Shell Scripts (1 concurrent)                   8151.3 lpm   (60.0 s, 2 samples)
=> Shell Scripts (8 concurrent)                   1106.9 lpm   (60.0 s, 2 samples)
=> System Call Overhead                         443391.9 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   59529711.0   5101.1
Double-Precision Whetstone                       55.0       8005.9   1455.6
Execl Throughput                                 43.0       5962.1   1386.5
File Copy 1024 bufsize 2000 maxblocks          3960.0     573321.5   1447.8
File Copy 256 bufsize 500 maxblocks            1655.0     135742.4    820.2
File Copy 4096 bufsize 8000 maxblocks          5800.0    1838405.3   3169.7
Pipe Throughput                               12440.0     804986.8    647.1
Pipe-based Context Switching                   4000.0     221877.9    554.7
Process Creation                                126.0      14708.9   1167.4
Shell Scripts (1 concurrent)                     42.4       8151.3   1922.5
Shell Scripts (8 concurrent)                      6.0       1106.9   1844.8
System Call Overhead                          15000.0     443391.9    295.6
                                                                   ========
System Benchmarks Index Score                                        1266.4

1.2 参数源码以及含义

src下面有这些文件

wanglei@wanglei-PC:~/unixbench/unixbench-5.1.2/src$ ls
arith.c     dhry_1.c  dummy.c   hanoi.c   spawn.c    time-polling.c
big.c       dhry_2.c  execl.c   looper.c  syscall.c  ubgears.c
context1.c  dhry.h    fstime.c  pipe.c    timeit.c   whets.c

1.2.1 arith.c(*)

char SCCSid[] = "@(#) @(#)arith.c:3.3 -- 5/15/91 19:30:19";
/* 算术测验 */

#include <stdio.h>
#include <stdlib.h>
#include "timeit.c"

int dumb_stuff( int );

unsigned long iter;

/* this function is called when the alarm expires */
void report()
{
    
    
	fprintf( stderr, "COUNT|%ld|1|lps\n", iter );
	exit( 0 );
}

int main( argc, argv )
int argc;
char *argv[];
{
    
    
	int	duration;
	int	result = 0;

	if ( argc != 2 )
	{
    
    
		printf( "Usage: %s duration\n", argv[0] );
		exit( 1 );
	}

	duration = atoi( argv[1] );

	/* set up alarm call */
	iter = 0; /* init iteration count */
	wake_me( duration, report );

	/* this loop will be interrupted by the alarm call */
	while ( 1 )
	{
    
    
		++iter;
		result = dumb_stuff( result );
	}
}


/************************** dumb_stuff *******************/
int dumb_stuff( i )
int i;

{
    
    
#ifndef arithoh
	datum x, y, z;
	z = 0;
#endif

	/* i值始终由循环重置 */
	for ( i = 2; i <= 101; i++ )
	{
    
    
#ifndef arithoh
		x	= i;
		y	= x * x;
		z	+= y / (y - 1);
	}
	return(x + y + z);
#else
	}
	return(0);
#endif
}

1.2.2 context1.c

char SCCSid[] = "@(#) @(#)context1.c:3.3 -- 5/15/91 19:30:18";
/*
 *  Context switching via synchronized unbuffered pipe i/o
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "timeit.c"

unsigned long iter;

void report()
{
    
    
	fprintf(stderr, "COUNT|%lu|1|lps\n", iter);
	exit(0);
}

int main(argc, argv)
int	argc;
char	*argv[];
{
    
    
	int duration;
	unsigned long	check;
	int	p1[2], p2[2];

	if (argc != 2) {
    
    
		fprintf(stderr, "Usage: context duration\n");
		exit(1);
	}

	duration = atoi(argv[1]);

	/* set up alarm call */
	iter = 0;
	wake_me(duration, report);

	if (pipe(p1) || pipe(p2)) {
    
    
		perror("pipe create failed");
		exit(1);
	}

	if (fork()) {
    
    	/* parent process */
		/* master, write p1 & read p2 */
		close(p1[0]); close(p2[1]);
		while (1) {
    
    
			if (write(p1[1], (char *)&iter, sizeof(iter)) != sizeof(iter)) {
    
    
				if ((errno != 0) && (errno != EINTR))
					perror("master write failed");
				exit(1);
			}
			if (read(p2[0], (char *)&check, sizeof(check)) != sizeof(check)) {
    
    
				if ((errno != 0) && (errno != EINTR))
					perror("master read failed");
				exit(1);
			}
			if (check != iter) {
    
    
				fprintf(stderr, "Master sync error: expect %lu, got %lu\n",
					iter, check);
				exit(2);
			}
			iter++;
		}
	}
	else {
    
     /* child process */
		unsigned long iter1;

		iter1 = 0;
		/* slave, read p1 & write p2 */
		close(p1[1]); close(p2[0]);
		while (1) {
    
    
			if (read(p1[0], (char *)&check, sizeof(check)) != sizeof(check)) {
    
    
				if ((errno != 0) && (errno != EINTR))
					perror("slave read failed");
				exit(1);
			}
			if (check != iter1) {
    
    
				fprintf(stderr, "Slave sync error: expect %lu, got %lu\n",
					iter, check);
				exit(2);
			}
			if (write(p2[1], (char *)&iter1, sizeof(iter1)) != sizeof(check)) {
    
    
				if ((errno != 0) && (errno != EINTR))
					perror("slave write failed");
				exit(1);
			}
			iter1++;
		}
	}
}

1.2.3 dhry.h

/* Compiler and system dependent definitions: */

#ifndef TIME
#define TIMES
#endif
                /* Use times(2) time function unless    */
                /* explicitly defined otherwise         */

#ifdef TIMES
#include <sys/types.h>
#include <sys/times.h>
                /* for "times" */
#endif

#define Mic_secs_Per_Second     1000000.0
                /* Berkeley UNIX C returns process times in seconds/HZ */

#ifdef  NOSTRUCTASSIGN
#define structassign(d, s)      memcpy(&(d), &(s), sizeof(d))
#else
#define structassign(d, s)      d = s
#endif

#ifdef  NOENUM
#define Ident_1 0
#define Ident_2 1
#define Ident_3 2
#define Ident_4 3
#define Ident_5 4
  typedef int   Enumeration;
#else
  typedef       enum    {
    
    Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
                Enumeration;
#endif
        /* for boolean and enumeration types in Ada, Pascal */

/* General definitions: */

#include <stdio.h>
                /* for strcpy, strcmp */

#define Null 0 
                /* Value of a Null pointer */
#define true  1
#define false 0

typedef int     One_Thirty;
typedef int     One_Fifty;
typedef char    Capital_Letter;
typedef int     Boolean;
typedef char    Str_30 [3class1];
typedef int     Arr_1_Dim [50];
typedef int     Arr_2_Dim [50] [50];

typedef struct record 
    {
    
    
    struct record *Ptr_Comp;
    Enumeration    Discr;
    union {
    
    
          struct {
    
    
                  Enumeration Enum_Comp;
                  int         Int_Comp;
                  char        Str_Comp [31];
                  } var_1;
          struct {
    
    
                  Enumeration E_Comp_2;
                  char        Str_2_Comp [31];
                  } var_2;
          struct {
    
    
                  char        Ch_1_Comp;
                  char        Ch_2_Comp;
                  } var_3;
          } variant;
      } Rec_Type, *Rec_Pointer;

1.2.4 dhry_1.c

char SCCSid[] = "@(#) @(#)dhry_1.c:3.4 -- 5/15/91 19:30:21";

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dhry.h"
#include "timeit.c"

unsigned long Run_Index;

void report()
{
    
    
	fprintf(stderr,"COUNT|%ld|1|lps\n", Run_Index);
	exit(0);
}

/* Global Variables: */

Rec_Pointer     Ptr_Glob,
                Next_Ptr_Glob;
int             Int_Glob;
Boolean         Bool_Glob;
char            Ch_1_Glob,
                Ch_2_Glob;
int             Arr_1_Glob [50];
int             Arr_2_Glob [50] [50];

Enumeration     Func_1 ();
  /* forward declaration necessary since Enumeration may not simply be int */

#ifndef REG
        Boolean Reg = false;
#define REG
        /* REG becomes defined as empty */
        /* i.e. no register variables   */
#else
        Boolean Reg = true;
#endif

/* variables for time measurement: */

#ifdef TIMES
struct tms      time_info;
extern  int     times ();
                /* see library function "times" */
#define Too_Small_Time 120
                /* Measurements should last at least about 2 seconds */
#endif
#ifdef TIME
extern long     time();
                /* see library function "time"  */
#define Too_Small_Time 2
                /* Measurements should last at least 2 seconds */
#endif

long            Begin_Time,
                End_Time,
                User_Time;
float           Microseconds,
                Dhrystones_Per_Second;

/* end of variables for time measurement */

void Proc_1 (REG Rec_Pointer Ptr_Val_Par);
void Proc_2 (One_Fifty   *Int_Par_Ref);
void Proc_3 (Rec_Pointer *Ptr_Ref_Par);
void Proc_4 (void);
void Proc_5 (void);


extern Boolean Func_2(Str_30, Str_30);
extern void Proc_6(Enumeration, Enumeration *);
extern void Proc_7(One_Fifty, One_Fifty, One_Fifty *);
extern void Proc_8(Arr_1_Dim, Arr_2_Dim, int, int);

int main (argc, argv)
int	argc;
char	*argv[];
  /* main program, corresponds to procedures        */
  /* Main and Proc_0 in the Ada version             */
{
    
    
        int             duration;
        One_Fifty       Int_1_Loc;
  REG   One_Fifty       Int_2_Loc;
        One_Fifty       Int_3_Loc;
  REG   char            Ch_Index;
        Enumeration     Enum_Loc;
        Str_30          Str_1_Loc;
        Str_30          Str_2_Loc;

  /* Initializations */

  Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
  Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));

  Ptr_Glob->Ptr_Comp                    = Next_Ptr_Glob;
  Ptr_Glob->Discr                       = Ident_1;
  Ptr_Glob->variant.var_1.Enum_Comp     = Ident_3;
  Ptr_Glob->variant.var_1.Int_Comp      = 40;
  strcpy (Ptr_Glob->variant.var_1.Str_Comp,
          "DHRYSTONE PROGRAM, SOME STRING");
  strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");

  Arr_2_Glob [8][7] = 10;
        /* Was missing in published program. Without this statement,    */
        /* Arr_2_Glob [8][7] would have an undefined value.             */
        /* Warning: With 16-Bit processors and Number_Of_Runs > 32000,  */
        /* overflow may occur for this array element.                   */

#ifdef PRATTLE
  printf ("\n");
  printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
  printf ("\n");
  if (Reg)
  {
    
    
    printf ("Program compiled with 'register' attribute\n");
    printf ("\n");
  }
  else
  {
    
    
    printf ("Program compiled without 'register' attribute\n");
    printf ("\n");
  }
  printf ("Please give the number of runs through the benchmark: ");
  {
    
    
    int n;
    scanf ("%d", &n);
    Number_Of_Runs = n;
  }
  printf ("\n");

  printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs);
#endif /* PRATTLE */

  if (argc != 2) {
    
    
    fprintf(stderr, "Usage: %s duration\n", argv[0]);
    exit(1);
    }

  duration = atoi(argv[1]);
  Run_Index = 0;
  wake_me(duration, report);

  /***************/
  /* Start timer */
  /***************/

#ifdef SELF_TIMED
#ifdef TIMES
  times (&time_info);
  Begin_Time = (long) time_info.tms_utime;
#endif
#ifdef TIME
  Begin_Time = time ( (long *) 0);
#endif
#endif /* SELF_TIMED */

  for (Run_Index = 1; ; ++Run_Index)
  {
    
    

    Proc_5();
    Proc_4();
      /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
    Int_1_Loc = 2;
    Int_2_Loc = 3;
    strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
    Enum_Loc = Ident_2;
    Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
      /* Bool_Glob == 1 */
    while (Int_1_Loc < Int_2_Loc)  /* loop body executed once */
    {
    
    
      Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
        /* Int_3_Loc == 7 */
      Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
        /* Int_3_Loc == 7 */
      Int_1_Loc += 1;
    } /* while */
      /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
    Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
      /* Int_Glob == 5 */
    Proc_1 (Ptr_Glob);
    for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
                             /* loop body executed twice */
    {
    
    
      if (Enum_Loc == Func_1 (Ch_Index, 'C'))
          /* then, not executed */
        {
    
    
        Proc_6 (Ident_1, &Enum_Loc);
        strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
        Int_2_Loc = Run_Index;
        Int_Glob = Run_Index;
        }
    }
      /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
    Int_2_Loc = Int_2_Loc * Int_1_Loc;
    Int_1_Loc = Int_2_Loc / Int_3_Loc;
    Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
      /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
    Proc_2 (&Int_1_Loc);
      /* Int_1_Loc == 5 */

  } /* loop "for Run_Index" */

  /**************/
  /* Stop timer */
  /**************/
#ifdef SELF_TIMED
#ifdef TIMES
  times (&time_info);
  End_Time = (long) time_info.tms_utime;
#endif
#ifdef TIME
  End_Time = time ( (long *) 0);
#endif
#endif /* SELF_TIMED */

  /* BYTE version never executes this stuff */
#ifdef SELF_TIMED
  printf ("Execution ends\n");
  printf ("\n");
  printf ("Final values of the variables used in the benchmark:\n");
  printf ("\n");
  printf ("Int_Glob:            %d\n", Int_Glob);
  printf ("        should be:   %d\n", 5);
  printf ("Bool_Glob:           %d\n", Bool_Glob);
  printf ("        should be:   %d\n", 1);
  printf ("Ch_1_Glob:           %c\n", Ch_1_Glob);
  printf ("        should be:   %c\n", 'A');
  printf ("Ch_2_Glob:           %c\n", Ch_2_Glob);
  printf ("        should be:   %c\n", 'B');
  printf ("Arr_1_Glob[8]:       %d\n", Arr_1_Glob[8]);
  printf ("        should be:   %d\n", 7);
  printf ("Arr_2_Glob[8][7]:    %d\n", Arr_2_Glob[8][7]);
  printf ("        should be:   Number_Of_Runs + 10\n");
  printf ("Ptr_Glob->\n");
  printf ("  Ptr_Comp:          %d\n", (int) Ptr_Glob->Ptr_Comp);
  printf ("        should be:   (implementation-dependent)\n");
  printf ("  Discr:             %d\n", Ptr_Glob->Discr);
  printf ("        should be:   %d\n", 0);
  printf ("  Enum_Comp:         %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
  printf ("        should be:   %d\n", 2);
  printf ("  Int_Comp:          %d\n", Ptr_Glob->variant.var_1.Int_Comp);
  printf ("        should be:   %d\n", 17);
  printf ("  Str_Comp:          %s\n", Ptr_Glob->variant.var_1.Str_Comp);
  printf ("        should be:   DHRYSTONE PROGRAM, SOME STRING\n");
  printf ("Next_Ptr_Glob->\n");
  printf ("  Ptr_Comp:          %d\n", (int) Next_Ptr_Glob->Ptr_Comp);
  printf ("        should be:   (implementation-dependent), same as above\n");
  printf ("  Discr:             %d\n", Next_Ptr_Glob->Discr);
  printf ("        should be:   %d\n", 0);
  printf ("  Enum_Comp:         %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
  printf ("        should be:   %d\n", 1);
  printf ("  Int_Comp:          %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
  printf ("        should be:   %d\n", 18);
  printf ("  Str_Comp:          %s\n",
                                Next_Ptr_Glob->variant.var_1.Str_Comp);
  printf ("        should be:   DHRYSTONE PROGRAM, SOME STRING\n");
  printf ("Int_1_Loc:           %d\n", Int_1_Loc);
  printf ("        should be:   %d\n", 5);
  printf ("Int_2_Loc:           %d\n", Int_2_Loc);
  printf ("        should be:   %d\n", 13);
  printf ("Int_3_Loc:           %d\n", Int_3_Loc);
  printf ("        should be:   %d\n", 7);
  printf ("Enum_Loc:            %d\n", Enum_Loc);
  printf ("        should be:   %d\n", 1);
  printf ("Str_1_Loc:           %s\n", Str_1_Loc);
  printf ("        should be:   DHRYSTONE PROGRAM, 1'ST STRING\n");
  printf ("Str_2_Loc:           %s\n", Str_2_Loc);
  printf ("        should be:   DHRYSTONE PROGRAM, 2'ND STRING\n");
  printf ("\n");

  User_Time = End_Time - Begin_Time;

  if (User_Time < Too_Small_Time)
  {
    
    
    printf ("Measured time too small to obtain meaningful results\n");
    printf ("Please increase number of runs\n");
    printf ("\n");
  }
  else
  {
    
    
#ifdef TIME
    Microseconds = (float) User_Time * Mic_secs_Per_Second
                        / (float) Number_Of_Runs;
    Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time;
#else
    Microseconds = (float) User_Time * Mic_secs_Per_Second
                        / ((float) HZ * ((float) Number_Of_Runs));
    Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs)
                        / (float) User_Time;
#endif
    printf ("Microseconds for one run through Dhrystone: ");
    printf ("%6.1f \n", Microseconds);
    printf ("Dhrystones per Second:                      ");
    printf ("%6.1f \n", Dhrystones_Per_Second);
    printf ("\n");
  }
#endif /* SELF_TIMED */
}


void Proc_1 (REG Rec_Pointer Ptr_Val_Par)
    /* executed once */
{
    
    
  REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
                                        /* == Ptr_Glob_Next */
  /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp,    */
  /* corresponds to "rename" in Ada, "with" in Pascal           */

  structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
  Ptr_Val_Par->variant.var_1.Int_Comp = 5;
  Next_Record->variant.var_1.Int_Comp
        = Ptr_Val_Par->variant.var_1.Int_Comp;
  Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
  Proc_3 (&Next_Record->Ptr_Comp);
    /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
                        == Ptr_Glob->Ptr_Comp */
  if (Next_Record->Discr == Ident_1)
    /* then, executed */
  {
    
    
    Next_Record->variant.var_1.Int_Comp = 6;
    Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
           &Next_Record->variant.var_1.Enum_Comp);
    Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
    Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
           &Next_Record->variant.var_1.Int_Comp);
  }
  else /* not executed */
    structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
} /* Proc_1 */


void Proc_2 (One_Fifty   *Int_Par_Ref)
    /* executed once */
    /* *Int_Par_Ref == 1, becomes 4 */
{
    
    
  One_Fifty  Int_Loc;
  Enumeration   Enum_Loc;

  Enum_Loc = 0;

  Int_Loc = *Int_Par_Ref + 10;
  do /* executed once */
    if (Ch_1_Glob == 'A')
      /* then, executed */
    {
    
    
      Int_Loc -= 1;
      *Int_Par_Ref = Int_Loc - Int_Glob;
      Enum_Loc = Ident_1;
    } /* if */
  while (Enum_Loc != Ident_1); /* true */
} /* Proc_2 */


void Proc_3 (Rec_Pointer *Ptr_Ref_Par)
    /* executed once */
    /* Ptr_Ref_Par becomes Ptr_Glob */
{
    
    
  if (Ptr_Glob != Null)
    /* then, executed */
    *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
  Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
} /* Proc_3 */


void Proc_4 (void) /* without parameters */
    /* executed once */
{
    
    
  Boolean Bool_Loc;

  Bool_Loc = Ch_1_Glob == 'A';
  Bool_Glob = Bool_Loc | Bool_Glob;
  Ch_2_Glob = 'B';
} /* Proc_4 */

void Proc_5 (void) /* without parameters */
/*******/
    /* executed once */
{
    
    
  Ch_1_Glob = 'A';
  Bool_Glob = false;
} /* Proc_5 */


        /* Procedure for the assignment of structures,          */
        /* if the C compiler doesn't support this feature       */
#ifdef  NOSTRUCTASSIGN
memcpy (d, s, l)
register char   *d;
register char   *s;
register int    l;
{
    
    
        while (l--) *d++ = *s++;
}
#endif

1.2.5 dhry_2.c

/* SCCSid is defined in dhry_1.c */

#include <string.h>
#include "dhry.h"

#ifndef REG
#define REG
        /* REG becomes defined as empty */
        /* i.e. no register variables   */
#endif

extern  int     Int_Glob;
extern  char    Ch_1_Glob;

void Proc_6(Enumeration, Enumeration *);
void Proc_7(One_Fifty, One_Fifty, One_Fifty *);
void Proc_8(Arr_1_Dim, Arr_2_Dim, int, int);
Enumeration Func_1(Capital_Letter, Capital_Letter);
Boolean Func_2(Str_30, Str_30);
Boolean Func_3(Enumeration);

void Proc_6 (Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par)
    /* executed once */
    /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
{
    
    
  *Enum_Ref_Par = Enum_Val_Par;
  if (! Func_3 (Enum_Val_Par))
    /* then, not executed */
    *Enum_Ref_Par = Ident_4;
  switch (Enum_Val_Par)
  {
    
    
    case Ident_1: 
      *Enum_Ref_Par = Ident_1;
      break;
    case Ident_2: 
      if (Int_Glob > 100)
        /* then */
      *Enum_Ref_Par = Ident_1;
      else *Enum_Ref_Par = Ident_4;
      break;
    case Ident_3: /* executed */
      *Enum_Ref_Par = Ident_2;
      break;
    case Ident_4: break;
    case Ident_5: 
      *Enum_Ref_Par = Ident_3;
      break;
  } /* switch */
} /* Proc_6 */

void Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref)
One_Fifty       Int_1_Par_Val;
One_Fifty       Int_2_Par_Val;
One_Fifty      *Int_Par_Ref;
/**********************************************/
    /* executed three times                                      */ 
    /* first call:      Int_1_Par_Val == 2, Int_2_Par_Val == 3,  */
    /*                  Int_Par_Ref becomes 7                    */
    /* second call:     Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
    /*                  Int_Par_Ref becomes 17                   */
    /* third call:      Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
    /*                  Int_Par_Ref becomes 18                   */
{
    
    
  One_Fifty Int_Loc;

  Int_Loc = Int_1_Par_Val + 2;
  *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
} /* Proc_7 */


void Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val)
/*********************************************************************/
    /* executed once      */
    /* Int_Par_Val_1 == 3 */
    /* Int_Par_Val_2 == 7 */
Arr_1_Dim       Arr_1_Par_Ref;
Arr_2_Dim       Arr_2_Par_Ref;
int             Int_1_Par_Val;
int             Int_2_Par_Val;
{
    
    
  REG One_Fifty Int_Index;
  REG One_Fifty Int_Loc;

  Int_Loc = Int_1_Par_Val + 5;
  Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
  Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
  Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
  for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
    Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
  Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
  Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
  Int_Glob = 5;
} /* Proc_8 */


Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
/*************************************************/
    /* executed three times                                         */
    /* first call:      Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R'    */
    /* second call:     Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C'    */
    /* third call:      Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C'    */
{
    
    
  Capital_Letter        Ch_1_Loc;
  Capital_Letter        Ch_2_Loc;

  Ch_1_Loc = Ch_1_Par_Val;
  Ch_2_Loc = Ch_1_Loc;
  if (Ch_2_Loc != Ch_2_Par_Val)
    /* then, executed */
    return (Ident_1);
  else  /* not executed */
  {
    
    
    Ch_1_Glob = Ch_1_Loc;
    return (Ident_2);
   }
} /* Func_1 */



Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref)
/*************************************************/
    /* executed once */
    /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
    /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */

Str_30  Str_1_Par_Ref;
Str_30  Str_2_Par_Ref;
{
    
    
  REG One_Thirty        Int_Loc;
      Capital_Letter    Ch_Loc;

  Ch_Loc = 'A';
  Int_Loc = 2;
  while (Int_Loc <= 2) /* loop body executed once */
    if (Func_1 (Str_1_Par_Ref[Int_Loc],
                Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
      /* then, executed */
    {
    
    
      Ch_Loc = 'A';
      Int_Loc += 1;
    } /* if, while */
  if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
    /* then, not executed */
    Int_Loc = 7;
  if (Ch_Loc == 'R')
    /* then, not executed */
    return (true);
  else /* executed */
  {
    
    
    if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
      /* then, not executed */
    {
    
    
      Int_Loc += 7;
      Int_Glob = Int_Loc;
      return (true);
    }
    else /* executed */
      return (false);
  } /* if Ch_Loc */
} /* Func_2 */


Boolean Func_3 (Enum_Par_Val)
/***************************/
    /* executed once        */
    /* Enum_Par_Val == Ident_3 */
Enumeration Enum_Par_Val;
{
    
    
  Enumeration Enum_Loc;

  Enum_Loc = Enum_Par_Val;
  if (Enum_Loc == Ident_3)
    /* then, executed */
    return (true);
  else /* not executed */
    return (false);
} /* Func_3 */

1.2.6 dummy.c

char SCCSid[] = "@(#) @(#)dummy.c:3.3 -- 5/15/91 19:30:19";

#include <stdio.h>
#include <signal.h>

#define DEF_RATE	5.0
#define GRANULE		5
#define CHUNK		60
#define MAXCHILD	12
#define MAXWORK		10

float	thres;
float	est_rate = DEF_RATE;
int	nusers;                 /* number of concurrent users to be simulated by this process */
int firstuser;                  /* ordinal identification of first user for this process */
int	nwork		= 0;    /* number of job streams */
int	exit_status	= 0;    /* returned to parent */
int	sigpipe;                /* pipe write error flag */

struct st_work {
    
    
	char *cmd;           /* name of command to run */
	char **av;           /* arguments to command */
	char *input;         /* standard input buffer */
	int	inpsize;        /* size of standard input buffer */
} work[MAXWORK];

struct {
    
    
	int	xmit;           /* # characters sent */
	char	*bp;            /* std input buffer pointer */
	int	blen;           /* std input buffer length */
	int	fd;             /* stdin to command */
	int	pid;            /* child PID */
	char *line;          /* start of input line */
	int	firstjob;       /* inital piece of work */
	int	thisjob;        /* current piece of work */
} child[MAXCHILD], *cp;

main( argc, argv )
int argc;
char *argv[];
{
    
    
	int	i;
	int	l;
	int	fcopy	= 0;    /* fd for copy output */
	int	master	= 1;    /* the REAL master, == 0 for clones */
	int	nchild;         /* no. of children for a clone to run */
	int	done;           /* count of children finished */
	int	output;         /* aggregate output char count for all children */
	int	c;
	int	thiswork = 0;   /* next job stream to allocate */
	int	nch;            /* # characters to write */
	int	written;        /* # characters actully written */
	char logname[15];    /* name of the log file(s) */
	void onalarm( void );
	void pipeerr( void );
	void wrapup( void );
	void grunt( void );
	char *malloc();

	int	pvec[2];        /* for pipes */
	char *p;
	char *prog;          /* my name */

#if !debug
	freopen( "masterlog.00", "a", stderr );
#endif
	fprintf( stderr, "*** New Run ***  " );
	prog = argv[0];
	while ( argc > 1 && argv[1][0] == '-' )
	{
    
    
		p = &argv[1][1];
		argc--;
		argv++;
		while ( *p )
		{
    
    
			switch ( *p )
			{
    
    
			case 'r':
				/* code DELETED here */
				argc--;
				argv++;
				break;

			case 'c':
				/* code DELETED here */
				lseek( fcopy, 0L, 2 ); /* append at end of file */
				break;

			default:
				fprintf( stderr, "%s: bad flag '%c'\n", prog, *p );
				exit( 4 );
			}
			p++;
		}
	}

	if ( argc < 2 )
	{
    
    
		fprintf( stderr, "%s: missing nusers\n", prog );
		exit( 4 );
	}

	nusers = atoi( argv[1] );
	if ( nusers < 1 )
	{
    
    
		fprintf( stderr, "%s: impossible nusers (%d<-%s)\n", prog, nusers, argv[1] );
		exit( 4 );
	}
	fprintf( stderr, "%d Users\n", nusers );
	argc--;
	argv++;

	/* build job streams */
	getwork();
#if debug
	dumpwork();
#endif

	/* clone copies of myself to run up to MAXCHILD jobs each */
	firstuser = MAXCHILD;
	fprintf( stderr, "master pid %d\n", getpid() );
	fflush( stderr );
	while ( nusers > MAXCHILD )
	{
    
    
		fflush( stderr );
		if ( nusers >= 2 * MAXCHILD )
			/* the next clone must run MAXCHILD jobs */
			nchild = MAXCHILD;
		else
			/* the next clone must run the leftover jobs */
			nchild = nusers - MAXCHILD;
		if ( (l = fork() ) == -1 )
		{
    
    
			/* fork failed */
			fatal( "** clone fork failed **\n" );
			goto bepatient;
		} else if ( l > 0 )
		{
    
    
			fprintf( stderr, "master clone pid %d\n", l );
			/* I am the master with nchild fewer jobs to run */
			nusers		-= nchild;
			firstuser	+= MAXCHILD;
			continue;
		} else {
    
    
			/* I am a clone, run MAXCHILD jobs */
#if !debug
			sprintf( logname, "masterlog.%02d", firstuser / MAXCHILD );
			freopen( logname, "w", stderr );
#endif
			master	= 0;
			nusers	= nchild;
			break;
		}
	}
	if ( master )
		firstuser = 0;

	close( 0 );

	/* code DELETED here */

	fflush( stderr );

	srand( time( 0 ) );
	thres	= 0;
	done	= output = 0;
	for ( i = 0; i < nusers; i++ )
	{
    
    
		if ( child[i].blen == 0 )
			done++;
		else
			thres += est_rate * GRANULE;
	}
	est_rate = thres;

	signal( SIGALRM, onalarm );
	signal( SIGPIPE, pipeerr );
	alarm( GRANULE );
	while ( done < nusers )
	{
    
    
		for ( i = 0; i < nusers; i++ )
		{
    
    
			cp = &child[i];
			if ( cp->xmit >= cp->blen )
				continue;
			l = rand() % CHUNK + 1; /* 1-CHUNK chars */
			if ( l == 0 )
				continue;
			if ( cp->xmit + l > cp->blen )
				l = cp->blen - cp->xmit;
			p		= cp->bp;
			cp->bp		+= l;
			cp->xmit	+= l;
#if debug
			fprintf( stderr, "child %d, %d processed, %d to go\n", i, cp->xmit, cp->blen - cp->xmit );
#endif
			while ( p < cp->bp )
			{
    
    
				if ( *p == '\n' || (p == &cp->bp[-1] && cp->xmit >= cp->blen) )
				{
    
    
					/* write it out */
					nch = p - cp->line + 1;
					if ( (written = write( cp->fd, cp->line, nch ) ) != nch )
					{
    
    
						/* code DELETED here */
					}
					if ( fcopy )
						write( fcopy, cp->line, p - cp->line + 1 );
#if debug
					fprintf( stderr, "child %d gets \"", i );
					{
    
    
						char *q = cp->line;
						while ( q <= p )
						{
    
    
							if ( *q >= ' ' && *q <= '~' )
								fputc( *q, stderr );
							else
								fprintf( stderr, "\\%03o", *q );
							q++;
						}
					}
					fputc( '"', stderr );
#endif
					cp->line = &p[1];
				}
				p++;
			}
			if ( cp->xmit >= cp->blen )
			{
    
    
				done++;
				close( cp->fd );
#if debug
				fprintf( stderr, "child %d, close std input\n", i );
#endif
			}
			output += l;
		}
		while ( output > thres )
		{
    
    
			pause();
#if debug
			fprintf( stderr, "after pause: output, thres, done %d %.2f %d\n", output, thres, done );
#endif
		}
	}

bepatient:
	alarm( 0 );
	/* code DELETED here */
}

onalarm()
{
    
    
	thres += est_rate;
	signal( SIGALRM, onalarm );
	alarm( GRANULE );
}

grunt()
{
    
    
	/* timeout after label "bepatient" in main */
	exit_status = 4;
	wrapup();
}

pipeerr()
{
    
    
	sigpipe++;
}

wrapup()
{
    
    
	/* DUMMY, real code dropped */
}

getwork()
{
    
    
	/* DUMMY, real code dropped */
	gets();
	strncpy();
	malloc(); realloc();
	open(); close();
}

fatal( s )
char *s;
{
    
    
	int i;
	fprintf( stderr, s );
	fflush( stderr );
	perror( "Reason?" );
	for ( i = 0; i < nusers; i++ )
	{
    
    
		if ( child[i].pid > 0 && kill( child[i].pid, SIGKILL ) != -1 )
			fprintf( stderr, "pid %d killed off\n", child[i].pid );
	}
	fflush( stderr );
	exit_status = 4;
	return;
}

1.2.7 fstime.c

char SCCSid[] = "@(#) @(#)fstime.c:3.5 -- 5/15/91 19:30:19";

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>

#define SECONDS 10

#define MAX_BUFSIZE 8192

/* This must be set to the smallest BUFSIZE or 1024, whichever is smaller */
#define COUNTSIZE 256
#define HALFCOUNT (COUNTSIZE/2)         /* Half of COUNTSIZE */

#define FNAME0  "dummy0"
#define FNAME1  "dummy1"

extern void sync(void);

int w_test(int timeSecs);
int r_test(int timeSecs);
int c_test(int timeSecs);

long read_score = 1, write_score = 1, copy_score = 1;

/****************** GLOBALS ***************************/

/* The buffer size for the tests. */
int bufsize = 1024;

/*
 * The max number of 1024-byte blocks in the file.
 * Don't limit it much, so that memory buffering
 * can be overcome.
 */
int max_blocks = 2000;

/* The max number of BUFSIZE blocks in the file. */
int max_buffs = 2000;

/* Countable units per 1024 bytes */
int count_per_k;

/* Countable units per bufsize */
int count_per_buf;

/* The actual buffer. */
/* char *buf = 0; */
/* Let's carry on using a static buffer for this, like older versions
 * of the code did.  It turns out that if you use a malloc buffer,
 * it goes 50% slower on reads, when using a 4k buffer -- at least on
 * my OpenSUSE 10.2 system.
 * What up wit dat?
 */
char buf[MAX_BUFSIZE];

int                     f;
int                     g;
int                     i;
void                    stop_count();
void                    clean_up();
int                     sigalarm = 0;

/******************** MAIN ****************************/

int main(argc, argv)
int     argc;
char    *argv[];
{
    
    
    /* The number of seconds to run for. */
    int                     seconds = SECONDS;

    /* The type of test to run. */
    char test = 'c';

    int status;
    int i;

    for (i = 1; i < argc; ++i) {
    
    
        if (argv[i][0] == '-') {
    
    
            switch (argv[i][1]) {
    
    
                case 'c':
                case 'r':
                case 'w':
                    test = argv[i][1];
                    break;
                case 'b':
                    bufsize = atoi(argv[++i]);
                    break;
                case 'm':
                    max_blocks = atoi(argv[++i]);
                    break;
                case 't':
                    seconds = atoi(argv[++i]);
                    break;
                case 'd':
                    if (chdir(argv[++i]) < 0) {
    
    
                        perror("fstime: chdir");
                        exit(1);
                    }
                    break;
                default:
                    fprintf(stderr, "Usage: fstime [-c|-r|-w] [-b <bufsize>] [-m <max_blocks>] [-t <seconds>]\n");
                    exit(2);
            }
        } else {
    
    
            fprintf(stderr, "Usage: fstime [-c|-r|-w] [-b <bufsize>] [-m <max_blocks>] [-t <seconds>]\n");
            exit(2);
        }
    }

    if (bufsize < COUNTSIZE || bufsize > MAX_BUFSIZE) {
    
    
        fprintf(stderr, "fstime: buffer size must be in range %d-%d\n",
                COUNTSIZE, 1024*1024);
        exit(3);
    }
    if (max_blocks < 1 || max_blocks > 1024*1024) {
    
    
        fprintf(stderr, "fstime: max blocks must be in range %d-%d\n",
                1, 1024*1024);
        exit(3);
    }
    if (seconds < 1 || seconds > 3600) {
    
    
        fprintf(stderr, "fstime: time must be in range %d-%d seconds\n",
                1, 3600);
        exit(3);
    }

    max_buffs = max_blocks * 1024 / bufsize;
    count_per_k = 1024 / COUNTSIZE;
    count_per_buf = bufsize / COUNTSIZE;

    /*
    if ((buf = malloc(bufsize)) == 0) {
        fprintf(stderr, "fstime: failed to malloc %d bytes\n", bufsize);
        exit(4);
    }
    */

    if((f = creat(FNAME0, 0600)) == -1) {
    
    
            perror("fstime: creat");
            exit(1);
    }
    close(f);

    if((g = creat(FNAME1, 0600)) == -1) {
    
    
            perror("fstime: creat");
            exit(1);
    }
    close(g);

    if( (f = open(FNAME0, 2)) == -1) {
    
    
            perror("fstime: open");
            exit(1);
    }
    if( ( g = open(FNAME1, 2)) == -1 ) {
    
    
            perror("fstime: open");
            exit(1);
    }

    /* fill buffer */
    for (i=0; i < bufsize; ++i)
            buf[i] = i & 0xff;

    signal(SIGKILL,clean_up);

    /*
     * Run the selected test.
     * When I got here, this program ran full 30-second tests for
     * write, read, and copy, outputting the results for each.  BUT
     * only the copy results are actually used in the benchmark index.
     * With multiple iterations and three sets of FS tests, that amounted
     * to about 10 minutes of wasted time per run.
     *
     * So, I've made the test selectable.  Except that the read and write
     * passes are used to create the test file and calibrate the rates used
     * to tweak the results of the copy test.  So, for copy tests, we do
     * a few seconds of write and read to prime the pump.
     *
     * Note that this will also pull the file into the FS cache on any
     * modern system prior to the copy test.  Whether this is good or
     * bad is a matter of perspective, but it's how it was when I got
     * here.
     *
     * Ian Smith <johantheghost at yahoo period com> 21 Sep 2007
     */
    switch (test) {
    
    
    case 'w':
        status = w_test(seconds);
        break;
    case 'r':
        w_test(2);
        status = r_test(seconds);
        break;
    case 'c':
        w_test(2);
        r_test(2);
        status = c_test(seconds);
        break;
    default:
        fprintf(stderr, "fstime: unknown test \'%c\'\n", test);
        exit(6);
    }
    if (status) {
    
    
        clean_up();
        exit(1);
    }

    clean_up();
    exit(0);
}


static double getFloatTime()
{
    
    
        struct timeval t;

        gettimeofday(&t, 0);
        return (double) t.tv_sec + (double) t.tv_usec / 1000000.0;
}


/*
 * Run the write test for the time given in seconds.
 */
int w_test(int timeSecs)
{
    
    
        unsigned long counted = 0L;
        unsigned long tmp;
        long f_blocks;
        double start, end;
        extern int sigalarm;

        /* Sync and let it settle */
        sync();
        sleep(2);
        sync();
        sleep(2);

        /* Set an alarm. */
        sigalarm = 0;
        signal(SIGALRM, stop_count);
        alarm(timeSecs);

        start = getFloatTime();

        while (!sigalarm) {
    
    
                for(f_blocks=0; f_blocks < max_buffs; ++f_blocks) {
    
    
                        if ((tmp=write(f, buf, bufsize)) != bufsize) {
    
    
                                if (errno != EINTR) {
    
    
                                        perror("fstime: write");
                                        return(-1);
                                }
                                stop_count();
                                counted += ((tmp+HALFCOUNT)/COUNTSIZE);
                        } else
                                counted += count_per_buf;
                }
                lseek(f, 0L, 0); /* rewind */
        }

        /* stop clock */
        end = getFloatTime();
        write_score = (long) ((double) counted / ((end - start) * count_per_k));
        printf("Write done: %ld in %.4f, score %ld\n",
                            counted, end - start, write_score);

        /*
         * Output the test results. Use the true time.
         */
        fprintf(stderr, "COUNT|%ld|0|KBps\n", write_score);
        fprintf(stderr, "TIME|%.1f\n", end - start);

        return(0);
}

/*
 * Run the read test for the time given in seconds.
 */
int r_test(int timeSecs)
{
    
    
        unsigned long counted = 0L;
        unsigned long tmp;
        double start, end;
        extern int sigalarm;
        extern int errno;

        /* Sync and let it settle */
        sync();
        sleep(2);
        sync();
        sleep(2);

        /* rewind */
        errno = 0;
        lseek(f, 0L, 0);

        /* Set an alarm. */
        sigalarm = 0;
        signal(SIGALRM, stop_count);
        alarm(timeSecs);

        start = getFloatTime();

        while (!sigalarm) {
    
    
                /* read while checking for an error */
                if ((tmp=read(f, buf, bufsize)) != bufsize) {
    
    
                        switch(errno) {
    
    
                        case 0:
                        case EINVAL:
                                lseek(f, 0L, 0);  /* rewind at end of file */
                                counted += (tmp+HALFCOUNT)/COUNTSIZE;
                                continue;
                        case EINTR:
                                stop_count();
                                counted += (tmp+HALFCOUNT)/COUNTSIZE;
                                break;
                        default:
                                perror("fstime: read");
                                return(-1);
                                break;
                        }
                } else
                        counted += count_per_buf;
        }

        /* stop clock */
        end = getFloatTime();
        read_score = (long) ((double) counted / ((end - start) * count_per_k));
        printf("Read done: %ld in %.4f, score %ld\n",
                            counted, end - start, read_score);

        /*
         * Output the test results. Use the true time.
         */
        fprintf(stderr, "COUNT|%ld|0|KBps\n", read_score);
        fprintf(stderr, "TIME|%.1f\n", end - start);

        return(0);
}


/*
 * Run the copy test for the time given in seconds.
 */
int c_test(int timeSecs)
{
    
    
        unsigned long counted = 0L;
        unsigned long tmp;
        double start, end;
        extern int sigalarm;

        sync();
        sleep(2);
        sync();
        sleep(1);

        /* rewind */
        errno = 0;
        lseek(f, 0L, 0);

        /* Set an alarm. */
        sigalarm = 0;
        signal(SIGALRM, stop_count);
        alarm(timeSecs);

        start = getFloatTime();

        while (!sigalarm) {
    
    
                if ((tmp=read(f, buf, bufsize)) != bufsize) {
    
    
                        switch(errno) {
    
    
                        case 0:
                        case EINVAL:
                                lseek(f, 0L, 0);  /* rewind at end of file */
                                lseek(g, 0L, 0);  /* rewind the output too */
                                continue;
                        case EINTR:
                                /* part credit for leftover bytes read */
                                counted += ( (tmp * write_score) /
                                        (read_score + write_score)
                                        + HALFCOUNT) / COUNTSIZE;
                                stop_count();
                                break;
                        default:
                                perror("fstime: copy read");
                                return(-1);
                                break;
                        }
                } else  {
    
    
                        if ((tmp=write(g, buf, bufsize)) != bufsize) {
    
    
                                if (errno != EINTR) {
    
    
                                        perror("fstime: copy write");
                                        return(-1);
                                }
                                counted += (
                                 /* Full credit for part of buffer written */
                                        tmp +

                                 /* Plus part credit having read full buffer */
                                        ( ((bufsize - tmp) * write_score) /
                                        (read_score + write_score) )
                                        + HALFCOUNT) / COUNTSIZE;
                                stop_count();
                        } else
                                counted += count_per_buf;
                }
        }

        /* stop clock */
        end = getFloatTime();
        copy_score = (long) ((double) counted / ((end - start) * count_per_k));
        printf("Copy done: %ld in %.4f, score %ld\n",
                            counted, end - start, copy_score);

        /*
         * Output the test results. Use the true time.
         */
        fprintf(stderr, "COUNT|%ld|0|KBps\n", copy_score);
        fprintf(stderr, "TIME|%.1f\n", end - start);

        return(0);
}

void stop_count(void)
{
    
    
        extern int sigalarm;
        sigalarm = 1;
}

void clean_up(void)
{
    
    
        unlink(FNAME0);
        unlink(FNAME1);
}

1.2.8 looper.c(*)

char SCCSid[] = "@(#) @(#)looper.c:1.4 -- 5/15/91 19:30:22";
/* Shell进程创建 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include "timeit.c"

unsigned long iter;

char	*cmd_argv[28];
int	cmd_argc;

void report( void )
{
    
    
	fprintf( stderr, "COUNT|%lu|60|lpm\n", iter );
	exit( 0 );
}


int main( argc, argv )
int argc;


char *argv[];
{
    
    
	int	slave, count, duration;
	int	status;

	if ( argc < 2 )
	{
    
    
		fprintf( stderr, "Usage: %s duration command [args..]\n", argv[0] );
		fprintf( stderr, "  duration in seconds\n" );
		exit( 1 );
	}

	if ( (duration = atoi( argv[1] ) ) < 1 )
	{
    
    
		fprintf( stderr, "Usage: %s duration command [arg..]\n", argv[0] );
		fprintf( stderr, "  duration in seconds\n" );
		exit( 1 );
	}

	/* get command  */
	cmd_argc = argc - 2;
	for ( count = 2; count < argc; ++count )
		cmd_argv[count - 2] = argv[count];
    
#ifdef DEBUG
	printf( "<<%s>>", cmd_argv[0] );
	for ( count = 1; count < cmd_argc; ++count )
		printf( " <%s>", cmd_argv[count] );
	putchar( '\n' );
	exit( 0 );
#endif
	
    iter = 0;
	wake_me( duration, report );
	while ( 1 )
	{
    
    
		if ( (slave = fork() ) == 0 )
		{
    
    
			/* 命令执行 */
			execvp( cmd_argv[0], cmd_argv );
			exit( 99 );
		} else if ( slave < 0 )
		{
    
    
			/* woops ... */
			fprintf( stderr, "Fork failed at iteration %lu\n", iter );
			perror( "Reason" );
			exit( 2 );
		} else
			/* master */
			wait( &status );
		
        //判断执行状态
        if ( status == 99 << 8 )
		{
    
    
			fprintf( stderr, "Command \"%s\" didn't exec\n", cmd_argv[0] );
			exit( 2 );
		} else if ( status != 0 )
		{
    
    
			fprintf( stderr, "Bad wait status: 0x%x\n", status );
			exit( 2 );
		}
		iter++;
	}
}

1.2.9 spawn.c

char SCCSid[] = "@(#) @(#)spawn.c:3.3 -- 5/15/91 19:30:20";
/*
 *  Process creation
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include "timeit.c"

unsigned long iter;

void report()
{
    
    
	fprintf(stderr,"COUNT|%lu|1|lps\n", iter);
	exit(0);
}

int main(argc, argv)
int	argc;
char	*argv[];
{
    
    
	int	slave, duration;
	int	status;

	if (argc != 2) {
    
    
		fprintf(stderr,"Usage: %s duration \n", argv[0]);
		exit(1);
	}

	duration = atoi(argv[1]);

	iter = 0;
	wake_me(duration, report);

	while (1) {
    
    
		if ((slave = fork()) == 0) {
    
    
			/* slave .. boring */
#if debug
			printf("fork OK\n");
#endif
			/* kill it right away */
			exit(0);
		} else if (slave < 0) {
    
    
			/* woops ... */
			fprintf(stderr,"Fork failed at iteration %lu\n", iter);
			perror("Reason");
			exit(2);
		} else
			/* master */
			wait(&status);
		if (status != 0) {
    
    
			fprintf(stderr,"Bad wait status: 0x%x\n", status);
			exit(2);
		}
		iter++;
#if debug
		printf("Child %d done.\n", slave);
#endif
		}
}

1.2.10 timeit.c

/* 此模块包含在其他模块中——没有单独的SCCS ID*/
// 定时程序
#include <signal.h>
#include <unistd.h>

void wake_me(seconds, func)
	int seconds;
	void (*func)();
{
    
    
	/* 设置信号处理程序 */
	signal(SIGALRM, func);
	/* 运行时钟 */
	alarm(seconds);
}

1.2.11 ubgears.c

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <sys/time.h>
#include <sched.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#ifndef M_PI
#define M_PI 3.14159265
#endif /* !M_PI */

/* Turn a NULL pointer string into an empty string */
#define NULLSTR(x) (((x)!=NULL)?(x):(""))
#define Log(x) {
      
       if(verbose) printf x; }
#define Msg(x) {
      
       printf x; }

/* Globla vars */
/* program name (from argv[0]) */
static const char *ProgramName;

/* verbose output what the program is doing */
static Bool  verbose = False;

/* time in microseconds to run for; -1 means forever. */
static int   runTime = -1;

/* Time at which start_time(void) was called. */
static struct timeval clockStart;

/* XXX this probably isn't very portable */

/* return current time (in seconds) */
static void
start_time(void)
{
    
    
   (void) gettimeofday(&clockStart, 0);
}

/*
 * return time (in microseconds) since start_time(void) was called.
 *
 * The older version of this function randomly returned negative results.
 * This version won't, up to 2000 seconds and some.
 */
static long
current_time(void)
{
    
    
   struct timeval tv;
   long secs, micros;

   (void) gettimeofday(&tv, 0);

   secs = tv.tv_sec - clockStart.tv_sec;
   micros = tv.tv_usec - clockStart.tv_usec;
   if (micros < 0) {
    
    
       --secs;
       micros += 1000000;
   }
   return secs * 1000000 + micros;
}

static
void usage(void)
{
    
    
   fprintf (stderr, "usage:  %s [options]\n", ProgramName);
   fprintf (stderr, "-display\tSet X11 display for output.\n");
   fprintf (stderr, "-info\t\tPrint additional GLX information.\n");
   fprintf (stderr, "-time t\t\tRun for t seconds and report performance.\n");
   fprintf (stderr, "-h\t\tPrint this help page.\n");
   fprintf (stderr, "-v\t\tVerbose output.\n");
   fprintf (stderr, "\n");
   exit(EXIT_FAILURE);
}


static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
static GLint gear1, gear2, gear3;
static GLfloat angle = 0.0;
static GLint speed = 60;
static GLboolean printInfo = GL_FALSE;

/*
 *
 *  Draw a gear wheel.  You'll probably want to call this function when
 *  building a display list since we do a lot of trig here.
 *
 *  Input:  inner_radius - radius of hole at center
 *          outer_radius - radius at center of teeth
 *          width - width of gear
 *          teeth - number of teeth
 *          tooth_depth - depth of tooth
 */
static void
gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
     GLint teeth, GLfloat tooth_depth)
{
    
    
   GLint i;
   GLfloat r0, r1, r2, maxr2, minr2;
   GLfloat angle, da;
   GLfloat u, v, len;

   r0 = inner_radius;
   r1 = outer_radius - tooth_depth / 2.0;
   maxr2 = r2 = outer_radius + tooth_depth / 2.0;
   minr2 = r2;

   da = 2.0 * M_PI / teeth / 4.0;

   glShadeModel(GL_FLAT);

   glNormal3f(0.0, 0.0, 1.0);

   /* draw front face */
   glBegin(GL_QUAD_STRIP);
   for (i = 0; i <= teeth; i++) {
    
    
      angle = i * 2.0 * M_PI / teeth;
      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
      if (i < teeth) {
    
    
         glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
         glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
                    width * 0.5);
      }
   }
   glEnd();

   /* draw front sides of teeth */
   glBegin(GL_QUADS);
   for (i = 0; i < teeth; i++) {
    
    
      angle = i * 2.0 * M_PI / teeth;

      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
                 width * 0.5);
      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
                 width * 0.5);
      r2 = minr2;
   }
   r2 = maxr2;
   glEnd();

   glNormal3f(0.0, 0.0, -1.0);

   /* draw back face */
   glBegin(GL_QUAD_STRIP);
   for (i = 0; i <= teeth; i++) {
    
    
      angle = i * 2.0 * M_PI / teeth;
      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
      if (i < teeth) {
    
    
         glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
                    -width * 0.5);
         glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
      }
   }
   glEnd();

   /* draw back sides of teeth */
   glBegin(GL_QUADS);
   da = 2.0 * M_PI / teeth / 4.0;
   for (i = 0; i < teeth; i++) {
    
    
      angle = i * 2.0 * M_PI / teeth;

      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
                 -width * 0.5);
      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
                 -width * 0.5);
      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
      r2 = minr2;
   }
   r2 = maxr2;
   glEnd();

   /* draw outward faces of teeth */
   glBegin(GL_QUAD_STRIP);
   for (i = 0; i < teeth; i++) {
    
    
      angle = i * 2.0 * M_PI / teeth;

      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
      u = r2 * cos(angle + da) - r1 * cos(angle);
      v = r2 * sin(angle + da) - r1 * sin(angle);
      len = sqrt(u * u + v * v);
      u /= len;
      v /= len;
      glNormal3f(v, -u, 0.0);
      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
      glNormal3f(cos(angle + 1.5 * da), sin(angle + 1.5 * da), 0.0);
      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
                 width * 0.5);
      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
                 -width * 0.5);
      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
      glNormal3f(v, -u, 0.0);
      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
                 width * 0.5);
      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
                 -width * 0.5);
      glNormal3f(cos(angle + 3.5 * da), sin(angle + 3.5 * da), 0.0);
      r2 = minr2;
   }
   r2 = maxr2;

   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);

   glEnd();

   glShadeModel(GL_SMOOTH);

   /* draw inside radius cylinder */
   glBegin(GL_QUAD_STRIP);
   for (i = 0; i <= teeth; i++) {
    
    
      angle = i * 2.0 * M_PI / teeth;
      glNormal3f(-cos(angle), -sin(angle), 0.0);
      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
   }
   glEnd();
}


static void
draw(void)
{
    
    
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   glPushMatrix();
   glRotatef(view_rotx, 1.0, 0.0, 0.0);
   glRotatef(view_roty, 0.0, 1.0, 0.0);
   glRotatef(view_rotz, 0.0, 0.0, 1.0);

   glPushMatrix();
   glTranslatef(-3.0, -2.0, 0.0);
   glRotatef(angle, 0.0, 0.0, 1.0);
   glCallList(gear1);
   glPopMatrix();

   glPushMatrix();
   glTranslatef(3.1, -2.0, 0.0);
   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
   glCallList(gear2);
   glPopMatrix();

   glPushMatrix();
   glTranslatef(-3.1, 4.2, 0.0);
   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
   glCallList(gear3);
   glPopMatrix();

   glPopMatrix();
}


/* new window size or exposure */
static void
reshape(int width, int height)
{
    
    
   GLfloat h = (GLfloat) height / (GLfloat) width;

   glViewport(0, 0, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   /* fit width and height */
   if (h >= 1.0)
     glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
   else
     glFrustum(-1.0/h, 1.0/h, -1.0, 1.0, 5.0, 60.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glTranslatef(0.0, 0.0, -40.0);
}


static void
init(void)
{
    
    
   static GLfloat pos[4] = {
    
     5.0, 5.0, 10.0, 0.0 };
   static GLfloat red[4] = {
    
     0.8, 0.1, 0.0, 1.0 };
   static GLfloat green[4] = {
    
     0.0, 0.8, 0.2, 1.0 };
   static GLfloat blue[4] = {
    
     0.2, 0.2, 1.0, 1.0 };

   glLightfv(GL_LIGHT0, GL_POSITION, pos);
   glEnable(GL_CULL_FACE);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_DEPTH_TEST);

   /* make the gears */
   gear1 = glGenLists(1);
   glNewList(gear1, GL_COMPILE);
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
   gear(1.0, 4.0, 1.0, 20, 0.7);
   glEndList();

   gear2 = glGenLists(1);
   glNewList(gear2, GL_COMPILE);
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
   gear(0.5, 2.0, 2.0, 10, 0.7);
   glEndList();

   gear3 = glGenLists(1);
   glNewList(gear3, GL_COMPILE);
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
   gear(1.3, 2.0, 0.5, 10, 0.7);
   glEndList();

   glEnable(GL_NORMALIZE);
}


/*
 * Create an RGB, double-buffered window.
 * Return the window and context handles.
 */
static void
make_window( Display *dpy, Screen *scr,
             const char *name,
             int x, int y, int width, int height,
             Window *winRet, GLXContext *ctxRet)
{
    
    
   int attrib[] = {
    
     GLX_RGBA,
                   GLX_RED_SIZE, 1,
                   GLX_GREEN_SIZE, 1,
                   GLX_BLUE_SIZE, 1,
                   GLX_DOUBLEBUFFER,
                   GLX_DEPTH_SIZE, 1,
                   None };
   int scrnum;
   XSetWindowAttributes attr;
   unsigned long mask;
   Window root;
   Window win;
   GLXContext ctx;
   XVisualInfo *visinfo;
   GLint max[2] = {
    
     0, 0 };

   scrnum = XScreenNumberOfScreen(scr);
   root   = XRootWindow(dpy, scrnum);

   visinfo = glXChooseVisual( dpy, scrnum, attrib );
   if (!visinfo) {
    
    
      fprintf(stderr, "%s: Error: couldn't get an RGB, Double-buffered visual.\n", ProgramName);
      exit(EXIT_FAILURE);
   }

   /* window attributes */
   attr.background_pixel = 0;
   attr.border_pixel = 0;
   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;

   win = XCreateWindow( dpy, root, x, y, width, height,
                       0, visinfo->depth, InputOutput,
                       visinfo->visual, mask, &attr );

   /* set hints and properties */
   {
    
    
      XSizeHints sizehints;
      sizehints.x = x;
      sizehints.y = y;
      sizehints.width  = width;
      sizehints.height = height;
      sizehints.flags = USSize | USPosition;
      XSetNormalHints(dpy, win, &sizehints);
      XSetStandardProperties(dpy, win, name, name,
                              None, (char **)NULL, 0, &sizehints);
   }

   ctx = glXCreateContext( dpy, visinfo, NULL, True );
   if (!ctx) {
    
    
      fprintf(stderr, "%s: Error: glXCreateContext failed.\n", ProgramName);
      exit(EXIT_FAILURE);
   }

   XFree(visinfo);

   XMapWindow(dpy, win);
   glXMakeCurrent(dpy, win, ctx);

   /* Check for maximum size supported by the GL rasterizer */
   glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max);
   if (printInfo)
      printf("GL_MAX_VIEWPORT_DIMS=%d/%d\n", (int)max[0], (int)max[1]);
   if (width > max[0] || height > max[1]) {
    
    
      fprintf(stderr, "%s: Error: Requested window size (%d/%d) larger than "
              "maximum supported by GL engine (%d/%d).\n",
              ProgramName, width, height, (int)max[0], (int)max[1]);
      exit(EXIT_FAILURE);
   }

   *winRet = win;
   *ctxRet = ctx;
}

static void
event_loop(Display *dpy, Window win)
{
    
    
   while (1) {
    
    
      /* Process interactive events */
      while (XPending(dpy) > 0) {
    
    
         XEvent event;
         XNextEvent(dpy, &event);
         switch (event.type) {
    
    
         case Expose:
            Log(("Event: Expose\n"));
            /* we'll redraw below */
            break;
         case ConfigureNotify:
            Log(("Event: ConfigureNotify\n"));
            reshape(event.xconfigure.width, event.xconfigure.height);
            break;
         }
      }

      {
    
    
         /* Time at which we started measuring. */
         static long startTime = 0;

         /* Time of the previous frame. */
         static long lastFrame = 0;

         /* Time of the previous FPS report. */
         static long lastFps = 0;

         /* Number of frames we've done. */
         static int frames = 0;

         /* Number of frames we've done in the measured run. */
         static long runFrames = 0;

         long t = current_time();
         long useconds;

         if (!lastFrame)
            lastFrame = t;
         if (!lastFps)
            lastFps = t;

         /* How many microseconds since the previous frame? */
         useconds = t - lastFrame;
         if (!useconds) /* assume 100FPS if we don't have timer */
            useconds = 10000;

         /* Calculate how far the gears need to move and redraw. */
         angle = angle + ((double)speed * useconds) / 1000000.0;
         if (angle > 360.0)
            angle = angle - 360.0; /* don't lose precision! */
         draw();
         glXSwapBuffers(dpy, win);

         /* Done this frame. */
         lastFrame = t;
         frames++;

         /* Every 5 seconds, print the FPS. */
         if (t - lastFps >= 5000000L) {
    
    
            GLfloat seconds = (t - lastFps) / 1000000.0;
            GLfloat fps = frames / seconds;

            printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
                   fps);
            lastFps = t;
            frames = 0;

            /*
             * Set the start time now -- ie. after one report.  This
             * gives us pump-priming time before we start for real.
             */
            if (runTime > 0 && startTime == 0) {
    
    
                printf("Start timing!\n");
                startTime = t;
            }
         }

         if (startTime > 0)
             ++runFrames;

         /* If our run time is done, finish. */
         if (runTime > 0 && startTime > 0 && t - startTime > runTime) {
    
    
             double time = (double) (t - startTime) / 1000000.0;
             fprintf(stderr, "COUNT|%ld|1|fps\n", runFrames);
             fprintf(stderr, "TIME|%.1f\n", time);
             exit(0);
         }

         /* Need to give cpu away in order to get precise timing next cycle,
          * otherwise, gettimeofday would return almost the same value. */
         sched_yield();
      }
   }
}


int
main(int argc, char *argv[])
{
    
    
   Bool           use_threadsafe_api = False;
   Display       *dpy;
   Window         win;
   Screen        *screen;
   GLXContext     ctx;
   char          *dpyName            = NULL;
   int            i;
   XRectangle     winrect;

   ProgramName = argv[0];

   for (i = 1; i < argc; i++) {
    
    
      const char *arg = argv[i];
      int         len = strlen(arg);

      if (strcmp(argv[i], "-display") == 0) {
    
    
         if (++i >= argc)
            usage();
         dpyName = argv[i];
      }
      else if (strcmp(argv[i], "-info") == 0) {
    
    
         printInfo = GL_TRUE;
      }
      else if (strcmp(argv[i], "-time") == 0) {
    
    
         if (++i >= argc)
            usage();
         runTime = atoi(argv[i]) * 1000000;
      }
      else if (!strncmp("-v", arg, len)) {
    
    
         verbose   = True;
         printInfo = GL_TRUE;
      }
      else if( !strncmp("-debug_use_threadsafe_api", arg, len) )
      {
    
    
         use_threadsafe_api = True;
      }
      else if (!strcmp(argv[i], "-h")) {
    
    
         usage();
      }
      else
      {
    
    
        fprintf(stderr, "%s: Unsupported option '%s'.\n", ProgramName, argv[i]);
        usage();
      }
   }

   /* Init X threading API on demand (for debugging) */
   if( use_threadsafe_api )
   {
    
    
      if( !XInitThreads() )
      {
    
    
         fprintf(stderr, "%s: XInitThreads() failure.\n", ProgramName);
         exit(EXIT_FAILURE);
      }
   }

   dpy = XOpenDisplay(dpyName);
   if (!dpy) {
    
    
      fprintf(stderr, "%s: Error: couldn't open display '%s'\n", ProgramName, dpyName);
      return EXIT_FAILURE;
   }

   screen = XDefaultScreenOfDisplay(dpy);

   winrect.x      = 0;
   winrect.y      = 0;
   winrect.width  = 300;
   winrect.height = 300;

   Log(("Window x=%d, y=%d, width=%d, height=%d\n",
       (int)winrect.x, (int)winrect.y, (int)winrect.width, (int)winrect.height));

   make_window(dpy, screen, "ubgears", winrect.x, winrect.y, winrect.width, winrect.height, &win, &ctx);
   reshape(winrect.width, winrect.height);

   if (printInfo) {
    
    
      printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
      printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
      printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
      printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
   }

   init();

   start_time();
   event_loop(dpy, win);

   glXDestroyContext(dpy, ctx);

   XDestroyWindow(dpy, win);
   XCloseDisplay(dpy);

   return EXIT_SUCCESS;
}

1.2.12 big.c

/* this code is included in other files and therefore has no SCCSid */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys/wait.h>


#define DEF_RATE	5.0
#define GRANULE		5
#define CHUNK		60
#define MAXCHILD	12
#define MAXWORK		10

/* Can't seem to get this declared in the headers... */
extern int kill(pid_t pid, int sig);

void	wrapup(char *);
void	onalarm(int);
void	pipeerr();
void	grunt();
void getwork(void);
#if debug
void dumpwork(void);
#endif
void fatal(char *s);

float	thres;
float	est_rate = DEF_RATE;
int	nusers;		/* number of concurrent users to be simulated by
			 * this process */
int	firstuser;	/* ordinal identification of first user for this
			 * process */
int	nwork = 0;	/* number of job streams */
int	exit_status = 0;	/* returned to parent */
int	sigpipe;	/* pipe write error flag */

struct st_work {
    
    
	char	*cmd;		/* name of command to run */
	char	**av;		/* arguments to command */
	char	*input;		/* standard input buffer */
	int	inpsize;	/* size of standard input buffer */
	char	*outf;		/* standard output (filename) */
} work[MAXWORK];

struct {
    
    
	int	xmit;	/* # characters sent */
	char	*bp;	/* std input buffer pointer */
	int	blen;	/* std input buffer length */
	int	fd;	/* stdin to command */
	int	pid;	/* child PID */
	char	*line;	/* start of input line */
	int	firstjob;	/* inital piece of work */
	int	thisjob;	/* current piece of work */
} child[MAXCHILD], *cp;

int main(argc, argv)
int	argc;
char	*argv[];
{
    
    
    int		i;
    int		l;
    int		fcopy = 0;	/* fd for copy output */
    int		master = 1;	/* the REAL master, == 0 for clones */
    int		nchild;		/* no. of children for a clone to run */
    int		done;		/* count of children finished */
    int		output;		/* aggregate output char count for all
				   children */
    int		c;
    int		thiswork = 0;	/* next job stream to allocate */
    int		nch;		/* # characters to write */
    int		written;	/* # characters actully written */
    char	logname[15];	/* name of the log file(s) */
    int		pvec[2];	/* for pipes */
    char	*p;
    char	*prog;		/* my name */

#if ! debug
    freopen("masterlog.00", "a", stderr);
#endif
    prog = argv[0];
    while (argc > 1 && argv[1][0] == '-')  {
    
    
	p = &argv[1][1];
	argc--;
	argv++;
	while (*p) {
    
    
	    switch (*p) {
    
    
	    case 'r':
			est_rate = atoi(argv[1]);
			sscanf(argv[1], "%f", &est_rate);
			if (est_rate <= 0) {
    
    
			    fprintf(stderr, "%s: bad rate, reset to %.2f chars/sec\n", prog, DEF_RATE);
			    est_rate = DEF_RATE;
			}
			argc--;
			argv++;
			break;

	    case 'c':
			fcopy = open(argv[1], 1);
			if (fcopy < 0)
				fcopy = creat(argv[1], 0600);
			if (fcopy < 0) {
    
    
			    fprintf(stderr, "%s: cannot open copy file '%s'\n",
				prog, argv[1]);
			    exit(2);
			}
			lseek(fcopy, 0L, 2);	/* append at end of file */
			argc--;
			argv++;
			break;

	    default:
		fprintf(stderr, "%s: bad flag '%c'\n", prog, *p);
			exit(4);
	    }
	    p++;
	}
    }

    if (argc < 2) {
    
    
	fprintf(stderr, "%s: missing nusers\n", prog);
	exit(4);
    }

    nusers = atoi(argv[1]);
    if (nusers < 1) {
    
    
	fprintf(stderr, "%s: impossible nusers (%d<-%s)\n", prog, nusers, argv[1]);
	exit(4);
    }
    fprintf(stderr, "%d Users\n", nusers);
    argc--;
    argv++;

    /* build job streams */
    getwork();
#if debug
    dumpwork();
#endif

    /* clone copies of myself to run up to MAXCHILD jobs each */
    firstuser = MAXCHILD;
    fprintf(stderr, "master pid %d\n", getpid());
    fflush(stderr);
    while (nusers > MAXCHILD) {
    
    
	fflush(stderr);
	if (nusers >= 2*MAXCHILD)
	    /* the next clone must run MAXCHILD jobs */
	    nchild = MAXCHILD;
	else
	    /* the next clone must run the leftover jobs */
	    nchild = nusers - MAXCHILD;
	if ((l = fork()) == -1) {
    
    
	    /* fork failed */
	    fatal("** clone fork failed **\n");
	    goto bepatient;
	} else if (l > 0) {
    
    
	    fprintf(stderr, "master clone pid %d\n", l);
	    /* I am the master with nchild fewer jobs to run */
	    nusers -= nchild;
	    firstuser += MAXCHILD;
	    continue;
	} else {
    
    
	    /* I am a clone, run MAXCHILD jobs */
#if ! debug
	    sprintf(logname, "masterlog.%02d", firstuser/MAXCHILD);
	    freopen(logname, "w", stderr);
#endif
	    master = 0;
	    nusers = nchild;
	    break;
	}
    }
    if (master)
	firstuser = 0;

    close(0);
    for (i = 0; i < nusers; i++ ) {
    
    
	fprintf(stderr, "user %d job %d ", firstuser+i, thiswork);
	if (pipe(pvec) == -1) {
    
    
	    /* this is fatal */
	    fatal("** pipe failed **\n");
	    goto bepatient;
	}
	fflush(stderr);
	if ((child[i].pid = fork()) == 0) {
    
    
	    int	fd;
	    /* the command */
	    if (pvec[0] != 0) {
    
    
		close(0);
		dup(pvec[0]);
	    }
#if ! debug
	    sprintf(logname, "userlog.%02d", firstuser+i);
	    freopen(logname, "w", stderr);
#endif
	    for (fd = 3; fd < 24; fd++)
		close(fd);
	    if (work[thiswork].outf[0] != '\0') {
    
    
		/* redirect std output */
		char	*q;
		for (q = work[thiswork].outf; *q != '\n'; q++) ;
		*q = '\0';
		if (freopen(work[thiswork].outf, "w", stdout) == NULL) {
    
    
		    fprintf(stderr, "makework: cannot open %s for std output\n",
			work[thiswork].outf);
		    fflush(stderr);
		}
		*q = '\n';
	    }
	    execv(work[thiswork].cmd, work[thiswork].av);
	    /* don't expect to get here! */
	    fatal("** exec failed **\n");
	    goto bepatient;
	}
	else if (child[i].pid == -1) {
    
    
	    fatal("** fork failed **\n");
	    goto bepatient;
	}
	else {
    
    
	    close(pvec[0]);
	    child[i].fd = pvec[1];
	    child[i].line = child[i].bp = work[thiswork].input;
	    child[i].blen = work[thiswork].inpsize;
	    child[i].thisjob = thiswork;
	    child[i].firstjob = thiswork;
	    fprintf(stderr, "pid %d pipe fd %d", child[i].pid, child[i].fd);
	    if (work[thiswork].outf[0] != '\0') {
    
    
		char *q;
		fprintf(stderr, " > ");
		for (q=work[thiswork].outf; *q != '\n'; q++)
		    fputc(*q, stderr);
	    }
	    fputc('\n', stderr);
	    thiswork++;
	    if (thiswork >= nwork)
		thiswork = 0;
	}
    }
    fflush(stderr);

    srand(time(0));
    thres = 0;
    done = output = 0;
    for (i = 0; i < nusers; i++) {
    
    
	if (child[i].blen == 0)
	    done++;
	else
	    thres += est_rate * GRANULE;
    }
    est_rate = thres;

    signal(SIGALRM, onalarm);
    signal(SIGPIPE, pipeerr);
    alarm(GRANULE);
    while (done < nusers) {
    
    
	for (i = 0; i < nusers; i++) {
    
    
	    cp = &child[i];
	    if (cp->xmit >= cp->blen) continue;
	    l = rand() % CHUNK + 1;	/* 1-CHUNK chars */
	    if (l == 0) continue;
	    if (cp->xmit + l > cp->blen)
		l = cp->blen - cp->xmit;
	    p = cp->bp;
	    cp->bp += l;
	    cp->xmit += l;
#if debug
	    fprintf(stderr, "child %d, %d processed, %d to go\n", i, cp->xmit, cp->blen - cp->xmit);
#endif
	    while (p < cp->bp) {
    
    
		if (*p == '\n' || (p == &cp->bp[-1] && cp->xmit >= cp->blen)) {
    
    
		    /* write it out */
		    nch = p - cp->line + 1;
		    if ((written = write(cp->fd, cp->line, nch)) != nch) {
    
    
			/* argh! */
			cp->line[nch] = '\0';
			fprintf(stderr, "user %d job %d cmd %s ",
				firstuser+i, cp->thisjob, cp->line);
 			fprintf(stderr, "write(,,%d) returns %d\n", nch, written);
			if (sigpipe)
			    fatal("** SIGPIPE error **\n");
			else
			    fatal("** write error **\n");
			goto bepatient;

		    }
		    if (fcopy)
			write(fcopy, cp->line, p - cp->line + 1);
#if debug
		    fprintf(stderr, "child %d gets \"", i);
		    {
    
    
			char *q = cp->line;
			while (q <= p) {
    
    
				if (*q >= ' ' && *q <= '~')
					fputc(*q, stderr);
				else
					fprintf(stderr, "\\%03o", *q);
				q++;
			}
		    }
		    fputc('"', stderr);
#endif
		    cp->line = &p[1];
		}
		p++;
	    }
	    if (cp->xmit >= cp->blen) {
    
    
		done++;
		close(cp->fd);
#if debug
	fprintf(stderr, "child %d, close std input\n", i);
#endif
	    }
	    output += l;
	}
	while (output > thres) {
    
    
	    pause();
#if debug
	    fprintf(stderr, "after pause: output, thres, done %d %.2f %d\n", output, thres, done);
#endif
	}
    }

bepatient:
    alarm(0);
/****
 *  If everything is going OK, we should simply be able to keep
 *  looping unitil 'wait' fails, however some descendent process may
 *  be in a state from which it can never exit, and so a timeout
 *  is used.
 *  5 minutes should be ample, since the time to run all jobs is of
 *  the order of 5-10 minutes, however some machines are painfully slow,
 *  so the timeout has been set at 20 minutes (1200 seconds).
 ****/
    signal(SIGALRM, grunt);
    alarm(1200);
    while ((c = wait(&l)) != -1) {
    
    
        for (i = 0; i < nusers; i++) {
    
    
	    if (c == child[i].pid) {
    
    
		fprintf(stderr, "user %d job %d pid %d done", firstuser+i, child[i].thisjob, c);
		if (l != 0) {
    
    
		    if (l & 0x7f)
			fprintf(stderr, " status %d", l & 0x7f);
		    if (l & 0xff00)
			fprintf(stderr, " exit code %d", (l>>8) & 0xff);
		    exit_status = 4;
		}
		fputc('\n', stderr);
		c = child[i].pid = -1;
		break;
	    }
	}
	if (c != -1) {
    
    
	    fprintf(stderr, "master clone done, pid %d ", c);
	    if (l != 0) {
    
    
		if (l & 0x7f)
		    fprintf(stderr, " status %d", l & 0x7f);
		if (l & 0xff00)
		    fprintf(stderr, " exit code %d", (l>>8) & 0xff);
		exit_status = 4;
	    }
	    fputc('\n', stderr);
	}
    }
    alarm(0);
    wrapup("Finished waiting ...");

    exit(0);
}

void onalarm(int foo)
{
    
    
    thres += est_rate;
    signal(SIGALRM, onalarm);
    alarm(GRANULE);
}

void grunt()
{
    
    
    /* timeout after label "bepatient" in main */
    exit_status = 4;
    wrapup("Timed out waiting for jobs to finish ...");
}

void pipeerr()
{
    
    
	sigpipe++;
}

void wrapup(char *reason)
{
    
    
    int i;
    int killed = 0;
    fflush(stderr);
    for (i = 0; i < nusers; i++) {
    
    
	if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) {
    
    
	    if (!killed) {
    
    
		killed++;
		fprintf(stderr, "%s\n", reason);
		fflush(stderr);
	    }
	    fprintf(stderr, "user %d job %d pid %d killed off\n", firstuser+i, child[i].thisjob, child[i].pid);
	fflush(stderr);
	}
    }
    exit(exit_status);
}

#define MAXLINE 512
void getwork(void)
{
    
    
    int			i;
    int			f;
    int			ac=0;
    char		*lp = (void *)0;
    char		*q = (void *)0;
    struct st_work	*w = (void *)0;
    char		line[MAXLINE];
    char		c;

    while (fgets(line, MAXLINE, stdin) != NULL) {
    
    
	if (nwork >= MAXWORK) {
    
    
	    fprintf(stderr, "Too many jobs specified, .. increase MAXWORK\n");
	    exit(4);
	}
	w = &work[nwork];
	lp = line;
	i = 1;
	while (*lp && *lp != ' ') {
    
    
	    i++;
	    lp++;
	}
	w->cmd = (char *)malloc(i);
	strncpy(w->cmd, line, i-1);
	w->cmd[i-1] = '\0';
	w->inpsize = 0;
	w->input = "";
	/* start to build arg list */
	ac = 2;
	w->av = (char **)malloc(2*sizeof(char *));
	q = w->cmd;
	while (*q) q++;
	q--;
	while (q >= w->cmd) {
    
    
	    if (*q == '/') {
    
    
		q++;
		break;
	    }
	    q--;
	}
	w->av[0] = q;
	while (*lp) {
    
    
	    if (*lp == ' ') {
    
    
		/* space */
		lp++;
		continue;
	    }
	    else if (*lp == '<') {
    
    
		/* standard input for this job */
		q = ++lp;
		while (*lp && *lp != ' ') lp++;
		c = *lp;
		*lp = '\0';
		if ((f = open(q, 0)) == -1) {
    
    
		    fprintf(stderr, "cannot open input file (%s) for job %d\n",
				q, nwork);
		    exit(4);
		}
		/* gobble input */
		w->input = (char *)malloc(512);
		while ((i = read(f, &w->input[w->inpsize], 512)) > 0) {
    
    
		    w->inpsize += i;
		    w->input = (char *)realloc(w->input, w->inpsize+512);
		}
		w->input = (char *)realloc(w->input, w->inpsize);
		close(f);
		/* extract stdout file name from line beginning "C=" */
		w->outf = "";
		for (q = w->input; q < &w->input[w->inpsize-10]; q++) {
    
    
		    if (*q == '\n' && strncmp(&q[1], "C=", 2) == 0) {
    
    
			w->outf = &q[3];
			break;
		    }
		}
#if debug
		if (*w->outf) {
    
    
		    fprintf(stderr, "stdout->");
		    for (q=w->outf; *q != '\n'; q++)
			fputc(*q, stderr);
		    fputc('\n', stderr);
		}
#endif
	    }
	    else {
    
    
		/* a command option */
		ac++;
		w->av = (char **)realloc(w->av, ac*sizeof(char *));
		q = lp;
		i = 1;
		while (*lp && *lp != ' ') {
    
    
		    lp++;
		    i++;
		}
		w->av[ac-2] = (char *)malloc(i);
		strncpy(w->av[ac-2], q, i-1);
		w->av[ac-2][i-1] = '\0';
	    }
	}
	w->av[ac-1] = (char *)0;
	nwork++;
    }
}

#if debug
void dumpwork(void)
{
    
    
    int		i;
    int		j;

    for (i = 0; i < nwork; i++) {
    
    
	fprintf(stderr, "job %d: cmd: %s\n", i, work[i].cmd);
	j = 0;
	while (work[i].av[j]) {
    
    
		fprintf(stderr, "argv[%d]: %s\n", j, work[i].av[j]);
		j++;
	}
	fprintf(stderr, "input: %d chars text: ", work[i].inpsize);
	if (work[i].input == (char *)0)
		fprintf(stderr, "<NULL>\n");
	else {
    
    
	        register char	*pend;
	        char		*p;
		char		c;
		p = work[i].input;
		while (*p) {
    
    
			pend = p;
			while (*pend && *pend != '\n')
				pend++;
			c = *pend;
			*pend = '\0';
			fprintf(stderr, "%s\n", p);
			*pend = c;
			p = &pend[1];
		}
	}
    }
}
#endif

void fatal(char *s)
{
    
    
    int	i;
    fprintf(stderr, s);
    fflush(stderr);
    perror("Reason?");
    fflush(stderr);
    for (i = 0; i < nusers; i++) {
    
    
	if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) {
    
    
	    fprintf(stderr, "pid %d killed off\n", child[i].pid);
	    fflush(stderr);
	}
    }
    exit_status = 4;
}

1.2.13 execl.c(*)

// 每秒execl函数调用次数
char SCCSid[] = "@(#) @(#)execl.c:3.3 -- 5/15/91 19:30:19";

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

char bss[8 * 1024];     /* something worthwhile */

#define main dummy
#include "big.c"        /* some real code */
#undef main

/* added by BYTE */
char *getenv();

int main( argc, argv ) /* the real program */
int argc;
char *argv[];
{
    
    
	unsigned long	iter = 0;
	char		*ptr;
	char		*fullpath;
	int		duration;
	char		count_str[12], start_str[24], path_str[256], *dur_str;
	time_t		start_time, this_time;

#ifdef DEBUG
	int count;
	for ( count = 0; count < argc; ++count )
		printf( "%s ", argv[count] );
	printf( "\n" );
#endif
	
    if ( argc < 2 )
	{
    
    
		fprintf( stderr, "Usage: %s duration\n", argv[0] );
		exit( 1 );
	}


	duration = atoi( argv[1] );
	if ( duration > 0 )
	/* 首次调用 */
	{
    
    
		dur_str = argv[1];
        // getenv(name) 搜索 name 所指向的环境字符串,并返回相关的值给字符串
		if ( (ptr = getenv( "UB_BINDIR" ) ) != NULL )
			sprintf( path_str, "%s/execl", ptr );
		fullpath = path_str;
		time( &start_time );
	}
    else   
    {
    
     /* 其中一个执行的调用 */
		/* real duration follow the phoney null duration */
		duration	= atoi( argv[2] );
		dur_str		= argv[2];
		iter		= (unsigned long) atoi( argv[3] );      /* where are we now ? */
		sscanf( argv[4], "%lu", (unsigned long *) &start_time );
		fullpath = argv[0];
	}

	sprintf( count_str, "%lu", ++iter );                            /* execl计数器自增 */
	sprintf( start_str, "%lu", (unsigned long) start_time );
	time( &this_time );
	
    if ( this_time - start_time >= duration )                       /* 超时了 */
	{
    
    
		fprintf( stderr, "COUNT|%lu|1|lps\n", iter );
		exit( 0 );
	}
	
    // execl("/bin/ls", "ls", "-al", "/etc/passwd", (char *)0);
    // int execl(const char * path, const char * arg, ...) 用来执行参数path 字符串所代表的文件路径
    execl( fullpath, fullpath, "0", dur_str, count_str, start_str, (void *) 0 );
	fprintf( stderr, "Exec failed at iteration %lu\n", iter );
	perror( "Reason" );
	exit( 1 );
}

1.2.14 hanoi.c(*)

汉诺塔算法

char SCCSid[] = "@(#) @(#)hanoi.c:3.3 -- 5/15/91 19:30:20";

#define other(i,j) (6-(i+j))

#include <stdio.h>
#include <stdlib.h>
#include "timeit.c"

void mov(int n, int f, int t);

unsigned long iter = 0;
int num[4];
long cnt;

void report()
{
    
    
	fprintf(stderr,"COUNT|%ld|1|lps\n", iter);
	exit(0);
}


int main(argc, argv)
int	argc;
char	*argv[];
{
    
    
	int disk=10, /* default number of disks */
         duration;

	if (argc < 2) {
    
    
		fprintf(stderr,"Usage: %s duration [disks]\n", argv[0]);
		exit(1);
		}
	duration = atoi(argv[1]);
	if(argc > 2) disk = atoi(argv[2]);
	num[1] = disk;

	wake_me(duration, report);

	while(1) {
    
    
		mov(disk,1,3);
		iter++;
	}

	exit(0);
}

void mov(int n, int f, int t)//运用了递归的思想
{
    
    
	int o;
	if(n == 1) {
    
    
		num[f]--;
		num[t]++;
		return;
	}
	o = other(f,t);
	mov(n-1,f,o);
	mov(1,f,t);
	mov(n-1,o,t);
}

1.2.15 pipe.c(*)

char SCCSid[] = "@(#) @(#)pipe.c:3.3 -- 5/15/91 19:30:20";
// 测试单进程管道吞吐量(无上下文切换)

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "timeit.c"

unsigned long iter;

void report()
{
    
    
	fprintf(stderr,"COUNT|%ld|1|lps\n", iter);
	exit(0);
}

int main(argc, argv)
int	argc;
char	*argv[];
{
    
    
	char	buf[512];
	int		pvec[2], duration;

	if (argc != 2) {
    
    
		fprintf(stderr,"Usage: %s duration\n", argv[0]);
		exit(1);
	}

	duration = atoi(argv[1]);

    /*  pipe()会建立管道,并将文件描述词由参数 pvec 数组返回。
     *  filedes[0]为管道里的读取端,所以pipe用read调用的
     *  filedes[1]则为管道的写入端。
     */
	pipe(pvec);

	wake_me(duration, report);
	iter = 0;

	while (1) {
    
    
        //对pipe管道进行读写
		if (write(pvec[1], buf, sizeof(buf)) != sizeof(buf)) {
    
    
			if ((errno != EINTR) && (errno != 0))
				fprintf(stderr,"write failed, error %d\n", errno);
		}
		if (read(pvec[0], buf, sizeof(buf)) != sizeof(buf)) {
    
    
			if ((errno != EINTR) && (errno != 0))
				fprintf(stderr,"read failed, error %d\n", errno);
		}
		iter++;
	}
}

1.2.16 syscall.c(*)

// 循环调用系统call
char SCCSid[] = "@(#) @(#)syscall.c:3.3 -- 5/15/91 19:30:21";

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "timeit.c"

unsigned long iter;

void report()
{
    
    
	/* 发送格式化输出到流 stream 中 */
	fprintf( stderr, "COUNT|%ld|1|lps\n", iter );
	exit( 0 );
}


int main( argc, argv )
int argc;       /* 参数数量 */
char *argv[];   /* 具体的参数 */
{
    
    
	char	*test;
	int	duration;

	if ( argc < 2 )
	{
    
    
		fprintf( stderr, "Usage: %s duration [ test ]\n", argv[0] );
		fprintf( stderr, "test is one of:\n" );
		fprintf( stderr, "  \"mix\" (default), \"close\", \"getpid\", \"exec\"\n" );
		exit( 1 );
	}
	if ( argc > 2 )
		test = argv[2];
	else
		test = "mix";

	/* 字符串转换成整型数 */
	duration = atoi( argv[1] );

	iter = 0;
    /* 定义在timeit.c里面 */
	wake_me( duration, report );

	switch ( test[0] )
	{
    
    
	case 'm':
		while ( 1 )
		{
    
    
			close( dup( 0 ) );
			getpid();
			getuid();
            //umask(mask)会将系统umask值设成参数mask&0777后的值,然后将先前的umask值返回
			umask( 022 );
			iter++;
		}
	/* NOTREACHED */
	case 'c':
		while ( 1 )
		{
    
    
			close( dup( 0 ) );
			iter++;
		}
	/* NOTREACHED */
	case 'g':
		while ( 1 )
		{
    
    
			getpid();
			iter++;
		}
	/* NOTREACHED */
	case 'e':
		while ( 1 )
		{
    
    
			pid_t pid = fork();
			if ( pid < 0 )
			{
    
    
				fprintf( stderr, "%s: fork failed\n", argv[0] );
				exit( 1 );
			} else if ( pid == 0 )
			{
    
    
                //true命令啥都不做,只设置退出码为0
				execl( "/bin/true", (char *) 0 );
				fprintf( stderr, "%s: exec /bin/true failed\n", argv[0] );
				exit( 1 );
			} else {
    
    
                //只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。
				if ( waitpid( pid, NULL, 0 ) < 0 )
				{
    
    
					fprintf( stderr, "%s: waitpid failed\n", argv[0] );
					exit( 1 );
				}
			}
			iter++;
		}
		/* NOTREACHED */
	}

	exit( 9 );
}

1.2.17 time-polling.c

#ifdef UNIXBENCH
	#define	OUT	stdout
#else
	#define OUT	stderr
#endif
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifdef HAS_POLL
#  include <sys/poll.h>
#endif
#ifdef HAS_POLL2
#  include <linux/poll2.h>
#endif
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#ifdef UNIXBENCH
	#define MAX_ITERATIONS 1000
#else
	#define MAX_ITERATIONS 30
#endif
#define MAX_FDS 40960
#define CONST const
#define ERRSTRING strerror (errno)

typedef int flag;

    
/*
static inline int find_first_set_bit (CONST void *array, int size)
*/
static int find_first_set_bit (CONST void *array, int size)
{
    
    
    int index;
    unsigned long word;
    unsigned int ul_size = 8 * sizeof (unsigned long);
    CONST unsigned long *ul_array = array;

    /*  Find first word with any bit set  */
    for (index = 0; (*ul_array == 0) && (index < size);
	 index += ul_size, ++ul_array);
    /*  Find first bit set in word  */
    for (word = *ul_array; !(word & 1) && (index < size);
	 ++index, word = word >> 1);
    return (index);
}   /*  End Function find_first_set_bit  */

/*
static inline int find_next_set_bit (CONST void *array, int size, int offset)
*/
static int find_next_set_bit (CONST void *array, int size, int offset)
{
    
    
    int index, tmp;
    unsigned long word;
    unsigned int ul_size = 8 * sizeof (unsigned long);
    CONST unsigned long *ul_array = array;

    if (++offset >= size) return (offset);
    index = offset;
    /*  Jump to the long word containing the next bit  */
    tmp = offset / ul_size;
    ul_array += tmp;
    offset -= tmp * ul_size;
    if ( (offset == 0) || (*ul_array == 0) )
	return (find_first_set_bit (ul_array, size - index) + index);
    /*  There is a bit set somewhere in this word  */
    if ( ( (word = *ul_array) != 0 ) && ( (word = word >> offset) != 0 ) )
    {
    
    
	/*  There is a bit set somewhere in this word at or after the offset
	    position  */
	for (; (word & 1) == 0; word = word >> 1, ++index);
	return (index);
    }
    /*  Have to go to subsequent word(s)  */
    index += ul_size - offset;
    return (find_first_set_bit (++ul_array, size - index) + index);
}   /*  End Function find_next_set_bit  */


struct callback_struct
{
    
    
    void (*input_func) (void *info);
    void (*output_func) (void *info);
    void (*exception_func) (void *info);
    void *info;
};

static int total_bits = 0;
struct callback_struct callbacks[MAX_FDS];


static void test_func (void *info)
{
    
    
    ++total_bits;
}

#ifdef HAS_SELECT
static void time_select (fd_set *input_fds, fd_set *output_fds,
			 fd_set *exception_fds, int max_fd, int num_iter, long *times)
{
    
    
    int fd, count, nready;
    fd_set i_fds, o_fds, e_fds;
    struct timeval time1, time2, tv;

    /*  Warm the cache a bit  */
    memcpy (&i_fds, input_fds, sizeof i_fds);
    memcpy (&o_fds, output_fds, sizeof i_fds);
    memcpy (&e_fds, exception_fds, sizeof i_fds);
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    select (max_fd + 1, &i_fds, &o_fds, &e_fds, &tv);
    for (count = 0; count < num_iter; ++count)
    {
    
    
	total_bits = 0;
	gettimeofday (&time1, NULL);
	memcpy (&i_fds, input_fds, sizeof i_fds);
	memcpy (&o_fds, output_fds, sizeof i_fds);
	memcpy (&e_fds, exception_fds, sizeof i_fds);
	tv.tv_sec = 0;
	tv.tv_usec = 0;
	nready = select (max_fd + 1, &i_fds, &o_fds, &e_fds, &tv);
	if (nready == -1)
	{
    
    
	    fprintf (stderr, "Error selecting\t%s\n", ERRSTRING);
	    exit (2);
	}
	if (nready < 1)
	{
    
    
	    fprintf (stderr, "Error: nready: %d\n", nready);
	    exit (1);
	}
	/*  Scan the output  */
	for (fd = find_first_set_bit (&e_fds, sizeof e_fds * 8); fd <= max_fd;
	     fd = find_next_set_bit (&e_fds, sizeof e_fds * 8, fd) )
	{
    
    
	    (*callbacks[fd].exception_func) (callbacks[fd].info);
	}
	for (fd = find_first_set_bit (&i_fds, sizeof i_fds * 8); fd <= max_fd;
	     fd = find_next_set_bit (&i_fds, sizeof i_fds * 8, fd) )
	{
    
    
	    (*callbacks[fd].input_func) (callbacks[fd].info);
	}
	for (fd = find_first_set_bit (&o_fds, sizeof o_fds * 8); fd <= max_fd;
	     fd = find_next_set_bit (&o_fds, sizeof o_fds * 8, fd) )
	{
    
    
	    (*callbacks[fd].output_func) (callbacks[fd].info);
	}
	gettimeofday (&time2, NULL);
	times[count] = (time2.tv_sec - time1.tv_sec) * 1000000;
	times[count] += time2.tv_usec - time1.tv_usec;
    }
}   /*  End Function time_select  */
#endif  /* HAS_SELECT */

#ifdef HAS_POLL
static void time_poll (struct pollfd *pollfd_array, int start_index,
		       int num_to_test, int num_iter, long *times)
{
    
    
    short revents;
    int fd, count, nready;
    struct timeval time1, time2;
    struct pollfd *pollfd_ptr, *stop_pollfd;

    /*  Warm the cache a bit  */
    poll (pollfd_array + start_index, num_to_test, 0);
    for (count = 0; count < num_iter; ++count)
    {
    
    
	total_bits = 0;
	gettimeofday (&time1, NULL);
	nready = poll (pollfd_array + start_index, num_to_test, 0);
	if (nready == -1)
	{
    
    
	    fprintf (stderr, "Error polling\t%s\n", ERRSTRING);
	    exit (2);
	}
	if (nready < 1)
	{
    
    
	    fprintf (stderr, "Error: nready: %d\n", nready);
	    exit (1);
	}
	stop_pollfd = pollfd_array + start_index + num_to_test;
	for (pollfd_ptr = pollfd_array + start_index; TRUE; ++pollfd_ptr)
	{
    
    
	    if (pollfd_ptr->revents == 0) continue;
	    /*  Have an active descriptor  */
	    revents = pollfd_ptr->revents;
	    fd = pollfd_ptr->fd;
	    if (revents & POLLPRI)
		(*callbacks[fd].exception_func) (callbacks[fd].info);
	    if (revents & POLLIN)
		(*callbacks[fd].input_func) (callbacks[fd].info);
	    if (revents & POLLOUT)
		(*callbacks[fd].output_func) (callbacks[fd].info);
	    if (--nready == 0) break;
	}
	gettimeofday (&time2, NULL);
	times[count] = (time2.tv_sec - time1.tv_sec) * 1000000;
	times[count] += time2.tv_usec - time1.tv_usec;
    }
}   /*  End Function time_poll  */
#endif  /* HAS_POLL */

#ifdef HAS_POLL2
static void time_poll2 (struct poll2ifd *poll2ifd_array, int start_index,
			int num_to_test, int num_iter, long *times)
{
    
    
    short revents;
    int fd, count, nready, i;
    struct timeval time1, time2;
    struct poll2ofd poll2ofd_array[MAX_FDS];

    /*  Warm the cache a bit  */
    poll2 (poll2ifd_array + start_index, poll2ofd_array, num_to_test, 0);
    for (count = 0; count < num_iter; ++count)
    {
    
    
	total_bits = 0;
	gettimeofday (&time1, NULL);
	nready = poll2 (poll2ifd_array + start_index, poll2ofd_array,
			num_to_test, 0);
	if (nready == -1)
	{
    
    
	    times[count] = -1;
	    if (errno == ENOSYS) return;  /*  Must do this first  */
	    fprintf (stderr, "Error calling poll2(2)\t%s\n", ERRSTRING);
	    exit (2);
	}
	if (nready < 1)
	{
    
    
	    fprintf (stderr, "Error: nready: %d\n", nready);
	    exit (1);
	}
	for (i = 0; i < nready; ++i)
	{
    
    
	    revents = poll2ofd_array[i].revents;
	    fd = poll2ofd_array[i].fd;
	    if (revents & POLLPRI)
		(*callbacks[fd].exception_func) (callbacks[fd].info);
	    if (revents & POLLIN)
		(*callbacks[fd].input_func) (callbacks[fd].info);
	    if (revents & POLLOUT)
		(*callbacks[fd].output_func) (callbacks[fd].info);
	}
	gettimeofday (&time2, NULL);
	times[count] = (time2.tv_sec - time1.tv_sec) * 1000000;
	times[count] += time2.tv_usec - time1.tv_usec;
    }
}   /*  End Function time_poll2  */
#endif  /* HAS_POLL2 */


int main (argc, argv)
int	argc;
char	*argv[];
{
    
    
    flag failed = FALSE;
    flag verbose = FALSE;
    int first_fd = -1;
    int fd, max_fd, count, total_fds;
    int num_to_test, num_active;
#ifdef UNIXBENCH
    int max_iter = 1000;
#else
    int max_iter = 10;
#endif
#ifdef HAS_SELECT
    long select_total = 0;
    fd_set input_fds, output_fds, exception_fds;
    long select_times[MAX_ITERATIONS];
#endif
#ifdef HAS_POLL
	int start_index;
    long poll_total = 0;
    struct pollfd pollfd_array[MAX_FDS];
    long poll_times[MAX_ITERATIONS];
#endif
#ifdef HAS_POLL2
    long poll2_total = 0;
    struct poll2ifd poll2ifd_array[MAX_FDS];
    struct poll2ofd poll2ofd_array[MAX_FDS];
    long poll2_times[MAX_ITERATIONS];
#endif
#if 0
    extern char *sys_errlist[];
#endif

#ifdef HAS_SELECT
    FD_ZERO (&input_fds);
    FD_ZERO (&output_fds);
    FD_ZERO (&exception_fds);
#endif
#ifdef HAS_POLL
    memset (pollfd_array, 0, sizeof pollfd_array);
#endif
    /*  Allocate file descriptors  */
    total_fds = 0;
    max_fd = 0;
    while (!failed)
    {
    
    
	if ( ( fd = dup (1) ) == -1 )
	{
    
    
	    if (errno != EMFILE)
	    {
    
    
		fprintf (stderr, "Error dup()ing\t%s\n", ERRSTRING);
		exit (1);
	    }
	    failed = TRUE;
	    continue;
	}
	if (fd >= MAX_FDS)
	{
    
    
	    fprintf (stderr, "File descriptor: %d larger than max: %d\n",
		     fd, MAX_FDS - 1);
	    exit (1);
	}
	callbacks[fd].input_func = test_func;
	callbacks[fd].output_func = test_func;
	callbacks[fd].exception_func = test_func;
	callbacks[fd].info = NULL;
	if (fd > max_fd) max_fd = fd;
	if (first_fd < 0) first_fd = fd;
#ifdef HAS_POLL
	pollfd_array[fd].fd = fd;
	pollfd_array[fd].events = 0;
#endif
#ifdef HAS_POLL2
	poll2ifd_array[fd].fd = fd;
	poll2ifd_array[fd].events = 0;
#endif
    }
    total_fds = max_fd + 1;
    /*  Process the command-line arguments  */
    if (argc > 5)
    {
    
    
	fputs ("Usage:\ttime-polling [num_iter] [num_to_test] [num_active] [-v]\n",
	       stderr);
	exit (1);
    }
    if (argc > 1) max_iter = atoi (argv[1]);
    if (max_iter > MAX_ITERATIONS)
    {
    
    
	fprintf (stderr, "num_iter too large\n");
	exit (1);
    }
    if (argc > 2) num_to_test = atoi (argv[2]);
    else num_to_test = total_fds - first_fd;
    if (argc > 3) num_active = atoi (argv[3]);
    else num_active = 1;
    if (argc > 4)
    {
    
    
	if (strcmp (argv[4], "-v") != 0)
	{
    
    
	    fputs ("Usage:\ttime-polling [num_iter] [num_to_test] [num_active] [-v]\n",
		   stderr);
	    exit (1);
	}
	verbose = TRUE;
    }

    /*  Sanity tests  */
    if (num_to_test > total_fds - first_fd) num_to_test = total_fds - first_fd;
    if (num_active > total_fds - first_fd) num_active = total_fds - first_fd;
    /*  Set activity monitoring flags  */
    for (fd = total_fds - num_to_test; fd < total_fds; ++fd)
    {
    
    
#ifdef HAS_SELECT
	FD_SET (fd, &exception_fds);
	FD_SET (fd, &input_fds);
#endif
#ifdef HAS_POLL
	pollfd_array[fd].events = POLLPRI | POLLIN;
#endif
#ifdef HAS_POLL2
	poll2ifd_array[fd].events = POLLPRI | POLLIN;
#endif
    }
    for (fd = total_fds - num_active; fd < total_fds; ++fd)
    {
    
    
#ifdef HAS_SELECT
	FD_SET (fd, &output_fds);
#endif
#ifdef HAS_POLL
	pollfd_array[fd].events |= POLLOUT;
#endif
#ifdef HAS_POLL2
	poll2ifd_array[fd].events |= POLLOUT;
#endif
    }
    fprintf (OUT, "Num fds: %d, polling descriptors %d-%d\n",
	     total_fds, total_fds - num_to_test, max_fd);
    /*  First do all the tests, then print the results  */
#ifdef HAS_SELECT
    time_select (&input_fds, &output_fds, &exception_fds, max_fd, max_iter,
		 select_times);
#endif
#ifdef HAS_POLL
    start_index = total_fds - num_to_test;
    time_poll (pollfd_array, start_index, num_to_test, max_iter, poll_times);
#endif
#ifdef HAS_POLL2
    start_index = total_fds - num_to_test;
    time_poll2 (poll2ifd_array, start_index, num_to_test, max_iter,
		poll2_times);
#endif
    /*  Now print out all the times  */
    fputs ("All times in microseconds\n", OUT);
    fputs ("ITERATION\t", OUT);
#ifdef HAS_SELECT
    fprintf (OUT, "%-12s", "select(2)");
#endif
#ifdef HAS_POLL
    fprintf (OUT, "%-12s", "poll(2)");
#endif
#ifdef HAS_POLL2
    if (poll2_times[0] >= 0) fprintf (OUT, "%-12s", "poll2(2)");
#endif
    for (count = 0; count < max_iter; ++count)
    {
    
    
	if (verbose) fprintf (OUT, "\n%d\t\t", count);
#ifdef HAS_SELECT
	if (verbose) fprintf (OUT, "%-12ld", select_times[count]);
	select_total += select_times[count];
#endif
#ifdef HAS_POLL
	if (verbose) fprintf (OUT, "%-12ld", poll_times[count]);
	poll_total += poll_times[count];
#endif
#ifdef HAS_POLL2
	if ( verbose && (poll2_times[0] >= 0) )
	    fprintf (OUT, "%-12ld", poll2_times[count]);
	poll2_total += poll2_times[count];
#endif
    }
    fputs ("\n\naverage\t\t", OUT);
#ifdef HAS_SELECT
    fprintf (OUT, "%-12ld", select_total / max_iter);
#endif
#ifdef HAS_POLL
    fprintf (OUT, "%-12ld", poll_total / max_iter);
#endif
#ifdef HAS_POLL2
    if (poll2_times[0] >= 0)
	fprintf (OUT, "%-12ld", poll2_total / max_iter);
#endif
    putc ('\n', OUT);
    fputs ("Per fd\t\t", OUT);
#ifdef HAS_SELECT
    fprintf (OUT, "%-12.2f",
	     (float) select_total / (float) max_iter / (float) num_to_test);
#ifdef UNIXBENCH
	fprintf (stderr, "lps\t%.2f\t%.1f\n",
		1000000 * (float) max_iter * (float) num_to_test
		 / (float) select_total, (float)select_total / 1000000);
#endif
#endif
#ifdef HAS_POLL
    fprintf (OUT, "%-12.2f",
	     (float) poll_total / (float) max_iter / (float) num_to_test);
#ifdef UNIXBENCH
	fprintf (stderr, "lps\t%.2f\t%.1f\n",
		1000000 * (float) max_iter * (float) num_to_test
		 / (float) poll_total, (float)poll_total / 1000000);
#endif
#endif
#ifdef HAS_POLL2
    if (poll2_times[0] >= 0) {
    
    
	fprintf (OUT, "%-12.2f",
		 (float) poll2_total / (float) max_iter / (float) num_to_test);
#ifdef UNIXBENCH
	fprintf (stderr, "lps\t%.2f\t%.1f\n",
		1000000 * (float) max_iter * (float) num_to_test
		 / (float) poll2_total, (float)poll2_total / 1000000);
#endif
    }

#endif
    fputs ("<- the most important value\n", OUT);

    exit(0);
}   /*  End Function main  */

1.2.18 whets.c

 #include <math.h>       /* for sin, exp etc.           */
 #include <stdio.h>      /* standard I/O                */
 #include <string.h>     /* for strcpy - 3 occurrences  */
 #include <stdlib.h>     /* for exit   - 1 occurrence   */

/*PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION*/

 /* #define DP */

 #ifdef DP
    #define SPDP double
    #define Precision "Double"
 #else
    #define SPDP float
    #define Precision "Single"
 #endif


/*PRECOMPILE  PRECOMPILE  PRECOMPILE  PRECOMPILE  PRECOMPILE  PRECOMPILE*/

 /* #define PRECOMP */

 #ifdef PRECOMP
    #define precompiler "INSERT COMPILER NAME HERE"
    #define preoptions  "INSERT OPTIMISATION OPTIONS HERE"
 #endif


 void whetstones(long xtra, long x100, int calibrate);
 void pa(SPDP e[4], SPDP t, SPDP t2);
 void po(SPDP e1[4], long j, long k, long l);
 void p3(SPDP *x, SPDP *y, SPDP *z, SPDP t, SPDP t1, SPDP t2);
 void pout(char title[22], float ops, int type, SPDP checknum,
		  SPDP time, int calibrate, int section);


 static SPDP loop_time[9];
 static SPDP loop_mops[9];
 static SPDP loop_mflops[9];
 static SPDP TimeUsed;
 static SPDP mwips;
 static char headings[9][18];
 static SPDP Check;
 static SPDP results[9];

int main(argc, argv)
int	argc;
char	*argv[];
{
    
    
    int count = 10, calibrate = 1;
    long xtra = 1;
    long x100 = 100;
#ifdef UNIXBENCH
    int duration = 10;
#else
    int section;
    int duration = 100;
    FILE *outfile;
    int getinput = 1;
    char compiler[80] = " ", options[256] = " ", general[10][80] = {
    
    " "};
    char *endit = " ";

    printf("##########################################\n");
    printf("%s Precision C/C++ Whetstone Benchmark\n\n", Precision);
#endif


#ifndef UNIXBENCH
    if (argc > 1)
     {
    
    
	switch (argv[1][0])
	{
    
    
	     case 'N':
	     case 'n':
	       getinput = 0;
	       break;
	}
     }
   if (! getinput)
    {
    
    
       printf ("No run time input data\n\n");
    }

    outfile = fopen("whets.res","a+");
    if (outfile == NULL)
      {
    
    
       printf ("Cannot open results file \n\n");
       printf("Press RETURN to exit\n");
       gets(endit);
       exit (0);
      }
#endif

  printf("Calibrate\n");
  do
   {
    
    
    TimeUsed=0;

    whetstones(xtra,x100,calibrate);

    printf("%11.2f Seconds %10.0f   Passes (x 100)\n", TimeUsed, (SPDP)(xtra));
    calibrate++;
    count--;

#ifndef UNIXBENCH
    if (TimeUsed > 2.0)
#else
    if (TimeUsed > 0.5)
#endif
      {
    
    
       count = 0;
      }
       else
      {
    
    
       xtra = xtra * 5;
      }
   }

   while (count > 0);

   if (TimeUsed > 0) xtra = (long)((SPDP)(duration * xtra) / TimeUsed);
   if (xtra < 1) xtra = 1;

   calibrate = 0;

   printf("\nUse %ld  passes (x 100)\n", xtra);

   printf("\n          %s Precision C/C++ Whetstone Benchmark",Precision);

   #ifdef PRECOMP
      printf("\n          Compiler  %s", precompiler);
      printf("\n          Options   %s\n", preoptions);
   #else
      printf("\n");
   #endif

   printf("\nLoop content                  Result              MFLOPS "
				"     MOPS   Seconds\n\n");

   TimeUsed=0;
   whetstones(xtra,x100,calibrate);

   printf("\nMWIPS            ");
   if (TimeUsed>0)
     {
    
    
      mwips=(float)(xtra) * (float)(x100) / (10 * TimeUsed);
     }
      else
     {
    
    
      mwips = 0;
     }

   printf("%39.3f%19.3f\n\n",mwips,TimeUsed);

   if (Check == 0) printf("Wrong answer  ");



 /************************************************************************/
 /*             Type details of hardware, software etc.                  */
 /************************************************************************/

#ifndef UNIXBENCH
 if (getinput)
   {
    
    
     printf ("Date:       ");
     gets(general[0]);

     printf ("Computer:   ");
     gets(general[1]);

     printf ("CPU chip:   ");
     gets(general[2]);

     printf ("Clock MHz:  ");
     gets(general[3]);

     printf ("Cache size: ");
     gets(general[4]);

     printf ("H/W options:");
     gets(general[5]);

     printf ("OS version: ");
     gets(general[6]);

     #ifdef PRECOMP
	strcpy (compiler, precompiler);
	strcpy (options, preoptions);
     #else
	printf ("Compiler:   ");
	gets(compiler);

	printf ("Options:    ");
	gets(options);
     #endif

     printf ("Your name:  ");
     gets(general[7]);

     printf ("From:       ");
     gets(general[8]);

     printf ("Email:      ");
     gets(general[9]);
   }
  else
   {
    
    
     #ifdef PRECOMP
	strcpy (compiler, precompiler);
	strcpy (options, preoptions);
     #endif
   }

 /************************************************************************/
 /*               Add results to output file whets.res                   */
 /************************************************************************/
 fprintf (outfile, "\n");
 fprintf (outfile, "##############################################\n");
 fprintf (outfile, "Whetstone %s  Precision Benchmark in C/C++\n\n",Precision);
 fprintf (outfile, "Date         %s\n", general[0]);
 fprintf (outfile, "Model        %s\n", general[1]);
 fprintf (outfile, "CPU          %s\n", general[2]);
 fprintf (outfile, "Clock MHz    %s\n", general[3]);
 fprintf (outfile, "Cache        %s\n", general[4]);
 fprintf (outfile, "H/W options  %s\n", general[5]);
 fprintf (outfile, "OS           %s\n", general[6]);
 fprintf (outfile, "Compiler     %s\n", compiler);
 fprintf (outfile, "Options      %s\n", options);
 fprintf (outfile, "Run by       %s\n", general[7]);
 fprintf (outfile, "From         %s\n", general[8]);
 fprintf (outfile, "Email        %s\n", general[9]);
 fprintf (outfile, "\n");

 fprintf (outfile,"Loop content                   Result"
	    "              MFLOPS      MOPS   Seconds\n\n");

 for (section=1; section<9; section++)
    {
    
    
     fprintf (outfile, "%s  %24.17f   ", headings[section],
					      results[section]);
     if (loop_mops[section] == 99999)
       {
    
    
	fprintf (outfile,"  %9.3f           %9.3f\n",
		 loop_mflops[section], loop_time[section]);
       }
       else
       {
    
    
	fprintf (outfile, "            %9.3f %9.3f\n",
	     loop_mops[section], loop_time[section], results[section]);
       }
    }

 fprintf (outfile, "\nMWIPS             ");
 fprintf (outfile, "%39.3f%20.3f\n\n",mwips,TimeUsed);
 fprintf (outfile, "Results  to  load  to  spreadsheet             ");
 fprintf (outfile, "     MWIPS   Mflops1   Mflops2   Mflops3   Cosmops   Expmops  Fixpmops    Ifmops    Eqmops\n");
 fprintf (outfile, "Results  to  load  to  spreadsheet             ");

 fprintf (outfile, " %9.3f %9.3f %9.3f", mwips, loop_mflops[1],loop_mflops[2]);
 fprintf (outfile, " %9.3f %9.3f %9.3f", loop_mflops[6], loop_mops[5], loop_mops[8]);
 fprintf (outfile, " %9.3f %9.3f %9.3f\n\n", loop_mops[4], loop_mops[3], loop_mops[7]);

 fclose (outfile);

#else	/* Unixbench */
	fprintf (stderr, "COUNT|%.3f|0|MWIPS\n", mwips);
        fprintf (stderr, "TIME|%.3f\n", TimeUsed);
	exit(0);
#endif
}

    void whetstones(long xtra, long x100, int calibrate)
      {
    
    

	long n1,n2,n3,n4,n5,n6,n7,n8,i,ix,n1mult;
	SPDP x,y,z;
	long j,k,l;
	SPDP e1[4],timea,timeb, dtime();

	SPDP t =  0.49999975;
	SPDP t0 = t;
	SPDP t1 = 0.50000025;
	SPDP t2 = 2.0;

	Check=0.0;

	n1 = 12*x100;
	n2 = 14*x100;
	n3 = 345*x100;
	n4 = 210*x100;
	n5 = 32*x100;
	n6 = 899*x100;
	n7 = 616*x100;
	n8 = 93*x100;
	n1mult = 10;

	/* Section 1, Array elements */

	e1[0] = 1.0;
	e1[1] = -1.0;
	e1[2] = -1.0;
	e1[3] = -1.0;
	timea = dtime();
	 {
    
    
	    for (ix=0; ix<xtra; ix++)
	      {
    
    
		for(i=0; i<n1*n1mult; i++)
		  {
    
    
		      e1[0] = (e1[0] + e1[1] + e1[2] - e1[3]) * t;
		      e1[1] = (e1[0] + e1[1] - e1[2] + e1[3]) * t;
		      e1[2] = (e1[0] - e1[1] + e1[2] + e1[3]) * t;
		      e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3]) * t;
		  }
		t = 1.0 - t;
	      }
	    t =  t0;
	 }
	timeb = (dtime()-timea)/(SPDP)(n1mult);
	pout("N1 floating point\0",(float)(n1*16)*(float)(xtra),
			     1,e1[3],timeb,calibrate,1);

	/* Section 2, Array as parameter */

	timea = dtime();
	 {
    
    
	    for (ix=0; ix<xtra; ix++)
	      {
    
    
		for(i=0; i<n2; i++)
		  {
    
    
		     pa(e1,t,t2);
		  }
		t = 1.0 - t;
	      }
	    t =  t0;
	 }
	timeb = dtime()-timea;
	pout("N2 floating point\0",(float)(n2*96)*(float)(xtra),
			     1,e1[3],timeb,calibrate,2);

	/* Section 3, Conditional jumps */
	j = 1;
	timea = dtime();
	 {
    
    
	    for (ix=0; ix<xtra; ix++)
	      {
    
    
		for(i=0; i<n3; i++)
		  {
    
    
		     if(j==1)       j = 2;
		     else           j = 3;
		     if(j>2)        j = 0;
		     else           j = 1;
		     if(j<1)        j = 1;
		     else           j = 0;
		  }
	      }
	 }
	timeb = dtime()-timea;
	pout("N3 if then else  \0",(float)(n3*3)*(float)(xtra),
			2,(SPDP)(j),timeb,calibrate,3);

	/* Section 4, Integer arithmetic */
	j = 1;
	k = 2;
	l = 3;
	timea = dtime();
	 {
    
    
	    for (ix=0; ix<xtra; ix++)
	      {
    
    
		for(i=0; i<n4; i++)
		  {
    
    
		     j = j *(k-j)*(l-k);
		     k = l * k - (l-j) * k;
		     l = (l-k) * (k+j);
		     e1[l-2] = j + k + l;
		     e1[k-2] = j * k * l;
		  }
	      }
	 }
	timeb = dtime()-timea;
	x = e1[0]+e1[1];
	pout("N4 fixed point   \0",(float)(n4*15)*(float)(xtra),
				 2,x,timeb,calibrate,4);

	/* Section 5, Trig functions */
	x = 0.5;
	y = 0.5;
	timea = dtime();
	 {
    
    
	    for (ix=0; ix<xtra; ix++)
	      {
    
    
		for(i=1; i<n5; i++)
		  {
    
    
		     x = t*atan(t2*sin(x)*cos(x)/(cos(x+y)+cos(x-y)-1.0));
		     y = t*atan(t2*sin(y)*cos(y)/(cos(x+y)+cos(x-y)-1.0));
		  }
		t = 1.0 - t;
	      }
	    t = t0;
	 }
	timeb = dtime()-timea;
	pout("N5 sin,cos etc.  \0",(float)(n5*26)*(float)(xtra),
				 2,y,timeb,calibrate,5);

	/* Section 6, Procedure calls */
	x = 1.0;
	y = 1.0;
	z = 1.0;
	timea = dtime();
	 {
    
    
	    for (ix=0; ix<xtra; ix++)
	      {
    
    
		for(i=0; i<n6; i++)
		  {
    
    
		     p3(&x,&y,&z,t,t1,t2);
		  }
	      }
	 }
	timeb = dtime()-timea;
	pout("N6 floating point\0",(float)(n6*6)*(float)(xtra),
				1,z,timeb,calibrate,6);

	/* Section 7, Array refrences */
	j = 0;
	k = 1;
	l = 2;
	e1[0] = 1.0;
	e1[1] = 2.0;
	e1[2] = 3.0;
	timea = dtime();
	 {
    
    
	    for (ix=0; ix<xtra; ix++)
	      {
    
    
		for(i=0;i<n7;i++)
		  {
    
    
		     po(e1,j,k,l);
		  }
	      }
	 }
	timeb = dtime()-timea;
	pout("N7 assignments   \0",(float)(n7*3)*(float)(xtra),
			    2,e1[2],timeb,calibrate,7);

	/* Section 8, Standard functions */
	x = 0.75;
	timea = dtime();
	 {
    
    
	    for (ix=0; ix<xtra; ix++)
	      {
    
    
		for(i=0; i<n8; i++)
		  {
    
    
		     x = sqrt(exp(log(x)/t1));
		  }
	      }
	 }
	timeb = dtime()-timea;
	pout("N8 exp,sqrt etc. \0",(float)(n8*4)*(float)(xtra),
				2,x,timeb,calibrate,8);

	return;
      }


    void pa(SPDP e[4], SPDP t, SPDP t2)
      {
    
    
	 long j;
	 for(j=0;j<6;j++)
	    {
    
    
	       e[0] = (e[0]+e[1]+e[2]-e[3])*t;
	       e[1] = (e[0]+e[1]-e[2]+e[3])*t;
	       e[2] = (e[0]-e[1]+e[2]+e[3])*t;
	       e[3] = (-e[0]+e[1]+e[2]+e[3])/t2;
	    }

	 return;
      }

    void po(SPDP e1[4], long j, long k, long l)
      {
    
    
	 e1[j] = e1[k];
	 e1[k] = e1[l];
	 e1[l] = e1[j];
	 return;
      }

    void p3(SPDP *x, SPDP *y, SPDP *z, SPDP t, SPDP t1, SPDP t2)
      {
    
    
	 *x = *y;
	 *y = *z;
	 *x = t * (*x + *y);
	 *y = t1 * (*x + *y);
	 *z = (*x + *y)/t2;
	 return;
      }


    void pout(char title[18], float ops, int type, SPDP checknum,
	      SPDP time, int calibrate, int section)
      {
    
    
	SPDP mops,mflops;

	Check = Check + checknum;
	loop_time[section] = time;
	strcpy (headings[section],title);
	TimeUsed =  TimeUsed + time;
	if (calibrate == 1)

	  {
    
    
	      results[section] = checknum;
	  }
	if (calibrate == 0)
	  {
    
    
	    printf("%s %24.17f    ",headings[section],results[section]);

	    if (type == 1)
	     {
    
    
		if (time>0)
		 {
    
    
		    mflops = ops/(1000000L*time);
		 }
		else
		 {
    
    
		   mflops = 0;
		 }
		loop_mops[section] = 99999;
		loop_mflops[section] = mflops;
		printf(" %9.3f          %9.3f\n",
		 loop_mflops[section], loop_time[section]);
	     }
	    else
	     {
    
    
		if (time>0)
		 {
    
    
		   mops = ops/(1000000L*time);
		 }
		else
		 {
    
    
		   mops = 0;
		 }
		loop_mops[section] = mops;
		loop_mflops[section] = 0;
		printf("           %9.3f%9.3f\n",
		 loop_mops[section], loop_time[section]);
	     }
	  }

	return;
      }


#ifdef Amiga
#include <ctype.h>
#define HZ 50

SPDP dtime()
{
    
    
 SPDP q;

 struct tt
       {
    
    
	long  days;
	long  minutes;
	long  ticks;
       } tt;

 DateStamp(&tt);

 q = ((SPDP)(tt.ticks + (tt.minutes * 60L * 50L))) / (SPDP)HZ;

 return q;
}
#endif


#ifdef UNIX
#include <sys/time.h>
#include <sys/resource.h>

#ifdef hpux
#include <sys/syscall.h>
#define getrusage(a,b) syscall(SYS_getrusage,a,b)
#endif

struct rusage rusage;

SPDP dtime()
{
    
    
 SPDP q;

 getrusage(RUSAGE_SELF,&rusage);

 q = (SPDP)(rusage.ru_utime.tv_sec);
 q = q + (SPDP)(rusage.ru_utime.tv_usec) * 1.0e-06;

 return q;
}
#endif


#ifdef UNIX_Old
#include <sys/types.h>
#include <sys/times.h>
#include <sys/param.h>

#ifndef HZ
#define HZ 60
#endif

struct tms tms;

SPDP dtime()
{
    
    
 SPDP q;

 times(&tms);

 q = (SPDP)(tms.tms_utime) / (SPDP)HZ;

 return q;
}
#endif


#ifdef VMS
#include time

#ifndef HZ
#define HZ 100
#endif

struct tbuffer_t
       {
    
    
	int proc_user_time;
	int proc_system_time;
	int child_user_time;
	int child_system_time;
       };
struct tbuffer_t tms;

SPDP dtime()
{
    
    
 SPDP q;

 times(&tms);

 q = (SPDP)(tms.proc_user_time) / (SPDP)HZ;

 return q;
}
#endif

/******************************/
/*  BORLAND C dtime() for DOS */
/******************************/
#ifdef BORLAND_C
#include <ctype.h>
#include <dos.h>
#include <time.h>

#define HZ 100
struct time tnow;

SPDP dtime()
{
    
    
 SPDP q;

 gettime(&tnow);

 q = 60.0 * (SPDP)(tnow.ti_min);
 q = q + (SPDP)(tnow.ti_sec);
 q = q + (SPDP)(tnow.ti_hund)/(SPDP)HZ;

 return q;
}
#endif


#ifdef MSC
#include <time.h>
#include <ctype.h>

#define HZ CLOCKS_PER_SEC
clock_t tnow;

SPDP dtime()
{
    
    
 SPDP q;

 tnow = clock();
 q = (SPDP)tnow / (SPDP)HZ;
 return q;
}
#endif


#ifdef MAC
#include <time.h>

#define HZ 60

SPDP dtime()
{
    
    
 SPDP q;

 q = (SPDP)clock() / (SPDP)HZ;

 return q;
}
#endif


#ifdef IPSC
extern double dclock();

SPDP dtime()
{
    
    
 SPDP q;

 q = dclock();

 return q;
}
#endif

/**************************************************/
/*  FORTRAN dtime() for Cray type systems.        */
/*  This is the preferred timer for Cray systems. */
/**************************************************/
#ifdef FORTRAN_SEC

fortran double second();

SPDP dtime()
{
    
    
 SPDP q;

 second(&q);

 return q;
}
#endif


#ifdef CTimer
#include <time.h>

SPDP dtime()
{
    
    
 SPDP q;
 clock_t   clock(void);

 q = (SPDP)clock() / (SPDP)CLOCKS_PER_SEC;

 return q;
}
#endif

/********************************************/
/* Another UNIX timer using gettimeofday(). */
/* However, getrusage() is preferred.       */
/********************************************/
#ifdef GTODay
#include <sys/time.h>

struct timeval tnow;

SPDP dtime()
{
    
    
 SPDP q;

 gettimeofday(&tnow,NULL);
 q = (SPDP)tnow.tv_sec + (SPDP)tnow.tv_usec * 1.0e-6;

 return q;
}
#endif


#ifdef UXPM
#include <sys/types.h>
#include <sys/timesu.h>
struct tmsu rusage;

SPDP dtime()
{
    
    
 SPDP q;

 timesu(&rusage);

 q = (SPDP)(rusage.tms_utime) * 1.0e-06;

 return q;
}
#endif


#ifdef MAC_TMgr
#include <Timer.h>
#include <stdlib.h>

static TMTask   mgrTimer;
static Boolean  mgrInited = false;
static SPDP     mgrClock;

#define RMV_TIMER RmvTime( (QElemPtr)&mgrTimer )
#define MAX_TIME  1800000000L


static void Remove_timer( )
{
    
    
 RMV_TIMER;
 mgrInited = false;
}

SPDP dtime( )
{
    
    
 if( mgrInited ) {
    
    
	RMV_TIMER;
	mgrClock += (MAX_TIME + mgrTimer.tmCount)*1.0e-6;
 } else {
    
    
	if( _atexit( &Remove_timer ) == 0 ) mgrInited = true;
	mgrClock = 0.0;
}
	if( mgrInited ) {
    
    
		mgrTimer.tmAddr = NULL;
		mgrTimer.tmCount = 0;
		mgrTimer.tmWakeUp = 0;
		mgrTimer.tmReserved = 0;
		InsTime( (QElemPtr)&mgrTimer );
		PrimeTime( (QElemPtr)&mgrTimer, -MAX_TIME );
	}
	return( mgrClock );
}
#endif


#ifdef PARIX
#include <sys/time.h>

SPDP dtime()
{
    
    
 SPDP q;

 q = (SPDP) (TimeNowHigh()) / (SPDP) CLK_TCK_HIGH;

 return q;
}
#endif

/************************************************/
/*  Sun Solaris POSIX dtime() routine           */
/*  Provided by: Case Larsen, CTLarsen.lbl.gov  */
/************************************************/
#ifdef POSIX
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/rusage.h>

#ifdef __hpux
#include <sys/syscall.h>
#endif

struct rusage rusage;

SPDP dtime()
{
    
    
 SPDP q;

 getrusage(RUSAGE_SELF,&rusage);

 q = (SPDP)(rusage.ru_utime.tv_sec);
 q = q + (SPDP)(rusage.ru_utime.tv_nsec) * 1.0e-09;

 return q;
}
#endif


/****************************************************/
/*  Windows NT (32 bit) dtime() routine             */
/*  Provided by: Piers Haken, [email protected]  */
/****************************************************/
#ifdef WIN32
#include <windows.h>

SPDP dtime(void)
{
    
    
 SPDP q;

 q = (SPDP)GetTickCount() * 1.0e-03;

 return q;
}
#endif

/*****************************************************/
/* Time according to POSIX.1  -  <[email protected]> */
/* Ref: "POSIX Programmer's Guide"  O'Reilly & Assoc.*/
/*****************************************************/
#ifdef POSIX1
#define _POSIX_SOURCE 1
#include <unistd.h>
#include <limits.h>
#include <sys/times.h>

struct tms tms;

SPDP dtime()
{
    
    
 SPDP q;
 times(&tms);
 q = (SPDP)tms.tms_utime / (SPDP)CLK_TCK;
 return q;
}
#endif

2. stream 内存性能

2.1 内存性能前置知识点

现在比较新的CPU一般都有三级缓存,L1 Cache(32KB-256KB),L2 Cache(128KB-2MB),L3 Cache(1M-32M)。缓存逐渐变大,CPU在取数据的时候,优先从缓存去取数据,取不到才去内存取数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m0k8DDAV-1637831705169)(a462607.jpeg)]

我们在写业务代码的时候,越贴近CPU性能越高。内存的时延都是纳秒为单位,而实际业务中都是毫秒为单位,优化的重点应该是那些以毫秒为单位的运算。

简单介绍下stream的算法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ekVjTkxq-1637831705172)(9ff2320.png)]

stream算法的原理从上图可知:某个内存块之间的数据读取出来,经过简单的运算放入另一个内存块。那所谓的内存带宽:内存带宽 = 搬运的内存大小 / 耗时。通过整机合理的测试,可以测出来内存控制器的带宽。

内存与NUMA的关系:

  • 开启NUMA(使众多服务器像单一系统那样运转,类似于分布式计算),可以有效地提供内存的吞吐性能,降低内存时延。
  • stream算法的编译方法选择:通过icc编译,可以有效地提供内存带宽性能分。原因是Intel优化了CPU的指令,通过指令向量化和指令Prefetch操作,加速了数据的读写操作以及指令操作。当然其他C代码都可以通过icc编译的方法,提供指令的效率。

2.2 系统架构的演进从SMP到NUMA

2.2.1 SMP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hKveYIVK-1637831705172)(20181230230507184.png)]

对称多处理器结构,是指服务器中多个CPU对称工作,无主次或从属关系。各CPU共享相同的物理内存,每个 CPU访问内存中的任何地址所需时间是相同的。

SMP服务器的主要特征是共享,系统中所有资源(CPU、内存、I/O等)都是共享的。也正是由于这种特征,导致了SMP服务器的主要问题,那就是它的扩展能力非常有限。对于SMP服务器而言,每一个共享的环节都可能造成SMP服务器扩展时的瓶颈,而最受限制的则是内存。由于每个CPU必须通过相同的内存总线访问相同的内存资源,因此随着CPU数量的增加,内存访问冲突将迅速增加,最终会造成CPU资源的浪费,使 CPU性能的有效性大大降低。

有实验数据表明,SMP型的服务器CPU最好是2-4颗就OK了,多余的就浪费了。

2.2.2 NUMA

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a4yPpq4C-1637831705174)(20181230230221461.gif)]

NUMA技术,可以把几十个CPU(甚至上百个CPU)组合在一个服务器内。

NUMA服务器的基本特征是具有多个CPU模块,每个CPU模块由多个CPU(如4个)组成,并且具有独立的本地内存、I/O槽口等。由于其节点之间可以通过互联模块(如称为Crossbar Switch)进行连接和信息交互,因此每个CPU可以访问整个系统的内存(这是NUMA系统与MPP系统的重要差别)。显然,访问本地内存的速度将远远高于访问远地内存(系统内其它节点的内存)的速度,这也是非一致存储访问NUMA的由来。

由于这个特点,开发应用程序时需要尽量减少不同CPU模块之间的信息交互。利用NUMA技术,可以较好地解决原来SMP系统的扩展问题,在一个物理服务器内可以支持上百个CPU。比较典型的NUMA服务器的例子包括HP的Superdome、SUN15K、IBMp690等。

2.3 stream实际测试操作

首先下载解压后,进行编译

gcc -O stream.c -o stream.o

然后执行

./stream.o

输出

-------------------------------------------------------------
STREAM version $Revision: 5.9 $
-------------------------------------------------------------
This system uses 8 bytes per DOUBLE PRECISION word.
-------------------------------------------------------------
Array size = 2000000, Offset = 0
Total memory required = 45.8 MB.
Each test is run 10 times, but only
the *best* time for each is used.
-------------------------------------------------------------
Printing one line per active thread....
-------------------------------------------------------------
Your clock granularity/precision appears to be 1 microseconds.
Each test below will take on the order of 1976 microseconds.
   (= 1976 clock ticks)
Increase the size of the arrays if this shows that
you are not getting at least 20 clock ticks per test.
-------------------------------------------------------------
WARNING -- The above is only a rough guideline.
For best results, please be sure you know the
precision of your system timer.
-------------------------------------------------------------
Function      Rate (MB/s)   Avg time     Min time     Max time
#是复制操作,即从内存单元中读取一个数,并复制到其他内存单元中,两次访问内存操作
Copy:       11332.1283       0.0034       0.0028       0.0050
#是乘法操作,即从内存单元中读取一个数,与常数相乘,得到的记过存到其他内存单元,两次访问内存操作
Scale:      11122.7089       0.0044       0.0029       0.0085
#是加法操作,从两个内存单元中分别读取两个数,将其进行加法操作后,得到的结果写入另一个内存单元中,3次访问内存操作
Add:        12769.6684       0.0052       0.0038       0.0080
#是前面三种的结合,先从内存中读取一个数,与一个常数相乘得到一个乘积,然后从另一个内存单元中读取一个数与刚才乘积结果相加,得到的结果写入内存。3次访问内存操作
Triad:      12879.1320       0.0052       0.0037       0.0075
-------------------------------------------------------------
Solution Validates
-------------------------------------------------------------

OpenEular机器上面的

[root@localhost kevin]# ./stream.o -------------------------------------------------------------STREAM version $Revision: 5.9 $-------------------------------------------------------------This system uses 8 bytes per DOUBLE PRECISION word.-------------------------------------------------------------Array size = 2000000, Offset = 0Total memory required = 45.8 MB.Each test is run 10 times, but onlythe *best* time for each is used.-------------------------------------------------------------Printing one line per active thread....-------------------------------------------------------------Your clock granularity/precision appears to be 1 microseconds.Each test below will take on the order of 1866 microseconds.   (= 1866 clock ticks)Increase the size of the arrays if this shows thatyou are not getting at least 20 clock ticks per test.-------------------------------------------------------------WARNING -- The above is only a rough guideline.For best results, please be sure you know theprecision of your system timer.-------------------------------------------------------------Function      Rate (MB/s)   Avg time     Min time     Max timeCopy:       13235.1571       0.0027       0.0024       0.0032Scale:      12672.8097       0.0029       0.0025       0.0036Add:        14733.0108       0.0036       0.0033       0.0040Triad:      14647.2602       0.0045       0.0033       0.0074-------------------------------------------------------------Solution Validates-----------------------------------um -fopenmp -DSTREAM_ARRAY_SIZE=<num> -DNTIMES=<num> -DOFFSET=<num> stream.c -o stream.o1参数介绍:--------------------------

猜你喜欢

转载自blog.csdn.net/qq_43553690/article/details/121542501