tests: latency_measure: Update mutexes

Updates the mutex benchmark tests to support user threads.

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
This commit is contained in:
Peter Mitsis 2023-09-18 14:21:30 -04:00 committed by Carles Cufí
commit 9b38aec366
2 changed files with 80 additions and 45 deletions

View file

@ -47,7 +47,7 @@ int error_count; /* track number of errors */
extern void thread_switch_yield(uint32_t num_iterations, bool is_cooperative); extern void thread_switch_yield(uint32_t num_iterations, bool is_cooperative);
extern void int_to_thread(uint32_t num_iterations); extern void int_to_thread(uint32_t num_iterations);
extern void sema_test_signal(uint32_t num_iterations, uint32_t options); extern void sema_test_signal(uint32_t num_iterations, uint32_t options);
extern void mutex_lock_unlock(void); extern void mutex_lock_unlock(uint32_t num_iterations, uint32_t options);
extern void sema_context_switch(uint32_t num_iterations, extern void sema_context_switch(uint32_t num_iterations,
uint32_t start_options, uint32_t alt_options); uint32_t start_options, uint32_t alt_options);
extern int thread_ops(uint32_t num_iterations, uint32_t start_options, extern int thread_ops(uint32_t num_iterations, uint32_t start_options,
@ -105,7 +105,10 @@ static void test_thread(void *arg1, void *arg2, void *arg3)
sema_context_switch(NUM_ITERATIONS, K_USER, K_USER); sema_context_switch(NUM_ITERATIONS, K_USER, K_USER);
#endif #endif
mutex_lock_unlock(); mutex_lock_unlock(NUM_ITERATIONS, 0);
#ifdef CONFIG_USERSPACE
mutex_lock_unlock(NUM_ITERATIONS, K_USER);
#endif
heap_malloc_free(); heap_malloc_free();

View file

@ -1,18 +1,64 @@
/* /*
* Copyright (c) 2012-2015 Wind River Systems, Inc. * Copyright (c) 2012-2015 Wind River Systems, Inc.
* Copyright (c) 2020 Intel Corporation * Copyright (c) 2020,2023 Intel Corporation
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
/*
* @file measure time for mutex lock and unlock
*
* This file contains the test that measures mutex lock and unlock times
* in the kernel. There is no contention on the mutex being tested.
*/
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/timing/timing.h> #include <zephyr/timing/timing.h>
#include "utils.h" #include "utils.h"
/* the number of mutex lock/unlock cycles */ static K_MUTEX_DEFINE(test_mutex);
#define N_TEST_MUTEX 1000
K_MUTEX_DEFINE(test_mutex); static void start_lock_unlock(void *p1, void *p2, void *p3)
{
uint32_t i;
uint32_t num_iterations = (uint32_t)(uintptr_t)p1;
timing_t start;
timing_t finish;
uint64_t lock_cycles;
uint64_t unlock_cycles;
ARG_UNUSED(p2);
ARG_UNUSED(p3);
start = timing_counter_get();
/* Recursively lock take the mutex */
for (i = 0; i < num_iterations; i++) {
k_mutex_lock(&test_mutex, K_NO_WAIT);
}
finish = timing_counter_get();
lock_cycles = timing_cycles_get(&start, &finish);
start = timing_counter_get();
/* Recursively unlock the mutex */
for (i = 0; i < num_iterations; i++) {
k_mutex_unlock(&test_mutex);
}
finish = timing_counter_get();
unlock_cycles = timing_cycles_get(&start, &finish);
timestamp.cycles = lock_cycles;
k_sem_take(&pause_sem, K_FOREVER);
timestamp.cycles = unlock_cycles;
}
/** /**
@ -24,55 +70,41 @@ K_MUTEX_DEFINE(test_mutex);
* *
* @return 0 on success * @return 0 on success
*/ */
int mutex_lock_unlock(void) int mutex_lock_unlock(uint32_t num_iterations, uint32_t options)
{ {
int i; char description[80];
uint32_t diff; int priority;
timing_t timestamp_start; uint64_t cycles;
timing_t timestamp_end;
const char *notes = "";
int end;
timing_start(); timing_start();
bench_test_start();
timestamp_start = timing_counter_get(); priority = k_thread_priority_get(k_current_get());
for (i = 0; i < N_TEST_MUTEX; i++) { k_thread_create(&start_thread, start_stack,
k_mutex_lock(&test_mutex, K_FOREVER); K_THREAD_STACK_SIZEOF(start_stack),
} start_lock_unlock,
(void *)(uintptr_t)num_iterations, NULL, NULL,
priority - 1, options, K_FOREVER);
timestamp_end = timing_counter_get(); k_thread_access_grant(&start_thread, &test_mutex, &pause_sem);
end = bench_test_end(); k_thread_start(&start_thread);
diff = timing_cycles_get(&timestamp_start, &timestamp_end); cycles = timestamp.cycles;
k_sem_give(&pause_sem);
if (end != 0) { snprintf(description, sizeof(description),
notes = TICK_OCCURRENCE_ERROR; "Lock a mutex from %s thread",
error_count++; (options & K_USER) == K_USER ? "user" : "kernel");
} PRINT_STATS_AVG(description, (uint32_t)cycles, num_iterations,
false, "");
PRINT_STATS_AVG("Average time to lock a mutex", diff, N_TEST_MUTEX, cycles = timestamp.cycles;
false, notes);
bench_test_start(); snprintf(description, sizeof(description),
timestamp_start = timing_counter_get(); "Unlock a mutex from %s thread",
(options & K_USER) == K_USER ? "user" : "kernel");
for (i = 0; i < N_TEST_MUTEX; i++) { PRINT_STATS_AVG(description, (uint32_t)cycles, num_iterations,
k_mutex_unlock(&test_mutex); false, "");
}
timestamp_end = timing_counter_get();
end = bench_test_end();
diff = timing_cycles_get(&timestamp_start, &timestamp_end);
if (end != 0) {
notes = TICK_OCCURRENCE_ERROR;
error_count++;
}
PRINT_STATS_AVG("Average time to unlock a mutex", diff, N_TEST_MUTEX,
false, notes);
timing_stop(); timing_stop();
return 0; return 0;