source: rtems/testsuites/libtests/record01/init.c @ dca6184

5
Last change on this file since dca6184 was dca6184, checked in by Sebastian Huber <sebastian.huber@…>, on 04/28/18 at 09:36:11

Add low level event recording support

Add low level event recording infrastructure for system and user
defined events. The infrastructure is able to record high frequency
events such as

  • SMP lock acquire/release,
  • interrupt entry/exit,
  • thread switches,
  • UMA zone allocate/free, and
  • Ethernet packet input/output, etc.

It allows post-mortem analysis in fatal error handlers, e.g. the last
events are in the record buffer, the newest event overwrites the oldest
event. It is possible to detect record buffer overflows for consumers
that expect a continuous stream of events, e.g. to display the system
state in real-time.

The implementation supports high-end SMP machines (more than 1GHz
processor frequency, more than four processors).

Add a new API instead. The implementation uses per-processor data
structures and no atomic read-modify-write operations. It is uses
per-processor ring buffers to record the events.

The CPU counter is used to get the time of events. It is combined with
periodic uptime events to synchronize it with CLOCK_REALTIME.

The existing capture engine tries to solve this problem also, but its
performance is not good enough for high-end production systems. The
main issues are the variable-size buffers and the use of SMP locks for
synchronization. To fix this, the API would change significantly.

Update #3665.

  • Property mode set to 100644
