From ae09d979b6cecdb83a4557d4e9889dadfdfa803c Mon Sep 17 00:00:00 2001 From: Masamichi Takagi Date: Mon, 2 Jul 2018 18:40:42 +0900 Subject: [PATCH] Add testcases for #1141 Refs: #1141 Change-Id: I50d1ac6248e9dfc33c372b825c10cf0bd8b61d3e --- test/issues/1141/1141_lin.c | 88 ++++++++++++++++++++++ test/issues/1141/1141_mck.c | 143 ++++++++++++++++++++++++++++++++++++ test/issues/1141/Makefile | 40 ++++++++++ test/issues/1141/README | 13 ++++ 4 files changed, 284 insertions(+) create mode 100644 test/issues/1141/1141_lin.c create mode 100644 test/issues/1141/1141_mck.c create mode 100644 test/issues/1141/Makefile create mode 100644 test/issues/1141/README diff --git a/test/issues/1141/1141_lin.c b/test/issues/1141/1141_lin.c new file mode 100644 index 00000000..f71bb582 --- /dev/null +++ b/test/issues/1141/1141_lin.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include "ihklib.h" + +#define Q(x) #x +#define QUOTE(x) Q(x) + +#define _OKNG(verb, cond, fmt, args...) do { \ + if (cond) { \ + if (verb) \ + printf("[OK] " fmt "\n", ##args); \ + } else { \ + printf("[NG] " fmt "\n", ##args); \ + goto out; \ + } \ +} while (0) + +#define OKNG(args...) _OKNG(1, ##args) +#define NG(args...) _OKNG(0, ##args) + +#define CVAL(event, mask) \ + ((((event) & 0xf00) << 24) | ((mask) << 8) | ((event) & 0xff)) + +#define CVAL2(event, mask, inv, count) \ + ((((event) & 0xf00) << 24) | ((mask) << 8) | ((event) & 0xff) | \ + ((inv & 1) << 23) | ((count & 0xff) << 24)) + +/* Intel Nehalem specific */ +struct ihk_perf_event_attr attr[] = { + { .config = CVAL(0xc0, 0x00), .exclude_kernel = 1 }, /* INSTRUCTIONS */ + { .config = CVAL(0x3c, 0x00), .exclude_kernel = 1 }, /* CYCLE */ + { .config = CVAL(0x43, 0x01), .exclude_kernel = 1 }, /* L1D_REQUEST */ + { .config = CVAL(0x51, 0x01), .exclude_kernel = 1 }, /* L1D_MISS */ + { .config = CVAL(0x80, 0x03), .exclude_kernel = 1 }, /* L1I_REQUEST */ + { .config = CVAL(0x80, 0x02), .exclude_kernel = 1 }, /* L1I_MISS */ + { .config = CVAL(0x24, 0xaa), .exclude_kernel = 1 }, /* L2_MISS */ + { .config = CVAL(0x2e, 0x41), .exclude_kernel = 1 }, /* LLC_MISS */ + { .config = CVAL(0x49, 0x01), .exclude_kernel = 1 }, /* DTLB_MISS */ + { .config = CVAL(0x85, 0x01), .exclude_kernel = 1 }, /* ITLB_MISS */ + { .config = CVAL2(0x0e, 0x01, 1, 1), .exclude_kernel = 1 }, /* STALL */ +}; + +int main(int argc, char **argv) +{ + int ret; + int i, j; + int event_num = 0; + char *prefix = QUOTE(MCKDIR); + char cmd[1024]; + + unsigned long counter[4] = {0, 0, 0, 0}; + + // INVALID index + ret = ihk_os_setperfevent(99, attr, 1); + OKNG(ret < 0, "INVALID index ret: %d", ret); + + // event_num 1 + for (j = 1; j < 5; j++) { + printf("*** event_num %d ***************************\n", j); + ret = ihk_os_setperfevent(0, attr, j); + OKNG(ret == j, "setperfevent ret: %d", ret); + + event_num = ret; + + ret = ihk_os_perfctl(0, PERF_EVENT_ENABLE); + OKNG(ret == 0, "ENABLE ret: %d", ret); + + sprintf(cmd, "%s/bin/mcexec ./1141_mck > /dev/null", prefix); + ret = system(cmd); + OKNG(ret == 0, "system mcexec"); + + ret = ihk_os_perfctl(0, PERF_EVENT_DISABLE); + OKNG(ret == 0, "DISABLE ret: %d", ret); + + ret = ihk_os_getperfevent(0, counter, event_num); + OKNG(ret == 0, "getperfevent ret: %d", ret); + + for (i = 0; i < event_num; i++) { + printf("read_value[%d] %ld\n", i, counter[i]); + } + } + ret = 0; +out: + return ret; +} diff --git a/test/issues/1141/1141_mck.c b/test/issues/1141/1141_mck.c new file mode 100644 index 00000000..0bcd9825 --- /dev/null +++ b/test/issues/1141/1141_mck.c @@ -0,0 +1,143 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define NTHR 1 + +struct thr_arg { + unsigned long delay; +}; + +struct thr_arg thr_arg[NTHR] = { { .delay = 1000000 } }; +pthread_t thr[NTHR]; + +#define DIFFNSEC(end, start) ((end.tv_sec - start.tv_sec) * 1000000000UL + \ + (end.tv_nsec - start.tv_nsec)) +#define TIMER_KIND CLOCK_MONOTONIC_RAW /* CLOCK_THREAD_CPUTIME_ID */ + +static int print_cpu_last_executed_on(void) +{ + int ret = 0; + char fn[256]; + char *result; + pid_t tid = syscall(SYS_gettid); + int fd; + int offset; + int amount = 0; + char *list; + char *token; + int i; + int cpu; + + sprintf(fn, "/proc/%d/task/%d/stat", getpid(), (int)tid); + fd = open(fn, O_RDONLY); + if (fd == -1) { + printf("open() failed\n"); + goto fn_fail; + } + + result = malloc(65536); + if (result == NULL) { + printf("malloc() failed"); + goto fn_fail; + } + + offset = 0; + while (1) { + amount = read(fd, result + offset, 65536); + // printf("amount=%d\n", amount); + if (amount == -1) { + printf("read() failed"); + goto fn_fail; + } + if (amount == 0) { + goto eof; + } + offset += amount; + } + eof:; + //printf("result:%s\n", result); + + list = result; + for (i = 0; i < 39; i++) { + token = strsep(&list, " "); + } + + cpu = sched_getcpu(); + if (cpu == -1) { + printf("getcpu() failed\n"); + goto fn_fail; + } + + printf("[INFO] stat-cpu=%02d,sched_getcpu=%02d,tid=%d\n", + token ? atoi(token) : -1, cpu, tid); + fn_exit: + free(result); + return ret; + fn_fail: + ret = -1; + goto fn_exit; +} + +static inline void asm_loop(unsigned long n) +{ + int j; + + for (j = 0; j < (n); j++) { + asm volatile( + "movq $0, %%rcx\n\t" + "1:\t" + "addq $1, %%rcx\n\t" + "cmpq $99, %%rcx\n\t" + "jle 1b\n\t" + : + : + : "rcx", "cc"); + } +} + +void *util_thread(void *_arg) +{ + struct thr_arg *arg = (struct thr_arg *)_arg; + + print_cpu_last_executed_on(); + asm_loop(arg->delay); + pthread_exit(NULL); +} + +int main(int argc, char **argv) +{ + int i; + int ret = 0; + + for (i = 0; i < NTHR; i++) { + + if ((ret = pthread_create(&thr[i], NULL, + util_thread, &thr_arg[i]))) { + fprintf(stderr, "ERROR: pthread_create failed (%d)\n", + ret); + ret = -EINVAL; + goto out; + } + } + + for (i = 0; i < NTHR; i++) { + pthread_join(thr[i], NULL); + } + + out: + return ret; +} + diff --git a/test/issues/1141/Makefile b/test/issues/1141/Makefile new file mode 100644 index 00000000..dd88b496 --- /dev/null +++ b/test/issues/1141/Makefile @@ -0,0 +1,40 @@ +.SUFFIXES: # Clear suffixes +.SUFFIXES: .c + +MCKDIR=$(HOME)/project/os/install +CC=gcc + +CPPFLAGS_LIN=-I$(MCKDIR)/include -DMCKDIR=$(MCKDIR) +CCFLAGS_LIN=-g -Wall +LDFLAGS_LIN=-L$(MCKDIR)/lib -lihk -Wl,-rpath -Wl,$(MCKDIR)/lib -lbfd +SRCS_LIN=$(shell ls *_lin.c) +EXES_LIN=$(SRCS_LIN:.c=) +OBJS_LIN=$(SRCS_LIN:.c=.o) + +CPPFLAGS_MCK = +CCFLAGS_MCK=-g -Wall +LDFLAGS_MCK=-lpthread +SRCS_MCK=$(shell ls *_mck.c) +EXES_MCK=$(SRCS_MCK:.c=) +OBJS_MCK=$(SRCS_MCK:.c=.o) + +all: $(EXES_LIN) $(EXES_MCK) + +test: $(EXES_LIN) $(EXES_MCK) + sudo ./1141_lin + +%_lin: %_lin.o + $(CC) -o $@ $^ $(LDFLAGS_LIN) + +%_lin.o: %_lin.c + $(CC) $(CCFLAGS_LIN) $(CPPFLAGS_LIN) -c $< + +%_mck: %_mck.o + $(CC) -o $@ $^ $(LDFLAGS_MCK) + +%_mck.o: %_mck.c + $(CC) $(CCFLAGS_MCK) $(CPPFLAGS_MCK) -c $< + +clean: + rm -f core $(EXES_LIN) $(OBJS_LIN) $(EXES_MCK) $(OBJS_MCK) + diff --git a/test/issues/1141/README b/test/issues/1141/README new file mode 100644 index 00000000..a3d9ca6e --- /dev/null +++ b/test/issues/1141/README @@ -0,0 +1,13 @@ +=========== +How to test +=========== +(1) Edit the following line in Makefile + + MCKDIR=$(HOME)/project/os/install + +(2) make test +(3) Check if the first value, number of instructions retired, + shows around 3 million. +(4) Check if the second value, number of cycles taken, + shows around 3 million / instructions-per-cycle + (1 - 1.5, depends on the processor).