misc changes

This commit is contained in:
nakst 2021-12-04 12:00:10 +00:00
parent 7d2ea59a4c
commit f201231f52
13 changed files with 100 additions and 66 deletions

View File

@ -382,6 +382,10 @@ extern "C" void InterruptHandler(InterruptContext *context) {
CPULocalStorage *local = GetLocalStorage();
uintptr_t interrupt = context->interruptNumber;
if (local && local->currentThread) {
local->currentThread->lastInterruptTimeStamp = ProcessorReadTimeStamp();
}
if (local && local->spinlockCount && context->cr8 != 0xE) {
KernelPanic("InterruptHandler - Local spinlockCount is %d but interrupts were enabled (%x/%x).\n", local->spinlockCount, local, context);
}

View File

@ -823,6 +823,15 @@ extern "C" bool PostContextSwitch(InterruptContext *context, MMSpace *oldAddress
KernelPanic("PostContextSwitch - spinlockCount is non-zero (%x).\n", local);
}
currentThread->timerAdjustTicks += ProcessorReadTimeStamp() - local->currentThread->lastInterruptTimeStamp;
if (currentThread->timerAdjustAddress && MMArchIsBufferInUserRange(currentThread->timerAdjustAddress, sizeof(uint64_t))) {
// TODO If the MMArchSafeCopy fails, then the kernel will panic because interrupts are disabled here.
// We probably need a special version of MMArchSafeCopy that doesn't try to resolve page faults and fails faster.
// TODO Instead of timerAdjustAddress, maybe copy it onto a fixed location at the base of thread's stack?
MMArchSafeCopy(currentThread->timerAdjustAddress, (uintptr_t) &local->currentThread->timerAdjustTicks, sizeof(uint64_t));
}
#ifdef ES_ARCH_X86_32
if (context->fromRing0) {
// Returning to a kernel thread; we need to fix the stack.

View File

@ -90,6 +90,7 @@ struct ThreadLocalStorage {
ThreadLocalStorage *self;
EsObjectID id;
uint64_t timerAdjustTicks;
};
struct MountPoint : EsMountPoint {
@ -1105,13 +1106,12 @@ EsMessage *EsMessageReceive() {
ProcessMessageTiming timing = {};
double start = EsTimeStampMs();
UIProcessWindowManagerMessage((EsWindow *) message.object, &message.message, &timing);
EsPrint("Processed message from WM %x in %Fms (%Fms logic, %Fms layout, %Fms paint, %Fms update screen). Profiling buffer %F%% full.\n",
EsPrint("Processed message from WM %x in %Fms (%Fms logic, %Fms layout, %Fms paint, %Fms update screen).\n",
type, EsTimeStampMs() - start,
timing.endLogic - timing.startLogic,
timing.endLayout - timing.startLayout,
timing.endPaint - timing.startPaint,
timing.endUpdate - timing.startUpdate,
profilingBufferSize ? profilingBufferPosition * 100.0 / profilingBufferSize : 0);
timing.endUpdate - timing.startUpdate);
#else
UIProcessWindowManagerMessage((EsWindow *) message.object, &message.message, nullptr);
#endif
@ -1474,7 +1474,8 @@ void ThreadInitialise(ThreadLocalStorage *local) {
EsMemoryZero(local, sizeof(ThreadLocalStorage));
EsSyscall(ES_SYSCALL_THREAD_GET_ID, ES_CURRENT_THREAD, (uintptr_t) &local->id, 0, 0);
local->self = local;
EsSyscall(ES_SYSCALL_PROCESS_SET_TLS, (uintptr_t) local - tlsStorageOffset, 0, 0, 0);
EsSyscall(ES_SYSCALL_THREAD_SET_TLS, (uintptr_t) local - tlsStorageOffset, 0, 0, 0);
EsSyscall(ES_SYSCALL_THREAD_SET_TIMER_ADJUST_ADDRESS, (uintptr_t) &local->timerAdjustTicks, 0, 0, 0);
}
#include "desktop.cpp"
@ -1509,6 +1510,12 @@ extern "C" void _start(EsProcessStartupInformation *_startupInformation) {
if (desktop) {
EsPrint("Reached Desktop process.\n");
#ifdef PROFILE_DESKTOP_FUNCTIONS
size_t profilingBufferSize = 64 * 1024 * 1024;
GfProfilingInitialise((ProfilingEntry *) EsHeapAllocate(profilingBufferSize, true),
profilingBufferSize / sizeof(ProfilingEntry), api.startupInformation->timeStampTicksPerMs);
#endif
// Process messages until we find the boot file system.
while (!api.foundBootFileSystem) {

View File

@ -8035,13 +8035,6 @@ void InspectorVisualizeLayoutBounds(EsInstance *instance, EsElement *, EsCommand
EsElementRepaint(window);
}
#ifdef PROFILE_DESKTOP_FUNCTIONS
void InspectorBeginProfiling(EsInstance *, EsElement *, EsCommand *) {
size_t entryCount = 3000000;
ProfilingSetup((ProfilingEntry *) EsHeapAllocate(sizeof(ProfilingEntry) * entryCount, false), entryCount);
}
#endif
void InspectorAddElement2(EsMenu *menu, EsGeneric context) {
InspectorWindow *inspector = (InspectorWindow *) menu->instance;
if (inspector->selectedElement == -1) return;
@ -8102,9 +8095,6 @@ void InspectorSetup(EsWindow *window) {
inspector->visualizePaintSteps = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR, 0, "Visualize paint steps");
EsButtonOnCommand(inspector->visualizePaintSteps, InspectorVisualizePaintSteps);
EsSpacerCreate(toolbar, ES_CELL_H_FILL);
#ifdef PROFILE_DESKTOP_FUNCTIONS
EsButtonOnCommand(EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR, 0, "Begin profiling"), InspectorBeginProfiling);
#endif
}
inspector->elementList = EsListViewCreate(panel1, ES_CELL_FILL | ES_LIST_VIEW_COLUMNS | ES_LIST_VIEW_SINGLE_SELECT);

View File

@ -1949,7 +1949,7 @@ struct EsListView : EsElement {
selectedCellStyle = GetStyle(MakeStyleKey(ES_STYLE_LIST_SELECTED_CHOICE_CELL, 0), false);
EsListViewChangeStyles(this, nullptr, nullptr, nullptr, nullptr, ES_FLAGS_DEFAULT, ES_FLAGS_DEFAULT);
} else if (message->type == ES_MSG_LIST_VIEW_GET_CONTENT && activeColumns.Length()) {
} else if (message->type == ES_MSG_LIST_VIEW_GET_CONTENT && (activeColumns.Length() || (flags & ES_LIST_VIEW_FIXED_ITEMS))) {
uintptr_t index = message->getContent.index;
ListViewFixedItemData data = {};

View File

@ -805,11 +805,12 @@ private enum EsSyscallType {
ES_SYSCALL_PROCESS_GET_TLS
ES_SYSCALL_PROCESS_OPEN
ES_SYSCALL_PROCESS_PAUSE
ES_SYSCALL_PROCESS_SET_TLS
ES_SYSCALL_PROCESS_TERMINATE
ES_SYSCALL_SLEEP
ES_SYSCALL_THREAD_CREATE
ES_SYSCALL_THREAD_GET_ID
ES_SYSCALL_THREAD_SET_TLS
ES_SYSCALL_THREAD_SET_TIMER_ADJUST_ADDRESS
ES_SYSCALL_THREAD_STACK_SIZE
ES_SYSCALL_THREAD_TERMINATE
ES_SYSCALL_WAIT

View File

@ -670,7 +670,7 @@ long EsPOSIXSystemCall(long n, long a1, long a2, long a3, long a4, long a5, long
case -1000: {
// Update thread local storage:
void *apiTLS = ProcessorTLSRead(tlsStorageOffset);
EsSyscall(ES_SYSCALL_PROCESS_SET_TLS, a1, 0, 0, 0);
EsSyscall(ES_SYSCALL_THREAD_SET_TLS, a1, 0, 0, 0);
tlsStorageOffset = -a2;
ProcessorTLSWrite(tlsStorageOffset, apiTLS);
} break;

View File

@ -1,55 +1,51 @@
// TODO Adjust time stamps for thread preemption.
#include <stdint.h>
#include <stddef.h>
// TODO Include external events on the flame graph, such as context switches.
struct ProfilingEntry {
void *thisFunction;
uint64_t timeStamp;
};
extern ptrdiff_t tlsStorageOffset;
extern "C" uintptr_t ProcessorTLSRead(uintptr_t offset);
extern "C" uint64_t ProcessorReadTimeStamp();
void EnterDebugger();
ProfilingEntry *gfProfilingBuffer;
size_t gfProfilingBufferSize;
uintptr_t gfProfilingBufferPosition;
volatile ThreadLocalStorage *gfProfilingThread;
uint64_t gfProfilingTicksPerMs;
extern size_t profilingBufferSize;
extern uintptr_t profilingBufferPosition;
void ProfilingSetup(ProfilingEntry *buffer, size_t size /* number of entries */);
#ifdef PROFILING_IMPLEMENTATION
ProfilingEntry *profilingBuffer;
size_t profilingBufferSize;
uintptr_t profilingBufferPosition;
uintptr_t profilingThread;
#define PROFILING_FUNCTION(_exiting) \
#define GF_PROFILING_FUNCTION(_exiting) \
(void) callSite; \
\
if (profilingBufferPosition < profilingBufferSize && profilingThread == ProcessorTLSRead(tlsStorageOffset)) { \
ProfilingEntry *entry = (ProfilingEntry *) &profilingBuffer[profilingBufferPosition++]; \
if (gfProfilingBufferPosition < gfProfilingBufferSize \
&& gfProfilingThread == (ThreadLocalStorage *) ProcessorTLSRead(tlsStorageOffset)) { \
ProfilingEntry *entry = (ProfilingEntry *) &gfProfilingBuffer[gfProfilingBufferPosition++]; \
entry->thisFunction = thisFunction; \
entry->timeStamp = ProcessorReadTimeStamp() | ((uint64_t) _exiting << 63); \
} else if (profilingBufferSize && profilingThread == ProcessorTLSRead(tlsStorageOffset)) { \
profilingBufferSize = 0; \
EnterDebugger(); \
entry->timeStamp = (ProcessorReadTimeStamp() - gfProfilingThread->timerAdjustTicks) | ((uint64_t) _exiting << 63); \
}
extern "C" void __cyg_profile_func_enter(void *thisFunction, void *callSite) {
PROFILING_FUNCTION(0);
extern "C" __attribute__((no_instrument_function))
void __cyg_profile_func_enter(void *thisFunction, void *callSite) {
GF_PROFILING_FUNCTION(0);
}
extern "C" void __cyg_profile_func_exit(void *thisFunction, void *callSite) {
PROFILING_FUNCTION(1);
extern "C" __attribute__((no_instrument_function))
void __cyg_profile_func_exit(void *thisFunction, void *callSite) {
GF_PROFILING_FUNCTION(1);
}
void ProfilingSetup(ProfilingEntry *buffer, size_t size) {
profilingThread = ProcessorTLSRead(tlsStorageOffset);
__attribute__((no_instrument_function))
void GfProfilingInitialise(ProfilingEntry *buffer, size_t size, uint64_t ticksPerMs) {
gfProfilingTicksPerMs = ticksPerMs;
gfProfilingBuffer = buffer;
gfProfilingBufferSize = size;
}
__attribute__((no_instrument_function))
void GfProfilingStart() {
gfProfilingThread = GetThreadLocalStorage();
gfProfilingBufferPosition = 0;
}
__attribute__((no_instrument_function))
void GfProfilingStop() {
gfProfilingThread = nullptr;
__sync_synchronize();
profilingBuffer = buffer;
profilingBufferSize = size;
profilingBufferPosition = 0;
}
#endif

View File

@ -3385,6 +3385,8 @@ void EsTextboxEnsureCaretVisible(EsTextbox *textbox, bool verticallyCenter) {
textbox->scroll.SetX(scrollX);
}
UIQueueEnsureVisibleMessage(textbox);
}
bool TextboxMoveCaret(EsTextbox *textbox, TextboxCaret *caret, bool right, int moveType, bool strongWhitespace = false) {
@ -4418,10 +4420,6 @@ int ProcessTextboxMessage(EsElement *element, EsMessage *message) {
}
TextboxRefreshVisibleLines(textbox);
if (textbox->editing && (~textbox->flags & ES_TEXTBOX_MULTILINE)) {
EsTextboxEnsureCaretVisible(textbox);
}
} else if (message->type == ES_MSG_DESTROY) {
textbox->visibleLines.Free();
textbox->lines.Free();
@ -4560,7 +4558,6 @@ int ProcessTextboxMessage(EsElement *element, EsMessage *message) {
TextboxFindLongestLine(textbox);
textbox->scroll.Refresh();
EsTextboxEnsureCaretVisible(textbox);
UIQueueEnsureVisibleMessage(textbox);
}
} else if (message->type == ES_MSG_MOUSE_LEFT_DOWN || message->type == ES_MSG_MOUSE_RIGHT_DOWN) {
TextboxMoveCaretToCursor(textbox, message->mouseDown.positionX, message->mouseDown.positionY, message->type == ES_MSG_MOUSE_RIGHT_DOWN);

View File

@ -84,10 +84,15 @@ struct Thread {
uintptr_t userStackBase;
uintptr_t kernelStackBase;
uintptr_t kernelStack;
uintptr_t tlsAddress;
size_t userStackReserve;
volatile size_t userStackCommit;
uintptr_t tlsAddress;
uintptr_t timerAdjustAddress;
uint64_t timerAdjustTicks;
uint64_t lastInterruptTimeStamp;
ThreadType type;
bool isKernelThread, isPageGenerator;
int8_t priority;

View File

@ -1313,12 +1313,17 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_OPEN) {
}
}
SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_SET_TLS) {
SYSCALL_IMPLEMENT(ES_SYSCALL_THREAD_SET_TLS) {
currentThread->tlsAddress = argument0; // Set this first, otherwise we could get pre-empted and restore without TLS set.
ProcessorSetThreadStorage(argument0);
SYSCALL_RETURN(ES_SUCCESS, false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_THREAD_SET_TIMER_ADJUST_ADDRESS) {
currentThread->timerAdjustAddress = argument0;
SYSCALL_RETURN(ES_SUCCESS, false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_GET_TLS) {
SYSCALL_RETURN(currentThread->tlsAddress, false);
}

View File

@ -571,9 +571,8 @@ void BuildDesktop(Application *application) {
ExecuteForApp(application, toolchainNasm, buffer, "-MD", "bin/api1.d", "-o", "bin/api1.o", ArgString(commonAssemblyFlags));
ExecuteForApp(application, toolchainCXX, "-MD", "-c", "desktop/api.cpp", "-o", "bin/api2.o", ArgString(commonCompileFlags), ArgString(desktopProfilingFlags));
ExecuteForApp(application, toolchainCXX, "-MD", "-c", "desktop/posix.cpp", "-o", "bin/api3.o", ArgString(commonCompileFlags));
ExecuteForApp(application, toolchainCXX, "-MD", "-c", "desktop/profiling.cpp", "-o", "bin/api4.o", "-DPROFILING_IMPLEMENTATION", ArgString(commonCompileFlags));
ExecuteForApp(application, toolchainCC, "-o", "bin/Desktop", "bin/crti.o", "bin/crtbegin.o",
"bin/api1.o", "bin/api2.o", "bin/api3.o", "bin/api4.o", "bin/crtend.o", "bin/crtn.o",
"bin/api1.o", "bin/api2.o", "bin/api3.o", "bin/crtend.o", "bin/crtn.o",
ArgString(apiLinkFlags1), ArgString(apiLinkFlags2), ArgString(apiLinkFlags3));
ExecuteForApp(application, toolchainStrip, "-o", "bin/Desktop.no_symbols", "--strip-all", "bin/Desktop");
@ -1579,7 +1578,6 @@ int main(int argc, char **argv) {
ADD_DEPENDENCY_FILE(application, "bin/api1.d", "API1");
ADD_DEPENDENCY_FILE(application, "bin/api2.d", "API2");
ADD_DEPENDENCY_FILE(application, "bin/api3.d", "API3");
ADD_DEPENDENCY_FILE(application, "bin/api4.d", "API4");
arrput(applications, application);
}

View File

@ -514,7 +514,7 @@ typedef struct UITable {
UIScrollBar *vScroll;
int itemCount;
char *columns;
int *columnWidths, columnCount;
int *columnWidths, columnCount, columnHighlight;
} UITable;
typedef struct UITextbox {
@ -633,6 +633,7 @@ void UITextboxMoveCaret(UITextbox *textbox, bool backward, bool word);
UITable *UITableCreate(UIElement *parent, uint32_t flags, const char *columns /* separate with \t, terminate with \0 */);
int UITableHitTest(UITable *table, int x, int y); // Returns item index. Returns -1 if not on an item.
int UITableHeaderHitTest(UITable *table, int x, int y); // Returns column index or -1.
bool UITableEnsureVisible(UITable *table, int index); // Returns false if the item was already visible.
void UITableResizeColumns(UITable *table);
@ -1366,7 +1367,6 @@ void UIDrawString(UIPainter *painter, UIRectangle r, const char *string, ptrdiff
}
}
for (; j < bytes; j++) {
char c = *string++;
uint32_t colorText = color;
@ -2633,6 +2633,26 @@ int UITableHitTest(UITable *table, int x, int y) {
return y / rowHeight;
}
int UITableHeaderHitTest(UITable *table, int x, int y) {
if (!table->columnCount) return -1;
UIRectangle header = table->e.bounds;
header.b = header.t + UI_SIZE_TABLE_HEADER * table->e.window->scale;
header.l += UI_SIZE_TABLE_COLUMN_GAP * table->e.window->scale;
int position = 0, index = 0;
while (true) {
int end = position;
for (; table->columns[end] != '\t' && table->columns[end]; end++);
header.r = header.l + table->columnWidths[index];
if (UIRectangleContains(header, x, y)) return index;
header.l += table->columnWidths[index] + UI_SIZE_TABLE_COLUMN_GAP * table->e.window->scale;
if (table->columns[end] != '\t') break;
position = end + 1, index++;
}
return -1;
}
bool UITableEnsureVisible(UITable *table, int index) {
int rowHeight = UI_SIZE_TABLE_ROW * table->e.window->scale;
int y = index * rowHeight;
@ -2768,6 +2788,7 @@ int _UITableMessage(UIElement *element, UIMessage message, int di, void *dp) {
header.r = header.l + table->columnWidths[index];
UIDrawString(painter, header, table->columns + position, end - position, ui.theme.text, UI_ALIGN_LEFT, NULL);
if (index == table->columnHighlight) UIDrawInvert(painter, header);
header.l += table->columnWidths[index] + UI_SIZE_TABLE_COLUMN_GAP * table->e.window->scale;
if (table->columns[end] == '\t') {
@ -2802,6 +2823,7 @@ UITable *UITableCreate(UIElement *parent, uint32_t flags, const char *columns) {
UITable *table = (UITable *) UIElementCreate(sizeof(UITable), parent, flags, _UITableMessage, "Table");
table->vScroll = UIScrollBarCreate(&table->e, 0);
table->columns = UIStringCopy(columns, -1);
table->columnHighlight = -1;
return table;
}