feat: build out sched
This commit is contained in:
1 parent
1a8cd39270
commit
785e147d44
1 file changed
+77
@@ -452,6 +452,83 @@ WaitScanResult threadJoinAnyChild(uint32 parentId, uint32* outId, int64* outCode
|
|||||||
so a parent genuinely blocked in userWaitAny wakes the instant ANY of
|
so a parent genuinely blocked in userWaitAny wakes the instant ANY of
|
||||||
its children exits, not just one it named specifically. */
|
its children exits, not just one it named specifically. */
|
||||||
void threadExit(uint64 code);
|
void threadExit(uint64 code);
|
||||||
|
|
||||||
|
/* Exit code threadKill assigns its victim -- named after SIGKILL (9), the
|
||||||
|
nearest real-world equivalent, though this kernel has no signal delivery
|
||||||
|
at all: threadKill is a hard, unconditional termination, not something a
|
||||||
|
target thread can catch, mask, or clean up after (see threadKill). */
|
||||||
|
#define threadKilledExitCode 9u
|
||||||
|
|
||||||
|
/* Unconditionally terminates thread `id` from OUTSIDE it -- the only way to
|
||||||
|
ever get back a process that is genuinely stuck (e.g. blocked forever in
|
||||||
|
a syscall-level pipe read with no writer ever coming, now that
|
||||||
|
sysRead/sysWrite can really block, see pipe.h/vfs.h). Works on a thread
|
||||||
|
in any of Runnable/Sleeping/Blocked: its state is simply set straight to
|
||||||
|
threadDead with exitCode threadKilledExitCode, exactly as if it had
|
||||||
|
called threadExit(threadKilledExitCode) itself, and whoever is (or later
|
||||||
|
becomes) threadJoin()ing it wakes up and reaps it normally -- there is no
|
||||||
|
"half-dead" state and no cleanup callback, since a mid-syscall thread has
|
||||||
|
no user-mode cleanup path to run anyway. Returns false, changing nothing,
|
||||||
|
for id 0 (idle), an out-of-range id, an already-Dead/never-created slot,
|
||||||
|
or (implicitly, since only the CPU's one currently-executing thread is
|
||||||
|
ever threadRunning) the caller's own id -- a syscall handler always runs
|
||||||
|
as its OWN thread, which is Running, not Runnable/Sleeping/Blocked, at
|
||||||
|
the moment it would try to kill itself, so self-kill is naturally
|
||||||
|
rejected without a special-case check. Real termination (sysExit) is
|
||||||
|
still how a thread should ever end itself. Also raises sigChld against
|
||||||
|
the victim's parentId, exactly like threadExit does -- a killed child
|
||||||
|
is still a dead child as far as its parent's SIGCHLD is concerned, the
|
||||||
|
same way real kill(2)ing a child still generates SIGCHLD to its real
|
||||||
|
parent. Also wakes the victim's parent's OWN slot as a wait channel,
|
||||||
|
exactly like threadExit does -- a parent parked in userWaitAny does not
|
||||||
|
care whether a child exited on its own or was killed, same as real
|
||||||
|
waitpid(-1) does not distinguish the two either. */
|
||||||
|
bool threadKill(uint32 id);
|
||||||
|
|
||||||
|
/* Job control (signal.h): unconditionally moves thread `id` -- Runnable,
|
||||||
|
Running (including the caller itself, unlike threadKill which naturally
|
||||||
|
excludes self-targeting), Sleeping, or Blocked -- into threadStopped.
|
||||||
|
Idempotent if `id` is already Stopped (matches real kill(pid, SIGSTOP)
|
||||||
|
succeeding again on an already-stopped process). Safe on a
|
||||||
|
Sleeping/Blocked thread for the same reason threadKill already is: every
|
||||||
|
such thread is parked mid-retry-loop right after its own halt() (see
|
||||||
|
pipeReadBlocking/pipeWriteBlocking, or the restart-syscall pattern
|
||||||
|
syscall.c's sysRead/sysWrite/sysWait use), so simply not being picked by
|
||||||
|
schedule() again until threadContinue moves it back is enough -- no
|
||||||
|
wait-channel state is lost, since that retry loop re-checks its own
|
||||||
|
condition from scratch every time it runs at all. Returns false,
|
||||||
|
changing nothing, for id 0 (idle -- stopping it would wedge the whole
|
||||||
|
machine the instant nothing else was runnable), an out-of-range id, or
|
||||||
|
an already-Dead/never-created slot. */
|
||||||
|
bool threadStop(uint32 id);
|
||||||
|
|
||||||
|
/* Job control (signal.h): moves thread `id` from threadStopped back to
|
||||||
|
threadRunnable. Returns false, changing nothing, if `id` is out of
|
||||||
|
range or not currently Stopped (matches real SIGCONT delivered to a
|
||||||
|
process that was never stopped -- a harmless no-op at the process-state
|
||||||
|
level; signal.c's sigRaise still delivers the signal itself/runs a
|
||||||
|
handler regardless of this return value). */
|
||||||
|
bool threadContinue(uint32 id);
|
||||||
|
|
||||||
|
/* Real Unix's interruptible sleep/EINTR: forces thread `id` from
|
||||||
|
threadSleeping or threadBlocked straight to threadRunnable, early --
|
||||||
|
before its sleep timer expires or its wait-channel condition is ever
|
||||||
|
satisfied -- so the NEXT schedule() eventually resumes it, letting
|
||||||
|
isr.c's deliverPendingSignals (which only ever runs at a return-to-ring3
|
||||||
|
point) actually reach a thread that would otherwise never naturally
|
||||||
|
produce one. Called only by signal.c's sigRaise, and only for a signal it
|
||||||
|
has already determined would genuinely be delivered (not blocked, not
|
||||||
|
ignored) if this thread resumed right now -- callers must not use this to
|
||||||
|
wake a thread for an unrelated reason. Deliberately excludes
|
||||||
|
threadStopped (only threadContinue, an explicit SIGCONT, may ever move a
|
||||||
|
Stopped thread -- the same asymmetry schedWakeChannel already has, for
|
||||||
|
the same reason: job control's "stopped means stopped" must survive an
|
||||||
|
ordinary signal arriving too). Returns false, changing nothing, for an
|
||||||
|
out-of-range id or any state other than Sleeping/Blocked (Runnable/
|
||||||
|
Running need no forcing; Stopped/Dead/Unused have nothing to wake, or
|
||||||
|
must not be woken this way at all). */
|
||||||
|
bool threadWakeForSignal(uint32 id);
|
||||||
|
|
||||||
void threadSleep(uint64 milliseconds);
|
void threadSleep(uint64 milliseconds);
|
||||||
void threadSetBrk(uint32 id, uint64 brk);
|
void threadSetBrk(uint32 id, uint64 brk);
|
||||||
uint64 currentThreadSbrk(int64 increment);
|
uint64 currentThreadSbrk(int64 increment);
|
||||||
|
|||||||
Reference in new issue
Block a user