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 + -
显示快捷键?