History

um: add shared memory optimisation for time-travel=ext

With external time travel, a LOT of message can end up being exchanged on the socket, taking a significant amount of time just to do that. Add a new shared memory optimisation to that, where a number of changes are made: - the controller sends a client ID and a shared memory FD (and a logging FD we don't use) in the ACK message to the initial START - the shared memory holds the current time and the free_until value, so that there's no need to exchange messages for that - if the client that's running has shared memory support, any client (the running one included) can request the next time it wants to run inside the shared memory, rather than sending a message, by also updating the free_until value - when shared memory is enabled, RUN/WAIT messages no longer have an ACK, further cutting down on messages Together, this can reduce the number of messages very significantly, and reduce overall test/simulation run time.

Johannes Berg committed 2 years ago

Commit bfb80d81 parent e20f9b32 files · +283 −26Browse files

Showing the changes to include/uapi (1 of 2 files). Show all

Unified · Split

include/uapi/linux/um_timetravel.h+165−14
@@ -1,17 +1,6 @@
1+/* SPDX-License-Identifier: BSD-3-Clause */
12 /*
2− * Permission to use, copy, modify, and/or distribute this software for any
3− * purpose with or without fee is hereby granted, provided that the above
4− * copyright notice and this permission notice appear in all copies.
5− *
6− * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
7− * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
8− * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
9− * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
10− * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
11− * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
12− * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
13− *
14− * Copyright (C) 2019 Intel Corporation
3+ * Copyright (C) 2019 - 2023 Intel Corporation
154 */
165 #ifndef _UAPI_LINUX_UM_TIMETRAVEL_H
176 #define _UAPI_LINUX_UM_TIMETRAVEL_H
@@ -50,6 +39,36 @@ struct um_timetravel_msg { · 32 unmodified lines
5039 __u64 time;
5140 };
5241
42+/* max number of file descriptors that can be sent/received in a message */
43+#define UM_TIMETRAVEL_MAX_FDS 2
44+
45+/**
46+ * enum um_timetravel_shared_mem_fds - fds sent in ACK message for START message
47+ */
48+enum um_timetravel_shared_mem_fds {
49+ /**
50+ * @UM_TIMETRAVEL_SHARED_MEMFD: Index of the shared memory file
51+ * descriptor in the control message
52+ */
53+ UM_TIMETRAVEL_SHARED_MEMFD,
54+ /**
55+ * @UM_TIMETRAVEL_SHARED_LOGFD: Index of the logging file descriptor
56+ * in the control message
57+ */
58+ UM_TIMETRAVEL_SHARED_LOGFD,
59+ UM_TIMETRAVEL_SHARED_MAX_FDS,
60+};
61+
62+/**
63+ * enum um_timetravel_start_ack - ack-time mask for start message
64+ */
65+enum um_timetravel_start_ack {
66+ /**
67+ * @UM_TIMETRAVEL_START_ACK_ID: client ID that controller allocated.
68+ */
69+ UM_TIMETRAVEL_START_ACK_ID = 0xffff,
70+};
71+
5372 /**
5473 * enum um_timetravel_ops - Operation codes
5574 */
@@ -57,7 +76,9 @@ enum um_timetravel_ops { · 1 unmodified line
5776 /**
5877 * @UM_TIMETRAVEL_ACK: response (ACK) to any previous message,
5978 * this usually doesn't carry any data in the 'time' field
60− * unless otherwise specified below
79+ * unless otherwise specified below, note: while using shared
80+ * memory no ACK for WAIT and RUN messages, for more info see
81+ * &struct um_timetravel_schedshm.
6182 */
6283 UM_TIMETRAVEL_ACK = 0,
6384
@@ -136,4 +157,134 @@ enum um_timetravel_ops { · 72 unmodified lines
136157 UM_TIMETRAVEL_BROADCAST = 9,
137158 };
138159
160+/* version of struct um_timetravel_schedshm */
161+#define UM_TIMETRAVEL_SCHEDSHM_VERSION 2
162+
163+/**
164+ * enum um_timetravel_schedshm_cap - time travel capabilities of every client
165+ *
166+ * These flags must be set immediately after processing the ACK to
167+ * the START message, before sending any message to the controller.
168+ */
169+enum um_timetravel_schedshm_cap {
170+ /**
171+ * @UM_TIMETRAVEL_SCHEDSHM_CAP_TIME_SHARE: client can read current time
172+ * update internal time request to shared memory and read
173+ * free until and send no Ack on RUN and doesn't expect ACK on
174+ * WAIT.
175+ */
176+ UM_TIMETRAVEL_SCHEDSHM_CAP_TIME_SHARE = 0x1,
177+};
178+
179+/**
180+ * enum um_timetravel_schedshm_flags - time travel flags of every client
181+ */
182+enum um_timetravel_schedshm_flags {
183+ /**
184+ * @UM_TIMETRAVEL_SCHEDSHM_FLAGS_REQ_RUN: client has a request to run.
185+ * It's set by client when it has a request to run, if (and only
186+ * if) the @running_id points to a client that is able to use
187+ * shared memory, i.e. has %UM_TIMETRAVEL_SCHEDSHM_CAP_TIME_SHARE
188+ * (this includes the client itself). Otherwise, a message must
189+ * be used.
190+ */
191+ UM_TIMETRAVEL_SCHEDSHM_FLAGS_REQ_RUN = 0x1,
192+};
193+
194+/**
195+ * DOC: Time travel shared memory overview
196+ *
197+ * The main purpose of the shared memory is to avoid all time travel message
198+ * that don't need any action, for example current time can be held in shared
199+ * memory without the need of any client to send a message UM_TIMETRAVEL_GET
200+ * in order to know what's the time.
201+ *
202+ * Since this is shared memory with all clients and controller and controller
203+ * creates the shared memory space, all time values are absolute to controller
204+ * time. So first time client connects to shared memory mode it should take the
205+ * current_time value in shared memory and keep it internally as a diff to
206+ * shared memory times, and once shared memory is initialized, any interaction
207+ * with the controller must happen in the controller time domain, including any
208+ * messages (for clients that are not using shared memory, the controller will
209+ * handle an offset and make the clients think they start at time zero.)
210+ *
211+ * Along with the shared memory file descriptor is sent to the client a logging
212+ * file descriptor, to have all logs related to shared memory,
213+ * logged into one place. note: to have all logs synced into log file at write,
214+ * file should be flushed (fflush) after writing to it.
215+ *
216+ * To avoid memory corruption, we define below for each field who can write to
217+ * it at what time, defined in the structure fields.
218+ *
219+ * To avoid having to pack this struct, all fields in it must be naturally aligned
220+ * (i.e. aligned to their size).
221+ */
222+
223+/**
224+ * union um_timetravel_schedshm_client - UM time travel client struct
225+ *
226+ * Every entity using the shared memory including the controller has a place in
227+ * the um_timetravel_schedshm clients array, that holds info related to the client
228+ * using the shared memory, and can be set only by the client after it gets the
229+ * fd memory.
230+ *
231+ * @capa: bit fields with client capabilities see
232+ * &enum um_timetravel_schedshm_cap, set by client once after getting the
233+ * shared memory file descriptor.
234+ * @flags: bit fields for flags see &enum um_timetravel_schedshm_flags for doc.
235+ * @req_time: request time to run, set by client on every request it needs.
236+ * @name: unique id sent to the controller by client with START message.
237+ */
238+union um_timetravel_schedshm_client {
239+ struct {
240+ __u32 capa;
241+ __u32 flags;
242+ __u64 req_time;
243+ __u64 name;
244+ };
245+ char reserve[128]; /* reserved for future usage */
246+};
247+
248+/**
249+ * struct um_timetravel_schedshm - UM time travel shared memory struct
250+ *
251+ * @hdr: header fields:
252+ * @version: Current version struct UM_TIMETRAVEL_SCHEDSHM_VERSION,
253+ * set by controller once at init, clients must check this after mapping
254+ * and work without shared memory if they cannot handle the indicated
255+ * version.
256+ * @len: Length of all the memory including header (@hdr), clients should once
257+ * per connection first mmap the header and take the length (@len) to remap the entire size.
258+ * This is done in order to support dynamic struct size letting number of
259+ * clients be dynamic based on controller support.
260+ * @free_until: Stores the next request to run by any client, in order for the
261+ * current client to know how long it can still run. A client needs to (at
262+ * least) reload this value immediately after communicating with any other
263+ * client, since the controller will update this field when a new request
264+ * is made by any client. Clients also must update this value when they
265+ * insert/update an own request into the shared memory while not running
266+ * themselves, and the new request is before than the current value.
267+ * current_time: Current time, can only be set by the client in running state
268+ * (indicated by @running_id), though that client may only run until @free_until,
269+ * so it must remain smaller than @free_until.
270+ * @running_id: The current client in state running, set before a client is
271+ * notified that it's now running.
272+ * @max_clients: size of @clients array, set once at init by the controller.
273+ * @clients: clients array see &union um_timetravel_schedshm_client for doc,
274+ * set only by client.
275+ */
276+struct um_timetravel_schedshm {
277+ union {
278+ struct {
279+ __u32 version;
280+ __u32 len;
281+ __u64 free_until;
282+ __u64 current_time;
283+ __u16 running_id;
284+ __u16 max_clients;
285+ };
286+ char hdr[4096]; /* align to 4K page size */
287+ };
288+ union um_timetravel_schedshm_client clients[];
289+};
139290 #endif /* _UAPI_LINUX_UM_TIMETRAVEL_H */