Skip to content

Commit 9bd2e1e

Browse files
committed
display_task: Pre-ack render commands
The drop-oldest path in display_task_consume_mailbox can silently drop an update message to make room for a newer one (rendering a stale frame is wasted when a fresher one is queued). The dropped caller was left without a reply and timed out at gen_server:call — an ugly failure mode for a frame-loss-tolerant design. Send {Ref, ok} on arrival, before the enqueue-or-drop decision. Drivers skip the reply on the update path so the caller never sees a duplicate. draw_buffer gets the same treatment: it is gen_call-shaped but fire-and-forget at the driver, today timing out the caller. register_font and load_image still reply synchronously: they need to convey the operation outcome (registered handle / decoded binary) and do not share the drop-for-newer rationale.
1 parent 6c0e995 commit 9bd2e1e

5 files changed

Lines changed: 40 additions & 1 deletion

File tree

dcs_lcd_display_driver.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ static void process_message(Message *message, Context *ctx)
223223
"update")) {
224224
term display_list = term_get_tuple_element(req, 1);
225225
do_update(ctx, display_list);
226+
return;
226227

227228
} else if (cmd == context_make_atom(ctx, "\xB"
228229
"draw_buffer")) {
@@ -237,7 +238,8 @@ static void process_message(Message *message, Context *ctx)
237238

238239
dcs_lcd_draw_buffer(&driver->bus, &driver->screen, driver->desc->pixel_bytes, x, y, width, height, data);
239240

240-
// draw_buffer is a kind of cast, no need to reply
241+
// Reply already sent at enqueue time by
242+
// try_pre_ack_render_cmd in display_task.c.
241243
return;
242244

243245
} else if (cmd == globalcontext_make_atom(ctx->global, "\xA" "load_image")) {

display_task.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,47 @@
3232

3333
UFontManager *ufont_manager;
3434

35+
static bool try_pre_ack_render_cmd(Message *message, Context *ctx)
36+
{
37+
GenMessage gen_message;
38+
if (UNLIKELY(port_parse_gen_message(message->message,
39+
&gen_message) != GenCallMessage)) {
40+
return false;
41+
}
42+
43+
term req = gen_message.req;
44+
if (UNLIKELY(!term_is_tuple(req) || term_get_tuple_arity(req) < 1)) {
45+
return false;
46+
}
47+
term cmd = term_get_tuple_element(req, 0);
48+
49+
if (cmd != globalcontext_make_atom(ctx->global, "\x6" "update")
50+
&& cmd != globalcontext_make_atom(ctx->global,
51+
"\xB" "draw_buffer")) {
52+
return false;
53+
}
54+
55+
BEGIN_WITH_STACK_HEAP(TUPLE_SIZE(2) + REF_SIZE, heap);
56+
term return_tuple = term_alloc_tuple(2, &heap);
57+
term_put_tuple_element(return_tuple, 0, gen_message.ref);
58+
term_put_tuple_element(return_tuple, 1, OK_ATOM);
59+
display_message_send(gen_message.pid, return_tuple, ctx->global);
60+
END_WITH_STACK_HEAP(heap, ctx->global);
61+
62+
return true;
63+
}
64+
3565
NativeHandlerResult display_task_consume_mailbox(Context *ctx)
3666
{
3767
struct DisplayTaskArgs *args = ctx->platform_data;
3868

3969
MailboxMessage *mbox_msg = mailbox_take_message(&ctx->mailbox);
4070
Message *msg = CONTAINER_OF(mbox_msg, Message, base);
4171

72+
// Pre-ack update / draw_buffer before the enqueue-or-drop
73+
// dance so the caller doesn't time out if dropped.
74+
try_pre_ack_render_cmd(msg, ctx);
75+
4276
// Non-blocking enqueue; drop oldest on overflow.
4377
if (xQueueSend(args->messages_queue, &msg, 0) != pdTRUE) {
4478

epaper_display_driver.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ static void process_message(Message *message, Context *ctx)
260260

261261
term display_list = term_get_tuple_element(req, 1);
262262
do_update(ctx, display_list);
263+
return;
263264

264265
} else if (cmd == globalcontext_make_atom(ctx->global, "\xA" "load_image")) {
265266
handle_load_image(req, gen_message.ref, gen_message.pid, ctx);

memory_display_driver.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ static void process_message(Message *message, Context *ctx)
179179
"update")) {
180180
term display_list = term_get_tuple_element(req, 1);
181181
do_update(ctx, display_list);
182+
return;
182183

183184
} else if (cmd == globalcontext_make_atom(ctx->global, "\xA" "load_image")) {
184185
handle_load_image(req, gen_message.ref, gen_message.pid, ctx);

oled_display_driver.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ static void process_message(Message *message, Context *ctx)
193193
"update")) {
194194
term display_list = term_get_tuple_element(req, 1);
195195
do_update(ctx, display_list);
196+
return;
196197

197198
} else if (cmd == globalcontext_make_atom(ctx->global, "\xA" "load_image")) {
198199
handle_load_image(req, gen_message.ref, gen_message.pid, ctx);

0 commit comments

Comments
 (0)