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.
This commit is contained in:
Jonas 'Sortie' Termansen 2012-12-23 21:00:17 +01:00
parent ca7ad9709f
commit ef53864d36
7 changed files with 45 additions and 2 deletions

View File

@ -26,6 +26,7 @@
#include <sys/display.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@ -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;
}

View File

@ -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; }

View File

@ -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<TextBufferHandle> 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();

View File

@ -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);

View File

@ -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*/)

View File

@ -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 )

View File

@ -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);