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
4 changes: 2 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.17.1"
openkal = "0.19.0"

[target.'cfg(windows)'.dependencies]
openkal-windows = "0.14.0"
openkal-windows = "0.15.0"
```

Its purpose is as much to test the specification as to be used. openkal was
Expand Down
4 changes: 2 additions & 2 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.14.0"
version = "0.15.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 @@ -63,7 +63,7 @@ provides-interfaces = [
]

[dependencies]
openkal = "0.18.0"
openkal = "0.19.0"

# The package contributes definitions and no modules. The interface it
# implements is declared by the specification package, which this package
Expand Down
4 changes: 4 additions & 0 deletions port/kernel32.def
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ GetConsoleScreenBufferInfo
GetCurrentDirectoryW
GetCurrentProcess
GetCurrentProcessId
GetCurrentThread
GetCurrentThreadId
GetCurrentThreadStackLimits
GetEnvironmentStringsW
Expand All @@ -39,9 +40,11 @@ GetHandleInformation
GetLastError
GetLogicalDriveStringsW
GetLogicalDrives
GetLogicalProcessorInformationEx
GetModuleFileNameW
GetOverlappedResult
GetProcAddress
GetProcessAffinityMask
GetProcessHeap
GetProcessId
GetProcessTimes
Expand All @@ -67,6 +70,7 @@ SetConsoleMode
SetFilePointerEx
SetHandleInformation
SetInformationJobObject
SetThreadPriority
Sleep
SwitchToThread
TerminateJobObject
Expand Down
68 changes: 67 additions & 1 deletion src/task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,72 @@ int kal_task_wake(const kal_u32* word, kal_uintptr count, kal_uintptr* woken) {
// this implementation doing anything to earn it.
kal_uintptr kal_task_props(void) { return
KAL_TASK_PROP_PREEMPTIVE | KAL_TASK_PROP_PARALLEL
| KAL_TASK_PROP_WAIT_TIMEOUT | KAL_TASK_PROP_THREAD_LOCAL; }
| KAL_TASK_PROP_WAIT_TIMEOUT | KAL_TASK_PROP_THREAD_LOCAL
| KAL_TASK_PROP_PRIORITY; }

// THE PHYSICAL CORES BENEATH THE PROCESSORS THIS PROGRAM MAY RUN ON. The system
// lists each core with the processors of it (RelationProcessorCore); a core
// counts when one of its processors is in the process's affinity mask --- of
// processor group 0, which is the set kal_task_parallelism counts here, so the
// two answers are about the same processors. Zero is "cannot say".
kal_uintptr kal_task_cores(void) {
unsigned long long process = 0, system = 0;
if (!GetProcessAffinityMask(GetCurrentProcess(), &process, &system)) return 0;
DWORD length = 0;
GetLogicalProcessorInformationEx(0 /* RelationProcessorCore */, nullptr, &length);
if (length == 0) return 0;
auto* buffer = static_cast<unsigned char*>(kal_alloc(length, 16));
if (!buffer) return 0;
kal_uintptr cores = 0;
if (GetLogicalProcessorInformationEx(0, buffer, &length)) {
// SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX: Relationship and Size, then
// PROCESSOR_RELATIONSHIP, whose GroupCount is at 30 and whose first
// GROUP_AFFINITY (Mask, then Group) is at 32.
for (DWORD at = 0; at + 48 <= length;) {
const unsigned char* record = buffer + at;
DWORD size = 0;
for (int i = 0; i < 4; ++i) size |= static_cast<DWORD>(record[4 + i]) << (8 * i);
if (size == 0) break;
unsigned long long mask = 0;
for (int i = 0; i < 8; ++i) mask |= static_cast<unsigned long long>(record[32 + i]) << (8 * i);
const unsigned group = static_cast<unsigned>(record[40]) | (static_cast<unsigned>(record[41]) << 8);
if (group == 0 && (mask & process)) ++cores;
at += size;
}
}
kal_free(buffer, length, 16);
return cores;
}

// THE CALLING THREAD'S CLAIM. Background mode lowers the thread's processor,
// I/O and memory priority together, which is this system's word for work that
// runs when nothing else wants the machine; below-normal is the lower claim
// short of it. Each other claim first leaves background mode. A thread may
// raise its own priority within its process's class.
int kal_task_set_priority(kal_uintptr priority) {
constexpr int kBackgroundBegin = 0x00010000, kBackgroundEnd = 0x00020000;
constexpr int kNormal = 0, kBelowNormal = -1;
if (priority != KAL_TASK_PRIORITY_DEFAULT && priority != KAL_TASK_PRIORITY_LOW
&& priority != KAL_TASK_PRIORITY_BACKGROUND)
return kal_err_invalid;
HANDLE self = GetCurrentThread();
if (priority == KAL_TASK_PRIORITY_BACKGROUND) {
if (!SetThreadPriority(self, kNormal)) return okw::translate_win32(GetLastError());
if (SetThreadPriority(self, kBackgroundBegin) || GetLastError() == 402 /* ERROR_THREAD_MODE_ALREADY_BACKGROUND */)
return kal_ok;
// AN ENVIRONMENT WITHOUT BACKGROUND MODE (Wine refuses it) is given the
// scheduling half of it: the idle priority, the lowest a thread may
// set for itself.
constexpr int kIdle = -15; // THREAD_PRIORITY_IDLE
return SetThreadPriority(self, kIdle) ? kal_ok : okw::translate_win32(GetLastError());
}
// Leaving background mode is refused to a thread not in it, and by an
// environment without the mode; in either the thread was not in it, and
// the claim below is what decides the answer.
SetThreadPriority(self, kBackgroundEnd);
if (!SetThreadPriority(self, priority == KAL_TASK_PRIORITY_LOW ? kBelowNormal : kNormal))
return okw::translate_win32(GetLastError());
return kal_ok;
}

}
6 changes: 6 additions & 0 deletions src/win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,12 @@ struct SYSTEM_INFO {
unsigned short wProcessorRevision;
};
OKW_IMPORT void OKW_API GetSystemInfo(SYSTEM_INFO*);
// The calling thread's claim on the processors (kal_task_set_priority), and the
// physical cores beneath the processors this program may run on (kal_task_cores).
OKW_IMPORT HANDLE OKW_API GetCurrentThread(void);
OKW_IMPORT BOOL OKW_API SetThreadPriority(HANDLE, int);
OKW_IMPORT BOOL OKW_API GetProcessAffinityMask(HANDLE, unsigned long long*, unsigned long long*);
OKW_IMPORT BOOL OKW_API GetLogicalProcessorInformationEx(int, void*, DWORD*);
OKW_IMPORT BOOL OKW_API VirtualProtect(LPVOID, unsigned long long, DWORD, DWORD*);
OKW_IMPORT BOOL OKW_API VirtualFree(LPVOID, unsigned long long, DWORD);
OKW_IMPORT BOOL OKW_API FlushInstructionCache(HANDLE, LPCVOID, unsigned long long);
Expand Down
Loading