Threads
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:
parent
2372806862
commit
f4d7f9100d
19 changed files with 1300 additions and 248 deletions
|
|
@ -369,7 +369,8 @@ exec_elf(char *path, struct argsrc *av, struct argsrc *ev)
|
|||
uint64 sz, sp;
|
||||
struct elfhdr elf;
|
||||
struct inode *ip;
|
||||
pml4e_t *pgdir, *oldpgdir;
|
||||
pml4e_t *pgdir;
|
||||
struct mm *oldmm, *newmm;
|
||||
|
||||
// The arguments are measured before anything is loaded, so that too many
|
||||
// of them is E2BIG with nothing to undo -- and so the stack can be sized to
|
||||
|
|
@ -540,10 +541,10 @@ exec_elf(char *path, struct argsrc *av, struct argsrc *ev)
|
|||
safestrcpy(myproc()->exe, path, sizeof(myproc()->exe));
|
||||
|
||||
for(int i = 0; i < NOFILE; i++){
|
||||
if(myproc()->ofile[i] && (myproc()->ofile_flags[i] & FD_CLOEXEC)){
|
||||
fileclose(myproc()->ofile[i]);
|
||||
myproc()->ofile[i] = 0;
|
||||
myproc()->ofile_flags[i] = 0;
|
||||
if(myproc()->files->ofile[i] && (myproc()->files->flags[i] & FD_CLOEXEC)){
|
||||
fileclose(myproc()->files->ofile[i]);
|
||||
myproc()->files->ofile[i] = 0;
|
||||
myproc()->files->flags[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -557,18 +558,19 @@ exec_elf(char *path, struct argsrc *av, struct argsrc *ev)
|
|||
myproc()->map_size = 0;
|
||||
}
|
||||
|
||||
// Detach shared segments before anything forgets which mappings they were.
|
||||
//
|
||||
// This has to happen while myproc()->pgdir and myproc()->vma[] still describe the
|
||||
// *old* image: the memset below erases the bookkeeping, and freevm() at the
|
||||
// end would then free a shared memory segment's pages as though they were
|
||||
// ordinary heap. Doing it here rather than there is the difference between
|
||||
// detaching a segment and corrupting whoever else has it mapped.
|
||||
proc_release_shared(myproc());
|
||||
|
||||
oldpgdir = myproc()->pgdir;
|
||||
// A new image is a new address space: a fresh mm, and the old one dropped
|
||||
// at the end. mm_put() detaches shared segments before freeing anything,
|
||||
// and does nothing at all while a vfork parent is still using it.
|
||||
if ((newmm = mm_alloc()) == 0)
|
||||
goto bad;
|
||||
proc_exec_threads();
|
||||
newmm->pgdir = pgdir;
|
||||
newmm->sz = sz;
|
||||
oldmm = myproc()->mm;
|
||||
myproc()->mm = newmm;
|
||||
myproc()->pgdir = pgdir;
|
||||
myproc()->sz = sz;
|
||||
pgdir = 0; // newmm owns it now; not bad:'s to free
|
||||
|
||||
// New address space: reset all per-process mmap/signal/TLS state.
|
||||
// sig_handler/sig_restorer point into the *old* image — POSIX resets
|
||||
|
|
@ -579,26 +581,25 @@ exec_elf(char *path, struct argsrc *av, struct argsrc *ev)
|
|||
// Ignored signals stay ignored, and the mask is inherited (execve(2)):
|
||||
// neither points into the old image. `nohup` and every program that ignores
|
||||
// SIGPIPE before running a helper depend on it.
|
||||
memset(myproc()->vma, 0, sizeof(myproc()->vma));
|
||||
for (int i = 0; i < 32; i++)
|
||||
if (myproc()->sig_handler[i] != 1)
|
||||
myproc()->sig_handler[i] = 0;
|
||||
memset(myproc()->sig_restorer, 0, sizeof(myproc()->sig_restorer));
|
||||
if (myproc()->sighand->handler[i] != 1)
|
||||
myproc()->sighand->handler[i] = 0;
|
||||
memset(myproc()->sighand->restorer, 0, sizeof(myproc()->sighand->restorer));
|
||||
myproc()->fs_base = 0;
|
||||
myproc()->pending_signals = 0;
|
||||
myproc()->in_signal = 0;
|
||||
myproc()->sigsusp_active = 0;
|
||||
myproc()->mmap_next = 0;
|
||||
myproc()->mm->mmap_next = 0;
|
||||
|
||||
// The interpreter is ordinary memory to everything after this: fork copies
|
||||
// it, exit frees it. mmap carries on above it.
|
||||
if (interp[0]) {
|
||||
myproc()->vma[0].addr = INTERP_BASE;
|
||||
myproc()->vma[0].length = PGROUNDUP(interp_end);
|
||||
myproc()->vma[0].used = 1;
|
||||
myproc()->vma[0].no_free = 0;
|
||||
myproc()->vma[0].shmid = -1;
|
||||
myproc()->mmap_next = INTERP_BASE + PGROUNDUP(interp_end);
|
||||
myproc()->mm->vma[0].addr = INTERP_BASE;
|
||||
myproc()->mm->vma[0].length = PGROUNDUP(interp_end);
|
||||
myproc()->mm->vma[0].used = 1;
|
||||
myproc()->mm->vma[0].no_free = 0;
|
||||
myproc()->mm->vma[0].shmid = -1;
|
||||
myproc()->mm->mmap_next = INTERP_BASE + PGROUNDUP(interp_end);
|
||||
}
|
||||
|
||||
myproc()->tf->rax = 0;
|
||||
|
|
@ -637,7 +638,8 @@ exec_elf(char *path, struct argsrc *av, struct argsrc *ev)
|
|||
// old one's registers.
|
||||
memmove(myproc()->fpu, fpu_default, sizeof(myproc()->fpu));
|
||||
fxrstor(myproc()->fpu);
|
||||
freevm(oldpgdir);
|
||||
mm_put(oldmm);
|
||||
proc_exec_done(); // a vfork parent may have its memory back
|
||||
kfree((char*)scratch);
|
||||
kfree(bounce);
|
||||
fsstat.exec_cycles += rdtsc() - _t0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue