replace nob with ms' build, move disk creation to build.bat, major comment cleanup, remove old and stupid tests, overhaul interrupt management with per-CPU vector allocation, affinity migration and safe teardown, add proper IOAPIC routing and PCI MSI/MSI-X/INTx support, migrate drivers to the new interrupt API, integrate ACPICA with a proper OS services layer, move ACPI firmware events, power button handling and S5 shutdown into acpi.sys, add parallel driver startup and atomic publication, replace PnP arrays with dynamic lists, redesign service startup again to be asynchronous, add delayed startup mode for services, allow omitting keys in services.ini, fix acpi ec deferred work handling, fix kernel threads having garbage exit code.

This commit is contained in:
maksw committed 2026-10-28 15:18:43 +01:00
1 parent d36f19509c
commit 36eef8f58d
696 files changed
+147281 -7530

No files matched your search

+191
View File
@@ -0,0 +1,191 @@
/* Small external watch supervisor. Each build runs in a fresh child process. */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>
#include <wchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <wctype.h>
struct WatchState {
HANDLE directory;
HANDLE changed;
volatile LONG generation;
};
/* Exclude generated object directories, caches and build logs. */
static int IgnoreChange(const WCHAR *name, DWORD length)
{
WCHAR component[260];
DWORD i = 0;
while (i < length) {
DWORD j = 0;
while (i < length && (name[i] == L'\\' || name[i] == L'/')) ++i;
while (i < length && name[i] != L'\\' && name[i] != L'/') {
if (j + 1 < 260) component[j++] = towlower(name[i]);
++i;
}
component[j] = 0;
if (!wcscmp(component, L"obj") || !wcscmp(component, L"objd") ||
!wcscmp(component, L"out") || !wcscmp(component, L".git") ||
!wcscmp(component, L".vs")) return 1;
if (i >= length) {
if (!wcscmp(component, L"build.dat") ||
!wcscmp(component, L"build.log") ||
!wcscmp(component, L"build.err") ||
!wcscmp(component, L"build.wrn") ||
!wcscmp(component, L"build.inc")) return 1;
}
}
return 0;
}
static DWORD WINAPI WatchThread(void *param)
{
struct WatchState *state = (struct WatchState *)param;
BYTE buffer[32768];
DWORD bytes;
for (;;) {
if (!ReadDirectoryChangesW(state->directory, buffer, sizeof(buffer), TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION,
&bytes, NULL, NULL)) return 1;
if (bytes) {
BYTE *cursor = buffer;
for (;;) {
FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION *)cursor;
if (!IgnoreChange(info->FileName, info->FileNameLength / sizeof(WCHAR))) {
InterlockedIncrement(&state->generation);
SetEvent(state->changed);
break;
}
if (!info->NextEntryOffset) break;
cursor += info->NextEntryOffset;
}
}
}
}
/* Quote an individual argument according to the Win32 CRT argv rules. */
static void AddQuoted(WCHAR *dst, const WCHAR *src, size_t *position)
{
size_t slash = 0;
dst[(*position)++] = L'"';
while (*src) {
if (*src == L'\\') { ++slash; ++src; continue; }
if (*src == L'"') {
while (slash--) dst[(*position)++] = L'\\';
dst[(*position)++] = L'\\';
dst[(*position)++] = L'"';
slash = 0;
++src;
continue;
}
while (slash) { dst[(*position)++] = L'\\'; --slash; }
dst[(*position)++] = *src++;
}
while (slash--) { dst[(*position)++] = L'\\'; dst[(*position)++] = L'\\'; }
dst[(*position)++] = L'"';
dst[*position] = 0;
}
static WCHAR *MakeChildCommand(int argc, WCHAR **argv)
{
size_t capacity = 4, pos = 0;
WCHAR *command;
int i;
for (i = 0; i < argc; ++i) capacity += wcslen(argv[i]) * 2 + 5;
command = (WCHAR *)calloc(capacity, sizeof(WCHAR));
if (!command) return NULL;
for (i = 0; i < argc; ++i) {
if (!argv[i] || !argv[i][0]) continue;
if (pos) command[pos++] = L' ';
AddQuoted(command, argv[i], &pos);
}
return command;
}
static int RunChild(WCHAR *command)
{
PROCESS_INFORMATION pi = {0};
STARTUPINFOW si = {0};
DWORD status = 1;
si.cb = sizeof(si);
if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
fwprintf(stderr, L"BUILD: error: cannot launch build (%lu)\n", GetLastError());
return 1;
}
WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &status);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return (int)status;
}
/* Return -1 for a normal build; otherwise supervise -w until Ctrl+C. */
int TryWatchMode(void)
{
int argc, i, watch = 0;
WCHAR **argv = CommandLineToArgvW(GetCommandLineW(), &argc);
WCHAR *command;
struct WatchState state = {0};
HANDLE worker;
DWORD threadId;
if (!argv) return -1;
for (i = 1; i < argc; ++i) {
WCHAR *arg = argv[i];
size_t j, k;
if (arg[0] != L'-' && arg[0] != L'/') continue;
if (!_wcsicmp(arg + 1, L"why")) continue;
/* Keep whole-word and target switches unchanged. */
if (wcslen(arg) > 1 && wcschr(L"aAcCnN", arg[1]) &&
(wcslen(arg) > 3)) continue;
for (j = 1, k = 1; arg[j]; ++j) {
if (arg[j] == L'w' || arg[j] == L'W') {
watch = 1;
} else {
arg[k++] = arg[j];
}
}
arg[k] = 0;
if (k == 1) argv[i][0] = 0;
}
if (!watch) { LocalFree(argv); return -1; }
command = MakeChildCommand(argc, argv);
LocalFree(argv);
if (!command) return 1;
state.changed = CreateEventW(NULL, FALSE, FALSE, NULL);
state.directory = CreateFileW(L".", FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (!state.changed || state.directory == INVALID_HANDLE_VALUE) {
fprintf(stderr, "BUILD: error: unable to watch project directory\n");
free(command);
return 1;
}
worker = CreateThread(NULL, 0, WatchThread, &state, 0, &threadId);
if (!worker) {
fprintf(stderr, "BUILD: error: unable to start watcher\n");
free(command);
return 1;
}
for (;;) {
LONG before = InterlockedCompareExchange(&state.generation, 0, 0);
RunChild(command);
if (before == InterlockedCompareExchange(&state.generation, 0, 0)) {
printf("BUILD: Watching...\n");
fflush(stdout);
{
HANDLE signals[2] = { state.changed, worker };
if (WaitForMultipleObjects(2, signals, FALSE, INFINITE) != WAIT_OBJECT_0) {
fprintf(stderr, "BUILD: error: watcher stopped\n");
free(command);
return 1;
}
}
}
Sleep(200);
/* Drain coalesced notifications before next build. */
ResetEvent(state.changed);
}
}