summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_kthread.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2000-12-06 03:45:15 +0000
committerjhb <jhb@FreeBSD.org>2000-12-06 03:45:15 +0000
commite40c6d5192329b031191f5c5f4dafc5893273528 (patch)
tree4f4a52704492e5f711a7b717dd2e2c9d8a66564e /sys/kern/kern_kthread.c
parentcf92dabe14c7581217daf96f6257caae8c56b826 (diff)
downloadFreeBSD-src-e40c6d5192329b031191f5c5f4dafc5893273528.zip
FreeBSD-src-e40c6d5192329b031191f5c5f4dafc5893273528.tar.gz
Pass RFSTOPPED to fork1() in kthread_create() to avoid a race condition
where fork1() could put the process on the run queue where it could be snatched up by another CPU before kthread_create() had set the proper fork handler. Instead, we put the new kthread on the runqueue after its fork handler has been sent. Noticed by: jake Looked over by: peter
Diffstat (limited to 'sys/kern/kern_kthread.c')
-rw-r--r--sys/kern/kern_kthread.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
index 9ae2df2..bc97c55 100644
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -78,7 +78,7 @@ kthread_create(void (*func)(void *), void *arg,
if (!proc0.p_stats /* || proc0.p_stats->p_start.tv_sec == 0 */)
panic("kthread_create called too soon");
- error = fork1(&proc0, RFMEM | RFFDG | RFPROC | flags, &p2);
+ error = fork1(&proc0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags, &p2);
if (error)
return error;
@@ -99,6 +99,14 @@ kthread_create(void (*func)(void *), void *arg,
/* call the processes' main()... */
cpu_set_fork_handler(p2, func, arg);
+ /* Delay putting it on the run queue until now. */
+ if (!(flags & RFSTOPPED)) {
+ mtx_enter(&sched_lock, MTX_SPIN);
+ p2->p_stat = SRUN;
+ setrunqueue(p2);
+ mtx_exit(&sched_lock, MTX_SPIN);
+ }
+
return 0;
}
OpenPOWER on IntegriCloud