File size: 20.3 KB
Line 
1/*
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (C) 2018, 2019 embedded brains GmbH
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include <rtems/record.h>
33#include <rtems.h>
34
35#include <sys/endian.h>
36#include <sys/socket.h>
37
38#include <string.h>
39#include <unistd.h>
40
41#include <netinet/in.h>
42
43#ifdef RTEMS_NETWORKING
44#include <rtems/rtems_bsdnet.h>
45#endif
46
47#include <tmacros.h>
48
49const char rtems_test_name[] = "RECORD 1";
50
51#define ITEM_COUNT 4
52
53#define ITEM_SIZE (ITEM_COUNT * sizeof(rtems_record_item))
54
55typedef struct {
56  Record_Control control;
57  rtems_record_item items[ITEM_COUNT];
58} test_context;
59
60static test_context test_instance;
61
62const unsigned int _Record_Item_count = ITEM_COUNT;
63
64#define UE(user) (RTEMS_RECORD_USER + (user))
65
66#define TE(t, e) RTEMS_RECORD_TIME_EVENT(t, e)
67
68static const rtems_record_item expected_items_0[ITEM_COUNT] = {
69  { .event = TE(2, UE(1)), .data = 3 }
70};
71
72static const rtems_record_item expected_items_1[ITEM_COUNT] = {
73  { .event = TE(2, UE(1)), .data = 3 },
74  { .event = TE(6, UE(5)), .data = 7 }
75};
76
77static const rtems_record_item expected_items_2[ITEM_COUNT] = {
78  { .event = TE(2, UE(1)), .data = 3 },
79  { .event = TE(6, UE(5)), .data = 7 },
80  { .event = TE(10, UE(9)), .data = 11 }
81};
82
83static const rtems_record_item expected_items_3[ITEM_COUNT] = {
84  { .event = TE(2, UE(1)), .data = 3 },
85  { .event = TE(6, UE(5)), .data = 7 },
86  { .event = TE(10, UE(9)), .data = 11 },
87  { .event = TE(14, UE(13)), .data = 15 }
88};
89
90static const rtems_record_item expected_items_4[ITEM_COUNT] = {
91  { .event = TE(18, UE(17)), .data = 19 },
92  { .event = TE(6, UE(5)), .data = 7 },
93  { .event = TE(10, UE(9)), .data = 11 },
94  { .event = TE(14, UE(13)), .data = 15 }
95};
96
97static const rtems_record_item expected_items_5[ITEM_COUNT] = {
98  { .event = TE(2, UE(1)), .data = 3 }
99};
100
101static const rtems_record_item expected_items_6[ITEM_COUNT] = {
102  { .event = TE(2, UE(1)), .data = 3 },
103  { .event = TE(6, UE(5)), .data = 7 }
104};
105
106static const rtems_record_item expected_items_7[ITEM_COUNT] = {
107  { .event = TE(2, UE(1)), .data = 3 },
108  { .event = TE(6, UE(5)), .data = 7 },
109  { .event = TE(10, UE(9)), .data = 11 }
110};
111
112static const rtems_record_item expected_items_8[] = {
113  { .event = TE(0, RTEMS_RECORD_PROCESSOR), .data = 0 },
114  { .event = TE(0, RTEMS_RECORD_TAIL), .data = 0 },
115  { .event = TE(0, RTEMS_RECORD_HEAD), .data = 3 },
116  { .event = TE(2, UE(1)), .data = 3 },
117  { .event = TE(5, UE(4)), .data = 6 },
118  { .event = TE(8, UE(7)), .data = 9 }
119};
120
121static const rtems_record_item expected_items_9[] = {
122  { .event = TE(0, RTEMS_RECORD_PROCESSOR), .data = 0 },
123  { .event = TE(0, RTEMS_RECORD_TAIL), .data = 3 },
124  { .event = TE(0, RTEMS_RECORD_HEAD), .data = 5 },
125  { .event = TE(11, UE(10)), .data = 12 },
126  { .event = TE(14, UE(13)), .data = 15 }
127};
128
129static const rtems_record_item expected_items_10[] = {
130  { .event = TE(0, RTEMS_RECORD_PROCESSOR), .data = 0 },
131  { .event = TE(0, RTEMS_RECORD_TAIL), .data = 5 },
132  { .event = TE(0, RTEMS_RECORD_HEAD), .data = 8 },
133  { .event = TE(17, UE(16)), .data = 18 },
134  { .event = TE(20, UE(19)), .data = 21 },
135  { .event = TE(23, UE(22)), .data = 24 }
136};
137
138static const rtems_record_item expected_items_11[] = {
139  { .event = TE(0, RTEMS_RECORD_PROCESSOR), .data = 0 },
140  { .event = TE(0, RTEMS_RECORD_TAIL), .data = 8 },
141  { .event = TE(0, RTEMS_RECORD_HEAD), .data = 9 },
142  { .event = TE(26, UE(25)), .data = 27 }
143};
144
145static const rtems_record_item expected_items_12[] = {
146  { .event = TE(0, RTEMS_RECORD_PROCESSOR), .data = 0 },
147  { .event = TE(0, RTEMS_RECORD_TAIL), .data = 9 },
148  { .event = TE(0, RTEMS_RECORD_HEAD), .data = 15 },
149  { .event = TE(38, UE(37)), .data = 39 },
150  { .event = TE(41, UE(40)), .data = 42 },
151  { .event = TE(44, UE(43)), .data = 45 }
152};
153
154static void init_context(test_context *ctx)
155{
156  memset(ctx, 0, sizeof(*ctx));
157  ctx->control.mask = ITEM_COUNT - 1;
158}
159
160static void test_capacity(const Record_Control *control)
161{
162  unsigned int capacity;
163
164  capacity = _Record_Capacity(control, 0, 0);
165  rtems_test_assert(capacity == 3);
166
167  capacity = _Record_Capacity(control, 0, 1);
168  rtems_test_assert(capacity == 2);
169
170  capacity = _Record_Capacity(control, 0, 2);
171  rtems_test_assert(capacity == 1);
172
173  capacity = _Record_Capacity(control, 0, 3);
174  rtems_test_assert(capacity == 0);
175
176  capacity = _Record_Capacity(control, 3, 3);
177  rtems_test_assert(capacity == 3);
178
179  capacity = _Record_Capacity(control, 3, 0);
180  rtems_test_assert(capacity == 2);
181
182  capacity = _Record_Capacity(control, 3, 1);
183  rtems_test_assert(capacity == 1);
184
185  capacity = _Record_Capacity(control, 3, 2);
186  rtems_test_assert(capacity == 0);
187}
188
189static void test_index(const Record_Control *control)
190{
191  unsigned int index;
192
193  index = _Record_Index(control, 0);
194  rtems_test_assert(index == 0);
195
196  index = _Record_Index(control, 1);
197  rtems_test_assert(index == 1);
198
199  index = _Record_Index(control, 2);
200  rtems_test_assert(index == 2);
201
202  index = _Record_Index(control, 3);
203  rtems_test_assert(index == 3);
204
205  index = _Record_Index(control, 4);
206  rtems_test_assert(index == 0);
207}
208
209static void test_add_2_items(test_context *ctx, Record_Control *control)
210{
211  rtems_record_context rc;
212
213  init_context(ctx);
214
215  rtems_record_prepare(&rc);
216  rtems_test_assert(rc.control == control);
217  rtems_test_assert(rc.head == 0);
218  rtems_test_assert(_Record_Head(control) == 0);
219  rtems_test_assert(_Record_Tail(control) == 0);
220
221  rc.now = RTEMS_RECORD_TIME_EVENT(2, 0);
222  rtems_record_add(&rc, UE(1), 3);
223  rtems_test_assert(rc.head == 1);
224  rtems_test_assert(memcmp(control->Items, expected_items_0, ITEM_SIZE) == 0);
225  rtems_test_assert(_Record_Head(control) == 0);
226  rtems_test_assert(_Record_Tail(control) == 0);
227
228  rc.now = RTEMS_RECORD_TIME_EVENT(6, 0);
229  rtems_record_add(&rc, UE(5), 7);
230  rtems_record_commit(&rc);
231  rtems_test_assert(rc.head == 2);
232  rtems_test_assert(memcmp(control->Items, expected_items_1, ITEM_SIZE) == 0);
233  rtems_test_assert(_Record_Head(control) == 2);
234  rtems_test_assert(_Record_Tail(control) == 0);
235}
236
237static void test_add_3_items(test_context *ctx, Record_Control *control)
238{
239  rtems_record_context rc;
240
241  init_context(ctx);
242
243  rtems_record_prepare(&rc);
244  rtems_test_assert(rc.control == control);
245  rtems_test_assert(rc.head == 0);
246  rtems_test_assert(_Record_Head(control) == 0);
247  rtems_test_assert(_Record_Tail(control) == 0);
248
249  rc.now = RTEMS_RECORD_TIME_EVENT(2, 0);
250  rtems_record_add(&rc, UE(1), 3);
251  rtems_test_assert(rc.head == 1);
252  rtems_test_assert(memcmp(control->Items, expected_items_5, ITEM_SIZE) == 0);
253  rtems_test_assert(_Record_Head(control) == 0);
254  rtems_test_assert(_Record_Tail(control) == 0);
255
256  rc.now = RTEMS_RECORD_TIME_EVENT(6, 0);
257  rtems_record_add(&rc, UE(5), 7);
258  rtems_test_assert(rc.head == 2);
259  rtems_test_assert(memcmp(control->Items, expected_items_6, ITEM_SIZE) == 0);
260  rtems_test_assert(_Record_Head(control) == 0);
261  rtems_test_assert(_Record_Tail(control) == 0);
262
263  rc.now = RTEMS_RECORD_TIME_EVENT(10, 0);
264  rtems_record_add(&rc, UE(9), 11);
265  rtems_record_commit(&rc);
266  rtems_test_assert(rc.head == 3);
267  rtems_test_assert(memcmp(control->Items, expected_items_7, ITEM_SIZE) == 0);
268  rtems_test_assert(_Record_Head(control) == 3);
269  rtems_test_assert(_Record_Tail(control) == 0);
270}
271
272static void set_time(rtems_record_item *item, uint32_t time)
273{
274  uint32_t event;
275
276  event = item->event;
277  event &= 0x3ff;
278  event |= time << 10;
279  item->event = event;
280}
281
282static void test_produce(test_context *ctx, Record_Control *control)
283{
284  init_context(ctx);
285
286  rtems_record_produce(UE(1), 3);
287  set_time(&control->Items[0], 2);
288  rtems_test_assert(memcmp(control->Items, expected_items_0, ITEM_SIZE) == 0);
289  rtems_test_assert(_Record_Head(control) == 1);
290  rtems_test_assert(_Record_Tail(control) == 0);
291
292  rtems_record_produce(UE(5), 7);
293  set_time(&control->Items[1], 6);
294  rtems_test_assert(memcmp(control->Items, expected_items_1, ITEM_SIZE) == 0);
295  rtems_test_assert(_Record_Head(control) == 2);
296  rtems_test_assert(_Record_Tail(control) == 0);
297
298  rtems_record_produce(UE(9), 11);
299  set_time(&control->Items[2], 10);
300  rtems_test_assert(memcmp(control->Items, expected_items_2, ITEM_SIZE) == 0);
301  rtems_test_assert(_Record_Head(control) == 3);
302  rtems_test_assert(_Record_Tail(control) == 0);
303
304  rtems_record_produce(UE(13), 15);
305  set_time(&control->Items[3], 14);
306  rtems_test_assert(memcmp(control->Items, expected_items_3, ITEM_SIZE) == 0);
307  rtems_test_assert(_Record_Head(control) == 4);
308  rtems_test_assert(_Record_Tail(control) == 0);
309
310  rtems_record_produce(UE(17), 19);
311  set_time(&control->Items[0], 18);
312  rtems_test_assert(memcmp(control->Items, expected_items_4, ITEM_SIZE) == 0);
313  rtems_test_assert(_Record_Head(control) == 5);
314  rtems_test_assert(_Record_Tail(control) == 0);
315}
316
317static void test_produce_2(test_context *ctx, Record_Control *control)
318{
319  init_context(ctx);
320
321  rtems_record_produce_2(UE(1), 3, UE(5), 7);
322  set_time(&control->Items[0], 2);
323  set_time(&control->Items[1], 6);
324  rtems_test_assert(memcmp(control->Items, expected_items_1, ITEM_SIZE) == 0);
325  rtems_test_assert(_Record_Head(control) == 2);
326  rtems_test_assert(_Record_Tail(control) == 0);
327
328  rtems_record_produce(UE(9), 11);
329  set_time(&control->Items[2], 10);
330  rtems_test_assert(memcmp(control->Items, expected_items_2, ITEM_SIZE) == 0);
331  rtems_test_assert(_Record_Head(control) == 3);
332  rtems_test_assert(_Record_Tail(control) == 0);
333
334  rtems_record_produce_2(UE(13), 15, UE(17), 19);
335  set_time(&control->Items[3], 14);
336  set_time(&control->Items[0], 18);
337  rtems_test_assert(memcmp(control->Items, expected_items_4, ITEM_SIZE) == 0);
338  rtems_test_assert(_Record_Head(control) == 5);
339  rtems_test_assert(_Record_Tail(control) == 0);
340}
341
342static void test_produce_n(test_context *ctx, Record_Control *control)
343{
344  rtems_record_item items[5];
345
346  init_context(ctx);
347
348  items[0].event = UE(1);
349  items[0].data = 3;
350  items[1].event = UE(5);
351  items[1].data = 7;
352  items[2].event = UE(9);
353  items[2].data = 11;
354  items[3].event = UE(13);
355  items[3].data = 15;
356  items[4].event = UE(17);
357  items[4].data = 19;
358  rtems_record_produce_n(items, RTEMS_ARRAY_SIZE(items));
359  set_time(&control->Items[1], 6);
360  set_time(&control->Items[2], 10);
361  set_time(&control->Items[3], 14);
362  set_time(&control->Items[0], 18);
363  rtems_test_assert(memcmp(control->Items, expected_items_4, ITEM_SIZE) == 0);
364  rtems_test_assert(_Record_Head(control) == 5);
365  rtems_test_assert(_Record_Tail(control) == 0);
366}
367
368typedef struct {
369  size_t todo;
370  const rtems_record_item *items;
371} visitor_context;
372
373static void visitor(const rtems_record_item *items, size_t count, void *arg)
374{
375  visitor_context *vctx;
376
377  vctx = arg;
378  rtems_test_assert(vctx->todo >= count);
379
380  while (count > 0) {
381    rtems_test_assert(memcmp(items, vctx->items, sizeof(*items)) == 0);
382    ++items;
383    ++vctx->items;
384    --count;
385    --vctx->todo;
386  }
387}
388
389static void test_drain(test_context *ctx, Record_Control *control)
390{
391  visitor_context vctx;
392
393  init_context(ctx);
394
395  vctx.todo = 0;
396  vctx.items = NULL;
397  rtems_record_drain(visitor, &vctx);
398  rtems_test_assert(vctx.todo == 0);
399
400  rtems_record_produce(UE(1), 3);
401  set_time(&control->Items[0], 2);
402  rtems_record_produce(UE(4), 6);
403  set_time(&control->Items[1], 5);
404  rtems_record_produce(UE(7), 9);
405  set_time(&control->Items[2], 8);
406
407  vctx.todo = RTEMS_ARRAY_SIZE(expected_items_8);
408  vctx.items = expected_items_8;
409  rtems_record_drain(visitor, &vctx);
410  rtems_test_assert(vctx.todo == 0);
411
412  vctx.todo = 0;
413  vctx.items = NULL;
414  rtems_record_drain(visitor, &vctx);
415  rtems_test_assert(vctx.todo == 0);
416
417  rtems_record_produce(UE(10), 12);
418  set_time(&control->Items[3], 11);
419  rtems_record_produce(UE(13), 15);
420  set_time(&control->Items[0], 14);
421
422  vctx.todo = RTEMS_ARRAY_SIZE(expected_items_9);
423  vctx.items = expected_items_9;
424  rtems_record_drain(visitor, &vctx);
425  rtems_test_assert(vctx.todo == 0);
426
427  vctx.todo = 0;
428  vctx.items = NULL;
429  rtems_record_drain(visitor, &vctx);
430  rtems_test_assert(vctx.todo == 0);
431
432  rtems_record_produce(UE(16), 18);
433  set_time(&control->Items[1], 17);
434  rtems_record_produce(UE(19), 21);
435  set_time(&control->Items[2], 20);
436  rtems_record_produce(UE(22), 24);
437  set_time(&control->Items[3], 23);
438
439  vctx.todo = RTEMS_ARRAY_SIZE(expected_items_10);
440  vctx.items = expected_items_10;
441  rtems_record_drain(visitor, &vctx);
442  rtems_test_assert(vctx.todo == 0);
443
444  vctx.todo = 0;
445  vctx.items = NULL;
446  rtems_record_drain(visitor, &vctx);
447  rtems_test_assert(vctx.todo == 0);
448
449  rtems_record_produce(UE(25), 27);
450  set_time(&control->Items[0], 26);
451
452  vctx.todo = RTEMS_ARRAY_SIZE(expected_items_11);
453  vctx.items = expected_items_11;
454  rtems_record_drain(visitor, &vctx);
455  rtems_test_assert(vctx.todo == 0);
456
457  vctx.todo = 0;
458  vctx.items = NULL;
459  rtems_record_drain(visitor, &vctx);
460  rtems_test_assert(vctx.todo == 0);
461
462  rtems_record_produce(UE(28), 30);
463  set_time(&control->Items[1], 29);
464  rtems_record_produce(UE(31), 33);
465  set_time(&control->Items[2], 32);
466  rtems_record_produce(UE(34), 36);
467  set_time(&control->Items[3], 35);
468  rtems_record_produce(UE(37), 39);
469  set_time(&control->Items[0], 38);
470  rtems_record_produce(UE(40), 42);
471  set_time(&control->Items[1], 41);
472  rtems_record_produce(UE(43), 45);
473  set_time(&control->Items[2], 44);
474
475  vctx.todo = RTEMS_ARRAY_SIZE(expected_items_12);
476  vctx.items = expected_items_12;
477  rtems_record_drain(visitor, &vctx);
478  rtems_test_assert(vctx.todo == 0);
479
480  vctx.todo = 0;
481  vctx.items = NULL;
482  rtems_record_drain(visitor, &vctx);
483  rtems_test_assert(vctx.todo == 0);
484}
485
486#ifdef RTEMS_NETWORKING
487#define PORT 1234
488
489static uint32_t get_format(void)
490{
491  uint32_t format;
492
493#if BYTE_ORDER == LITTLE_ENDIAN
494#if __INTPTR_WIDTH__ == 32
495  format = RTEMS_RECORD_FORMAT_LE_32;
496#elif __INTPTR_WIDTH__ == 64
497  format = RTEMS_RECORD_FORMAT_LE_64;
498#else
499#error "unexpected __INTPTR_WIDTH__"
500#endif
501#elif BYTE_ORDER == BIG_ENDIAN
502#if __INTPTR_WIDTH__ == 32
503  format = RTEMS_RECORD_FORMAT_BE_32;
504#elif __INTPTR_WIDTH__ == 64
505  format = RTEMS_RECORD_FORMAT_BE_64;
506#else
507#error "unexpected __INTPTR_WIDTH__"
508#endif
509#else
510#error "unexpected BYTE_ORDER"
511#endif
512
513  return format;
514}
515
516static int connect_client(void)
517{
518  struct sockaddr_in addr;
519  int fd;
520  int rv;
521  ssize_t n;
522  uint32_t v;
523  rtems_record_item item;
524
525  fd = socket(PF_INET, SOCK_STREAM, 0);
526  rtems_test_assert(fd >= 0);
527
528  memset(&addr, 0, sizeof(addr));
529  addr.sin_family = AF_INET;
530  addr.sin_port = htons(PORT);
531  addr.sin_addr.s_addr = htonl(INADDR_ANY);
532  rv = connect(fd, (struct sockaddr *) &addr, sizeof(addr));
533  rtems_test_assert(rv == 0);
534
535  n = read(fd, &v, sizeof(v));
536  rtems_test_assert(n == 4);
537  rtems_test_assert(v == get_format());
538
539  n = read(fd, &v, sizeof(v));
540  rtems_test_assert(n == 4);
541  rtems_test_assert(v == RTEMS_RECORD_MAGIC);
542
543  n = read(fd, &item, sizeof(item));
544  rtems_test_assert(n == (ssize_t) sizeof(item));
545  rtems_test_assert(item.event == TE(0, RTEMS_RECORD_VERSION));
546  rtems_test_assert(item.data == RTEMS_RECORD_THE_VERSION);
547
548  n = read(fd, &item, sizeof(item));
549  rtems_test_assert(n == (ssize_t) sizeof(item));
550  rtems_test_assert(item.event == TE(0, RTEMS_RECORD_PROCESSOR_MAXIMUM));
551  rtems_test_assert(item.data == 0);
552
553  n = read(fd, &item, sizeof(item));
554  rtems_test_assert(n == (ssize_t) sizeof(item));
555  rtems_test_assert(item.event == TE(0, RTEMS_RECORD_COUNT));
556  rtems_test_assert(item.data == ITEM_COUNT);
557
558  n = read(fd, &item, sizeof(item));
559  rtems_test_assert(n == (ssize_t) sizeof(item));
560  rtems_test_assert(item.event == TE(0, RTEMS_RECORD_FREQUENCY));
561  rtems_test_assert(item.data == rtems_counter_frequency());
562
563  return fd;
564}
565
566static void produce_and_read(int fd, Record_Control *control)
567{
568  rtems_record_item items[6];
569  ssize_t n;
570
571  rtems_record_produce(UE(1), 3);
572  set_time(&control->Items[0], 2);
573  rtems_record_produce(UE(4), 6);
574  set_time(&control->Items[1], 5);
575  rtems_record_produce(UE(7), 9);
576  set_time(&control->Items[2], 8);
577
578  n = read(fd, items, sizeof(expected_items_8));
579  rtems_test_assert(n == (ssize_t) sizeof(expected_items_8));
580  rtems_test_assert(
581    memcmp(items, expected_items_8, sizeof(expected_items_8)) == 0
582  );
583
584  rtems_record_produce(UE(10), 12);
585  set_time(&control->Items[3], 11);
586  rtems_record_produce(UE(13), 15);
587  set_time(&control->Items[0], 14);
588
589  n = read(fd, items, sizeof(expected_items_9));
590  rtems_test_assert(n == (ssize_t) sizeof(expected_items_9));
591  rtems_test_assert(
592    memcmp(items, expected_items_9, sizeof(expected_items_9)) == 0
593  );
594
595  rtems_record_produce(UE(16), 18);
596  set_time(&control->Items[1], 17);
597  rtems_record_produce(UE(19), 21);
598  set_time(&control->Items[2], 20);
599  rtems_record_produce(UE(22), 24);
600  set_time(&control->Items[3], 23);
601
602  n = read(fd, items, sizeof(expected_items_10));
603  rtems_test_assert(n == (ssize_t) sizeof(expected_items_10));
604  rtems_test_assert(
605    memcmp(items, expected_items_10, sizeof(expected_items_10)) == 0
606  );
607
608  rtems_record_produce(UE(25), 27);
609  set_time(&control->Items[0], 26);
610
611  n = read(fd, items, sizeof(expected_items_11));
612  rtems_test_assert(n == (ssize_t) sizeof(expected_items_11));
613  rtems_test_assert(
614    memcmp(items, expected_items_11, sizeof(expected_items_11)) == 0
615  );
616
617  rtems_record_produce(UE(28), 30);
618  set_time(&control->Items[1], 29);
619  rtems_record_produce(UE(31), 33);
620  set_time(&control->Items[2], 32);
621  rtems_record_produce(UE(34), 36);
622  set_time(&control->Items[3], 35);
623  rtems_record_produce(UE(37), 39);
624  set_time(&control->Items[0], 38);
625  rtems_record_produce(UE(40), 42);
626  set_time(&control->Items[1], 41);
627  rtems_record_produce(UE(43), 45);
628  set_time(&control->Items[2], 44);
629
630  n = read(fd, items, sizeof(expected_items_12));
631  rtems_test_assert(n == (ssize_t) sizeof(expected_items_12));
632  rtems_test_assert(
633    memcmp(items, expected_items_12, sizeof(expected_items_12)) == 0
634  );
635}
636
637static void test_server(test_context *ctx, Record_Control *control)
638{
639  rtems_status_code sc;
640  int rv;
641  int fd;
642
643  init_context(ctx);
644
645  rv = rtems_bsdnet_initialize_network();
646  rtems_test_assert(rv == 0);
647
648  sc = rtems_record_start_server(1, PORT, 1);
649  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
650
651  fd = connect_client();
652  produce_and_read(fd, control);
653
654  rv = close(fd);
655  rtems_test_assert(rv == 0);
656}
657#endif
658
659static void Init(rtems_task_argument arg)
660{
661  test_context *ctx;
662  Per_CPU_Control *cpu_self;
663
664  TEST_BEGIN();
665
666  ctx = &test_instance;
667
668  cpu_self = _Per_CPU_Get_snapshot();
669  cpu_self->record = &ctx->control;
670
671  init_context(ctx);
672  test_capacity(&ctx->control);
673  test_index(&ctx->control);
674  test_add_2_items(ctx, &ctx->control);
675  test_add_3_items(ctx, &ctx->control);
676  test_produce(ctx, &ctx->control);
677  test_produce_2(ctx, &ctx->control);
678  test_produce_n(ctx, &ctx->control);
679  test_drain(ctx, &ctx->control);
680#ifdef RTEMS_NETWORKING
681  test_server(ctx, &ctx->control);
682#endif
683
684  TEST_END();
685  rtems_test_exit(0);
686}
687
688#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
689
690#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
691
692#ifdef RTEMS_NETWORKING
693#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 7
694
695#define CONFIGURE_MAXIMUM_TASKS 3
696
697#define CONFIGURE_MAXIMUM_TIMERS 1
698
699#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT
700#else
701#define CONFIGURE_MAXIMUM_TASKS 1
702#endif
703
704#define CONFIGURE_INIT_TASK_PRIORITY 2
705
706#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
707
708#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
709
710#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
711
712#define CONFIGURE_INIT
713
714#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.