xref: /aosp_15_r20/external/wayland/patches/0001-connection-Simplify-wl_closure_print.diff (revision 84e872a0dc482bffdb63672969dd03a827d67c73)
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Lloyd Pique <[email protected]>
3Date: Thu, 10 Mar 2022 14:56:02 -0800
4Subject: [PATCH 1/6] connection: Simplify wl_closure_print
5
6Client message observers 1/6
7
8Cleans up wl_closure_print(), and adds a client-private closure_log()
9intermediate function.
10
11This patch simplifies wl_closure_print() slightly by moving some client-only
12details to a new closure_log() intermediate function. This new function will
13also handle delivering messages to the new listener callback in a subsequent
14patch.
15
16closure_log() internally handles the check for logging being enabled,
17simplifying its callers, and returns early if logging is not enabled. This check
18becomes a bit more complex when there can be listeners.
19
20closure_log() also handles the work same transformation performed by
21id_from_object(), by making a copy of the args, and applying the transform to
22the copy before passing the arguments to wl_closure_print(). Doing it this way
23means the same arguments can also be passed to the eventual listeners.
24
25The boolean "discarded" argument for wl_closure_print() has been replaced by a
26"discarded_reason" string argument, allowing an arbitrary reason string to be
27passed in. For now only "discarded[]" is printed as an empty reason string is
28passed if the message was discarded, but that will also change.
29
30Signed-off-by: Lloyd Pique <[email protected]>
31
32diff --git a/COPYING b/COPYING
33index eb25a4e..843b844 100644
34--- a/COPYING
35+++ b/COPYING
36@@ -2,6 +2,7 @@ Copyright © 2008-2012 Kristian Høgsberg
37 Copyright © 2010-2012 Intel Corporation
38 Copyright © 2011 Benjamin Franzke
39 Copyright © 2012 Collabora, Ltd.
40+Copyright 2022 Google LLC
41
42 Permission is hereby granted, free of charge, to any person obtaining a
43 copy of this software and associated documentation files (the "Software"),
44diff --git a/src/connection.c b/src/connection.c
45index ceaeac1..110b614 100644
46--- a/src/connection.c
47+++ b/src/connection.c
48@@ -1264,7 +1264,7 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
49
50 void
51 wl_closure_print(struct wl_closure *closure, struct wl_object *target,
52-		 int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg))
53+		 bool send, const char *discarded_reason)
54 {
55 	int i;
56 	struct argument_details arg;
57@@ -1283,9 +1283,11 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
58 	clock_gettime(CLOCK_REALTIME, &tp);
59 	time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
60
61-	fprintf(f, "[%7u.%03u] %s%s%s@%u.%s(",
62+	fprintf(f, "[%7u.%03u] %s%s%s%s%s@%u.%s(",
63 		time / 1000, time % 1000,
64-		discarded ? "discarded " : "",
65+		(discarded_reason != NULL) ? "discarded[" : "",
66+		(discarded_reason != NULL) ? discarded_reason : "",
67+		(discarded_reason != NULL) ? "] " : "",
68 		send ? " -> " : "",
69 		target->interface->name, target->id,
70 		closure->message->name);
71@@ -1330,10 +1332,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
72 				fprintf(f, "nil");
73 			break;
74 		case 'n':
75-			if (n_parse)
76-				nval = n_parse(&closure->args[i]);
77-			else
78-				nval = closure->args[i].n;
79+			nval = closure->args[i].n;
80
81 			fprintf(f, "new id %s@",
82 				(closure->message->types[i]) ?
83diff --git a/src/wayland-client.c b/src/wayland-client.c
84index 105f9be..ae47307 100644
85--- a/src/wayland-client.c
86+++ b/src/wayland-client.c
87@@ -115,6 +115,73 @@ struct wl_display {
88
89 static int debug_client = 0;
90
91+/**
92+ * This helper function adjusts the closure arguments before they are logged.
93+ * On the client, after the call to create_proxies(), NEW_ID arguments will
94+ * point to a wl_proxy accessible via arg.o instead of being an int32
95+ * accessible by arg.n, which is what wl_closure_print() attempts to print.
96+ * This helper transforms the argument back into an id, so wl_closure_print()
97+ * doesn't need to handle that as a special case.
98+ *
99+ * \param closure  closure to adjust
100+ * \param send     if this is closure is for a request
101+ *
102+ */
103+static void
104+adjust_closure_args_for_logging(struct wl_closure *closure, bool send)
105+{
106+	int i;
107+	struct argument_details arg;
108+	const struct wl_proxy *proxy;
109+	const char *signature = closure->message->signature;
110+
111+	// No adjustment needed for a send.
112+	if (send)
113+		return;
114+
115+	for (i = 0; i < closure->count; i++) {
116+		signature = get_next_argument(signature, &arg);
117+
118+		switch (arg.type) {
119+		case 'n':
120+			proxy = (struct wl_proxy *)closure->args[i].o;
121+			closure->args[i].n = proxy ? proxy->object.id : 0;
122+			break;
123+		}
124+	}
125+}
126+
127+/**
128+ * This function helps log closures from the client, assuming logging is
129+ * enabled.
130+ *
131+ * \param closure    closure for the message
132+ * \param proxy      proxy for the message
133+ * \param send       true if this is closure is for a request
134+ * \param discarded  true if this is message is being discarded
135+ *
136+ */
137+static void
138+closure_log(struct wl_closure *closure, struct wl_proxy *proxy, bool send,
139+	    bool discarded)
140+{
141+	struct wl_closure adjusted_closure = { 0 };
142+
143+	if (!debug_client)
144+		return;
145+
146+	// Note: The real closure has extra data (referenced by its args
147+	// immediately following the structure in memory, but we don't
148+	// need to duplicate that.
149+	memcpy(&adjusted_closure, closure, sizeof(struct wl_closure));
150+
151+	// Adjust the closure arguments.
152+	adjust_closure_args_for_logging(&adjusted_closure, send);
153+
154+	wl_closure_print(&adjusted_closure, &proxy->object, send,
155+			 discarded ? "" : NULL);
156+}
157+
158 /**
159  * This helper function wakes up all threads that are
160  * waiting for display->reader_cond (i. e. when reading is done,
161@@ -885,8 +952,7 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
162 		goto err_unlock;
163 	}
164
165-	if (debug_client)
166-		wl_closure_print(closure, &proxy->object, true, false, NULL);
167+	closure_log(closure, proxy, true, false);
168
169 	if (wl_closure_send(closure, proxy->display->connection)) {
170 		wl_log("Error sending request: %s\n", strerror(errno));
171@@ -1579,19 +1645,6 @@ queue_event(struct wl_display *display, int len)
172 	return size;
173 }
174
175-static uint32_t
176-id_from_object(union wl_argument *arg)
177-{
178-	struct wl_proxy *proxy;
179-
180-	if (arg->o) {
181-		proxy = (struct wl_proxy *)arg->o;
182-		return proxy->object.id;
183-	}
184-
185-	return 0;
186-}
187-
188 static void
189 dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
190 {
191@@ -1610,8 +1663,7 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
192 	proxy = closure->proxy;
193 	proxy_destroyed = !!(proxy->flags & WL_PROXY_FLAG_DESTROYED);
194 	if (proxy_destroyed) {
195-		if (debug_client)
196-			wl_closure_print(closure, &proxy->object, false, true, id_from_object);
197+		closure_log(closure, proxy, false, true);
198 		destroy_queued_closure(closure);
199 		return;
200 	}
201@@ -1619,15 +1671,11 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
202 	pthread_mutex_unlock(&display->mutex);
203
204 	if (proxy->dispatcher) {
205-		if (debug_client)
206-			wl_closure_print(closure, &proxy->object, false, false, id_from_object);
207-
208+		closure_log(closure, proxy, false, false);
209 		wl_closure_dispatch(closure, proxy->dispatcher,
210 				    &proxy->object, opcode);
211 	} else if (proxy->object.implementation) {
212-		if (debug_client)
213-			wl_closure_print(closure, &proxy->object, false, false, id_from_object);
214-
215+		closure_log(closure, proxy, false, false);
216 		wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT,
217 				  &proxy->object, opcode, proxy->user_data);
218 	}
219diff --git a/src/wayland-private.h b/src/wayland-private.h
220index 9274f1b..66fc78f 100644
221--- a/src/wayland-private.h
222+++ b/src/wayland-private.h
223@@ -211,9 +211,8 @@ int
224 wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection);
225
226 void
227-wl_closure_print(struct wl_closure *closure,
228-		 struct wl_object *target, int send, int discarded,
229-		 uint32_t (*n_parse)(union wl_argument *arg));
230+wl_closure_print(struct wl_closure *closure, struct wl_object *target,
231+		 bool send, const char *discarded_reason);
232
233 void
234 wl_closure_destroy(struct wl_closure *closure);
235diff --git a/src/wayland-server.c b/src/wayland-server.c
236index d51acc6..be98f7d 100644
237--- a/src/wayland-server.c
238+++ b/src/wayland-server.c
239@@ -157,7 +157,7 @@ log_closure(struct wl_resource *resource,
240 	struct wl_protocol_logger_message message;
241
242 	if (debug_server)
243-		wl_closure_print(closure, object, send, false, NULL);
244+		wl_closure_print(closure, object, send, NULL);
245
246 	if (!wl_list_empty(&display->protocol_loggers)) {
247 		message.resource = resource;
248