From ef53864d363e30bc3b1325c01906b4b1313e4ed3 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sun, 23 Dec 2012 21:00:17 +0100 Subject: [PATCH] dispd: Wait for console rendering to finish. This prevents a race condition where the console may still be rendering, but the process may be able to get data on the screen faster, which results in visual corruption as the two race. --- dispd/client/session.cpp | 15 +++++++++++++++ sortix/include/sortix/kernel/log.h | 7 +++++++ sortix/kernel.cpp | 8 +++++++- sortix/log.cpp | 3 +++ sortix/logterminal.cpp | 2 +- sortix/textterminal.cpp | 11 +++++++++++ sortix/textterminal.h | 1 + 7 files changed, 45 insertions(+), 2 deletions(-) diff --git a/dispd/client/session.cpp b/dispd/client/session.cpp index 5b6d0024..32581806 100644 --- a/dispd/client/session.cpp +++ b/dispd/client/session.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -121,5 +122,19 @@ bool dispd_session_setup_game_rgba(struct dispd_session* session) perror(chvideomode); exit(127); } + + // TODO: HACK: The console may be rendered asynchronously and it is still + // rendering to the framebuffer, but this process may be able to write to + // the framebuffer before it is done. We need to wait for the console to + // finish to fix this race condition. + int ttyfd = open("/dev/tty", O_WRONLY); + if ( 0 <= ttyfd ) + { + // TODO: There is no fsync system call yet! Whoops! However, closing a + // file descriptor also happens to sync it, so this actually works. + //fsync(ttyfd); + close(ttyfd); + } + return session->is_rgba = true; } diff --git a/sortix/include/sortix/kernel/log.h b/sortix/include/sortix/kernel/log.h index f7ca4a91..0a1ea898 100644 --- a/sortix/include/sortix/kernel/log.h +++ b/sortix/include/sortix/kernel/log.h @@ -35,11 +35,13 @@ namespace Sortix extern size_t (*deviceCallback)(void*, const char*, size_t); extern size_t (*deviceWidth)(void*); extern size_t (*deviceHeight)(void*); + extern bool (*deviceSync)(void*); extern void* devicePointer; void Init(size_t (*callback)(void*, const char*, size_t), size_t (*widthfunc)(void*), size_t (*heightfunc)(void*), + bool (*syncfunc)(void*), void* user); inline void Flush() @@ -57,6 +59,11 @@ namespace Sortix return deviceHeight(devicePointer); } + inline bool Sync() + { + return deviceSync(devicePointer); + } + inline size_t Print(const char* str) { if ( !deviceCallback ) { return 0; } diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index 1d03d3a0..d5151c7a 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -135,6 +135,11 @@ static size_t TextTermHeight(void* user) return ((TextTerminal*) user)->Height(); } +static bool TextTermSync(void* user) +{ + return ((TextTerminal*) user)->Sync(); +} + addr_t initrd; size_t initrdsize; Ref textbufhandle; @@ -166,7 +171,8 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo) TextTerminal textterm(textbufhandle); // Register the text terminal as the kernel log and initialize it. - Log::Init(PrintToTextTerminal, TextTermWidth, TextTermHeight, &textterm); + Log::Init(PrintToTextTerminal, TextTermWidth, TextTermHeight, TextTermSync, + &textterm); // Display the boot welcome screen. DoWelcome(); diff --git a/sortix/log.cpp b/sortix/log.cpp index d6a92ba9..83898b55 100644 --- a/sortix/log.cpp +++ b/sortix/log.cpp @@ -35,6 +35,7 @@ namespace Sortix size_t (*deviceCallback)(void*, const char*, size_t) = NULL; size_t (*deviceWidth)(void*) = NULL; size_t (*deviceHeight)(void*) = NULL; + bool (*deviceSync)(void*) = NULL; void* devicePointer = NULL; size_t SysPrintString(const char* str) @@ -47,11 +48,13 @@ namespace Sortix void Init(size_t (*callback)(void*, const char*, size_t), size_t (*widthfunc)(void*), size_t (*heightfunc)(void*), + bool (*syncfunc)(void*), void* user) { deviceCallback = callback; deviceWidth = widthfunc; deviceHeight = heightfunc; + deviceSync = syncfunc; devicePointer = user; Syscall::Register(SYSCALL_PRINT_STRING, (void*) SysPrintString); diff --git a/sortix/logterminal.cpp b/sortix/logterminal.cpp index 8eb12b14..5c40777e 100644 --- a/sortix/logterminal.cpp +++ b/sortix/logterminal.cpp @@ -125,7 +125,7 @@ int LogTerminal::tcgetwinsize(ioctx_t* ctx, struct winsize* ws) int LogTerminal::sync(ioctx_t* /*ctx*/) { - return 0; // Not needed. + return Log::Sync() ? 0 : -1; } void LogTerminal::OnKeystroke(Keyboard* kb, void* /*user*/) diff --git a/sortix/textterminal.cpp b/sortix/textterminal.cpp index 2d6128d8..2a642b5d 100644 --- a/sortix/textterminal.cpp +++ b/sortix/textterminal.cpp @@ -89,6 +89,17 @@ size_t TextTerminal::Height() const return height; } +bool TextTerminal::Sync() +{ + // Reading something from the textbuffer may cause it to block while + // finishing rendering, effectively synchronizing with it. + ScopedLock lock(&termlock); + TextBuffer* textbuf = textbufhandle->Acquire(); + textbuf->GetCursorPos(); + textbufhandle->Release(textbuf); + return true; +} + void TextTerminal::PutChar(TextBuffer* textbuf, char c) { if ( ansimode ) diff --git a/sortix/textterminal.h b/sortix/textterminal.h index 30c66cee..2990dadb 100644 --- a/sortix/textterminal.h +++ b/sortix/textterminal.h @@ -40,6 +40,7 @@ public: size_t Print(const char* string, size_t stringlen); size_t Width() const; size_t Height() const; + bool Sync(); private: void PutChar(TextBuffer* textbuf, char c);