From f61c6ee336d381f9cb98a6b9c50256d4a526f174 Mon Sep 17 00:00:00 2001 From: Lukasz Leczkowski Date: Tue, 26 Nov 2024 15:00:08 +0100 Subject: [PATCH] add rhealstone benchmark --- _user/rhealstone/common/Makefile | 11 ++ _user/rhealstone/common/common.c | 74 ++++++++ _user/rhealstone/common/rhcommon.h | 53 ++++++ _user/rhealstone/deadlock-break/Makefile | 11 ++ _user/rhealstone/deadlock-break/main.c | 170 ++++++++++++++++++ _user/rhealstone/irq-latency/Makefile | 11 ++ _user/rhealstone/irq-latency/main.c | 77 ++++++++ _user/rhealstone/msg-latency/Makefile | 11 ++ _user/rhealstone/msg-latency/main.c | 187 ++++++++++++++++++++ _user/rhealstone/preempt/Makefile | 11 ++ _user/rhealstone/preempt/main.c | 105 +++++++++++ _user/rhealstone/semaphore-shuffle/Makefile | 11 ++ _user/rhealstone/semaphore-shuffle/main.c | 132 ++++++++++++++ _user/rhealstone/task-switch/Makefile | 11 ++ _user/rhealstone/task-switch/main.c | 92 ++++++++++ 15 files changed, 967 insertions(+) create mode 100644 _user/rhealstone/common/Makefile create mode 100644 _user/rhealstone/common/common.c create mode 100644 _user/rhealstone/common/rhcommon.h create mode 100644 _user/rhealstone/deadlock-break/Makefile create mode 100644 _user/rhealstone/deadlock-break/main.c create mode 100644 _user/rhealstone/irq-latency/Makefile create mode 100644 _user/rhealstone/irq-latency/main.c create mode 100644 _user/rhealstone/msg-latency/Makefile create mode 100644 _user/rhealstone/msg-latency/main.c create mode 100644 _user/rhealstone/preempt/Makefile create mode 100644 _user/rhealstone/preempt/main.c create mode 100644 _user/rhealstone/semaphore-shuffle/Makefile create mode 100644 _user/rhealstone/semaphore-shuffle/main.c create mode 100644 _user/rhealstone/task-switch/Makefile create mode 100644 _user/rhealstone/task-switch/main.c diff --git a/_user/rhealstone/common/Makefile b/_user/rhealstone/common/Makefile new file mode 100644 index 00000000..4bc94f6f --- /dev/null +++ b/_user/rhealstone/common/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for Phoenix-RTOS librhcommon +# +# Copyright 2024 Phoenix Systems +# + +NAME := librhcommon +LOCAL_HEADERS := rhcommon.h +LOCAL_SRCS := common.c + +include $(static-lib.mk) diff --git a/_user/rhealstone/common/common.c b/_user/rhealstone/common/common.c new file mode 100644 index 00000000..b71af5fe --- /dev/null +++ b/_user/rhealstone/common/common.c @@ -0,0 +1,74 @@ +/* + * Phoenix-RTOS + * + * Rhealstone benchmark + * + * Common functions + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include "rhcommon.h" + +#include +#include +#include +#include + + +uint64_t printResult(uint64_t start, uint64_t end, int loops, uint64_t loopOverhead, uint64_t singleOverhead) +{ + uint64_t elapsed = end - start - loopOverhead; + float time = ((float)elapsed / (float)loops) - (float)singleOverhead; + printf("Result: %.1f cycles\n", time); + + return elapsed; +} + + +static void emptyThread(void *arg) +{ + endthread(); +} + + +uint64_t threadJoinOverhead(void) +{ + uint64_t start, end; + int tid; + char stack[512]; + if (beginthreadex(emptyThread, 0, stack, sizeof(stack), NULL, &tid) < 0) { + perror("beginthreadex"); + return 0; + } + + usleep(100000); + + start = getCntr(); + threadJoin(tid, 0); + end = getCntr(); + + return end - start; +} + + +uint64_t mutexLockOverhead(handle_t mutex) +{ + const int loops = 100; + uint64_t start, end, total = 0; + + for (int i = 0; i < loops; i++) { + start = getCntr(); + mutexLock(mutex); + end = getCntr(); + mutexUnlock(mutex); + total += end - start; + } + + return total / loops; +} diff --git a/_user/rhealstone/common/rhcommon.h b/_user/rhealstone/common/rhcommon.h new file mode 100644 index 00000000..d2835687 --- /dev/null +++ b/_user/rhealstone/common/rhcommon.h @@ -0,0 +1,53 @@ +/* + * Phoenix-RTOS + * + * Rhealstone benchmark + * + * Common functions + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _RHCOMMON_H_ +#define _RHCOMMON_H_ + + +#include +#include + + +#define BENCH_NAME(name) \ + do { \ + printf("Rhealstone benchmark suite\n%s\n", name); \ + } while (0) + +uint64_t printResult(uint64_t start, uint64_t end, int loops, uint64_t loopOverhead, uint64_t singleOverhead); + + +static inline uint64_t getCntr(void) +{ + uint32_t asr22, asr23; + uint64_t cntr; + __asm__ volatile( + "rd %%asr22, %0\n\t" + "rd %%asr23, %1\n\t" + : "=r"(asr22), "=r"(asr23) :); + + cntr = ((uint64_t)(asr22 & 0xffffffu) << 32) | asr23; + + return cntr; +} + + +uint64_t threadJoinOverhead(void); + + +uint64_t mutexLockOverhead(handle_t mutex); + + +#endif diff --git a/_user/rhealstone/deadlock-break/Makefile b/_user/rhealstone/deadlock-break/Makefile new file mode 100644 index 00000000..e003b8aa --- /dev/null +++ b/_user/rhealstone/deadlock-break/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for user application +# +# Copyright 2024 Phoenix Systems +# + +NAME := rh-deadlock-break +LOCAL_SRCS := main.c +DEP_LIBS := librhcommon + +include $(binary.mk) diff --git a/_user/rhealstone/deadlock-break/main.c b/_user/rhealstone/deadlock-break/main.c new file mode 100644 index 00000000..66171804 --- /dev/null +++ b/_user/rhealstone/deadlock-break/main.c @@ -0,0 +1,170 @@ +/* + * Phoenix-RTOS + * + * Rhealstone benchmark + * + * Task switch + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#define BENCHMARKS 10000 + +bool deadBrk; +volatile bool done = false; +handle_t mutex; + +unsigned char stack[3][4096]; +int maxLoops = BENCHMARKS; +int tid1, tid2, tid3; + +atomic_bool t3_started = false; + +uint64_t totalNoDeadBrk = 0; +uint64_t totalDeadBrk = 0; + +/* High priority task */ +void task3(void *arg) +{ + t3_started = true; + uint64_t time = getCntr(); + if (deadBrk) { + mutexLock(mutex); + } + + if (deadBrk) { + mutexUnlock(mutex); + time = getCntr() - time; + totalDeadBrk += time; + } + else { + time = getCntr() - time; + totalNoDeadBrk += time; + } + done = true; + endthread(); +} + + +/* Medium priority task */ +void task2(void *arg) +{ + if (beginthreadex(task3, 1, stack[2], sizeof(stack[2]), NULL, &tid3)) { + perror("beginthreadex"); + endthread(); + } + + while (!done) { + __asm__ volatile("nop"); + } + + threadJoin(tid3, 0); + + endthread(); +} + +/* Low priority task */ +void task1(void *arg) +{ + if (deadBrk) { + mutexLock(mutex); + } + + if (beginthreadex(task2, 2, stack[1], sizeof(stack[1]), NULL, &tid2)) { + perror("beginthreadex"); + endthread(); + } + + while (!t3_started) { + usleep(0); + } + + if (deadBrk) { + mutexUnlock(mutex); + } + + threadJoin(tid2, 0); + t3_started = false; + endthread(); +} + + +int doTest(void) +{ + if (beginthreadex(task1, 3, stack[0], sizeof(stack[0]), NULL, &tid1)) { + perror("beginthreadex"); + return -1; + } + + priority(4); + + usleep(0); + + threadJoin(tid1, 0); + + priority(0); + + return 0; +} + + +int main(int argc, char *argv[]) +{ + BENCH_NAME("Deadlock Break"); + + if (argc > 1) { + maxLoops = atoi(argv[1]); + } + + priority(0); + + mutexCreate(&mutex); + + uint64_t mutexOverhead = mutexLockOverhead(mutex); + uint64_t joinOverhead = threadJoinOverhead(); + + deadBrk = false; + + + for (int i = 0; i < maxLoops; i++) { + if (doTest() < 0) { + return -1; + } + } + + printf("No deadlock: \n"); + printResult(0, totalNoDeadBrk, 1, joinOverhead, 0); + + deadBrk = true; + + for (int i = 0; i < maxLoops; i++) { + if (doTest() < 0) { + return -1; + } + } + + printf("Deadlocks: full time\n"); + printResult(0, totalDeadBrk, 1, joinOverhead, 0); + + printf("Deadlocks: per resolution\n"); + printResult(0, totalDeadBrk, maxLoops, totalNoDeadBrk, mutexOverhead); + + return 0; +} diff --git a/_user/rhealstone/irq-latency/Makefile b/_user/rhealstone/irq-latency/Makefile new file mode 100644 index 00000000..27b55625 --- /dev/null +++ b/_user/rhealstone/irq-latency/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for user application +# +# Copyright 2024 Phoenix Systems +# + +NAME := rh-irq-latency +LOCAL_SRCS := main.c +DEP_LIBS := librhcommon + +include $(binary.mk) diff --git a/_user/rhealstone/irq-latency/main.c b/_user/rhealstone/irq-latency/main.c new file mode 100644 index 00000000..7e3db516 --- /dev/null +++ b/_user/rhealstone/irq-latency/main.c @@ -0,0 +1,77 @@ +/* + * Phoenix-RTOS + * + * Rhealstone benchmark + * + * Message latency + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#define BENCHMARKS 10000 + +volatile uint64_t benchEnd = 0; + +#ifdef __CPU_GR740 +#define IRQ_UNUSED 13 +#endif + +uint64_t results[BENCHMARKS] = { 0 }; + + +int irqHandler(unsigned int n, void *arg) +{ + benchEnd = getCntr(); + + return 0; +} + + +int main(void) +{ + BENCH_NAME("Interrupt latency"); + + volatile uint32_t *irqCtrl = mmap(NULL, _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE | MAP_PHYSMEM | MAP_ANONYMOUS, -1, (uintptr_t)INT_CTRL_BASE); + + priority(1); + + interrupt(IRQ_UNUSED, irqHandler, NULL, 0, NULL); + + for (int i = 0; i < BENCHMARKS; ++i) { + benchEnd = 0; + uint64_t benchStart = getCntr(); + /* Force interrupt on CPU 0 */ + *(irqCtrl + 2) = (1 << IRQ_UNUSED); + + while (benchEnd == 0) { + __asm__ volatile("nop"); + } + + results[i] = benchEnd - benchStart; + } + + for (int i = 0; i < BENCHMARKS; i++) { + printf("%llu%c", results[i], (i == BENCHMARKS - 1) ? '\n' : ','); + } + + return 0; +} diff --git a/_user/rhealstone/msg-latency/Makefile b/_user/rhealstone/msg-latency/Makefile new file mode 100644 index 00000000..68755754 --- /dev/null +++ b/_user/rhealstone/msg-latency/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for user application +# +# Copyright 2024 Phoenix Systems +# + +NAME := rh-msg-latency +LOCAL_SRCS := main.c +DEP_LIBS := librhcommon + +include $(binary.mk) diff --git a/_user/rhealstone/msg-latency/main.c b/_user/rhealstone/msg-latency/main.c new file mode 100644 index 00000000..bfc4c8cb --- /dev/null +++ b/_user/rhealstone/msg-latency/main.c @@ -0,0 +1,187 @@ +/* + * Phoenix-RTOS + * + * Rhealstone benchmark + * + * Message latency + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define BENCHMARKS 100000 +#define MESSAGE_SIZE (sizeof(long) * 4) + +struct queueCtx { + handle_t mutex; + handle_t condReady; + handle_t condFree; + int head; + int tail; + int currSize; + int totalSize; + size_t itemSize; + void *buffer; +}; + + +int queueCreate(struct queueCtx *ctx, int totalCount, size_t itemSize) +{ + ctx->buffer = malloc(totalCount * itemSize); + if (ctx->buffer == NULL) { + return -1; + } + ctx->head = 0; + ctx->tail = -1; + ctx->currSize = 0; + ctx->totalSize = totalCount; + ctx->itemSize = itemSize; + if (mutexCreate(&ctx->mutex) < 0) { + free(ctx->buffer); + return -1; + } + if (condCreate(&ctx->condReady) < 0) { + resourceDestroy(ctx->mutex); + free(ctx->buffer); + return -1; + } + if (condCreate(&ctx->condFree) < 0) { + resourceDestroy(ctx->condReady); + resourceDestroy(ctx->mutex); + free(ctx->buffer); + return -1; + } + + return 0; +} + + +void queueDestroy(struct queueCtx *ctx) +{ + free(ctx->buffer); + ctx->buffer = NULL; + resourceDestroy(ctx->mutex); + resourceDestroy(ctx->condReady); + resourceDestroy(ctx->condFree); +} + + +void queueSend(struct queueCtx *ctx, void *buf) +{ + mutexLock(ctx->mutex); + while (ctx->currSize == ctx->totalSize) { + condWait(ctx->condFree, ctx->mutex, 0); + } + ctx->tail = (ctx->tail + 1) % ctx->totalSize; + memcpy((char *)ctx->buffer + ctx->tail * ctx->itemSize, buf, ctx->itemSize); + ctx->currSize++; + mutexUnlock(ctx->mutex); + condSignal(ctx->condReady); +} + + +void queueRecv(struct queueCtx *ctx, void *buf) +{ + mutexLock(ctx->mutex); + while (ctx->currSize == 0) { + condWait(ctx->condReady, ctx->mutex, 0); + } + memcpy(buf, (char *)ctx->buffer + ctx->head * ctx->itemSize, ctx->itemSize); + ctx->head = (ctx->head + 1) % ctx->totalSize; + ctx->currSize--; + condSignal(ctx->condFree); + mutexUnlock(ctx->mutex); +} + + +unsigned char stack[2][4096]; +struct queueCtx queue; +uint64_t benchStart, benchEnd; + +/* Low priority */ +void task1(void *arg) +{ + long sendBuf[4] = { 0 }; + + benchStart = getCntr(); + + for (int i = 0; i < BENCHMARKS; i++) { + queueSend(&queue, sendBuf); + } + endthread(); +} + +/* High priority */ +void task2(void *arg) +{ + long recvBuf[4]; + + for (int i = 0; i < BENCHMARKS; i++) { + queueRecv(&queue, recvBuf); + } + benchEnd = getCntr(); + endthread(); +} + + +int main(void) +{ + BENCH_NAME("Message Queue"); + + priority(1); + + if (queueCreate(&queue, 1, MESSAGE_SIZE) < 0) { + perror("queueCreate"); + return -1; + } + + uint64_t loopOverhead = getCntr(); + + for (int i = 0; i < BENCHMARKS; i++) { + __asm__ volatile("nop"); + } + + for (int i = 0; i < BENCHMARKS; i++) { + __asm__ volatile("nop"); + } + + loopOverhead = getCntr() - loopOverhead; + + int tid1, tid2; + if (beginthreadex(task2, 2, stack[1], sizeof(stack[1]), NULL, &tid2) < 0) { + perror("beginthreadex"); + return -1; + } + + if (beginthreadex(task1, 3, stack[0], sizeof(stack[0]), NULL, &tid1) < 0) { + perror("beginthreadex"); + return -1; + } + + priority(4); + usleep(0); + + threadJoin(tid1, 0); + threadJoin(tid2, 0); + + printResult(benchStart, benchEnd, BENCHMARKS, loopOverhead, 0); + + queueDestroy(&queue); + + return 0; +} diff --git a/_user/rhealstone/preempt/Makefile b/_user/rhealstone/preempt/Makefile new file mode 100644 index 00000000..867baef7 --- /dev/null +++ b/_user/rhealstone/preempt/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for user application +# +# Copyright 2024 Phoenix Systems +# + +NAME := rh-preempt +LOCAL_SRCS := main.c +DEP_LIBS := librhcommon + +include $(binary.mk) diff --git a/_user/rhealstone/preempt/main.c b/_user/rhealstone/preempt/main.c new file mode 100644 index 00000000..a1327bc9 --- /dev/null +++ b/_user/rhealstone/preempt/main.c @@ -0,0 +1,105 @@ +/* + * Phoenix-RTOS + * + * Rhealstone benchmark + * + * Task switch + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_LOOPS 10000 + +#define ONE_TICK 26000 /* Number dependent on CPU. For loop to this count must be longer than sleep period (1 ms) */ +#define ONE_TICK_AVG 24990 /* For loop up to this count takes 1ms */ + +unsigned char stack[5][4096]; +volatile atomic_int delay = 0; + +uint64_t start1, start2, end1, end2; + + +/* Low priority */ +void task1(void *arg) +{ + start1 = getCntr(); + for (volatile int cnt1 = 0; cnt1 < MAX_LOOPS; cnt1++) { + for (delay = 0; delay < ONE_TICK; delay++) { + __asm__ volatile("nop"); + /* Delay loop */ + } + } + end1 = getCntr(); + endthread(); +} + +/* High priority */ +void task2(void *arg) +{ + start2 = getCntr(); + for (volatile int cnt2 = 0; cnt2 < MAX_LOOPS; cnt2++) { + delay = ONE_TICK; + usleep(1000); + } + end2 = getCntr(); + endthread(); +} + + +int main(void) +{ + BENCH_NAME("Preemption"); + + priority(1); + + uint64_t overhead = getCntr(); + + for (volatile int cnt1 = 0; cnt1 < MAX_LOOPS; cnt1++) { + for (volatile int i = 0; i < ONE_TICK_AVG; i++) { + /* Delay loop */ + } + } + for (int cnt2 = 0; cnt2 < MAX_LOOPS; cnt2++) { + __asm__ volatile("nop"); + } + + overhead = getCntr() - overhead; + + int tid1, tid2; + int res = beginthreadex(task1, 3, stack[0], sizeof(stack[0]), NULL, &tid1); + if (res < 0) { + perror("beginthreadex"); + return -1; + } + + res = beginthreadex(task2, 2, stack[1], sizeof(stack[1]), NULL, &tid2); + if (res < 0) { + perror("beginthreadex"); + return -1; + } + + priority(4); + + usleep(0); + + threadJoin(tid1, 0); + threadJoin(tid2, 0); + + printResult(min(start1, start2), max(end1, end2), 2 * MAX_LOOPS, overhead, 0); + + return 0; +} diff --git a/_user/rhealstone/semaphore-shuffle/Makefile b/_user/rhealstone/semaphore-shuffle/Makefile new file mode 100644 index 00000000..6c4a7087 --- /dev/null +++ b/_user/rhealstone/semaphore-shuffle/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for user application +# +# Copyright 2024 Phoenix Systems +# + +NAME := rh-semaphore-shuffle +LOCAL_SRCS := main.c +DEP_LIBS := librhcommon + +include $(binary.mk) diff --git a/_user/rhealstone/semaphore-shuffle/main.c b/_user/rhealstone/semaphore-shuffle/main.c new file mode 100644 index 00000000..fa2c03f3 --- /dev/null +++ b/_user/rhealstone/semaphore-shuffle/main.c @@ -0,0 +1,132 @@ +/* + * Phoenix-RTOS + * + * Rhealstone benchmark + * + * Task switch + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include +#include +#include +#include +#include +#include + +#include + + +#define BENCHMARKS 500000 + + +bool semExe = false; +atomic_int count = 0, ready = 0; +handle_t mutex; +uint64_t overhead = 0; + +unsigned char stack[2][4096]; + + +void task2(void *arg) +{ + uint64_t start, end; + start = getCntr(); + + for (count = 0; count < BENCHMARKS; count++) { + if (semExe) { + mutexLock(mutex); + } + + usleep(0); + + if (semExe) { + mutexUnlock(mutex); + } + + usleep(0); + } + end = getCntr(); + + if (!semExe) { + overhead = end - start; + } + else { + printResult(start, end, BENCHMARKS, overhead, 0); + } + endthread(); +} + + +void task1(void *arg) +{ + int tid; + if (beginthreadex(task2, 2, stack[1], sizeof(stack[1]), NULL, &tid)) { + perror("beginthreadex"); + endthread(); + } + + usleep(0); + for (; count < BENCHMARKS;) { + if (semExe) { + mutexLock(mutex); + } + + usleep(0); + + if (semExe) { + mutexUnlock(mutex); + } + + usleep(0); + } + + threadJoin(tid, 0); + + endthread(); +} + + +int main(void) +{ + BENCH_NAME("Semaphore shuffle"); + + priority(1); + + mutexCreate(&mutex); + + int tid1; + if (beginthreadex(task1, 2, stack[0], sizeof(stack[0]), NULL, &tid1) < 0) { + perror("beginthreadex"); + return -1; + } + + priority(3); + + usleep(0); + + threadJoin(tid1, 0); + + priority(1); + + semExe = true; + + if (beginthreadex(task1, 2, stack[0], sizeof(stack[0]), NULL, &tid1) < 0) { + perror("beginthreadex"); + return -1; + } + + priority(3); + + usleep(0); + + threadJoin(tid1, 0); + + return 0; +} diff --git a/_user/rhealstone/task-switch/Makefile b/_user/rhealstone/task-switch/Makefile new file mode 100644 index 00000000..edf3c6e9 --- /dev/null +++ b/_user/rhealstone/task-switch/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for user application +# +# Copyright 2024 Phoenix Systems +# + +NAME := rh-task-switch +LOCAL_SRCS := main.c +DEP_LIBS := librhcommon + +include $(binary.mk) diff --git a/_user/rhealstone/task-switch/main.c b/_user/rhealstone/task-switch/main.c new file mode 100644 index 00000000..c5cbd2ba --- /dev/null +++ b/_user/rhealstone/task-switch/main.c @@ -0,0 +1,92 @@ +/* + * Phoenix-RTOS + * + * Rhealstone benchmark + * + * Task switch + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include +#include +#include +#include +#include +#include + +#define MAX_LOOPS 4000000 + + +unsigned char stack[5][4096]; +uint64_t start1, start2, end1, end2; + + +void task1(void *arg) +{ + start1 = getCntr(); + for (unsigned int i = 0; i < MAX_LOOPS; i++) { + usleep(0); + } + end1 = getCntr(); + endthread(); +} + + +void task2(void *arg) +{ + start2 = getCntr(); + for (unsigned int i = 0; i < MAX_LOOPS; i++) { + usleep(0); + } + end2 = getCntr(); + endthread(); +} + + +int main(void) +{ + printf("Task Switch benchmark\n"); + + priority(1); + + uint64_t overhead = getCntr(); + + for (unsigned int i = 0; i < MAX_LOOPS; i++) { + __asm__ volatile("nop"); + } + for (unsigned int i = 0; i < MAX_LOOPS; i++) { + __asm__ volatile("nop"); + } + + overhead = getCntr() - overhead; + + int tid1, tid2; + int res = beginthreadex(task1, 2, stack[0], sizeof(stack[0]), NULL, &tid1); + if (res < 0) { + perror("beginthreadex"); + return -1; + } + + res = beginthreadex(task2, 2, stack[1], sizeof(stack[1]), NULL, &tid2); + if (res < 0) { + perror("beginthreadex"); + return -1; + } + + priority(3); + + usleep(0); + + threadJoin(tid1, 0); + threadJoin(tid2, 0); + + printResult(min(start1, start2), max(end1, end2), 2 * MAX_LOOPS, overhead, 0); + + return 0; +}