Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ jobs:
headers = sorted(glob.glob("src/*.h"))
for h in headers:
text = open(h, encoding="utf-8").read()
declared |= set(re.findall(r'OKW_IMPORT\s+\w+\s+OKW_API\s+(\w+)\s*\(', text))
# A return type of several words (`unsigned long long') too.
declared |= set(re.findall(r'OKW_IMPORT\s+[\w\s\*]+?\s+OKW_API\s+(\w+)\s*\(', text))
declared |= set(re.findall(
r'__declspec\(dllimport\)[\w\s\*]*?(\w+)\s*\(', text))
exported = set()
Expand Down Expand Up @@ -258,11 +259,11 @@ jobs:
# `kal_space_start`, which is clause 6.1's report arriving where a
# report was not wanted.
#
# So the six this implementation does provide are named, and the
# seventh is absent from the list for the same reason it is absent
# So the ones this implementation does provide are named, and
# `space` is absent from the list for the same reason it is absent
# from the objects.
bash .spec/tools/run-conformance.sh openkal-windows . \
full,exec,random,terminal,net,datagram,timeout,map $extra
full,exec,random,terminal,net,datagram,timeout,map,region,prof,debug $extra

# run-conformance.sh above has already pointed the manifest at the
# specification's working tree and restored it through a trap; this
Expand Down Expand Up @@ -447,7 +448,7 @@ jobs:
WINEDEBUG: '-all'
run: |
bash .spec/tools/run-conformance.sh openkal-windows . \
full,exec,random,terminal,net,datagram,timeout,map \
full,exec,random,terminal,net,datagram,timeout,map,region,prof,debug \
--target x86_64-windows-gnu

- name: The exported surface is complete and contains nothing else
Expand All @@ -458,7 +459,7 @@ jobs:
# interface: a name it fails to export is a failure, not an interface
# it declines to provide.
rm -rf target && mcpp build --target x86_64-windows-gnu
objs="$(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o' | tr '\n' ' ')"
objs="$(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o' ! -path '*/.build-mcpp/*' | tr '\n' ' ')"
test -n "$objs" || { echo "no objects were found" >&2; exit 1; }
bash .spec/tools/check-surface.sh --complete .spec/SURFACE.txt $objs

Expand Down Expand Up @@ -489,7 +490,7 @@ jobs:
for profile in dev release; do
echo "--- profile $profile"
rm -rf target && mcpp build --features standalone --target x86_64-windows-gnu --profile "$profile"
objs="$(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o')"
objs="$(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o' ! -path '*/.build-mcpp/*')"
test -n "$objs" || { echo "no objects were found; the check would pass vacuously" >&2; exit 1; }

# The permitted set, and why each entry is in it.
Expand Down Expand Up @@ -526,7 +527,7 @@ jobs:
run: |
printf 'extern "C" int puts(const char*);\nextern "C" void okw_probe(void) { puts("x"); }\n' > src/probe.cpp
rm -rf target && mcpp build --features standalone --target x86_64-windows-gnu
objs="$(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o')"
objs="$(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o' ! -path '*/.build-mcpp/*')"
if ! nm --undefined-only $objs | awk '{print $2}' | grep -qx puts; then
echo "the probe did not produce the reference it was written to produce" >&2
rm -f src/probe.cpp; exit 1
Expand Down
59 changes: 57 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ An implementation of [openkal](https://github.com/mcpplibs/openkal) for Windows.

```toml
[dependencies]
openkal = "0.22.0"
openkal = "0.23.0"

[target.'cfg(windows)'.dependencies]
openkal-windows = "0.18.0"
openkal-windows = "0.19.0"
```

Its purpose is as much to test the specification as to be used. openkal was
Expand Down Expand Up @@ -142,6 +142,61 @@ observes is the part a caller depends on rather than the choice between the
two: the region contains the stack of the thread that asked. It is measured on
this system's own runner and again under Wine on a Linux one.

## Version 0.19 (openkal 0.23)

**A region at an address.** `kal_exec_alloc_at` reserves at the address, and
nothing where anything is there or the address is not a multiple of the
sixty-four kibibytes of reservation. `KAL_EXEC_PROP_PLACE` is claimed.

**A part of a region is a file's** (`KAL_EXEC_PROP_FILE`, where the system has
placeholders: Windows 10 1803). A region is a placeholder replaced by a view of a
section of the paging file of the region's size. A part made a file's is the
view unmapped back to a placeholder, split, the part replaced by a view of the
file and the rest by views of the same section at the same offsets, which hold
what they held; the region is a short table of those views. Views are placed in
sixty-four kibibytes, so a part not at that granularity is `kal_err_not_supported`
and the region is unchanged. `KAL_EXEC_MAP_PREFETCH` is `PrefetchVirtualMemory`.
`kal_exec_seal_part` makes a part read-only; `KAL_EXEC_PROP_SEAL_FOREVER` is not
claimed, because the holder of a view can always change its protection.

