A thread is a struct proc that shares three counted objects with others of
its group: the address space (struct mm: page tables, heap top, VMAs and a
lock for changing them), the descriptor table, and the signal dispositions.
clone() shares what its flags say and fork() copies.

- clone(): pthread_create's shape (VM, FILES, SIGHAND, THREAD, SETTLS,
  PARENT_SETTID, CHILD_CLEARTID) and posix_spawn's (VM, VFORK, a stack).
- futex: WAIT, WAIT_BITSET with timeouts, WAKE, REQUEUE, CMP_REQUEUE, keyed
  by the word's kernel address so shared pages meet. set_tid_address keeps
  the word that exit zeroes and wakes, for pthread_join.
- exit ends a thread; exit_group, a fatal signal, or the leader exiting ends
  them all. reapd frees exited threads; the leader is reaped by its parent
  once the rest are gone. getpid is the group, gettid the thread.
- Stops and resumes reach every thread; other process signals the leader.
- exec kills the other threads and unshares the dispositions.
- No TLB shootdown, so pages unmapped from a shared address space are freed
  only once every CPU has reloaded CR3 or is idle.
- procfs: /proc lists processes, task/ lists threads, comm, Threads:, Tgid.
- The console honours VMIN 0 / VTIME (btop's input drain hung on it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-25 03:03:50 +01:00
commit f4d7f9100d
19 changed files with 1300 additions and 248 deletions

View file

@ -115,12 +115,12 @@ sys_rt_sigaction(void)
struct proc *p = myproc();
if (oldactp) {
put_user(p->sig_handler[sig], oldactp + SA_HANDLER_OFF);
put_user(p->sig_restorer[sig], oldactp + SA_RESTORER_OFF(p));
put_user(p->sighand->handler[sig], oldactp + SA_HANDLER_OFF);
put_user(p->sighand->restorer[sig], oldactp + SA_RESTORER_OFF(p));
if (p->syscall_map) {
put_user(p->sig_flags[sig], oldactp + SA_FLAGS_OFF(p));
put_user(p->sighand->flags[sig], oldactp + SA_FLAGS_OFF(p));
} else {
uint32 fl = (uint32)p->sig_flags[sig];
uint32 fl = (uint32)p->sighand->flags[sig];
put_user(fl, oldactp + SA_FLAGS_OFF(p));
}
}
@ -134,9 +134,9 @@ sys_rt_sigaction(void)
// SIGKILL and SIGSTOP cannot be caught or ignored.
if (sig == SIGKILL || sig == SIGSTOP)
return -EINVAL;
p->sig_handler[sig] = h;
p->sig_restorer[sig] = r;
p->sig_flags[sig] = fl;
p->sighand->handler[sig] = h;
p->sighand->restorer[sig] = r;
p->sighand->flags[sig] = fl;
}
return 0;
}
@ -218,16 +218,16 @@ deliver_signals(struct trapframe *tf)
// SIGSTOP cannot be caught or ignored; the other three stop only by
// default. Stopped here and resumed here, by SIGCONT or SIGKILL.
if (sig == SIGSTOP ||
(sig_default_stops(sig) && myproc()->sig_handler[sig] == 0)) {
(sig_default_stops(sig) && myproc()->sighand->handler[sig] == 0)) {
myproc()->pending_signals &= ~(1ULL << sig);
proc_stop(sig);
if (myproc()->killed)
exit(W_EXITCODE(0, myproc()->killsig ? myproc()->killsig : SIGKILL));
continue;
}
if (myproc()->sig_handler[sig] <= 1) {
if (myproc()->sighand->handler[sig] <= 1) {
myproc()->pending_signals &= ~(1ULL << sig);
if (myproc()->sig_handler[sig] == 0 && sig_default_kills(sig)) {
if (myproc()->sighand->handler[sig] == 0 && sig_default_kills(sig)) {
myproc()->killed = 1;
if (myproc()->killsig == 0)
myproc()->killsig = sig;
@ -283,8 +283,8 @@ deliver_signals(struct trapframe *tf)
// shifted rsp, and its ret fell into the sigreturn trampoline,
// silently undoing everything. exec() handles this same quirk by
// setting tf->rcx = elf.entry.
tf->rip = myproc()->sig_handler[sig];
tf->rcx = myproc()->sig_handler[sig];
tf->rip = myproc()->sighand->handler[sig];
tf->rcx = myproc()->sighand->handler[sig];
return;
}
}
@ -344,7 +344,7 @@ addr_t sys_rt_sigsuspend(void)
uint64 deliverable = myproc()->pending_signals & ~myproc()->signal_mask;
int will_deliver = 0;
for (int sig = 1; sig < 32; sig++)
if ((deliverable & (1ULL << sig)) && myproc()->sig_handler[sig])
if ((deliverable & (1ULL << sig)) && myproc()->sighand->handler[sig])
{ will_deliver = 1; break; }
if (will_deliver && !myproc()->in_signal) {