summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_thread.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2007-11-05 11:36:16 +0000
committerkib <kib@FreeBSD.org>2007-11-05 11:36:16 +0000
commit9ae733819b7cdf0eef51ba1b18d39feb136a9dbf (patch)
treecccec36134d2cab5ce1eabb67dcaab5981e9beb0 /sys/kern/kern_thread.c
parentf3f033b9b90ea07350fbe7483af3d9636cb31d1d (diff)
downloadFreeBSD-src-9ae733819b7cdf0eef51ba1b18d39feb136a9dbf.zip
FreeBSD-src-9ae733819b7cdf0eef51ba1b18d39feb136a9dbf.tar.gz
Fix for the panic("vm_thread_new: kstack allocation failed") and
silent NULL pointer dereference in the i386 and sparc64 pmap_pinit() when the kmem_alloc_nofault() failed to allocate address space. Both functions now return error instead of panicing or dereferencing NULL. As consequence, vmspace_exec() and vmspace_unshare() returns the errno int. struct vmspace arg was added to vm_forkproc() to avoid dealing with failed allocation when most of the fork1() job is already done. The kernel stack for the thread is now set up in the thread_alloc(), that itself may return NULL. Also, allocation of the first process thread is performed in the fork1() to properly deal with stack allocation failure. proc_linkup() is separated into proc_linkup() called from fork1(), and proc_linkup0(), that is used to set up the kernel process (was known as swapper). In collaboration with: Peter Holm Reviewed by: jhb
Diffstat (limited to 'sys/kern/kern_thread.c')
-rw-r--r--sys/kern/kern_thread.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index 2a28823..cde764f 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -181,13 +181,12 @@ thread_init(void *mem, int size, int flags)
td = (struct thread *)mem;
- vm_thread_new(td, 0);
- cpu_thread_setup(td);
td->td_sleepqueue = sleepq_alloc();
td->td_turnstile = turnstile_alloc();
td->td_sched = (struct td_sched *)&td[1];
sched_newthread(td);
umtx_thread_init(td);
+ td->td_kstack = 0;
return (0);
}
@@ -203,7 +202,6 @@ thread_fini(void *mem, int size)
turnstile_free(td->td_turnstile);
sleepq_free(td->td_sleepqueue);
umtx_thread_fini(td);
- vm_thread_dispose(td);
}
/*
@@ -215,10 +213,16 @@ thread_fini(void *mem, int size)
* proc_init()
*/
void
+proc_linkup0(struct proc *p, struct thread *td)
+{
+ TAILQ_INIT(&p->p_threads); /* all threads in proc */
+ proc_linkup(p, td);
+}
+
+void
proc_linkup(struct proc *p, struct thread *td)
{
- TAILQ_INIT(&p->p_threads); /* all threads in proc */
#ifdef KSE
TAILQ_INIT(&p->p_upcalls); /* upcall list */
#endif
@@ -310,9 +314,18 @@ thread_reap(void)
struct thread *
thread_alloc(void)
{
+ struct thread *td;
thread_reap(); /* check if any zombies to get */
- return (uma_zalloc(thread_zone, M_WAITOK));
+
+ td = (struct thread *)uma_zalloc(thread_zone, M_WAITOK);
+ KASSERT(td->td_kstack == 0, ("thread_alloc got thread with kstack"));
+ if (!vm_thread_new(td, 0)) {
+ uma_zfree(thread_zone, td);
+ return (NULL);
+ }
+ cpu_thread_setup(td);
+ return (td);
}
@@ -324,6 +337,10 @@ thread_free(struct thread *td)
{
cpu_thread_clean(td);
+ if (td->td_altkstack != 0)
+ vm_thread_dispose_altkstack(td);
+ if (td->td_kstack != 0)
+ vm_thread_dispose(td);
uma_zfree(thread_zone, td);
}
OpenPOWER on IntegriCloud