1 /* pipe_b.c */
2 
3 /*
4  * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include "master.h"
10 
11 #define PRINT_ALL_TO_N_HEADER_UNIT()                                       \
12 	PRINT_STRING("|   size(B) |       time/packet (nsec)       |     " \
13 		     "     KB/sec                |\n")
14 
15 #define PRINT_ALL_TO_N() \
16 	PRINT_F("|%5u|%5u|%10u|%10u|%10u|%10u|%10u|%10u|\n",                 \
17 		putsize, putsize, puttime[0], puttime[1],                    \
18 		puttime[2],                                                  \
19 		(1000000 * putsize) / SAFE_DIVISOR(puttime[0]),              \
20 		(1000000 * putsize) / SAFE_DIVISOR(puttime[1]),              \
21 		(1000000 * putsize) / SAFE_DIVISOR(puttime[2]))
22 
23 #define PRINT_1_TO_N_HEADER()                                                 \
24 	do {                                                                  \
25 		PRINT_STRING("|   size(B) |       time/packet (nsec)       |" \
26 			     "          KB/sec                |\n");          \
27 		PRINT_STRING(dashline);                                       \
28 	} while (0)
29 
30 #define  PRINT_1_TO_N()                                                 \
31 	PRINT_F("|%5u|%5d|%10u|%10u|%10u|%10u|%10u|%10u|\n",	        \
32 		putsize,                                                \
33 		getsize,                                                \
34 		puttime[0],                                             \
35 		puttime[1],                                             \
36 		puttime[2],                                             \
37 		(uint32_t)(((uint64_t)putsize * 1000000U) /             \
38 			   SAFE_DIVISOR(puttime[0])),                   \
39 		(uint32_t)(((uint64_t)putsize * 1000000U) /             \
40 			   SAFE_DIVISOR(puttime[1])),                   \
41 		(uint32_t)(((uint64_t)putsize * 1000000U) /             \
42 			   SAFE_DIVISOR(puttime[2])))
43 
44 /*
45  * Function prototypes.
46  */
47 int pipeput(struct k_pipe *pipe, enum pipe_options
48 		 option, int size, int count, uint32_t *time);
49 
50 /*
51  * Function declarations.
52  */
53 
54 /**
55  * @brief Test the pipes transfer speed
56  */
pipe_test(void)57 void pipe_test(void)
58 {
59 	uint32_t	putsize;
60 	int         getsize;
61 	uint32_t	puttime[3];
62 	int		putcount;
63 	int		pipe;
64 	uint32_t	TaskPrio = UINT32_MAX;
65 	int		prio;
66 	struct getinfo	getinfo;
67 
68 	k_sem_reset(&SEM0);
69 	k_sem_give(&STARTRCV);
70 
71 	/* action: */
72 
73 	/* non-buffered operation, matching (ALL_N) */
74 	PRINT_STRING(dashline);
75 	PRINT_STRING("|                   "
76 		     "P I P E   M E A S U R E M E N T S"
77 		     "                         |\n");
78 	PRINT_STRING(dashline);
79 	PRINT_STRING("| Send data into a pipe towards a "
80 		     "receiving high priority task and wait       |\n");
81 	PRINT_STRING(dashline);
82 	PRINT_STRING("|                          "
83 		     "matching sizes (_ALL_N)"
84 		     "                            |\n");
85 	PRINT_STRING(dashline);
86 	PRINT_ALL_TO_N_HEADER_UNIT();
87 	PRINT_STRING(dashline);
88 	PRINT_STRING("| put | get |  no buf  | small buf| big buf  |"
89 		     "  no buf  | small buf| big buf  |\n");
90 	PRINT_STRING(dashline);
91 
92 	for (putsize = 8U; putsize <= MESSAGE_SIZE_PIPE; putsize <<= 1) {
93 		for (pipe = 0; pipe < 3; pipe++) {
94 			putcount = NR_OF_PIPE_RUNS;
95 			pipeput(test_pipes[pipe], _ALL_N, putsize, putcount,
96 				 &puttime[pipe]);
97 
98 			/* waiting for ack */
99 			k_msgq_get(&CH_COMM, &getinfo, K_FOREVER);
100 		}
101 		PRINT_ALL_TO_N();
102 	}
103 	PRINT_STRING(dashline);
104 
105 	/* Test with two different sender priorities */
106 	for (prio = 0; prio < 2; prio++) {
107 		/* non-buffered operation, non-matching (1_TO_N) */
108 		if (prio == 0) {
109 			PRINT_STRING("|                      "
110 			 "non-matching sizes (1_TO_N) to higher priority"
111 						 "         |\n");
112 			TaskPrio = k_thread_priority_get(k_current_get());
113 		}
114 		if (prio == 1) {
115 			PRINT_STRING("|                      "
116 				 "non-matching sizes (1_TO_N) to lower priority"
117 						 "          |\n");
118 			k_thread_priority_set(k_current_get(), TaskPrio - 2);
119 		}
120 		PRINT_STRING(dashline);
121 		PRINT_1_TO_N_HEADER();
122 		PRINT_STRING("| put | get |  no buf  | small buf| big buf  |  "
123 			     "no buf  | small buf| big buf  |\n");
124 		PRINT_STRING(dashline);
125 
126 	for (putsize = 8U; putsize <= (MESSAGE_SIZE_PIPE); putsize <<= 1) {
127 		putcount = MESSAGE_SIZE_PIPE / putsize;
128 		for (pipe = 0; pipe < 3; pipe++) {
129 			pipeput(test_pipes[pipe], _1_TO_N, putsize,
130 					 putcount, &puttime[pipe]);
131 			/* size*count == MESSAGE_SIZE_PIPE */
132 			/* waiting for ack */
133 			k_msgq_get(&CH_COMM, &getinfo, K_FOREVER);
134 			getsize = getinfo.size;
135 		}
136 		PRINT_1_TO_N();
137 	}
138 		PRINT_STRING(dashline);
139 		k_thread_priority_set(k_current_get(), TaskPrio);
140 	}
141 }
142 
143 
144 /**
145  * @brief Write a data portion to the pipe and measure time
146  *
147  * @return 0 on success, 1 on error
148  *
149  * @param pipe     The pipe to be tested.
150  * @param option   _ALL_TO_N or _1_TO_N.
151  * @param size     Data chunk size.
152  * @param count    Number of data chunks.
153  * @param time     Total write time.
154  */
pipeput(struct k_pipe * pipe,enum pipe_options option,int size,int count,uint32_t * time)155 int pipeput(struct k_pipe *pipe,
156 	    enum pipe_options option,
157 	    int size,
158 	    int count,
159 	    uint32_t *time)
160 {
161 	int i;
162 	unsigned int t;
163 	timing_t  start;
164 	timing_t  end;
165 	size_t sizexferd_total = 0;
166 	size_t size2xfer_total = size * count;
167 
168 	/* first sync with the receiver */
169 	k_sem_give(&SEM0);
170 	start = timing_timestamp_get();
171 	for (i = 0; option == _1_TO_N || (i < count); i++) {
172 		size_t sizexferd = 0;
173 		size_t size2xfer = MIN(size, size2xfer_total - sizexferd_total);
174 		int ret;
175 		size_t mim_num_of_bytes = 0;
176 
177 		if (option == _ALL_N) {
178 			mim_num_of_bytes = size2xfer;
179 		}
180 		ret = k_pipe_put(pipe, data_bench, size2xfer,
181 				&sizexferd, mim_num_of_bytes, K_FOREVER);
182 
183 		if (ret != 0) {
184 			return 1;
185 		}
186 		if (option == _ALL_N && sizexferd != size2xfer) {
187 			return 1;
188 		}
189 
190 		sizexferd_total += sizexferd;
191 		if (size2xfer_total == sizexferd_total) {
192 			break;
193 		}
194 
195 		if (size2xfer_total < sizexferd_total) {
196 			return 1;
197 		}
198 	}
199 
200 	end = timing_timestamp_get();
201 	t = (unsigned int)timing_cycles_get(&start, &end);
202 
203 	*time = SYS_CLOCK_HW_CYCLES_TO_NS_AVG(t, count);
204 
205 	return 0;
206 }
207