| /* |
| * Copyright (c) 2013-2015 Wind River Systems, Inc. |
| * Copyright (c) 2016 Intel Corporation. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <kernel.h> |
| #include <zephyr.h> |
| #include <tc_util.h> |
| #include <ksched.h> |
| #include "timing_info.h" |
| |
| extern char sline[]; |
| |
| /* mailbox*/ |
| /* K_MBOX_DEFINE(test_msg_queue) */ |
| K_MSGQ_DEFINE(benchmark_q, sizeof(int), 10, 4); |
| K_MSGQ_DEFINE(benchmark_q_get, sizeof(int), 3, 4); |
| K_MBOX_DEFINE(benchmark_mbox); |
| |
| /* Declare a semaphore for the msgq*/ |
| K_SEM_DEFINE(mbox_sem, 1, 1); |
| |
| /* common location for the swap to write the tsc data*/ |
| extern u32_t __read_swap_end_time_value; |
| extern u64_t __common_var_swap_end_time; |
| |
| /* location of the time stamps*/ |
| u64_t __msg_q_put_state; |
| u64_t __msg_q_get_state; |
| |
| u64_t __msg_q_put_w_cxt_start_time; |
| u64_t __msg_q_put_w_cxt_end_time; |
| |
| u64_t __msg_q_put_wo_cxt_start_time; /* without context switch */ |
| u64_t __msg_q_put_wo_cxt_end_time; |
| |
| u64_t __msg_q_get_w_cxt_start_time; |
| u64_t __msg_q_get_w_cxt_end_time; |
| |
| u64_t msg_q_get_wo_cxt_start_time; |
| u64_t msg_q_get_wo_cxt_end_time; |
| |
| u32_t __mbox_sync_put_state; |
| u64_t mbox_sync_put_start_time; |
| u64_t mbox_sync_put_end_time; |
| |
| u32_t __mbox_sync_get_state; |
| u64_t mbox_sync_get_start_time; |
| u64_t mbox_sync_get_end_time; |
| |
| u64_t mbox_async_put_start_time; |
| u64_t mbox_async_put_end_time; |
| |
| u64_t mbox_get_w_cxt_start_time; |
| u64_t mbox_get_w_cxt_end_time; |
| |
| /*For benchmarking msg queues*/ |
| k_tid_t producer_w_cxt_switch_tid; |
| k_tid_t producer_wo_cxt_switch_tid; |
| k_tid_t producer_get_w_cxt_switch_tid; |
| k_tid_t consumer_get_w_cxt_switch_tid; |
| extern k_tid_t consumer_tid; |
| k_tid_t thread_mbox_sync_put_send_tid; |
| k_tid_t thread_mbox_sync_put_receive_tid; |
| k_tid_t thread_mbox_sync_get_send_tid; |
| k_tid_t thread_mbox_sync_get_receive_tid; |
| k_tid_t thread_mbox_async_put_send_tid; |
| k_tid_t thread_mbox_async_put_receive_tid; |
| |
| /* To time thread creation*/ |
| extern K_THREAD_STACK_DEFINE(my_stack_area, STACK_SIZE); |
| extern K_THREAD_STACK_DEFINE(my_stack_area_0, STACK_SIZE); |
| extern struct k_thread my_thread; |
| extern struct k_thread my_thread_0; |
| |
| /* thread functions*/ |
| void thread_producer_msgq_w_cxt_switch(void *p1, void *p2, void *p3); |
| void thread_producer_msgq_wo_cxt_switch(void *p1, void *p2, void *p3); |
| |
| void thread_producer_get_msgq_w_cxt_switch(void *p1, void *p2, void *p3); |
| void thread_consumer_get_msgq_w_cxt_switch(void *p1, void *p2, void *p3); |
| |
| void thread_mbox_sync_put_send(void *p1, void *p2, void *p3); |
| void thread_mbox_sync_put_receive(void *p1, void *p2, void *p3); |
| |
| void thread_mbox_sync_get_send(void *p1, void *p2, void *p3); |
| void thread_mbox_sync_get_receive(void *p1, void *p2, void *p3); |
| |
| void thread_mbox_async_put_send(void *p1, void *p2, void *p3); |
| void thread_mbox_async_put_receive(void *p1, void *p2, void *p3); |
| |
| volatile u64_t time_check; |
| int received_data_get; |
| int received_data_consumer; |
| int data_to_send; |
| |
| #define MBOX_CHECK(status) { if (status != 0) { \ |
| if (status == -ENOMSG) { \ |
| TC_PRINT("Returned -ENOMSG\n"); \ |
| return; \ |
| } else { /* Status will be -EAGAIN */ \ |
| TC_PRINT("Returned -EAGAIN\n"); \ |
| return; \ |
| } \ |
| } \ |
| } \ |
| |
| void msg_passing_bench(void) |
| { |
| DECLARE_VAR(msg_q, put_w_cxt) |
| DECLARE_VAR(msg_q, put_wo_cxt) |
| |
| DECLARE_VAR(msg_q, get_w_cxt) |
| DECLARE_VAR(msg_q, get_wo_cxt) |
| |
| DECLARE_VAR(mbox, sync_put) |
| DECLARE_VAR(mbox, sync_get) |
| DECLARE_VAR(mbox, async_put) |
| |
| DECLARE_VAR(mbox, get_w_cxt) |
| |
| |
| /*******************************************************************/ |
| /* Msg queue for put*/ |
| int received_data = 0; |
| |
| producer_w_cxt_switch_tid = |
| k_thread_create(&my_thread, my_stack_area, STACK_SIZE, |
| thread_producer_msgq_w_cxt_switch, NULL, |
| NULL, NULL, 2 /*priority*/, 0, 50); |
| |
| u32_t msg_status = k_msgq_get(&benchmark_q, &received_data, 300); |
| |
| producer_wo_cxt_switch_tid = |
| k_thread_create(&my_thread_0, my_stack_area_0, STACK_SIZE, |
| thread_producer_msgq_wo_cxt_switch, |
| NULL, NULL, NULL, -2 /*priority*/, 0, 0); |
| |
| k_thread_abort(producer_w_cxt_switch_tid); |
| k_thread_abort(producer_wo_cxt_switch_tid); |
| __msg_q_put_w_cxt_end_time = ((u32_t)__common_var_swap_end_time); |
| ARG_UNUSED(msg_status); |
| |
| /*******************************************************************/ |
| |
| /* Msg queue for get*/ |
| |
| producer_get_w_cxt_switch_tid = |
| k_thread_create(&my_thread, my_stack_area, |
| STACK_SIZE, |
| thread_producer_get_msgq_w_cxt_switch, NULL, |
| NULL, NULL, 1 /*priority*/, 0, 50); |
| consumer_get_w_cxt_switch_tid = |
| k_thread_create(&my_thread_0, my_stack_area_0, |
| STACK_SIZE, |
| thread_consumer_get_msgq_w_cxt_switch, |
| NULL, NULL, NULL, |
| 2 /*priority*/, 0, 50); |
| k_sleep(2000); /* make the main thread sleep */ |
| k_thread_abort(producer_get_w_cxt_switch_tid); |
| __msg_q_get_w_cxt_end_time = (__common_var_swap_end_time); |
| |
| /*******************************************************************/ |
| |
| /* Msg queue for get*/ |
| /* from previous step got the msg_q full now just do a simple read*/ |
| TIMING_INFO_PRE_READ(); |
| msg_q_get_wo_cxt_start_time = TIMING_INFO_OS_GET_TIME(); |
| |
| received_data_get = k_msgq_get(&benchmark_q_get, |
| &received_data_consumer, |
| K_NO_WAIT); |
| |
| TIMING_INFO_PRE_READ(); |
| msg_q_get_wo_cxt_end_time = TIMING_INFO_OS_GET_TIME(); |
| |
| |
| /*******************************************************************/ |
| |
| /* Msg box to benchmark sync put */ |
| |
| thread_mbox_sync_put_send_tid = |
| k_thread_create(&my_thread, my_stack_area, |
| STACK_SIZE, |
| thread_mbox_sync_put_send, |
| NULL, NULL, NULL, |
| 2 /*priority*/, 0, 0); |
| thread_mbox_sync_put_receive_tid = |
| k_thread_create(&my_thread_0, my_stack_area_0, |
| STACK_SIZE, |
| thread_mbox_sync_put_receive, |
| NULL, NULL, NULL, |
| 1 /*priority*/, 0, 0); |
| k_sleep(1000); /* make the main thread sleep */ |
| mbox_sync_put_end_time = (__common_var_swap_end_time); |
| |
| /*******************************************************************/ |
| |
| /* Msg box to benchmark sync get */ |
| |
| thread_mbox_sync_get_send_tid = |
| k_thread_create(&my_thread, my_stack_area, |
| STACK_SIZE, |
| thread_mbox_sync_get_send, |
| NULL, NULL, NULL, |
| 1 /*prio*/, 0, 0); |
| thread_mbox_sync_get_receive_tid = |
| k_thread_create(&my_thread_0, my_stack_area_0, |
| STACK_SIZE, |
| thread_mbox_sync_get_receive, NULL, |
| NULL, NULL, 2 /*priority*/, 0, 0); |
| k_sleep(1000); /* make the main thread sleep */ |
| mbox_sync_get_end_time = (__common_var_swap_end_time); |
| |
| /*******************************************************************/ |
| |
| /* Msg box to benchmark async put */ |
| |
| thread_mbox_async_put_send_tid = |
| k_thread_create(&my_thread, my_stack_area, |
| STACK_SIZE, |
| thread_mbox_async_put_send, |
| NULL, NULL, NULL, |
| 2 /*prio*/, 0, 0); |
| thread_mbox_async_put_receive_tid = |
| k_thread_create(&my_thread_0, my_stack_area_0, |
| STACK_SIZE, |
| thread_mbox_async_put_receive, |
| NULL, NULL, NULL, |
| 3 /*priority*/, 0, 0); |
| k_sleep(1000); /* make the main thread sleep */ |
| |
| /*******************************************************************/ |
| int single_element_buffer = 0, status; |
| struct k_mbox_msg rx_msg = { |
| .size = sizeof(int), |
| .rx_source_thread = K_ANY, |
| .tx_target_thread = K_ANY |
| }; |
| TIMING_INFO_PRE_READ(); |
| mbox_get_w_cxt_start_time = TIMING_INFO_OS_GET_TIME(); |
| |
| status = k_mbox_get(&benchmark_mbox, &rx_msg, &single_element_buffer, 300); |
| MBOX_CHECK(status); |
| |
| TIMING_INFO_PRE_READ(); |
| mbox_get_w_cxt_end_time = TIMING_INFO_OS_GET_TIME(); |
| |
| /*******************************************************************/ |
| |
| /* calculation for msg put with context switch */ |
| CALCULATE_TIME(__, msg_q, put_w_cxt) |
| |
| /* calculation for msg put without context switch */ |
| CALCULATE_TIME(__, msg_q, put_wo_cxt) |
| |
| /* calculation for msg get */ |
| CALCULATE_TIME(__, msg_q, get_w_cxt) |
| |
| /* calculation for msg get without context switch */ |
| CALCULATE_TIME(, msg_q, get_wo_cxt) |
| |
| /*calculation for msg box for sync put |
| * (i.e with a context to make the pending rx ready) |
| */ |
| CALCULATE_TIME(, mbox, sync_put) |
| |
| /*calculation for msg box for sync get |
| * (i.e with a context to make the pending tx ready) |
| */ |
| CALCULATE_TIME(, mbox, sync_get) |
| |
| /* calculation for msg box for async put */ |
| CALCULATE_TIME(, mbox, async_put) |
| |
| /* calculation for msg box for get without any context switch */ |
| CALCULATE_TIME(, mbox, get_w_cxt) |
| |
| /*******************************************************************/ |
| |
| /* Only print lower 32bit of time result */ |
| PRINT_STATS("Message Queue Put with context switch", |
| (u32_t)((__msg_q_put_w_cxt_end_time - |
| __msg_q_put_w_cxt_start_time) & 0xFFFFFFFFULL), |
| (u32_t) (total_msg_q_put_w_cxt_time & 0xFFFFFFFFULL)); |
| |
| PRINT_STATS("Message Queue Put without context switch", |
| (u32_t)((__msg_q_put_wo_cxt_end_time - |
| __msg_q_put_wo_cxt_start_time) & 0xFFFFFFFFULL), |
| (u32_t) (total_msg_q_put_wo_cxt_time & 0xFFFFFFFFULL)); |
| |
| PRINT_STATS("Message Queue get with context switch", |
| (u32_t)((__msg_q_get_w_cxt_end_time - |
| __msg_q_get_w_cxt_start_time) & 0xFFFFFFFFULL), |
| (u32_t) (total_msg_q_get_w_cxt_time & 0xFFFFFFFFULL)); |
| |
| PRINT_STATS("Message Queue get without context switch", |
| (u32_t)((msg_q_get_wo_cxt_end_time - |
| msg_q_get_wo_cxt_start_time) & 0xFFFFFFFFULL), |
| (u32_t) (total_msg_q_get_wo_cxt_time & 0xFFFFFFFFULL)); |
| |
| PRINT_STATS("MailBox synchronous put", |
| (u32_t)((mbox_sync_put_end_time - mbox_sync_put_start_time) |
| & 0xFFFFFFFFULL), |
| (u32_t) (total_mbox_sync_put_time & 0xFFFFFFFFULL)); |
| |
| PRINT_STATS("MailBox synchronous get", |
| (u32_t)((mbox_sync_get_end_time - mbox_sync_get_start_time) |
| & 0xFFFFFFFFULL), |
| (u32_t) (total_mbox_sync_get_time & 0xFFFFFFFFULL)); |
| |
| PRINT_STATS("MailBox asynchronous put", |
| (u32_t)((mbox_async_put_end_time - mbox_async_put_start_time) |
| & 0xFFFFFFFFULL), |
| (u32_t) (total_mbox_async_put_time & 0xFFFFFFFFULL)); |
| |
| PRINT_STATS("MailBox get without context switch", |
| (u32_t)((mbox_get_w_cxt_end_time - mbox_get_w_cxt_start_time) |
| & 0xFFFFFFFFULL), |
| (u32_t) (total_mbox_get_w_cxt_time & 0xFFFFFFFFULL)); |
| |
| } |
| |
| void thread_producer_msgq_w_cxt_switch(void *p1, void *p2, void *p3) |
| { |
| int data_to_send = 5050; |
| |
| __read_swap_end_time_value = 1U; |
| TIMING_INFO_PRE_READ(); |
| __msg_q_put_w_cxt_start_time = (u32_t) TIMING_INFO_OS_GET_TIME(); |
| k_msgq_put(&benchmark_q, &data_to_send, K_NO_WAIT); |
| } |
| |
| |
| void thread_producer_msgq_wo_cxt_switch(void *p1, void *p2, void *p3) |
| { |
| int data_to_send = 5050; |
| |
| TIMING_INFO_PRE_READ(); |
| __msg_q_put_wo_cxt_start_time = TIMING_INFO_OS_GET_TIME(); |
| |
| k_msgq_put(&benchmark_q, &data_to_send, K_NO_WAIT); |
| |
| TIMING_INFO_PRE_READ(); |
| __msg_q_put_wo_cxt_end_time = TIMING_INFO_OS_GET_TIME(); |
| } |
| |
| |
| void thread_producer_get_msgq_w_cxt_switch(void *p1, void *p2, void *p3) |
| { |
| int status = 0; |
| |
| while (1) { |
| if (status == 0) { |
| data_to_send++; |
| } |
| status = k_msgq_put(&benchmark_q_get, &data_to_send, 20); |
| } |
| } |
| |
| void thread_consumer_get_msgq_w_cxt_switch(void *p1, void *p2, void *p3) |
| { |
| producer_get_w_cxt_switch_tid->base.timeout.dticks = _EXPIRED; |
| __read_swap_end_time_value = 1U; |
| TIMING_INFO_PRE_READ(); |
| __msg_q_get_w_cxt_start_time = TIMING_INFO_OS_GET_TIME(); |
| received_data_get = k_msgq_get(&benchmark_q_get, |
| &received_data_consumer, |
| 300); |
| TIMING_INFO_PRE_READ(); |
| time_check = TIMING_INFO_OS_GET_TIME(); |
| } |
| |
| |
| void thread_mbox_sync_put_send(void *p1, void *p2, void *p3) |
| { |
| int single_element_buffer = 1234, status; |
| struct k_mbox_msg tx_msg = { |
| .size = sizeof(int), |
| .info = 5050, |
| .tx_data = &single_element_buffer, |
| .rx_source_thread = K_ANY, |
| .tx_target_thread = K_ANY, |
| }; |
| |
| TIMING_INFO_PRE_READ(); |
| mbox_sync_put_start_time = TIMING_INFO_OS_GET_TIME(); |
| __read_swap_end_time_value = 1U; |
| |
| status = k_mbox_put(&benchmark_mbox, &tx_msg, 300); |
| MBOX_CHECK(status); |
| |
| TIMING_INFO_PRE_READ(); |
| time_check = TIMING_INFO_OS_GET_TIME(); |
| } |
| |
| void thread_mbox_sync_put_receive(void *p1, void *p2, void *p3) |
| { |
| int single_element_buffer = 1234, status; |
| struct k_mbox_msg rx_msg = { |
| .size = sizeof(int), |
| .rx_source_thread = K_ANY, |
| .tx_target_thread = K_ANY |
| }; |
| |
| status = k_mbox_get(&benchmark_mbox, &rx_msg, &single_element_buffer, 300); |
| MBOX_CHECK(status); |
| } |
| |
| void thread_mbox_sync_get_send(void *p1, void *p2, void *p3) |
| { |
| int single_element_buffer = 1234, status; |
| struct k_mbox_msg tx_msg = { |
| .size = sizeof(int), |
| .info = 5050, |
| .tx_data = &single_element_buffer, |
| .rx_source_thread = K_ANY, |
| .tx_target_thread = K_ANY, |
| }; |
| |
| status = k_mbox_put(&benchmark_mbox, &tx_msg, 300); |
| MBOX_CHECK(status); |
| } |
| |
| void thread_mbox_sync_get_receive(void *p1, void *p2, void *p3) |
| { |
| int single_element_buffer, status; |
| struct k_mbox_msg rx_msg = { |
| .size = sizeof(int), |
| .rx_source_thread = K_ANY, |
| .tx_target_thread = K_ANY |
| }; |
| |
| __read_swap_end_time_value = 1U; |
| TIMING_INFO_PRE_READ(); |
| mbox_sync_get_start_time = TIMING_INFO_OS_GET_TIME(); |
| |
| status = k_mbox_get(&benchmark_mbox, &rx_msg, &single_element_buffer, 300); |
| MBOX_CHECK(status); |
| } |
| |
| void thread_mbox_async_put_send(void *p1, void *p2, void *p3) |
| { |
| int single_element_buffer = 1234; |
| struct k_mbox_msg tx_msg = { |
| .size = sizeof(int), |
| .info = 5050, |
| .tx_data = &single_element_buffer, |
| .rx_source_thread = K_ANY, |
| .tx_target_thread = K_ANY, |
| }; |
| |
| TIMING_INFO_PRE_READ(); |
| mbox_async_put_start_time = TIMING_INFO_OS_GET_TIME(); |
| k_mbox_async_put(&benchmark_mbox, &tx_msg, &mbox_sem); |
| TIMING_INFO_PRE_READ(); |
| mbox_async_put_end_time = TIMING_INFO_OS_GET_TIME(); |
| k_mbox_async_put(&benchmark_mbox, &tx_msg, &mbox_sem); |
| } |
| |
| void thread_mbox_async_put_receive(void *p1, void *p2, void *p3) |
| { |
| int single_element_buffer, status; |
| struct k_mbox_msg rx_msg = { |
| .size = sizeof(int), |
| .rx_source_thread = K_ANY, |
| .tx_target_thread = K_ANY |
| }; |
| |
| status = k_mbox_get(&benchmark_mbox, &rx_msg, &single_element_buffer, 300); |
| MBOX_CHECK(status); |
| } |