diff options
author | jhb <jhb@FreeBSD.org> | 2000-12-06 03:45:15 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2000-12-06 03:45:15 +0000 |
commit | e40c6d5192329b031191f5c5f4dafc5893273528 (patch) | |
tree | 4f4a52704492e5f711a7b717dd2e2c9d8a66564e /sys | |
parent | cf92dabe14c7581217daf96f6257caae8c56b826 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/kern/kern_kthread.c | 10 |
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; } |