1 /*
2  * Copyright (c) 2021 Nordic Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Test log message
10  */
11 
12 #include <zephyr/sys/mpsc_pbuf.h>
13 
14 #include <zephyr/tc_util.h>
15 #include <stdbool.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/ztest.h>
18 #include <zephyr/random/random.h>
19 
20 #define PUT_EXT_LEN \
21 	((sizeof(union mpsc_pbuf_generic) + sizeof(void *)) / sizeof(uint32_t))
22 
23 #define LEN_BITS 9
24 
25 struct test_data {
26 	MPSC_PBUF_HDR;
27 	uint32_t len : LEN_BITS;
28 	uint32_t data : 32 - MPSC_PBUF_HDR_BITS - LEN_BITS;
29 };
30 
31 struct test_data_ext {
32 	struct test_data hdr;
33 	void *data;
34 } __packed;
35 
36 struct test_data_var {
37 	struct test_data hdr;
38 	uint32_t data[];
39 };
40 
41 union test_item {
42 	struct test_data data;
43 	struct test_data_ext data_ext;
44 	union mpsc_pbuf_generic item;
45 };
46 
get_wlen(const union mpsc_pbuf_generic * item)47 static uint32_t get_wlen(const union mpsc_pbuf_generic *item)
48 {
49 	union test_item *t_item = (union test_item *)item;
50 
51 	return t_item->data.len;
52 }
53 
54 static uint32_t drop_cnt;
55 static uint32_t exp_drop_cnt;
56 static uintptr_t exp_dropped_data[10];
57 static uint32_t exp_dropped_len[10];
58 
drop(const struct mpsc_pbuf_buffer * buffer,const union mpsc_pbuf_generic * item)59 static void drop(const struct mpsc_pbuf_buffer *buffer, const union mpsc_pbuf_generic *item)
60 {
61 	struct test_data_var *packet = (struct test_data_var *)item;
62 
63 	zassert_true(drop_cnt < exp_drop_cnt);
64 	zassert_equal(packet->hdr.len, exp_dropped_len[drop_cnt],
65 			"(%d) Got:%08x, Expected: %08x",
66 			drop_cnt, packet->hdr.len, exp_dropped_len[drop_cnt]);
67 	zassert_equal(packet->hdr.data, exp_dropped_data[drop_cnt],
68 			"(%d) Got:%08x, Expected: %08x",
69 			drop_cnt, packet->hdr.data, exp_dropped_data[drop_cnt]);
70 	for (int i = 0; i < exp_dropped_len[drop_cnt] - 1; i++) {
71 		int err = memcmp(packet->data, &exp_dropped_data[drop_cnt],
72 				 sizeof(uint32_t));
73 
74 
75 		zassert_equal(err, 0);
76 	}
77 
78 	drop_cnt++;
79 }
80 
81 static uint32_t buf32[512];
82 
83 static struct mpsc_pbuf_buffer_config mpsc_buf_cfg = {
84 	.buf = buf32,
85 	.size = ARRAY_SIZE(buf32),
86 	.notify_drop = drop,
87 	.get_wlen = get_wlen
88 };
89 
init(struct mpsc_pbuf_buffer * buffer,uint32_t wlen,bool overwrite)90 static void init(struct mpsc_pbuf_buffer *buffer, uint32_t wlen, bool overwrite)
91 {
92 	drop_cnt = 0;
93 	exp_drop_cnt = 0;
94 	mpsc_buf_cfg.flags = overwrite ? MPSC_PBUF_MODE_OVERWRITE : 0;
95 	mpsc_buf_cfg.size = wlen;
96 	mpsc_pbuf_init(buffer, &mpsc_buf_cfg);
97 
98 #if CONFIG_SOC_SERIES_NRF52X
99 	CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
100 	DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
101 	DWT->CYCCNT = 0;
102 #endif
103 }
104 
get_cyc(void)105 static inline uint32_t get_cyc(void)
106 {
107 #if CONFIG_SOC_SERIES_NRF52X
108 	return DWT->CYCCNT;
109 #else
110 	return k_cycle_get_32();
111 #endif
112 }
113 
item_put_no_overwrite(bool pow2)114 void item_put_no_overwrite(bool pow2)
115 {
116 	struct mpsc_pbuf_buffer buffer;
117 
118 	init(&buffer, 4 - !pow2, false);
119 
120 	int repeat = buffer.size*2;
121 	union test_item test_1word = {.data = {.valid = 1, .len = 1 }};
122 
123 	for (int i = 0; i < repeat; i++) {
124 		union test_item *t;
125 
126 		test_1word.data.data = i;
127 		mpsc_pbuf_put_word(&buffer, test_1word.item);
128 
129 		t = (union test_item *)mpsc_pbuf_claim(&buffer);
130 		zassert_true(t);
131 		zassert_equal(t->data.data, i);
132 		mpsc_pbuf_free(&buffer, &t->item);
133 
134 	}
135 
136 	zassert_is_null(mpsc_pbuf_claim(&buffer));
137 }
138 
ZTEST(log_buffer,test_item_put_no_overwrite)139 ZTEST(log_buffer, test_item_put_no_overwrite)
140 {
141 	item_put_no_overwrite(true);
142 	item_put_no_overwrite(false);
143 }
144 
item_put_overwrite(bool pow2)145 void item_put_overwrite(bool pow2)
146 {
147 	struct mpsc_pbuf_buffer buffer;
148 
149 	init(&buffer, 4 - !pow2, true);
150 
151 	union test_item test_1word = {.data = {.valid = 1, .len = 1 }};
152 
153 	exp_dropped_data[0] = 0;
154 	exp_dropped_len[0] = 1;
155 	exp_drop_cnt = 1;
156 
157 	for (int i = 0; i < buffer.size + 1; i++) {
158 		test_1word.data.data = i;
159 		mpsc_pbuf_put_word(&buffer, test_1word.item);
160 	}
161 
162 	zassert_equal(drop_cnt, exp_drop_cnt,
163 			"Unexpected number of dropped messages: %d", drop_cnt);
164 }
165 
ZTEST(log_buffer,test_item_put_overwrite)166 ZTEST(log_buffer, test_item_put_overwrite)
167 {
168 	item_put_overwrite(true);
169 	item_put_overwrite(false);
170 }
171 
item_put_saturate(bool pow2)172 void item_put_saturate(bool pow2)
173 {
174 	struct mpsc_pbuf_buffer buffer;
175 
176 	init(&buffer, 4 - !pow2, false);
177 
178 	int repeat = buffer.size;
179 	union test_item test_1word = {.data = {.valid = 1, .len = 1 }};
180 	union test_item *t;
181 
182 	zassert_false(mpsc_pbuf_is_pending(&buffer));
183 
184 	for (int i = 0; i < repeat / 2; i++) {
185 		test_1word.data.data = i;
186 		mpsc_pbuf_put_word(&buffer, test_1word.item);
187 
188 		zassert_true(mpsc_pbuf_is_pending(&buffer));
189 
190 		t = (union test_item *)mpsc_pbuf_claim(&buffer);
191 		zassert_true(t);
192 		zassert_equal(t->data.data, i);
193 		mpsc_pbuf_free(&buffer, &t->item);
194 	}
195 
196 	for (int i = 0; i < repeat + 1; i++) {
197 		test_1word.data.data = i;
198 		mpsc_pbuf_put_word(&buffer, test_1word.item);
199 	}
200 
201 	for (int i = 0; i < repeat; i++) {
202 		t = (union test_item *)mpsc_pbuf_claim(&buffer);
203 		zassert_true(t);
204 		zassert_equal(t->data.data, i);
205 		mpsc_pbuf_free(&buffer, &t->item);
206 	}
207 
208 	zassert_is_null(mpsc_pbuf_claim(&buffer));
209 }
210 
ZTEST(log_buffer,test_item_put_saturate)211 ZTEST(log_buffer, test_item_put_saturate)
212 {
213 	item_put_saturate(true);
214 	item_put_saturate(false);
215 }
216 
benchmark_item_put(bool pow2)217 void benchmark_item_put(bool pow2)
218 {
219 	struct mpsc_pbuf_buffer buffer;
220 
221 	init(&buffer, ARRAY_SIZE(buf32) - !pow2, true);
222 
223 	int repeat = buffer.size - 1;
224 	union test_item test_1word = {.data = {.valid = 1, .len = 1 }};
225 	uint32_t t = get_cyc();
226 
227 	for (int i = 0; i < repeat; i++) {
228 		test_1word.data.data = i;
229 		mpsc_pbuf_put_word(&buffer, test_1word.item);
230 	}
231 
232 	t = get_cyc() - t;
233 	PRINT("%s buffer\n", pow2 ? "pow2" : "non-pow2");
234 	PRINT("single word put time: %d cycles\n", t/repeat);
235 
236 	t = get_cyc();
237 	for (int i = 0; i < repeat; i++) {
238 		union test_item *ti;
239 
240 		ti = (union test_item *)mpsc_pbuf_claim(&buffer);
241 		zassert_true(ti);
242 		zassert_equal(ti->data.data, i);
243 		mpsc_pbuf_free(&buffer, &ti->item);
244 	}
245 
246 	t = get_cyc() - t;
247 	PRINT("single word item claim,free: %d cycles\n", t/repeat);
248 
249 	zassert_is_null(mpsc_pbuf_claim(&buffer));
250 }
251 
ZTEST(log_buffer,test_benchmark_item_put)252 ZTEST(log_buffer, test_benchmark_item_put)
253 {
254 	benchmark_item_put(true);
255 	benchmark_item_put(false);
256 }
257 
item_put_ext_no_overwrite(bool pow2)258 void item_put_ext_no_overwrite(bool pow2)
259 {
260 	struct mpsc_pbuf_buffer buffer;
261 
262 	init(&buffer, 8 - !pow2, false);
263 
264 	int repeat = buffer.size * 2;
265 	union test_item test_ext_item = {
266 		.data = {
267 			.valid = 1,
268 			.len = PUT_EXT_LEN
269 		}
270 	};
271 	void *data;
272 
273 	for (uintptr_t i = 0; i < repeat; i++) {
274 		union test_item *t;
275 
276 		data = (void *)i;
277 		test_ext_item.data.data = i;
278 		mpsc_pbuf_put_word_ext(&buffer, test_ext_item.item, data);
279 
280 		t = (union test_item *)mpsc_pbuf_claim(&buffer);
281 		zassert_true(t);
282 		zassert_equal(t->data_ext.hdr.data, i);
283 		zassert_equal(t->data_ext.data, (void *)i);
284 		mpsc_pbuf_free(&buffer, &t->item);
285 	}
286 
287 	zassert_is_null(mpsc_pbuf_claim(&buffer));
288 }
289 
ZTEST(log_buffer,test_item_put_ext_no_overwrite)290 ZTEST(log_buffer, test_item_put_ext_no_overwrite)
291 {
292 	item_put_ext_no_overwrite(true);
293 	item_put_ext_no_overwrite(false);
294 }
295 
item_put_word_ext_overwrite(bool pow2)296 void item_put_word_ext_overwrite(bool pow2)
297 {
298 	struct mpsc_pbuf_buffer buffer;
299 
300 	init(&buffer, 8 - !pow2, true);
301 
302 	size_t w = (sizeof(uint32_t) + sizeof(void *)) / sizeof(uint32_t);
303 	int repeat = 1 + buffer.size / w;
304 	union test_item test_ext_item = {
305 		.data = {
306 			.valid = 1,
307 			.len = PUT_EXT_LEN
308 		}
309 	};
310 
311 	exp_dropped_data[0] = 0;
312 	exp_dropped_len[0] = w;
313 	exp_drop_cnt = 1;
314 
315 	for (uintptr_t i = 0; i < repeat; i++) {
316 		test_ext_item.data.data = i;
317 		mpsc_pbuf_put_word_ext(&buffer, test_ext_item.item, (void *)i);
318 	}
319 
320 	zassert_equal(drop_cnt, exp_drop_cnt,
321 			"Unexpected number of dropped messages: %d (exp: %d)",
322 			drop_cnt, exp_drop_cnt);
323 }
324 
ZTEST(log_buffer,test_item_put_word_ext_overwrite)325 ZTEST(log_buffer, test_item_put_word_ext_overwrite)
326 {
327 	item_put_word_ext_overwrite(true);
328 	item_put_word_ext_overwrite(false);
329 }
330 
item_put_ext_saturate(bool pow2)331 void item_put_ext_saturate(bool pow2)
332 {
333 	struct mpsc_pbuf_buffer buffer;
334 
335 	init(&buffer, 8 - !pow2, false);
336 
337 	int repeat = buffer.size / PUT_EXT_LEN;
338 	union test_item test_ext_item = {
339 		.data = {
340 			.valid = 1,
341 			.len = PUT_EXT_LEN
342 		}
343 	};
344 	void *data;
345 	union test_item *t;
346 
347 	for (uintptr_t i = 0; i < repeat/2; i++) {
348 		test_ext_item.data.data = i;
349 		data = (void *)i;
350 		mpsc_pbuf_put_word_ext(&buffer, test_ext_item.item, data);
351 
352 		t = (union test_item *)mpsc_pbuf_claim(&buffer);
353 		zassert_true(t);
354 		zassert_equal(t->data.data, i);
355 		mpsc_pbuf_free(&buffer, &t->item);
356 	}
357 
358 	for (uintptr_t i = 0; i < repeat; i++) {
359 		test_ext_item.data.data = i;
360 		data = (void *)i;
361 		mpsc_pbuf_put_word_ext(&buffer, test_ext_item.item, data);
362 	}
363 
364 	for (uintptr_t i = 0; i < repeat; i++) {
365 		t = (union test_item *)mpsc_pbuf_claim(&buffer);
366 		zassert_true(t);
367 		zassert_equal(t->data_ext.data, (void *)i);
368 		zassert_equal(t->data_ext.hdr.data, i);
369 		mpsc_pbuf_free(&buffer, &t->item);
370 	}
371 
372 	zassert_is_null(mpsc_pbuf_claim(&buffer));
373 }
374 
ZTEST(log_buffer,test_item_put_ext_saturate)375 ZTEST(log_buffer, test_item_put_ext_saturate)
376 {
377 	item_put_ext_saturate(true);
378 	item_put_ext_saturate(false);
379 }
380 
benchmark_item_put_ext(bool pow2)381 void benchmark_item_put_ext(bool pow2)
382 {
383 	struct mpsc_pbuf_buffer buffer;
384 
385 	init(&buffer, ARRAY_SIZE(buf32) - !pow2, false);
386 
387 	int repeat = (buffer.size - 1) / PUT_EXT_LEN;
388 	union test_item test_ext_item = {
389 		.data = {
390 			.valid = 1,
391 			.len = PUT_EXT_LEN
392 		}
393 	};
394 	void *data = NULL;
395 	uint32_t t = get_cyc();
396 
397 	for (int i = 0; i < repeat; i++) {
398 		test_ext_item.data.data = i;
399 		mpsc_pbuf_put_word_ext(&buffer, test_ext_item.item, data);
400 	}
401 
402 	t = get_cyc() - t;
403 	PRINT("%spow2 buffer\n", pow2 ? "" : "non-");
404 	PRINT("put_ext time: %d cycles\n", t/repeat);
405 
406 	t = get_cyc();
407 	for (int i = 0; i < repeat; i++) {
408 		union test_item *ti;
409 
410 		ti = (union test_item *)mpsc_pbuf_claim(&buffer);
411 		zassert_true(ti);
412 		zassert_equal(ti->data.data, i);
413 		mpsc_pbuf_free(&buffer, &ti->item);
414 	}
415 
416 	t = get_cyc() - t;
417 	PRINT("ext item claim,free: %d cycles\n", t/repeat);
418 
419 	zassert_is_null(mpsc_pbuf_claim(&buffer));
420 }
421 
ZTEST(log_buffer,test_benchmark_item_put_ext)422 ZTEST(log_buffer, test_benchmark_item_put_ext)
423 {
424 	benchmark_item_put_ext(true);
425 	benchmark_item_put_ext(false);
426 }
427 
benchmark_item_put_data(bool pow2)428 void benchmark_item_put_data(bool pow2)
429 {
430 	struct mpsc_pbuf_buffer buffer;
431 
432 	init(&buffer, ARRAY_SIZE(buf32) - !pow2, false);
433 
434 	int repeat = (buffer.size - 1) / PUT_EXT_LEN;
435 	union test_item test_ext_item = {
436 		.data_ext = {
437 			.hdr = {
438 				.valid = 1,
439 				.len = PUT_EXT_LEN
440 			},
441 			.data = NULL
442 		}
443 	};
444 	uint32_t cyc = get_cyc();
445 
446 	for (uintptr_t i = 0; i < repeat; i++) {
447 		test_ext_item.data_ext.hdr.data = i;
448 		test_ext_item.data_ext.data = (void *)i;
449 		mpsc_pbuf_put_data(&buffer, (uint32_t *)&test_ext_item,
450 				    PUT_EXT_LEN);
451 	}
452 
453 	cyc = get_cyc() - cyc;
454 	PRINT("%spow2 buffer\n", pow2 ? "" : "non-");
455 	PRINT("put_ext time: %d cycles\n", cyc/repeat);
456 
457 	cyc = get_cyc();
458 	for (int i = 0; i < repeat; i++) {
459 		union test_item *ti;
460 
461 		ti = (union test_item *)mpsc_pbuf_claim(&buffer);
462 		zassert_true(ti);
463 		zassert_equal(ti->data.data, i);
464 		mpsc_pbuf_free(&buffer, &ti->item);
465 	}
466 
467 	cyc = get_cyc() - cyc;
468 	PRINT("ext item claim,free: %d cycles\n", cyc/repeat);
469 
470 	zassert_is_null(mpsc_pbuf_claim(&buffer));
471 }
472 
ZTEST(log_buffer,test_benchmark_item_put_data)473 ZTEST(log_buffer, test_benchmark_item_put_data)
474 {
475 	benchmark_item_put_data(true);
476 	benchmark_item_put_data(false);
477 }
478 
item_put_data_overwrite(bool pow2)479 void item_put_data_overwrite(bool pow2)
480 {
481 	struct mpsc_pbuf_buffer buffer;
482 
483 	init(&buffer, 8 - !pow2, true);
484 
485 	size_t w = (sizeof(uint32_t) + sizeof(void *)) / sizeof(uint32_t);
486 	int repeat = 1 + buffer.size / w;
487 	static const int len = sizeof(struct test_data_ext) / sizeof(uint32_t);
488 	struct test_data_ext item = {
489 		.hdr = {
490 			.valid = 1,
491 			.len = len
492 		}
493 	};
494 
495 	exp_dropped_data[0] = 0;
496 	exp_dropped_len[0] = w;
497 	exp_drop_cnt = 1;
498 
499 	for (uintptr_t i = 0; i < repeat; i++) {
500 		void *vitem;
501 		item.data = (void *)i;
502 		item.hdr.data = i;
503 		vitem = (uint32_t *)&item;
504 		zassert_true(IS_PTR_ALIGNED(vitem, uint32_t), "unaligned ptr");
505 		mpsc_pbuf_put_data(&buffer, (uint32_t *)vitem, len);
506 	}
507 
508 	zassert_equal(drop_cnt, exp_drop_cnt,
509 			"Unexpected number of dropped messages: %d", drop_cnt);
510 }
511 
ZTEST(log_buffer,test_put_data_overwrite)512 ZTEST(log_buffer, test_put_data_overwrite)
513 {
514 	item_put_data_overwrite(true);
515 	item_put_data_overwrite(false);
516 }
517 
item_alloc_commit(bool pow2)518 void item_alloc_commit(bool pow2)
519 {
520 	struct mpsc_pbuf_buffer buffer;
521 
522 	init(&buffer, 16 - !pow2, false);
523 
524 	struct test_data_var *packet;
525 	uint32_t len = 5;
526 	int repeat = 1024;
527 
528 	for (int i = 0; i < repeat; i++) {
529 		packet = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, len,
530 								 K_NO_WAIT);
531 		packet->hdr.len = len;
532 		for (int j = 0; j < len - 1; j++) {
533 			packet->data[j] = i + j;
534 		}
535 
536 		mpsc_pbuf_commit(&buffer, (union mpsc_pbuf_generic *)packet);
537 
538 		packet = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
539 		zassert_true(packet);
540 		zassert_equal(packet->hdr.len, len);
541 
542 		for (int j = 0; j < len - 1; j++) {
543 			zassert_equal(packet->data[j], i + j);
544 		}
545 
546 		mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)packet);
547 	}
548 }
549 
ZTEST(log_buffer,test_item_alloc_commit)550 ZTEST(log_buffer, test_item_alloc_commit)
551 {
552 	item_alloc_commit(true);
553 	item_alloc_commit(false);
554 }
555 
item_max_alloc(bool overwrite)556 void item_max_alloc(bool overwrite)
557 {
558 	struct mpsc_pbuf_buffer buffer;
559 	struct test_data_var *packet;
560 
561 	init(&buffer, 8, overwrite);
562 
563 	/* First try to allocate the biggest possible packet. */
564 	for (int i = 0; i < 2; i++) {
565 		packet = (struct test_data_var *)mpsc_pbuf_alloc(&buffer,
566 								 buffer.size,
567 								 K_NO_WAIT);
568 		zassert_true(packet != NULL);
569 		packet->hdr.len = buffer.size;
570 		mpsc_pbuf_commit(&buffer, (union mpsc_pbuf_generic *)packet);
571 
572 		packet = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
573 		mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)packet);
574 	}
575 
576 	/* Too big packet cannot be allocated. */
577 	packet = (struct test_data_var *)mpsc_pbuf_alloc(&buffer,
578 							 buffer.size + 1,
579 							 K_NO_WAIT);
580 	zassert_true(packet == NULL);
581 }
582 
ZTEST(log_buffer,test_item_max_alloc)583 ZTEST(log_buffer, test_item_max_alloc)
584 {
585 	item_max_alloc(true);
586 	item_max_alloc(false);
587 }
588 
saturate_buffer_uneven(struct mpsc_pbuf_buffer * buffer,uint32_t len)589 static uint32_t saturate_buffer_uneven(struct mpsc_pbuf_buffer *buffer,
590 					uint32_t len)
591 {
592 	struct test_data_var *packet;
593 	uint32_t uneven = 3;
594 	uint32_t cnt = 0;
595 	int repeat =
596 		uneven + ((buffer->size - (uneven * len)) / len);
597 
598 	/* Put some data to include wrapping */
599 	for (int i = 0; i < uneven; i++) {
600 		packet = (struct test_data_var *)mpsc_pbuf_alloc(buffer, len,
601 								 K_NO_WAIT);
602 		packet->hdr.len = len;
603 		mpsc_pbuf_commit(buffer, (union mpsc_pbuf_generic *)packet);
604 
605 		packet = (struct test_data_var *)mpsc_pbuf_claim(buffer);
606 		zassert_true(packet);
607 		mpsc_pbuf_free(buffer, (union mpsc_pbuf_generic *)packet);
608 	}
609 
610 	for (int i = 0; i < repeat; i++) {
611 		packet = (struct test_data_var *)mpsc_pbuf_alloc(buffer, len,
612 								 K_NO_WAIT);
613 		zassert_true(packet);
614 		packet->hdr.len = len;
615 		packet->hdr.data = i;
616 		for (int j = 0; j < len - 1; j++) {
617 			packet->data[j] = i + j;
618 		}
619 
620 		mpsc_pbuf_commit(buffer, (union mpsc_pbuf_generic *)packet);
621 		cnt++;
622 	}
623 
624 	return cnt;
625 }
626 
item_alloc_commit_saturate(bool pow2)627 void item_alloc_commit_saturate(bool pow2)
628 {
629 	struct mpsc_pbuf_buffer buffer;
630 
631 	init(&buffer, 32 - !pow2, false);
632 
633 	saturate_buffer_uneven(&buffer, 5);
634 
635 	struct test_data_var *packet;
636 	uint32_t len = 5;
637 
638 	packet = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, len,
639 							 K_NO_WAIT);
640 	zassert_is_null(packet);
641 
642 	/* Get one packet from the buffer. */
643 	packet = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
644 	zassert_true(packet);
645 	mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)packet);
646 
647 	/* and try to allocate one more time, this time with success. */
648 	packet = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, len,
649 							 K_NO_WAIT);
650 	zassert_true(packet);
651 }
652 
ZTEST(log_buffer,test_item_alloc_commit_saturate)653 ZTEST(log_buffer, test_item_alloc_commit_saturate)
654 {
655 	item_alloc_commit_saturate(true);
656 	item_alloc_commit_saturate(false);
657 }
658 
item_alloc_preemption(bool pow2)659 void item_alloc_preemption(bool pow2)
660 {
661 	struct mpsc_pbuf_buffer buffer;
662 
663 	init(&buffer, ARRAY_SIZE(buf32) - !pow2, false);
664 
665 	struct test_data_var *p0;
666 	struct test_data_var *p1;
667 	struct test_data_var *p;
668 
669 	p0 = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, 10, K_NO_WAIT);
670 	zassert_true(p0);
671 	p0->hdr.len = 10;
672 
673 	/* Check that no packet is yet available */
674 	p = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
675 	zassert_is_null(p);
676 
677 	p1 = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, 20, K_NO_WAIT);
678 	zassert_true(p1);
679 	p1->hdr.len = 20;
680 
681 	/* Commit p1, p0 is still not committed, there should be no packets
682 	 * available for reading.
683 	 */
684 	mpsc_pbuf_commit(&buffer, (union mpsc_pbuf_generic *)p1);
685 
686 	/* Check that no packet is yet available */
687 	p = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
688 	zassert_is_null(p);
689 
690 	mpsc_pbuf_commit(&buffer, (union mpsc_pbuf_generic *)p0);
691 
692 	/* Validate that p0 is the first one. */
693 	p = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
694 	zassert_true(p);
695 	zassert_equal(p->hdr.len, 10);
696 	mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)p);
697 
698 	/* Validate that p1 is the next one. */
699 	p = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
700 	zassert_true(p);
701 	zassert_equal(p->hdr.len, 20);
702 	mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)p);
703 
704 	/* No more packets. */
705 	p = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
706 	zassert_is_null(p);
707 }
708 
ZTEST(log_buffer,test_item_alloc_preemption)709 ZTEST(log_buffer, test_item_alloc_preemption)
710 {
711 	item_alloc_preemption(true);
712 	item_alloc_preemption(false);
713 }
714 
overwrite(bool pow2)715 void overwrite(bool pow2)
716 {
717 	struct test_data_var *p;
718 	uint32_t fill_len = 5;
719 	uint32_t len0, len1;
720 	struct mpsc_pbuf_buffer buffer;
721 
722 	init(&buffer, 32 - !pow2, true);
723 	uint32_t packet_cnt = saturate_buffer_uneven(&buffer, fill_len);
724 
725 	zassert_equal(drop_cnt, exp_drop_cnt, NULL);
726 
727 	exp_dropped_data[0] = 0;
728 	exp_dropped_len[0] = fill_len;
729 	exp_drop_cnt++;
730 	exp_dropped_data[1] = 1;
731 	exp_dropped_len[1] = fill_len;
732 	exp_drop_cnt++;
733 
734 	len0 = 6;
735 	p = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, len0, K_NO_WAIT);
736 
737 	p->hdr.len = len0;
738 	mpsc_pbuf_commit(&buffer, (union mpsc_pbuf_generic *)p);
739 	zassert_equal(drop_cnt, exp_drop_cnt);
740 
741 	/* Request allocation which will require dropping 2 packets. */
742 	len1 = 9;
743 	exp_dropped_data[1] = 1;
744 	exp_dropped_len[1] = fill_len;
745 	exp_dropped_data[2] = 2;
746 	exp_dropped_len[2] = fill_len;
747 	exp_drop_cnt = 3;
748 
749 	p = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, len1, K_NO_WAIT);
750 
751 	p->hdr.len = len1;
752 	mpsc_pbuf_commit(&buffer, (union mpsc_pbuf_generic *)p);
753 	zassert_equal(drop_cnt, exp_drop_cnt);
754 
755 	for (int i = 0; i < (packet_cnt - drop_cnt); i++) {
756 		p = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
757 		zassert_true(p);
758 		zassert_equal(p->hdr.len, fill_len);
759 		zassert_equal(p->hdr.data, i + drop_cnt);
760 		for (int j = 0; j < fill_len - 1; j++) {
761 			zassert_equal(p->data[j], p->hdr.data + j);
762 		}
763 
764 		mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)p);
765 	}
766 
767 	p = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
768 	zassert_true(p);
769 	zassert_equal(p->hdr.len, len0);
770 	mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)p);
771 
772 	p = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
773 	zassert_true(p);
774 	zassert_equal(p->hdr.len, len1);
775 	mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)p);
776 
777 	p = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
778 	zassert_is_null(p);
779 }
780 
ZTEST(log_buffer,test_overwrite)781 ZTEST(log_buffer, test_overwrite)
782 {
783 	overwrite(true);
784 	overwrite(false);
785 }
786 
overwrite_while_claimed(bool pow2)787 void overwrite_while_claimed(bool pow2)
788 {
789 	struct test_data_var *p0;
790 	struct test_data_var *p1;
791 	struct mpsc_pbuf_buffer buffer;
792 
793 	init(&buffer, 32 - !pow2, true);
794 
795 	uint32_t fill_len = 5;
796 	uint32_t len = 6;
797 	uint32_t packet_cnt = saturate_buffer_uneven(&buffer, fill_len);
798 
799 	/* Start by claiming a packet. Buffer is now full. Allocation shall
800 	 * skip claimed packed and drop the next one.
801 	 */
802 	p0 = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
803 	zassert_true(p0);
804 	zassert_equal(p0->hdr.len, fill_len);
805 
806 	exp_dropped_data[0] = p0->hdr.data + 1; /* next packet is dropped */
807 	exp_dropped_len[0] = fill_len;
808 	exp_dropped_data[1] = p0->hdr.data + 2; /* next packet is dropped */
809 	exp_dropped_len[1] = fill_len;
810 	exp_drop_cnt = 2;
811 	p1 = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, 6, K_NO_WAIT);
812 	zassert_equal(drop_cnt, exp_drop_cnt);
813 	p1->hdr.len = len;
814 	mpsc_pbuf_commit(&buffer, (union mpsc_pbuf_generic *)p1);
815 
816 	mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)p0);
817 
818 	for (int i = 0; i < packet_cnt - drop_cnt - 1; i++) {
819 		p0 = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
820 		zassert_true(p0);
821 		zassert_equal(p0->hdr.len, fill_len);
822 		zassert_equal(p0->hdr.data, i + drop_cnt + 1);
823 		mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)p0);
824 	}
825 
826 	p0 = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
827 	zassert_true(p0);
828 	zassert_equal(p0->hdr.len, len);
829 
830 	p0 = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
831 	zassert_is_null(p0);
832 }
833 
ZTEST(log_buffer,test_overwrite_while_claimed)834 ZTEST(log_buffer, test_overwrite_while_claimed)
835 {
836 	overwrite_while_claimed(true);
837 	overwrite_while_claimed(false);
838 }
839 
overwrite_while_claimed2(bool pow2)840 void overwrite_while_claimed2(bool pow2)
841 {
842 	struct test_data_var *p0;
843 	struct test_data_var *p1;
844 	struct mpsc_pbuf_buffer buffer;
845 
846 	init(&buffer, 32 - !pow2, true);
847 
848 	uint32_t fill_len = 1;
849 	uint32_t len = 3;
850 	uint32_t packet_cnt = saturate_buffer_uneven(&buffer, fill_len);
851 
852 	/* Start by claiming a packet. Buffer is now full. Allocation shall
853 	 * skip claimed packed and drop the next one.
854 	 */
855 	p0 = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
856 	zassert_true(p0);
857 	zassert_equal(p0->hdr.len, fill_len);
858 
859 	exp_dropped_data[0] = p0->hdr.data + 1; /* next packet is dropped */
860 	exp_dropped_len[0] = fill_len;
861 	exp_dropped_data[1] = p0->hdr.data + 2; /* next packet is dropped */
862 	exp_dropped_len[1] = fill_len;
863 	exp_dropped_data[2] = p0->hdr.data + 3; /* next packet is dropped */
864 	exp_dropped_len[2] = fill_len;
865 	exp_drop_cnt = 3;
866 	p1 = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, len, K_NO_WAIT);
867 
868 	zassert_equal(drop_cnt, exp_drop_cnt);
869 	p1->hdr.len = len;
870 	mpsc_pbuf_commit(&buffer, (union mpsc_pbuf_generic *)p1);
871 
872 	mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)p0);
873 
874 	for (int i = 0; i < packet_cnt - drop_cnt - 1; i++) {
875 		p0 = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
876 		zassert_true(p0);
877 		zassert_equal(p0->hdr.len, fill_len);
878 		zassert_equal(p0->hdr.data, i + drop_cnt + 1);
879 		mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)p0);
880 	}
881 
882 	p0 = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
883 	zassert_true(p0);
884 	zassert_equal(p0->hdr.len, len);
885 
886 	p0 = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
887 	zassert_is_null(p0);
888 }
889 
ZTEST(log_buffer,test_overwrite_while_claimed2)890 ZTEST(log_buffer, test_overwrite_while_claimed2)
891 {
892 	overwrite_while_claimed2(true);
893 	overwrite_while_claimed2(false);
894 }
895 
896 static uintptr_t current_rd_idx;
897 
validate_packet(struct test_data_var * packet)898 static void validate_packet(struct test_data_var *packet)
899 {
900 	zassert_equal((uintptr_t)packet->hdr.data, current_rd_idx,
901 			"Got %d, expected: %d",
902 			(uintptr_t)packet->hdr.data, current_rd_idx);
903 	current_rd_idx++;
904 }
905 
consistent_drop(const struct mpsc_pbuf_buffer * buffer,const union mpsc_pbuf_generic * item)906 static void consistent_drop(const struct mpsc_pbuf_buffer *buffer,
907 			    const union mpsc_pbuf_generic *item)
908 {
909 	validate_packet((struct test_data_var *)item);
910 }
911 
rand_get(uint32_t min,uint32_t max)912 uint32_t rand_get(uint32_t min, uint32_t max)
913 {
914 	return min + (sys_rand32_get() % max);
915 }
916 
ZTEST(log_buffer,test_overwrite_consistency)917 ZTEST(log_buffer, test_overwrite_consistency)
918 {
919 	struct mpsc_pbuf_buffer buffer;
920 	static struct mpsc_pbuf_buffer_config cfg = {
921 		.buf = buf32,
922 		.size = ARRAY_SIZE(buf32),
923 		.notify_drop = consistent_drop,
924 		.get_wlen = get_wlen,
925 		.flags = MPSC_PBUF_MODE_OVERWRITE
926 	};
927 
928 	mpsc_pbuf_init(&buffer, &cfg);
929 	int repeat = 50000;
930 	int id = 0;
931 
932 	while (id < repeat) {
933 		struct test_data_var *tdv = NULL;
934 		bool alloc_during_claim = (rand_get(1, 5) <= 2);
935 
936 		/* Occasionally claim buffer to simulate that claiming is
937 		 * interrupted by allocation.
938 		 */
939 		if (alloc_during_claim) {
940 			tdv = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
941 			if (tdv) {
942 				validate_packet(tdv);
943 			}
944 		}
945 
946 		uint32_t wr_cnt = rand_get(1, 15);
947 
948 		for (int i = 0; i < wr_cnt; i++) {
949 			uint32_t wlen = rand_get(1, 15);
950 			struct test_data_var *tdv2;
951 
952 			tdv2 = (struct test_data_var *)mpsc_pbuf_alloc(&buffer,
953 								       wlen,
954 								       K_NO_WAIT);
955 			tdv2->hdr.len = wlen;
956 			tdv2->hdr.data = id++;
957 			mpsc_pbuf_commit(&buffer, (union mpsc_pbuf_generic *)tdv2);
958 		}
959 
960 		/* Put back item claimed before committing new items. */
961 		if (tdv) {
962 			mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)tdv);
963 		}
964 
965 		uint32_t rd_cnt = rand_get(1, 30);
966 
967 		for (int i = 0; i < rd_cnt; i++) {
968 			struct test_data_var *tdv2;
969 
970 			tdv2 = (struct test_data_var *)mpsc_pbuf_claim(&buffer);
971 			if (!tdv2) {
972 				continue;
973 			}
974 
975 			validate_packet(tdv2);
976 			mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)tdv2);
977 		}
978 	}
979 }
980 
981 K_THREAD_STACK_DEFINE(t1_stack, 1024);
982 K_THREAD_STACK_DEFINE(t2_stack, 1024);
983 
984 static k_thread_stack_t *stacks[2] = {t1_stack, t2_stack};
985 static struct k_thread threads[2];
986 static k_tid_t tids[2];
987 
t_entry(void * p0,void * p1,void * p2)988 void t_entry(void *p0, void *p1, void *p2)
989 {
990 	struct mpsc_pbuf_buffer *buffer = p0;
991 	uintptr_t wait_ms = (uintptr_t)p1;
992 	struct test_data_ext *t;
993 	void *vt;
994 
995 	t = (struct test_data_ext *)mpsc_pbuf_alloc(buffer,
996 						    sizeof(*t) / sizeof(uint32_t),
997 						    K_MSEC(1));
998 	zassert_is_null(t);
999 
1000 	t = (struct test_data_ext *)mpsc_pbuf_alloc(buffer,
1001 						    sizeof(*t) / sizeof(uint32_t),
1002 						    K_MSEC(wait_ms));
1003 	t->hdr.len = PUT_EXT_LEN;
1004 	t->data = k_current_get();
1005 
1006 	vt = t;
1007 	zassert_true(IS_PTR_ALIGNED(vt, union mpsc_pbuf_generic), "unaligned ptr");
1008 	mpsc_pbuf_commit(buffer, (union mpsc_pbuf_generic *)vt);
1009 	while (1) {
1010 		k_sleep(K_MSEC(10));
1011 	}
1012 }
1013 
start_threads(struct mpsc_pbuf_buffer * buffer)1014 void start_threads(struct mpsc_pbuf_buffer *buffer)
1015 {
1016 	int prio = 2;
1017 	uintptr_t wait_ms = 1000;
1018 
1019 	for (int i = 0; i < ARRAY_SIZE(threads); i++) {
1020 		tids[i] = k_thread_create(&threads[i], stacks[i], 1024, t_entry,
1021 					  buffer, (void *)wait_ms, NULL,
1022 					  prio--,
1023 					  0, K_NO_WAIT);
1024 	}
1025 
1026 	k_sleep(K_MSEC(10));
1027 
1028 	for (int i = 0; i < ARRAY_SIZE(threads); i++) {
1029 		k_ticks_t t = k_thread_timeout_remaining_ticks(tids[i]);
1030 		k_ticks_t exp_wait = k_ms_to_ticks_ceil32(wait_ms);
1031 
1032 		/* Threads shall be blocked, waiting for available space. */
1033 		zassert_within(t, exp_wait, k_ms_to_ticks_ceil32(20));
1034 	}
1035 }
1036 
1037 /* Test creates two threads which pends on the buffer until there is a space
1038  * available. When enough buffers is released threads are woken up and they
1039  * allocate packets.
1040  */
ZTEST(log_buffer,test_pending_alloc)1041 ZTEST(log_buffer, test_pending_alloc)
1042 {
1043 	int prio = k_thread_priority_get(k_current_get());
1044 	struct mpsc_pbuf_buffer buffer;
1045 	void *vt;
1046 
1047 	k_thread_priority_set(k_current_get(), 3);
1048 
1049 	init(&buffer, ARRAY_SIZE(buf32) - 1, true);
1050 
1051 	uint32_t fill_len = 1;
1052 	uint32_t packet_cnt = saturate_buffer_uneven(&buffer, fill_len);
1053 
1054 	start_threads(&buffer);
1055 
1056 	k_sleep(K_MSEC(1));
1057 
1058 	for (int i = 0; i < packet_cnt; i++) {
1059 		union test_item *t = (union test_item *)mpsc_pbuf_claim(&buffer);
1060 
1061 		mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)t);
1062 	}
1063 
1064 
1065 	for (int i = 0; i < 2; i++) {
1066 		struct test_data_ext *t =
1067 			(struct test_data_ext *)mpsc_pbuf_claim(&buffer);
1068 
1069 		zassert_true(t);
1070 		zassert_equal(t->data, tids[ARRAY_SIZE(tids) - 1 - i]);
1071 		vt = t;
1072 		zassert_true(IS_PTR_ALIGNED(vt, union mpsc_pbuf_generic), "unaligned ptr");
1073 		mpsc_pbuf_free(&buffer, (union mpsc_pbuf_generic *)vt);
1074 	}
1075 
1076 	zassert_equal(mpsc_pbuf_claim(&buffer), NULL, "No more packets.");
1077 	k_thread_priority_set(k_current_get(), prio);
1078 }
1079 
check_packet(struct mpsc_pbuf_buffer * buffer,char exp_c)1080 static void check_packet(struct mpsc_pbuf_buffer *buffer, char exp_c)
1081 {
1082 	union test_item claimed_item;
1083 	const union mpsc_pbuf_generic *claimed;
1084 
1085 	claimed = mpsc_pbuf_claim(buffer);
1086 	zassert_true(claimed, NULL);
1087 	claimed_item.item = *claimed;
1088 	zassert_equal(claimed_item.data.data, exp_c, NULL);
1089 
1090 	mpsc_pbuf_free(buffer, claimed);
1091 }
1092 
ZTEST(log_buffer,test_put_while_claim)1093 ZTEST(log_buffer, test_put_while_claim)
1094 {
1095 	struct mpsc_pbuf_buffer buffer;
1096 	uint32_t buffer_storage[4];
1097 	const union mpsc_pbuf_generic *claimed;
1098 	struct mpsc_pbuf_buffer_config buffer_config = {
1099 		.buf = buffer_storage,
1100 		.size = 4,
1101 		.notify_drop = drop,
1102 		.get_wlen = get_wlen,
1103 		.flags = MPSC_PBUF_SIZE_POW2 | MPSC_PBUF_MODE_OVERWRITE
1104 	};
1105 	union test_item claimed_item;
1106 	union test_item item = {
1107 		.data = {
1108 			.valid = 1,
1109 			.busy = 0,
1110 			.len = 1,
1111 			.data = (uint32_t)'a'
1112 		}
1113 	};
1114 
1115 	exp_drop_cnt = 0;
1116 	drop_cnt = 0;
1117 	mpsc_pbuf_init(&buffer, &buffer_config);
1118 	/* Expect buffer = {} */
1119 
1120 	for (int i = 0; i < buffer.size; ++i) {
1121 		mpsc_pbuf_put_word(&buffer, item.item);
1122 		item.data.data++;
1123 	}
1124 
1125 	/* Expect buffer = {a, b, c, d}. Adding new word will drop 'a'. */
1126 	exp_dropped_data[exp_drop_cnt] = (uint32_t)'a';
1127 	exp_dropped_len[exp_drop_cnt] = 1;
1128 	exp_drop_cnt++;
1129 
1130 	item.data.data = 'e';
1131 	mpsc_pbuf_put_word(&buffer, item.item);
1132 	zassert_equal(drop_cnt, exp_drop_cnt, NULL);
1133 	/* Expect buffer = {e, b, c, d} */
1134 
1135 	claimed = mpsc_pbuf_claim(&buffer);
1136 	zassert_true(claimed, NULL);
1137 	claimed_item.item = *claimed;
1138 	zassert_equal(claimed_item.data.data, (uint32_t)'b', NULL);
1139 
1140 	/* Expect buffer = {e, B, c, d}. Adding new will drop 'c'. */
1141 	exp_dropped_data[exp_drop_cnt] = (int)'c';
1142 	exp_dropped_len[exp_drop_cnt] = 1;
1143 	exp_drop_cnt++;
1144 
1145 	item.data.data = 'f';
1146 	mpsc_pbuf_put_word(&buffer, item.item);
1147 	zassert_equal(drop_cnt, exp_drop_cnt, NULL);
1148 	/* Expect buffer = {e, B, f, d}, Adding new will drop 'd'. */
1149 
1150 	exp_dropped_data[exp_drop_cnt] = (int)'d';
1151 	exp_dropped_len[exp_drop_cnt] = 1;
1152 	exp_drop_cnt++;
1153 	item.data.data = 'g';
1154 	mpsc_pbuf_put_word(&buffer, item.item);
1155 	zassert_equal(drop_cnt, exp_drop_cnt, NULL);
1156 	/* Expect buffer = {e, B, f, g} */
1157 
1158 	mpsc_pbuf_free(&buffer, claimed);
1159 	/* Expect buffer = {e -, f, g} */
1160 
1161 	check_packet(&buffer, 'e');
1162 	/* Expect buffer = {-, -, f, g} */
1163 
1164 	check_packet(&buffer, 'f');
1165 	/* Expect buffer = {-, -, -, g} */
1166 
1167 	check_packet(&buffer, 'g');
1168 	/* Expect buffer = {-, -, -, -} */
1169 
1170 	claimed = mpsc_pbuf_claim(&buffer);
1171 	zassert_equal(claimed, NULL, NULL);
1172 }
1173 
check_usage(struct mpsc_pbuf_buffer * buffer,uint32_t now,int exp_err,uint32_t max,uint32_t line)1174 static void check_usage(struct mpsc_pbuf_buffer *buffer,
1175 			uint32_t now, int exp_err, uint32_t max, uint32_t line)
1176 {
1177 	uint32_t size;
1178 	uint32_t usage;
1179 	int err;
1180 
1181 	mpsc_pbuf_get_utilization(buffer, &size, &usage);
1182 	zassert_equal(size / sizeof(int), buffer->size - 1, "%d: got:%d, exp:%d",
1183 			line, size / sizeof(int), buffer->size - 1);
1184 	zassert_equal(usage, now, "%d: got:%d, exp:%d", line, usage, now);
1185 
1186 	err = mpsc_pbuf_get_max_utilization(buffer, &usage);
1187 	zassert_equal(err, exp_err);
1188 	if (err == 0) {
1189 		zassert_equal(usage, max, "%d: got:%d, exp:%d", line, usage, max);
1190 	}
1191 }
1192 
1193 #define CHECK_USAGE(buffer, now, max) \
1194 	check_usage(buffer, (now) * sizeof(int), 0, (max) * sizeof(int), __LINE__)
1195 
ignore_drop(const struct mpsc_pbuf_buffer * buffer,const union mpsc_pbuf_generic * item)1196 static void ignore_drop(const struct mpsc_pbuf_buffer *buffer,
1197 			const union mpsc_pbuf_generic *item)
1198 {
1199 	ARG_UNUSED(buffer);
1200 	ARG_UNUSED(item);
1201 }
1202 
ZTEST(log_buffer,test_utilization)1203 ZTEST(log_buffer, test_utilization)
1204 {
1205 	struct mpsc_pbuf_buffer buffer;
1206 	struct mpsc_pbuf_buffer_config config = {
1207 		.buf = buf32,
1208 		.size = ARRAY_SIZE(buf32),
1209 		.notify_drop = ignore_drop,
1210 		.get_wlen = get_wlen,
1211 		.flags = 0 /* Utilization not supported. */
1212 	};
1213 
1214 	mpsc_pbuf_init(&buffer, &config);
1215 
1216 	check_usage(&buffer, 0, -ENOTSUP, 0, __LINE__);
1217 
1218 	/* Initialize with max utilization support. */
1219 	config.flags = MPSC_PBUF_MAX_UTILIZATION;
1220 	mpsc_pbuf_init(&buffer, &config);
1221 
1222 	CHECK_USAGE(&buffer, 0, 0);
1223 
1224 	union test_item test_1word = {.data = {.valid = 1, .len = 1 }};
1225 	union test_item test_ext_item = {
1226 		.data = {
1227 			.valid = 1,
1228 			.len = PUT_EXT_LEN
1229 		}
1230 	};
1231 	union test_item *t;
1232 
1233 	mpsc_pbuf_put_word(&buffer, test_1word.item);
1234 
1235 	CHECK_USAGE(&buffer, 1, 1);
1236 
1237 	mpsc_pbuf_put_word_ext(&buffer, test_ext_item.item, NULL);
1238 
1239 	CHECK_USAGE(&buffer, 1 + PUT_EXT_LEN, 1 + PUT_EXT_LEN);
1240 
1241 	t = (union test_item *)mpsc_pbuf_claim(&buffer);
1242 
1243 	zassert_true(t != NULL);
1244 	CHECK_USAGE(&buffer, 1 + PUT_EXT_LEN, 1 + PUT_EXT_LEN);
1245 	mpsc_pbuf_free(&buffer, &t->item);
1246 
1247 	t = (union test_item *)mpsc_pbuf_claim(&buffer);
1248 	zassert_true(t != NULL);
1249 
1250 	CHECK_USAGE(&buffer, PUT_EXT_LEN, 1 + PUT_EXT_LEN);
1251 
1252 	mpsc_pbuf_free(&buffer, &t->item);
1253 
1254 	CHECK_USAGE(&buffer, 0, 1 + PUT_EXT_LEN);
1255 
1256 	union test_item test_ext_item2 = {
1257 		.data_ext = {
1258 			.hdr = {
1259 				.valid = 1,
1260 				.len = PUT_EXT_LEN
1261 			},
1262 			.data = NULL
1263 		}
1264 	};
1265 
1266 	mpsc_pbuf_put_data(&buffer, (uint32_t *)&test_ext_item2, PUT_EXT_LEN);
1267 
1268 	CHECK_USAGE(&buffer, PUT_EXT_LEN, 1 + PUT_EXT_LEN);
1269 
1270 	t = (union test_item *)mpsc_pbuf_claim(&buffer);
1271 	zassert_true(t != NULL);
1272 	mpsc_pbuf_free(&buffer, &t->item);
1273 
1274 	CHECK_USAGE(&buffer, 0, 1 + PUT_EXT_LEN);
1275 
1276 	memset(&buffer, 0, sizeof(buffer));
1277 	/* Initialize to reset indexes. */
1278 	mpsc_pbuf_init(&buffer, &config);
1279 
1280 	struct test_data_var *packet;
1281 	uint32_t len = 5;
1282 	uint32_t i;
1283 
1284 	for (i = 0; i < (buffer.size - 1) / len; i++) {
1285 		packet = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, len, K_NO_WAIT);
1286 		packet->hdr.len = len;
1287 
1288 		mpsc_pbuf_commit(&buffer, (union mpsc_pbuf_generic *)packet);
1289 		CHECK_USAGE(&buffer, len * (i + 1), len * (i + 1));
1290 	}
1291 
1292 	packet = (struct test_data_var *)mpsc_pbuf_alloc(&buffer, len, K_NO_WAIT);
1293 
1294 	zassert_true(packet == NULL);
1295 }
1296 
1297 /*test case main entry*/
1298 ZTEST_SUITE(log_buffer, NULL, NULL, NULL, NULL, NULL);
1299