lat_intr.c

来自「pebble」· C语言 代码 · 共 301 行

C
301
字号
/* 
 * Copyright 1999, 2000, 2001, 2002 Lucent Technologies Inc.
 * All Rights Reserved.
 * Information Sciences Research Center, Bell Labs.
 *
 * LUCENT TECHNOLOGIES DOES NOT CLAIM MERCHANTABILITY OF THIS SOFTWARE 
 * OR THE SUITABILITY OF THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The
 * software is provided "as is" without expressed or implied warranty 
 * of any kind.
 *
 * These notices must be retained in any copies of any part of this
 * software.
 *
 */

#include "pebble.h"
#include "unistd.h"
#include "string.h"
#include "types.h"
#include "time.h"
#include "synch.h"
#include "perfcount.h"

volatile int phase = 0;
static Time usec2ticks;		/* ticks in one usec. */

#define	N		1000	/* number of sleep operations */
#define	MIN_DELAY	10	/* minimal sleep in usec. */
#define	MAX_DELAY	2000	/* maximal sleep in usec. */

static	Time latency[N+1];	/* in cycles */

int	set_id;			/* set phase RPC */
int	call_id;		/* background RPC */
int	s1, s2;			/* semaphores */

/* set phase of background task */
void
set_phase(int n)
{
	call_portal(set_id, n);
}

int
f_set_phase(int asid, int n)
{
	phase = n;

	return n;
}

/* background RPC */
int
call_rpc(int n)
{
	return call_portal(call_id, n);
}

int
f_call_rpc(int asid, int n)
{
	return n+1;
}

/*
 * background task
 */
void
background1(void)
{
	int i = 0;

	printf("background1 task starting: TLB misses=%d general exceptions=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());

	/* reduce your own priority */
	if (set_priority(get_asid(), PRI_BACKGROUND) < 0)
		panic("set_priority:");

	printf("background1 task asid=%d priority=%d\n",
		get_asid(), get_priority());

	/* busy loop */
	printf("background busy wait: TLB misses=%d general exceptions=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());
	while (phase == 0)
		;

	printf("background yields: TLB misses=%d general exceptions=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());
	while (phase == 1)
		yield();

	/* short-circuit portal loop */
	printf("background short-circuit portals: TLB misses=%d general exceptions=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());
	while (phase == 2)
		get_asid();	

	printf("background RPCs: TLB misses=%d general exceptions=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());
	while (phase == 3)
		call_rpc(i++);

	printf("background semaphores: TLB misses=%d general exceptions=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());
	while (phase == 4) {
		sem_wait(s1);
		sem_post(s2);
	}

	printf("background completed: TLB misses=%d general exceptions=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());

	while (1)
		;
}


void
background2(void)
{
	printf("background2 task starting\n");

	/* reduce your own priority */
	if (set_priority(get_asid(), PRI_BACKGROUND) < 0)
		panic("set_priority:");

	printf("background2 task asid=%d priority=%d\n",
		get_asid(), get_priority());

	while(1) {
		sem_wait(s2);
		sem_post(s1);
	}
}


/*
 * Time comparison routine for qsort.
 */
static int
compare(const void *a, const void *b)
{
	if (*((const Time *)a) > *((const Time *)b))
		return 1;
	else if (*((const Time *)a) < *((const Time *)b))
		return -1;
	else
		return 0;
}


void
report(Time v[], int n)
{
	Time sum = 0;
	int i;

	qsort(v, n, sizeof(Time), compare);

	for (i = 0; i < n; i++)
		sum += v[i];

	printf("n=%d avg=%d min=%d median=%d q90=%d q95=%d q99=%d max=%d\n",
		n, (int)(sum/n), (int)v[0], (int)v[n/2], (int)v[(9*n)/10],
		(int)v[(95*n)/100], (int)v[(99*n)/100], (int)v[n-1]);
}


void
measure(void)
{
	Time start, now;
	int i;
	Time delay;
	int perf_ix;
	uint perf_count;

	/* wait for background thread to change phase */
	usleep(SEC2USEC);

	for (perf_ix = 0; perf_vec[perf_ix].name != NULL; perf_ix++) {
		srandom(7);
		set_perf_ctrl(perf_vec[perf_ix].ctrl);

		for (i = 0; i <= N; i++) {
			delay = (MIN_DELAY * usec2ticks) + 
				(random() % ((MAX_DELAY-MIN_DELAY)*usec2ticks));

			start = hrtime();
			hrsleep(start + delay);
			now = hrtime();
			latency[i] = 2 * (now - start - delay);

			if (latency[i] < 0)
				printf("i=%d start=%d delay=%d now=%d latency=%d\n",
					i, (int)start, (int)delay, (int)now,
					(int)latency[i]);
			
		}

		perf_count = get_perf_count();
		printf("%s: %d\n", perf_vec[perf_ix].name, perf_count);

		/* ignore the first measurement, which is higher due to */
		/* cold cache */
		report(latency+1, N);
	}
}


void
test(void)
{
	printf("testing task asid=%d priority=%d\n",
		get_asid(), get_priority());

	printf("wait for background initialization\n");
	usleep(4 * SEC2USEC);

	printf("============\n");
	printf("measure interrupt latency against the idle task\n");
	set_phase(0);
	measure();

	printf("============\n");
	printf("measure interrupt latency against yields\n");
	set_phase(1);
	measure();


	printf("============\n");
	printf("measure interrupt latency against short-circuit portals\n");
	set_phase(2);
	measure();

	printf("============\n");
	printf("measure interrupt latency against RPC\n");
	set_phase(3);
	measure();

	printf("============\n");
	printf("measure interrupt latency against semaphore ping-pong\n");
	set_phase(4);
	measure();

	/* signal background completion */
	set_phase(-1);

	/* allow background process to sense the new phase */
	usleep(SEC2USEC/10);
}

int
main(void)
{
	int code;


	printf("lat_intr benchmark starting\n");

	usec2ticks = (sec2ticks() + SEC2USEC/2) / SEC2USEC;
	printf("usec2ticks = %d\n", (int)usec2ticks);

	if ((set_id = portal_create(-1, "smaiii", 0, f_set_phase, 0)) < 0)
                panic("portal_create f_set_phase:");

	if ((s1 = sem_create(1)) < 0)
		panic("sem_create s1:");
	if ((s2 = sem_create(0)) < 0)
		panic("sem_create s2:");

	if ((call_id = portal_create(-1, "qpaiii", 0, f_call_rpc, 0)) < 0)
                panic("portal_create f_call_rpc:");

	if ((code = domain_fork(NULL)) < 0)
		panic("domain_fork:");
	if (code == 0) {
		/* child domain */
		test();
		printf("LAT_INTR ENDED\n");
		task_exit(0);
	}

	if ((code = domain_fork(NULL)) < 0)
		panic("domain_fork:");
	if (code == 0) {
		/* child domain */
		background2();
		printf("background2 ended\n");
		task_exit(0);
	}

	background1();

	printf("background1 ended\n");
	task_exit(0);
	return(1);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?