* Create a kernel thread. It shares its address space * with proc0 - ie: kernel only. * * func is the function to start. * arg is the parameter to pass to function on first startup. * newtdp is the return value pointing to the thread's struct thread. * ** XXX fix this --> flags are flags to fork1 (in unistd.h) * fmt and following will be *printf'd into (*newtd)->td_name (for ps, etc.).
| 261 | * fmt and following will be *printf'd into (*newtd)->td_name (for ps, etc.). |
| 262 | */ |
| 263 | int |
| 264 | kthread_add(void (*func)(void *), void *arg, struct proc *p, |
| 265 | struct thread **newtdp, int flags, int pages, const char *fmt, ...) |
| 266 | { |
| 267 | va_list ap; |
| 268 | struct thread *newtd, *oldtd; |
| 269 | |
| 270 | if (!proc0.p_stats) |
| 271 | panic("kthread_add called too soon"); |
| 272 | |
| 273 | /* If no process supplied, put it on proc0 */ |
| 274 | if (p == NULL) |
| 275 | p = &proc0; |
| 276 | |
| 277 | /* Initialize our new td */ |
| 278 | newtd = thread_alloc(pages); |
| 279 | if (newtd == NULL) |
| 280 | return (ENOMEM); |
| 281 | |
| 282 | PROC_LOCK(p); |
| 283 | oldtd = FIRST_THREAD_IN_PROC(p); |
| 284 | |
| 285 | bzero(&newtd->td_startzero, |
| 286 | __rangeof(struct thread, td_startzero, td_endzero)); |
| 287 | bcopy(&oldtd->td_startcopy, &newtd->td_startcopy, |
| 288 | __rangeof(struct thread, td_startcopy, td_endcopy)); |
| 289 | |
| 290 | /* set up arg0 for 'ps', et al */ |
| 291 | va_start(ap, fmt); |
| 292 | vsnprintf(newtd->td_name, sizeof(newtd->td_name), fmt, ap); |
| 293 | va_end(ap); |
| 294 | |
| 295 | TSTHREAD(newtd, newtd->td_name); |
| 296 | |
| 297 | newtd->td_proc = p; /* needed for cpu_copy_thread */ |
| 298 | /* might be further optimized for kthread */ |
| 299 | cpu_copy_thread(newtd, oldtd); |
| 300 | /* put the designated function(arg) as the resume context */ |
| 301 | cpu_fork_kthread_handler(newtd, func, arg); |
| 302 | |
| 303 | newtd->td_pflags |= TDP_KTHREAD; |
| 304 | thread_cow_get_proc(newtd, p); |
| 305 | |
| 306 | /* this code almost the same as create_thread() in kern_thr.c */ |
| 307 | p->p_flag |= P_HADTHREADS; |
| 308 | thread_link(newtd, p); |
| 309 | thread_lock(oldtd); |
| 310 | /* let the scheduler know about these things. */ |
| 311 | sched_fork_thread(oldtd, newtd); |
| 312 | TD_SET_CAN_RUN(newtd); |
| 313 | thread_unlock(oldtd); |
| 314 | PROC_UNLOCK(p); |
| 315 | |
| 316 | tidhash_add(newtd); |
| 317 | |
| 318 | /* Avoid inheriting affinity from a random parent. */ |
| 319 | cpuset_kernthread(newtd); |
| 320 | #ifdef HWPMC_HOOKS |
no test coverage detected