**Grants.** `KAL_PROCESS_PROP_GRANT_DIR` is claimed. A grant is a duplicate of the
caller's handle, inheritable for the one start and named in its explicit list;
an inherited handle keeps its value, and the started program learns the values,
the names and what each carries from `KAL_PREOPENS` and `KAL_GRANT_RIGHTS`, read
only where the number in them is the program that started it. A grant is made
uninheritable as it is taken over. `KAL_SPAWN_CONFINE` is refused: this system
holds a program to directories only through the files' security descriptors,
which a start does not change.

**Attenuation and records** (`kal_fs_dir_attenuate`): the table of the other two
implementations, indexed by a handle's slot. A listing answers that a name is
absent only where no other spelling could reach an entry: a name of ASCII with
no `~` (a short name the listing does not report), in a directory whose entries
are ASCII. A record is appended through a handle of its own opened with
`FILE_APPEND_DATA`, and ended by `kal_exit` or the runtime's terminators.

**One request where the system has one.** A listing reads
`FileIdFullDirectoryInformation`, whose records carry each entry's size, times,
attributes and identity (`kal_fs_list_next_info`; `KAL_FS_PROP_LIST_INFO` where
the volume states `FILE_SUPPORTS_OPEN_BY_FILE_ID`). `kal_fs_info` asks
`NtQueryInformationByName` for the node's record --- with the volume's serial
number from 24H2 (`FileStatBasicInformation`), and otherwise
(`FileStatInformation`, 1709) with the base directory's for a name of one
component --- and opens the node where the record cannot answer: a link to be
resolved, an identity across components, a volume that refuses the record.

**Observation.** A fault no handler takes is reported, by the filter this system
calls before it ends the program, with each frame's file, offset and symbol: the
file a part of a region maps (an ELF image) or the module (a PE image, from its
COFF symbol table). Samples are taken by a context of the program's own that
suspends each other context that used the processor since the last tick.
Touches are a part's execution taken away and given back, page by page, by a
first look at the access violations of the kind that executes.
`kal_process_info` reports page faults as one count, `faults_minor`.
`kal_process_wait` reports a program this system ended for a fault as
terminated. A preference for economy lowers the started program's memory
priority; `kal_memory_info` is `GlobalMemoryStatusEx` within the job's limits.

## Version 0.18 (openkal 0.22)

**The null device at a position.** `KAL_SPAWN_NULL_IN`, `KAL_SPAWN_NULL_OUT` and
Expand Down
8 changes: 5 additions & 3 deletions mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
namespace = "mcpplibs"
name = "openkal-windows"
version = "0.18.0"
version = "0.19.0"
description = "An implementation of openkal for Windows, written on the Win32 interfaces and the object manager beneath them, using no C runtime symbol."
license = "Apache-2.0"

Expand Down Expand Up @@ -29,7 +29,7 @@ repo = "https://github.com/mcpplibs/openkal-windows"
# the first of the three times clause 6.2 tabulates, and the earliest at which
# the question can be answered.
#
# FOURTEEN AND NOT FIFTEEN. `openkal.space` is absent: this environment has no
# EVERY ONE BUT ONE. `openkal.space` is absent: this environment has no
# operation upon an address space it can supply, and clause 3 says an
# implementation provides an interface in whole or not at all. A consumer that
# needs it is refused here and builds on openkal-linux, which is the whole
Expand Down Expand Up @@ -61,10 +61,12 @@ provides-interfaces = [
"openkal.timeout",
"openkal.map",
"openkal.region",
"openkal.prof",
"openkal.debug",
]

[dependencies]
openkal = "0.22.0"
openkal = "0.23.0"

# The package contributes definitions and no modules. The interface it
# implements is declared by the specification package, which this package
Expand Down
20 changes: 20 additions & 0 deletions port/kernel32.def
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
LIBRARY KERNEL32.dll
EXPORTS
AcquireSRWLockExclusive
AddVectoredExceptionHandler
AssignProcessToJobObject
CancelIoEx
CloseHandle
Expand All @@ -17,8 +18,11 @@ CreatePipe
CreateProcessW
CreateSymbolicLinkW
CreateThread
CreateToolhelp32Snapshot
CreateWaitableTimerExW
DeleteProcThreadAttributeList
DeviceIoControl
DuplicateHandle
ExitProcess
FlushFileBuffers
FlushInstructionCache
Expand Down Expand Up @@ -53,38 +57,54 @@ GetQueuedCompletionStatus
GetStdHandle
GetSystemInfo
GetSystemTimePreciseAsFileTime
GetThreadContext
GetThreadTimes
GlobalMemoryStatusEx
HeapAlloc
HeapFree
InitializeProcThreadAttributeList
IsProcessInJob
K32GetMappedFileNameW
K32GetProcessMemoryInfo
LoadLibraryW
LocalFree
MapViewOfFile
MultiByteToWideChar
OpenProcess
OpenThread
PeekNamedPipe
QueryInformationJobObject
QueryPerformanceCounter
QueryPerformanceFrequency
QueryThreadCycleTime
ReadFile
ReadProcessMemory
ReleaseSRWLockExclusive
ReleaseSRWLockShared
RemoveVectoredExceptionHandler
ResumeThread
SetConsoleCtrlHandler
SetConsoleMode
SetFilePointerEx
SetHandleInformation
SetInformationJobObject
SetThreadPriority
SetUnhandledExceptionFilter
SetWaitableTimer
Sleep
SuspendThread
SwitchToThread
TerminateJobObject
TerminateProcess
Thread32First
Thread32Next
TryAcquireSRWLockShared
UnmapViewOfFile
UpdateProcThreadAttribute
VirtualAlloc
VirtualFree
VirtualProtect
VirtualQuery
WaitForSingleObject
WideCharToMultiByte
WriteConsoleW
Expand Down
1 change: 1 addition & 0 deletions port/ntdll.def
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ NtFlushBuffersFile
NtLockFile
NtQueryDirectoryFile
NtQueryInformationFile
NtQueryInformationProcess
NtQueryVolumeInformationFile
NtReadFile
NtSetInformationFile
Expand Down
4 changes: 4 additions & 0 deletions src/abort.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "win.h"
#include "rights.h"
#include <openkal/abort.h>

extern "C" {
Expand Down Expand Up @@ -34,6 +35,9 @@ extern "C" {
// notifies every loaded module before the process ends, and a module's
// notification is code the caller did not ask to run.
[[noreturn]] void kal_exit(int code) {
// What the program's attenuated handles recorded is written, and ended
// (0.23, fs.h).
okw::rights::end_of_program();
TerminateProcess(GetCurrentProcess(), static_cast<UINT>(code));
for (;;) { }
}
Expand Down
37 changes: 37 additions & 0 deletions src/env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,41 @@ kal_intptr kal_env_system(char* out, kal_uintptr cap) {
return give("windows", 7, out, cap);
}

// THE RESOURCE PREFERENCE (0.23): what the starter conveyed in KAL_RESOURCES
// (process.cpp), read once; balanced where nothing was conveyed.
int kal_env_resources(void) {
static volatile long long answer = -1;
long long a = okw::atomic::load(&answer);
if (a < 0) {
char v[16];
const kal_intptr n = kal_env_var("KAL_RESOURCES", 13, v, sizeof v);
a = KAL_RESOURCES_BALANCED;
if (n == 11 && same(v, 11, "performance", 11)) a = KAL_RESOURCES_PERFORMANCE;
else if (n == 7 && same(v, 7, "economy", 7)) a = KAL_RESOURCES_ECONOMY;
okw::atomic::store(&answer, a);
}
return static_cast<int>(a);
}

}

namespace okw {
// ECONOMY ON THIS SYSTEM: the program's pages are the first taken back when
// memory is short (ProcessMemoryPriority, MEMORY_PRIORITY_LOW).
void lower_memory_priority(void* process) {
const auto set = reinterpret_cast<pfn_SetProcessInformation_>(
system_function(L"kernel32.dll", "SetProcessInformation"));
if (!set) return;
unsigned long priority = 2; // MEMORY_PRIORITY_LOW
set(process, 0 /* ProcessMemoryPriority */, &priority, sizeof priority);
}
} // namespace okw

namespace {
// A program started for economy by a starter that did not set it (one that is
// not of this implementation, or a person) sets it on itself.
OKW_START_FN(economy_at_start) {
if (kal_env_resources() == KAL_RESOURCES_ECONOMY) okw::lower_memory_priority(GetCurrentProcess());
}
OKW_AT_START(economy_at_start);
} // namespace
Loading
Loading