====== std.sched ======
Scheduling & CPU-Affinität (WP-8): Steuert auf welchen CPUs ein Prozess oder Thread läuft (CPU-Pinning), liest und setzt den Nice-Wert (Priorität) und gibt die CPU freiwillig ab. Enthält Helfer zum Aufbau von ''cpu_set_t''-Bitmasken für bis zu 1024 CPUs.
→ [[lyx_-_programmiersprache:units|Standard Library]] · [[lyx_-_programmiersprache:units:process_ext|std.process_ext]] · [[lyx_-_programmiersprache:units:thread|std.thread]]
----
===== Konstanten =====
==== cpu_set_t ====
^ Konstante ^ Wert ^ Beschreibung ^
| ''CPU_SET_SIZE'' | 128 | Größe einer ''cpu_set_t''-Bitmap in Bytes (1024 CPUs) |
==== Prioritäts-Scope ====
^ Konstante ^ Wert ^ Beschreibung ^
| ''PRIO_PROCESS'' | 0 | ''GetPriority''/''SetPriority'' operiert auf Prozess-ID |
| ''PRIO_PGRP'' | 1 | Operiert auf Prozessgruppen-ID |
| ''PRIO_USER'' | 2 | Operiert auf Benutzer-ID |
----
===== Funktionen =====
==== Scheduling ====
^ Signatur ^ Beschreibung ^
| ''SchedYield(): int64'' | Gibt die CPU freiwillig ab — der aktuelle Thread wird ans Ende der Run-Queue gestellt. Gibt immer 0 zurück |
==== CPU-Affinität ====
^ Signatur ^ Beschreibung ^
| ''SchedSetAffinity(pid: int64, cpuMask: int64): int64'' | Setzt die CPU-Affinität von ''pid'' auf die in ''cpuMask'' (''alloc(CPU_SET_SIZE)'') erlaubten CPUs. ''pid=0'' → aktueller Prozess. Gibt 0 bei Erfolg |
| ''SchedGetAffinity(pid: int64, outMask: int64): int64'' | Liest die aktuelle CPU-Affinität von ''pid'' in ''outMask'' (''alloc(CPU_SET_SIZE)''). Gibt 0 bei Erfolg |
==== cpu_set_t-Helfer ====
^ Signatur ^ Beschreibung ^
| ''CpuSetZero(buf: int64)'' | Setzt alle Bits auf 0 — keine CPU erlaubt |
| ''CpuSetAdd(buf: int64, cpu: int64)'' | Erlaubt CPU ''cpu'' (0-basiert) in der Maske |
| ''CpuSetRemove(buf: int64, cpu: int64)'' | Verbietet CPU ''cpu'' in der Maske |
| ''CpuSetHas(buf: int64, cpu: int64): bool'' | Gibt ''true'' zurück wenn CPU ''cpu'' in der Maske gesetzt ist |
| ''CpuSetCount(buf: int64): int64'' | Zählt die Anzahl erlaubter CPUs in der Maske |
==== Prozess-Priorität (Nice-Wert) ====
^ Signatur ^ Beschreibung ^
| ''GetPriority(pid: int64): int64'' | Gibt den Nice-Wert von ''pid'' zurück (−20 = höchste, 19 = niedrigste Priorität). ''pid=0'' → aktueller Prozess |
| ''SetPriority(pid: int64, nice: int64): int64'' | Setzt den Nice-Wert von ''pid''. Nicht-Root kann nur erhöhen (Priorität senken). Gibt 0 bei Erfolg |
==== Aktuelle CPU ====
^ Signatur ^ Beschreibung ^
| ''GetCPU(cpuOut: int64, nodeOut: int64): int64'' | Schreibt CPU-Nummer in ''cpuOut'' und NUMA-Knoten in ''nodeOut'' (je ''alloc(8)''). ''nodeOut=0'' auf Nicht-NUMA-Systemen |
| ''GetCurrentCPU(): int64'' | Gibt die aktuelle CPU-Nummer direkt zurück (< 0 bei Fehler) |
----
===== Verwendung =====
==== Prozess auf eine CPU pinnen ====
import std.sched;
import std.alloc;
fn PinToCore(cpu: int64): bool {
var mask: int64 := alloc(CPU_SET_SIZE);
CpuSetZero(mask);
CpuSetAdd(mask, cpu);
var r := SchedSetAffinity(0, mask);
free(mask, CPU_SET_SIZE);
return r == 0;
}
==== Aktuelle Affinität lesen und ausgeben ====
import std.sched;
import std.alloc;
import std.io;
fn PrintAffinity(): void {
var mask: int64 := alloc(CPU_SET_SIZE);
SchedGetAffinity(0, mask);
Print("Erlaubte CPUs: ");
var cpu: int64 := 0;
while (cpu < 64) { // Erste 64 CPUs prüfen
if (CpuSetHas(mask, cpu)) {
Print(IntToStr(cpu) + " ");
}
cpu := cpu + 1;
}
PrintLn("Anzahl: " + IntToStr(CpuSetCount(mask)));
free(mask, CPU_SET_SIZE);
}
==== Prozess auf CPUs 0–3 beschränken ====
import std.sched;
import std.alloc;
fn LimitToFirstFourCores(): void {
var mask: int64 := alloc(CPU_SET_SIZE);
CpuSetZero(mask);
CpuSetAdd(mask, 0);
CpuSetAdd(mask, 1);
CpuSetAdd(mask, 2);
CpuSetAdd(mask, 3);
SchedSetAffinity(0, mask);
free(mask, CPU_SET_SIZE);
}
==== Nice-Wert und CPU-Diagnose ====
import std.sched;
import std.io;
fn PrintSchedInfo(): void {
var cpu := GetCurrentCPU();
var nice := GetPriority(0);
PrintLn("Läuft auf CPU: " + IntToStr(cpu));
PrintLn("Nice-Wert: " + IntToStr(nice));
}
fn LowerPriority(): void {
// Priorität senken (Nice erhöhen) — kein Root nötig
SetPriority(0, 10);
}
==== SchedYield in einer Spinloop ====
import std.sched;
// Gibt CPU ab während auf ein Flag gewartet wird (statt busy-wait).
fn WaitForFlag(flagAddr: int64): void {
while (peek64(flagAddr) == 0) {
SchedYield();
}
}
----
===== Hinweise =====
* CPU-Pinning erhöht die Cache-Lokalität bei rechenintensiven Prozessen, kann aber den Durchsatz bei I/O-lastigen Programmen senken.
* ''SetPriority'' mit einem Nice-Wert < 0 (höhere Priorität) erfordert Root oder ''CAP_SYS_NICE''.
* ''GetCurrentCPU'' ist nicht garantiert stabil: Der Scheduler kann den Prozess jederzeit auf eine andere CPU verschieben.
* ''SchedYield'' gibt immer 0 zurück und schlägt nie fehl.
* ''CpuSetCount'' iteriert alle 128 Bytes (1024 CPUs) — für normale Systeme ist das vernachlässigbar.
----
===== Verwandte Units =====
* ''[[lyx_-_programmiersprache:units:process_ext|std.process_ext]]'' — Credentials, Session, uname
* ''[[lyx_-_programmiersprache:units:thread|std.thread]]'' — Threads (Affinität gilt pro Thread)
* ''[[lyx_-_programmiersprache:units:process|std.process]]'' — fork, exec, waitpid
Letzte Aktualisierung: 2026-06-05