ovni/test/emu/ovni/sort-flush.c
Rodrigo Arias 354f2f50eb Register emulation models only if required
Until now, emulation models were always being registered via probe(),
which causes the emulator to initialize all the channels. To reduce the
overhead, the channels were not connected or registered in the bay
until the first event of that model was received. This delayed connect
was causing issues in muxes where the newly connected model required
refreshing the touched channels. Which in turn was causing unexpected
PRV events.

By determining which models we need to enable, we can remove the delayed
connect mechanism and just enable those models at initialization time,
and connect the channels.
2023-11-16 12:39:05 +01:00

164 lines
3.8 KiB
C

/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#include <stddef.h>
#include <stdint.h>
#include "compat.h"
#include "instr.h"
#include "ovni.h"
static void
emit_jumbo(uint8_t *buf, size_t size, int64_t clock)
{
struct ovni_ev ev = {0};
ovni_ev_set_mcv(&ev, "OUj");
ovni_ev_set_clock(&ev, clock);
ovni_ev_jumbo_emit(&ev, buf, size);
}
static void
emit(char *mcv, int64_t clock)
{
struct ovni_ev ev = {0};
ovni_ev_set_mcv(&ev, mcv);
ovni_ev_set_clock(&ev, clock);
ovni_ev_emit(&ev);
}
static void
fill(long room)
{
/* Flush the buffer so we begin with a known size: the two flush
* events */
ovni_flush();
size_t ev_size = sizeof(struct ovni_ev_header);
/* Skip the jumbo event header and payload size */
size_t header = ev_size + 4;
size_t payload_size = OVNI_MAX_EV_BUF - room - header;
uint8_t *payload_buf = calloc(1, payload_size);
/* Fill the stream buffer */
int64_t t = ovni_clock_now();
emit_jumbo(payload_buf, payload_size, t);
/* Leave some room to prevent clashes */
sleep_us(100);
}
static void
test_flush_after_sort(void)
{
/* In this test we check with the flush events OF[ and OF]
* immediately after the sort region opening event OU[.
*
* $ ovnidump thread.150439.obs | cut -c -72
* ovnidump: INFO: loaded 1 streams
* 1778730985500133 +1778730985500133 OHx :00:00:00:00:ff:ff:ff:ff:00:0
* 1778730985503455 +3322 OF[
* 1778730985508228 +4773 OF]
* 1778730985666648 +158420 OUj :cc:ff:1f:00:00:00:00:00:00:00:00:00
* 1778730985666649 +1 OU[
* 1778730987234771 +1568122 OF[ <-- here we inject the
* 1778730988411065 +1176294 OF] flush events
* 1778730985666550 -2744515 KCI
* 1778730985666551 +1 KCO
* 1778730985666652 +101 OU]
* 1778730988411997 +2745345 OHe
*/
/* Skip the two flush events and leave room for OU[ */
fill(3 * sizeof(struct ovni_ev_header));
int64_t t = ovni_clock_now();
/* Emit the opening of the sort region */
emit("OU[", t++);
/* This should cause the stream to be flush and inject the two
* extra events OF[ and OF] */
emit("KCO", t++ - 100);
/* Finish the kernel event */
emit("KCI", t++ - 100);
/* Finish the sort region */
emit("OU]", ovni_clock_now());
}
static void
test_unsorted(void)
{
/* Test unsorted events in the sorting region */
sleep_us(100); /* Make room */
int64_t t = ovni_clock_now();
emit("OU[", t);
emit("KCI", t + 2 - 100); /* out of order */
emit("KCO", t + 1 - 100);
emit("OU]", t + 3);
}
static void
test_overlap(void)
{
/* Test overlapping events among regions */
int64_t t = ovni_clock_now();
/* Round time next 1 microsecond to be easier to read */
t += 1000 - (t % 1000);
emit("OU[", t + 20);
emit("KCO", t + 10);
emit("KCI", t + 11);
emit("OU]", t + 21);
emit("OU[", t + 22);
emit("KCO", t + 12); /* These two shold appear in the first region */
emit("KCI", t + 13);
emit("OU]", t + 23);
}
static void
test_overlap_flush(void)
{
/* Test overlapping events with flush events too */
/* Skip the two flush events and leave room for OU[ */
sleep_us(100);
fill(5 * sizeof(struct ovni_ev_header));
int64_t t = ovni_clock_now();
/* Round time next 1 microsecond to be easier to read */
t += 1000 - (t % 1000);
emit("OU[", t + 20);
emit("KCO", t + 10);
emit("KCI", t + 11);
emit("OU]", t + 21);
/* We need realistic clock due to incoming flush */
emit("OU[", ovni_clock_now());
/* Flush here */
emit("KCO", t + 12);
emit("KCI", t + 13);
emit("OU]", ovni_clock_now());
}
int
main(void)
{
/* This program tests various cases in which flush events are placed in
* the sorting region, disrupting the order. */
instr_start(0, 1);
instr_require("kernel");
test_flush_after_sort();
test_unsorted();
test_overlap();
test_overlap_flush();
instr_end();
return 0;
}