1 /*
2 * Copyright (c) 2012-2015 Wind River Systems, Inc.
3 * Copyright (c) 2020,2023 Intel Corporation
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 /*
9 * @file measure time for mutex lock and unlock
10 *
11 * This file contains the test that measures mutex lock and unlock times
12 * in the kernel. There is no contention on the mutex being tested.
13 */
14
15 #include <zephyr/kernel.h>
16 #include <zephyr/timing/timing.h>
17 #include "utils.h"
18 #include "timing_sc.h"
19
20 static K_MUTEX_DEFINE(test_mutex);
21
start_lock_unlock(void * p1,void * p2,void * p3)22 static void start_lock_unlock(void *p1, void *p2, void *p3)
23 {
24 uint32_t i;
25 uint32_t num_iterations = (uint32_t)(uintptr_t)p1;
26 timing_t start;
27 timing_t finish;
28 uint64_t lock_cycles;
29 uint64_t unlock_cycles;
30
31 ARG_UNUSED(p2);
32 ARG_UNUSED(p3);
33
34 start = timing_timestamp_get();
35
36 /* Recursively lock take the mutex */
37
38 for (i = 0; i < num_iterations; i++) {
39 k_mutex_lock(&test_mutex, K_NO_WAIT);
40 }
41
42 finish = timing_timestamp_get();
43
44 lock_cycles = timing_cycles_get(&start, &finish);
45
46 start = timing_timestamp_get();
47
48 /* Recursively unlock the mutex */
49
50 for (i = 0; i < num_iterations; i++) {
51 k_mutex_unlock(&test_mutex);
52 }
53
54 finish = timing_timestamp_get();
55
56 unlock_cycles = timing_cycles_get(&start, &finish);
57
58 timestamp.cycles = lock_cycles;
59 k_sem_take(&pause_sem, K_FOREVER);
60
61 timestamp.cycles = unlock_cycles;
62 }
63
64
65 /**
66 *
67 * @brief Test for the multiple mutex lock/unlock time
68 *
69 * The routine performs multiple mutex locks and then multiple mutex
70 * unlocks to measure the necessary time.
71 *
72 * @return 0 on success
73 */
mutex_lock_unlock(uint32_t num_iterations,uint32_t options)74 int mutex_lock_unlock(uint32_t num_iterations, uint32_t options)
75 {
76 char tag[50];
77 char description[120];
78 int priority;
79 uint64_t cycles;
80
81 timing_start();
82
83 priority = k_thread_priority_get(k_current_get());
84
85 k_thread_create(&start_thread, start_stack,
86 K_THREAD_STACK_SIZEOF(start_stack),
87 start_lock_unlock,
88 (void *)(uintptr_t)num_iterations, NULL, NULL,
89 priority - 1, options, K_FOREVER);
90
91 k_thread_access_grant(&start_thread, &test_mutex, &pause_sem);
92 k_thread_start(&start_thread);
93
94 cycles = timestamp.cycles;
95 k_sem_give(&pause_sem);
96
97 snprintf(tag, sizeof(tag),
98 "mutex.lock.immediate.recursive.%s",
99 (options & K_USER) == K_USER ? "user" : "kernel");
100 snprintf(description, sizeof(description),
101 "%-40s - Lock a mutex", tag);
102 PRINT_STATS_AVG(description, (uint32_t)cycles, num_iterations,
103 false, "");
104
105 cycles = timestamp.cycles;
106
107 snprintf(tag, sizeof(tag),
108 "mutex.unlock.immediate.recursive.%s",
109 (options & K_USER) == K_USER ? "user" : "kernel");
110 snprintf(description, sizeof(description),
111 "%-40s - Unlock a mutex", tag);
112 PRINT_STATS_AVG(description, (uint32_t)cycles, num_iterations,
113 false, "");
114
115 timing_stop();
116 return 0;
117 }
118