mirror of https://gitlab.com/nakst/essence
misc changes
This commit is contained in:
parent
7d2ea59a4c
commit
f201231f52
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 = {};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
26
util/luigi.h
26
util/luigi.h
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue