? usr.bin/top/sigdesc.h ? usr.bin/top/top ? usr.bin/top/top.1 ? usr.bin/top/top.1.gz ? usr.bin/top/top.local.h ? usr.bin/top/top.x ? sys/ys ? sys/dev/dell_bios ? sys/i386/compile/.gdbinit ? sys/sys/hold Index: usr.bin/top/machine.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/usr.bin/top/machine.c,v retrieving revision 1.82 diff -u -r1.82 machine.c --- usr.bin/top/machine.c 17 Sep 2007 05:27:19 -0000 1.82 +++ usr.bin/top/machine.c 26 Oct 2007 07:50:37 -0000 @@ -737,56 +737,72 @@ } if (!(flags & FMT_SHOWARGS)) { - snprintf(cmdbuf, cmdlengthdelta, "%s", pp->ki_comm); - } - else if (pp->ki_args == NULL || - (args = kvm_getargv(kd, pp, cmdlengthdelta)) == NULL || !(*args)) - snprintf(cmdbuf, cmdlengthdelta, "[%s]", pp->ki_comm); - else { - char *src, *dst, *argbuf; - char *cmd; - size_t argbuflen; - size_t len; - - argbuflen = cmdlengthdelta * 4; - argbuf = (char *)malloc(argbuflen + 1); - if (argbuf == NULL) { - warn("malloc(%d)", argbuflen + 1); - free(cmdbuf); - return NULL; + if (ps.thread && pp->ki_flag & P_HADTHREADS && + pp->ki_ocomm[0]) { + snprintf(cmdbuf, cmdlengthdelta, "{%s}", pp->ki_ocomm); + } else { + snprintf(cmdbuf, cmdlengthdelta, "%s", pp->ki_comm); } + } else { + if (pp->ki_flag & P_SYSTEM || + pp->ki_args == NULL || + (args = kvm_getargv(kd, pp, cmdlengthdelta)) == NULL || + !(*args)) { + if (ps.thread && pp->ki_flag & P_HADTHREADS && + pp->ki_ocomm[0]) { + snprintf(cmdbuf, cmdlengthdelta, + "{%s}", pp->ki_ocomm); + } else { + snprintf(cmdbuf, cmdlengthdelta, + "[%s]", pp->ki_comm); + } + } else { + char *src, *dst, *argbuf; + char *cmd; + size_t argbuflen; + size_t len; + + argbuflen = cmdlengthdelta * 4; + argbuf = (char *)malloc(argbuflen + 1); + if (argbuf == NULL) { + warn("malloc(%d)", argbuflen + 1); + free(cmdbuf); + return NULL; + } + + dst = argbuf; + + /* Extract cmd name from argv */ + cmd = strrchr(*args, '/'); + if (cmd == NULL) + cmd = *args; + else + cmd++; + + for (; (src = *args++) != NULL; ) { + if (*src == '\0') + continue; + len = (argbuflen - (dst - argbuf) - 1) / 4; + strvisx(dst, src, + strlen(src) < len ? strlen(src) : len, + VIS_NL | VIS_CSTYLE); + while (*dst != '\0') + dst++; + if ((argbuflen - (dst - argbuf) - 1) / 4 > 0) + *dst++ = ' '; /* add delimiting space */ + } + if (dst != argbuf && dst[-1] == ' ') + dst--; + *dst = '\0'; + + if (strcmp(cmd, pp->ki_comm) != 0 ) + snprintf(cmdbuf, cmdlengthdelta, + "%s (%s)",argbuf, pp->ki_comm); + else + strlcpy(cmdbuf, argbuf, cmdlengthdelta); - dst = argbuf; - - /* Extract cmd name from argv */ - cmd = strrchr(*args, '/'); - if (cmd == NULL) - cmd = *args; - else - cmd++; - - for (; (src = *args++) != NULL; ) { - if (*src == '\0') - continue; - len = (argbuflen - (dst - argbuf) - 1) / 4; - strvisx(dst, src, strlen(src) < len ? strlen(src) : len, - VIS_NL | VIS_CSTYLE); - while (*dst != '\0') - dst++; - if ((argbuflen - (dst - argbuf) - 1) / 4 > 0) - *dst++ = ' '; /* add delimiting space */ + free(argbuf); } - if (dst != argbuf && dst[-1] == ' ') - dst--; - *dst = '\0'; - - if (strcmp(cmd, pp->ki_comm) != 0 ) - snprintf(cmdbuf, cmdlengthdelta, "%s (%s)",argbuf, \ - pp->ki_comm); - else - strlcpy(cmdbuf, argbuf, cmdlengthdelta); - - free(argbuf); } if (ps.jail == 0) Index: lib/libkvm/kvm_proc.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/lib/libkvm/kvm_proc.c,v retrieving revision 1.94 diff -u -r1.94 kvm_proc.c --- lib/libkvm/kvm_proc.c 21 Sep 2007 04:11:34 -0000 1.94 +++ lib/libkvm/kvm_proc.c 26 Oct 2007 07:50:37 -0000 @@ -120,6 +120,10 @@ kp = &kinfo_proc; kp->ki_structsize = sizeof(kinfo_proc); + /* + * Loop on the processes. this is completely broken because we need to be + * able to loop on the threads and merge the ones that are the same process some how. + */ for (; cnt < maxcnt && p != NULL; p = LIST_NEXT(&proc, p_list)) { memset(kp, 0, sizeof *kp); if (KREAD(kd, (u_long)p, &proc)) { @@ -403,7 +407,8 @@ kp->ki_lastcpu = mtd.td_lastcpu; kp->ki_wchan = mtd.td_wchan; kp->ki_oncpu = mtd.td_oncpu; - + if (mtd.td_name[0] != '\0') + strlcpy(kp->ki_ocomm, mtd.td_name, sizeof(kp->ki_ocomm)); if (!(proc.p_flag & P_SA)) { kp->ki_pctcpu = 0; kp->ki_rqindex = 0; Index: bin/ps/extern.h =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/bin/ps/extern.h,v retrieving revision 1.37 diff -u -r1.37 extern.h --- bin/ps/extern.h 23 Jun 2004 23:48:09 -0000 1.37 +++ bin/ps/extern.h 26 Oct 2007 07:50:37 -0000 @@ -39,7 +39,7 @@ extern int cflag, eval, fscale, nlistread, rawcpu; extern unsigned long mempages; extern time_t now; -extern int sumrusage, termwidth, totwidth; +extern int showthreads, sumrusage, termwidth, totwidth; extern STAILQ_HEAD(velisthead, varent) varlist; __BEGIN_DECLS @@ -78,6 +78,7 @@ void showkey(void); void started(KINFO *, VARENT *); void state(KINFO *, VARENT *); +void tdnam(KINFO *, VARENT *); void tdev(KINFO *, VARENT *); void tname(KINFO *, VARENT *); void ucomm(KINFO *, VARENT *); Index: bin/ps/keyword.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/bin/ps/keyword.c,v retrieving revision 1.76 diff -u -r1.76 keyword.c --- bin/ps/keyword.c 6 Apr 2006 03:24:31 -0000 1.76 +++ bin/ps/keyword.c 26 Oct 2007 07:50:37 -0000 @@ -187,6 +187,8 @@ UINT, UIDFMT, 0}, {"tdev", "TDEV", NULL, 0, tdev, NULL, 4, 0, CHAR, NULL, 0}, {"time", "TIME", NULL, USER, cputime, NULL, 9, 0, CHAR, NULL, 0}, + {"tdnam", "THRDNAME", NULL, LJUST, tdnam, NULL, COMMLEN, 0, CHAR, + NULL, 0}, {"tpgid", "TPGID", NULL, 0, kvar, NULL, 4, KOFF(ki_tpgid), UINT, PIDFMT, 0}, {"tsid", "TSID", NULL, 0, kvar, NULL, PIDLEN, KOFF(ki_tsid), UINT, Index: bin/ps/print.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/bin/ps/print.c,v retrieving revision 1.95 diff -u -r1.95 print.c --- bin/ps/print.c 17 Sep 2007 05:27:18 -0000 1.95 +++ bin/ps/print.c 26 Oct 2007 07:50:37 -0000 @@ -129,9 +129,11 @@ v = ve->var; if (cflag) { /* If it is the last field, then don't pad */ - if (STAILQ_NEXT(ve, next_ve) == NULL) + if (STAILQ_NEXT(ve, next_ve) == NULL) { (void)printf("%s", k->ki_p->ki_comm); - else + if (showthreads && k->ki_p->ki_numthreads > 1) + printf("/%s", k->ki_p->ki_ocomm); + } else (void)printf("%-*s", v->width, k->ki_p->ki_comm); return; } @@ -178,10 +180,25 @@ VAR *v; v = ve->var; - if (STAILQ_NEXT(ve, next_ve) == NULL) /* last field, don't pad */ + if (STAILQ_NEXT(ve, next_ve) == NULL) { /* last field, don't pad */ (void)printf("%s", k->ki_p->ki_comm); - else + if (showthreads && k->ki_p->ki_numthreads > 1) + printf("/%s", k->ki_p->ki_ocomm); + } else (void)printf("%-*s", v->width, k->ki_p->ki_comm); +} + +void +tdnam(KINFO *k, VARENT *ve) +{ + VAR *v; + + v = ve->var; + if (showthreads && k->ki_p->ki_numthreads > 1) + (void)printf("%-*s", v->width, k->ki_p->ki_ocomm); + else + (void)printf("%-*s", v->width, " " ); + } void Index: bin/ps/ps.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/bin/ps/ps.c,v retrieving revision 1.111 diff -u -r1.111 ps.c --- bin/ps/ps.c 17 Sep 2007 05:27:18 -0000 1.111 +++ bin/ps/ps.c 26 Oct 2007 07:50:37 -0000 @@ -98,6 +98,7 @@ int sumrusage; /* -S */ int termwidth; /* Width of the screen (0 == infinity). */ int totwidth; /* Calculated-width of requested variables. */ +int showthreads; /* will threads be shown? */ struct velisthead varlist = STAILQ_HEAD_INITIALIZER(varlist); @@ -175,7 +176,7 @@ char *cols; int all, ch, elem, flag, _fmt, i, lineno; int nentries, nkept, nselectors; - int prtheader, showthreads, wflag, what, xkeep, xkeep_implied; + int prtheader, wflag, what, xkeep, xkeep_implied; char errbuf[_POSIX2_LINE_MAX]; (void) setlocale(LC_ALL, ""); Index: sys/kern/init_main.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/kern/init_main.c,v retrieving revision 1.285 diff -u -r1.285 init_main.c --- sys/kern/init_main.c 24 Oct 2007 19:03:54 -0000 1.285 +++ sys/kern/init_main.c 26 Oct 2007 07:50:39 -0000 @@ -427,12 +427,13 @@ td->td_priority = PVM; td->td_base_pri = PUSER; td->td_oncpu = 0; - td->td_flags = TDF_INMEM; + td->td_flags = TDF_INMEM|TDP_KTHREAD; p->p_peers = 0; p->p_leader = p; - bcopy("swapper", p->p_comm, sizeof ("swapper")); + strncpy(p->p_comm, "kernel", sizeof (p->p_comm)); + strncpy(td->td_name, "swapper", sizeof (td->td_name)); callout_init(&p->p_itcallout, CALLOUT_MPSAFE); callout_init_mtx(&p->p_limco, &p->p_mtx, 0); Index: sys/kern/kern_exit.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/kern/kern_exit.c,v retrieving revision 1.305 diff -u -r1.305 kern_exit.c --- sys/kern/kern_exit.c 24 Oct 2007 19:03:54 -0000 1.305 +++ sys/kern/kern_exit.c 26 Oct 2007 07:50:39 -0000 @@ -136,8 +136,7 @@ * MUST abort all other threads before proceeding past here. */ PROC_LOCK(p); - if (p->p_flag & P_HADTHREADS) { -retry: + while (p->p_flag & P_HADTHREADS) { /* * First check if some other thread got here before us.. * if so, act apropriatly, (exit or suspend); @@ -161,8 +160,8 @@ * re-check all suspension request, the thread should * either be suspended there or exit. */ - if (thread_single(SINGLE_EXIT)) - goto retry; + if (! thread_single(SINGLE_EXIT)) + break; /* * All other activity in this process is now stopped. Index: sys/kern/kern_idle.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/kern/kern_idle.c,v retrieving revision 1.49 diff -u -r1.49 kern_idle.c --- sys/kern/kern_idle.c 20 Oct 2007 23:23:21 -0000 1.49 +++ sys/kern/kern_idle.c 26 Oct 2007 07:50:39 -0000 @@ -60,27 +60,25 @@ #ifdef SMP SLIST_FOREACH(pc, &cpuhead, pc_allcpu) { - error = kproc_create(sched_idletd, NULL, &p, - RFSTOPPED | RFHIGHPID, 0, "idle: cpu%d", pc->pc_cpuid); - pc->pc_idlethread = FIRST_THREAD_IN_PROC(p); +#endif + error = kproc_kthread_add(sched_idletd, NULL, &p, &td, + RFSTOPPED | RFHIGHPID, 0, "idled", "idle: cpu%d", pc->pc_cpuid); +#ifdef SMP + pc->pc_idlethread = td; #else - error = kproc_create(sched_idletd, NULL, &p, - RFSTOPPED | RFHIGHPID, 0, "idle"); - PCPU_SET(idlethread, FIRST_THREAD_IN_PROC(p)); + PCPU_SET(idlethread, td); #endif + p = td->td_proc; if (error) panic("idle_setup: kproc_create error %d\n", error); - PROC_LOCK(p); p->p_flag |= P_NOLOAD; - td = FIRST_THREAD_IN_PROC(p); thread_lock(td); TD_SET_CAN_RUN(td); td->td_flags |= TDF_IDLETD; sched_class(td, PRI_IDLE); sched_prio(td, PRI_MAX_IDLE); thread_unlock(td); - PROC_UNLOCK(p); #ifdef SMP } #endif Index: sys/kern/kern_intr.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/kern/kern_intr.c,v retrieving revision 1.148 diff -u -r1.148 kern_intr.c --- sys/kern/kern_intr.c 20 Oct 2007 23:23:21 -0000 1.148 +++ sys/kern/kern_intr.c 26 Oct 2007 07:50:39 -0000 @@ -80,6 +80,7 @@ struct intr_event *tty_intr_event; void *softclock_ih; void *vm_ih; +struct proc *intrproc; static MALLOC_DEFINE(M_ITHREAD, "ithread", "Interrupt Threads"); @@ -171,8 +172,7 @@ pri = TAILQ_FIRST(&ie->ie_handlers)->ih_pri; /* Update name and priority. */ - strlcpy(td->td_proc->p_comm, ie->ie_fullname, - sizeof(td->td_proc->p_comm)); + strlcpy(td->td_name, ie->ie_fullname, sizeof(td->td_name)); thread_lock(td); sched_prio(td, pri); thread_unlock(td); @@ -332,16 +332,15 @@ { struct intr_thread *ithd; struct thread *td; - struct proc *p; int error; ithd = malloc(sizeof(struct intr_thread), M_ITHREAD, M_WAITOK | M_ZERO); - error = kproc_create(ithread_loop, ithd, &p, RFSTOPPED | RFHIGHPID, - 0, "%s", name); + error = kproc_kthread_add(ithread_loop, ithd, &intrproc, + &td, RFSTOPPED | RFHIGHPID, + 0, "interd", "%s", name); if (error) panic("kproc_create() failed with %d", error); - td = FIRST_THREAD_IN_PROC(p); /* XXXKSE */ thread_lock(td); sched_class(td, PRI_ITHD); TD_SET_IWAIT(td); @@ -357,16 +356,15 @@ { struct intr_thread *ithd; struct thread *td; - struct proc *p; int error; ithd = malloc(sizeof(struct intr_thread), M_ITHREAD, M_WAITOK | M_ZERO); - error = kproc_create(ithread_loop, ih, &p, RFSTOPPED | RFHIGHPID, - 0, "%s", name); + error = kproc_kthread_create(ithread_loop, ih, &intrproc, + &td, RFSTOPPED | RFHIGHPID, + 0, "interd", "%s", name); if (error) panic("kproc_create() failed with %d", error); - td = FIRST_THREAD_IN_PROC(p); /* XXXKSE */ thread_lock(td); sched_class(td, PRI_ITHD); TD_SET_IWAIT(td); @@ -688,7 +686,7 @@ */ if (harvest.interrupt && ie->ie_flags & IE_ENTROPY) { CTR3(KTR_INTR, "%s: pid %d (%s) gathering entropy", __func__, - p->p_pid, p->p_comm); + p->p_pid, td->td_name); entropy.event = (uintptr_t)ie; entropy.td = ctd; random_harvest(&entropy, sizeof(entropy), 2, 0, @@ -706,12 +704,12 @@ thread_lock(td); if (TD_AWAITING_INTR(td)) { CTR3(KTR_INTR, "%s: schedule pid %d (%s)", __func__, p->p_pid, - p->p_comm); + td->td_name); TD_CLR_IWAIT(td); sched_add(td, SRQ_INTR); } else { CTR5(KTR_INTR, "%s: pid %d (%s): it_need %d, state %d", - __func__, p->p_pid, p->p_comm, it->it_need, td->td_state); + __func__, p->p_pid, td->td_name, it->it_need, td->td_state); } thread_unlock(td); @@ -842,7 +840,7 @@ */ if (harvest.interrupt && ie->ie_flags & IE_ENTROPY) { CTR3(KTR_INTR, "%s: pid %d (%s) gathering entropy", __func__, - p->p_pid, p->p_comm); + p->p_pid, td->td_name); entropy.event = (uintptr_t)ie; entropy.td = ctd; random_harvest(&entropy, sizeof(entropy), 2, 0, @@ -860,12 +858,12 @@ thread_lock(td); if (TD_AWAITING_INTR(td)) { CTR3(KTR_INTR, "%s: schedule pid %d (%s)", __func__, p->p_pid, - p->p_comm); + th->th_name); TD_CLR_IWAIT(td); sched_add(td, SRQ_INTR); } else { CTR5(KTR_INTR, "%s: pid %d (%s): it_need %d, state %d", - __func__, p->p_pid, p->p_comm, it->it_need, td->td_state); + __func__, p->p_pid, td->td_name, it->it_need, td->td_state); } thread_unlock(td); @@ -1100,9 +1098,9 @@ */ if (ithd->it_flags & IT_DEAD) { CTR3(KTR_INTR, "%s: pid %d (%s) exiting", __func__, - p->p_pid, p->p_comm); + p->p_pid, td->td_name); free(ithd, M_ITHREAD); - kproc_exit(0); + kthread_exit(0); } /* @@ -1171,9 +1169,9 @@ */ if (ithd->it_flags & IT_DEAD) { CTR3(KTR_INTR, "%s: pid %d (%s) exiting", __func__, - p->p_pid, p->p_comm); + p->p_pid, td->td_name); free(ithd, M_ITHREAD); - kproc_exit(0); + kthread_exit(0); } /* Index: sys/kern/kern_kthread.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/kern/kern_kthread.c,v retrieving revision 1.39 diff -u -r1.39 kern_kthread.c --- sys/kern/kern_kthread.c 20 Oct 2007 23:23:21 -0000 1.39 +++ sys/kern/kern_kthread.c 26 Oct 2007 07:50:39 -0000 @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include @@ -95,7 +97,9 @@ /* this is a non-swapped system process */ PROC_LOCK(p2); + td = FIRST_THREAD_IN_PROC(p2); p2->p_flag |= P_SYSTEM | P_KTHREAD; + td->td_pflags |= TDP_KTHREAD; mtx_lock(&p2->p_sigacts->ps_mtx); p2->p_sigacts->ps_flag |= PS_NOCLDWAIT; mtx_unlock(&p2->p_sigacts->ps_mtx); @@ -105,9 +109,12 @@ va_start(ap, fmt); vsnprintf(p2->p_comm, sizeof(p2->p_comm), fmt, ap); va_end(ap); + /* set up arg0 for 'ps', et al */ + va_start(ap, fmt); + vsnprintf(td->td_name, sizeof(td->td_name), fmt, ap); + va_end(ap); /* call the processes' main()... */ - td = FIRST_THREAD_IN_PROC(p2); cpu_set_fork_handler(td, func, arg); TD_SET_CAN_RUN(td); @@ -167,7 +174,7 @@ } SIGADDSET(p->p_siglist, SIGSTOP); wakeup(p); - return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkt", timo); + return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkp", timo); } int @@ -194,7 +201,205 @@ PROC_LOCK(p); while (SIGISMEMBER(p->p_siglist, SIGSTOP)) { wakeup(&p->p_siglist); - msleep(&p->p_siglist, &p->p_mtx, PPAUSE, "ktsusp", 0); + msleep(&p->p_siglist, &p->p_mtx, PPAUSE, "kpsusp", 0); + } + PROC_UNLOCK(p); +} + + +/* + * Start a kernel thread. + * + * This function is used to start "internal" daemons and intended + * to be called from SYSINIT(). + */ + +void +kthread_start(udata) + const void *udata; +{ + const struct kthread_desc *kp = udata; + int error; + + error = kthread_add((void (*)(void *))kp->func, NULL, + NULL, kp->global_threadpp, 0, 0, "%s", kp->arg0); + if (error) + panic("kthread_start: %s: error %d", kp->arg0, error); +} + +/* + * 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) + * ** XXX are any used? + * fmt and following will be *printf'd into (*newtd)->td_name (for ps, etc.). + */ +int +kthread_add(void (*func)(void *), void *arg, struct proc *p, + struct thread **newtdp, int flags, int pages, const char *fmt, ...) +{ + va_list ap; + struct thread *newtd, *oldtd; + int error; + + if (!proc0.p_stats) + panic("kthread_add called too soon"); + + error = 0; + if (p == NULL) { + p = &proc0; + oldtd = &thread0; + } else { + oldtd = FIRST_THREAD_IN_PROC(p); } + + /* Initialize our td */ + newtd = thread_alloc(); + if (newtd == NULL) + return (ENOMEM); + + bzero(&newtd->td_startzero, + __rangeof(struct thread, td_startzero, td_endzero)); +/* XXX check if we should zero. */ + bcopy(&oldtd->td_startcopy, &newtd->td_startcopy, + __rangeof(struct thread, td_startcopy, td_endcopy)); + + /* set up arg0 for 'ps', et al */ + va_start(ap, fmt); + vsnprintf(newtd->td_name, sizeof(newtd->td_name), fmt, ap); + va_end(ap); + + newtd->td_proc = p; /* needed for cpu_set_upcall */ + + /* XXX optimise this probably? */ + /* On x86 (and probably the others too) it is way too full of junk */ + /* Needs a better name */ + cpu_set_upcall(newtd, oldtd); + /* put the designated function(arg) as the resume context */ + cpu_set_fork_handler(newtd, func, arg); + + newtd->td_pflags |= TDP_KTHREAD; + newtd->td_ucred = crhold(p->p_ucred); + /* Allocate and switch to an alternate kstack if specified. */ + if (pages != 0) + vm_thread_new_altkstack(newtd, pages); + + /* this code almost the same as create_thread() in kern_thr.c */ + PROC_LOCK(p); + p->p_flag |= P_HADTHREADS; + newtd->td_sigmask = oldtd->td_sigmask; /* XXX dubious */ + PROC_SLOCK(p); + thread_link(newtd, p); + thread_lock(oldtd); + /* let the scheduler know about these things. */ + sched_fork_thread(oldtd, newtd); + TD_SET_CAN_RUN(newtd); + thread_unlock(oldtd); + PROC_SUNLOCK(p); PROC_UNLOCK(p); + + + /* Delay putting it on the run queue until now. */ + if (!(flags & RFSTOPPED)) { + thread_lock(newtd); + sched_add(newtd, SRQ_BORING); + thread_unlock(newtd); + } + if (newtdp) + *newtdp = newtd; + return 0; +} + +void +kthread_exit(int ecode) +{ + thread_exit(); +} + +/* + * Advise a kernel process to suspend (or resume) in its main loop. + * Participation is voluntary. + */ +int +kthread_suspend(struct thread *td, int timo) +{ + if ((td->td_pflags & TDP_KTHREAD) == 0) { + return (EINVAL); + } + thread_lock(td); + td->td_flags |= TDF_KTH_SUSP; + thread_unlock(td); + /* + * If it's stopped for some other reason, + * kick it to notice our request + * or we'll end up timing out + */ + wakeup(td); /* traditional place for kernel threads to sleep on */ /* XXX ?? */ + return (tsleep(&td->td_flags, PPAUSE | PDROP, "suspkt", timo)); +} + +/* + * let the kthread it can keep going again. + */ +int +kthread_resume(struct thread *td) +{ + if ((td->td_pflags & TDP_KTHREAD) == 0) { + return (EINVAL); + } + thread_lock(td); + td->td_flags &= ~TDF_KTH_SUSP; + thread_unlock(td); + wakeup(&td->td_name); + return (0); +} + +/* + * Used by the thread to poll as to whether it should yield/sleep + * and notify the caller that is has happened. + */ +void +kthread_suspend_check(struct thread *td) +{ + while (td->td_flags & TDF_KTH_SUSP) { + /* + * let the caller know we got the message then sleep + */ + wakeup(&td->td_flags); + tsleep(&td->td_name, PPAUSE, "ktsusp", 0); + } +} + +int +kproc_kthread_add(void (*func)(void *), void *arg, + struct proc **procptr, struct thread **tdptr, + int flags, int pages, char * procname, const char *fmt, ...) +{ + int error; + va_list ap; + char buf[100]; + struct thread *td; + + if (*procptr == 0) { + error = kproc_create(func, arg, + procptr, flags, pages, "%s", procname); + if (error) + return (error); + td = FIRST_THREAD_IN_PROC(*procptr); + *tdptr = td; + va_start(ap, fmt); + vsnprintf(td->td_name, sizeof(td->td_name), fmt, ap); + va_end(ap); + return (0); + } + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + error = kthread_add(func, arg, *procptr, + tdptr, flags, pages, "%s", buf); + return (error); } Index: sys/kern/kern_shutdown.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/kern/kern_shutdown.c,v retrieving revision 1.184 diff -u -r1.184 kern_shutdown.c --- sys/kern/kern_shutdown.c 24 Oct 2007 19:03:54 -0000 1.184 +++ sys/kern/kern_shutdown.c 26 Oct 2007 07:50:39 -0000 @@ -616,6 +616,28 @@ printf("done\n"); } +void +kthread_shutdown(void *arg, int howto) +{ + struct thread *td; + char procname[MAXCOMLEN + 1]; + int error; + + if (panicstr) + return; + + td = (struct thread *)arg; + strlcpy(procname, td->td_name, sizeof(procname)); + printf("Waiting (max %d seconds) for system thread `%s' to stop...", + kproc_shutdown_wait, procname); + error = kthread_suspend(td, kproc_shutdown_wait * hz); + + if (error == EWOULDBLOCK) + printf("timed out\n"); + else + printf("done\n"); +} + /* Registration of dumpers */ int set_dumper(struct dumperinfo *di) Index: sys/kern/kern_thread.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/kern/kern_thread.c,v retrieving revision 1.255 diff -u -r1.255 kern_thread.c --- sys/kern/kern_thread.c 21 Sep 2007 04:04:22 -0000 1.255 +++ sys/kern/kern_thread.c 26 Oct 2007 07:50:39 -0000 @@ -657,12 +657,6 @@ sleepq_abort(td2, EINTR); break; case SINGLE_BOUNDARY: - if (TD_IS_SUSPENDED(td2) && - !(td2->td_flags & TDF_BOUNDARY)) - thread_unsuspend_one(td2); - if (TD_ON_SLEEPQ(td2) && - (td2->td_flags & TDF_SINTR)) - sleepq_abort(td2, ERESTART); break; default: if (TD_IS_SUSPENDED(td2)) { Index: sys/kern/sched_4bsd.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/kern/sched_4bsd.c,v retrieving revision 1.106 diff -u -r1.106 sched_4bsd.c --- sys/kern/sched_4bsd.c 8 Oct 2007 23:45:24 -0000 1.106 +++ sys/kern/sched_4bsd.c 26 Oct 2007 07:50:39 -0000 @@ -1367,11 +1367,9 @@ void sched_idletd(void *dummy) { - struct proc *p; struct thread *td; td = curthread; - p = td->td_proc; for (;;) { mtx_assert(&Giant, MA_NOTOWNED); Index: sys/sys/kthread.h =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/sys/kthread.h,v retrieving revision 1.10 diff -u -r1.10 kthread.h --- sys/sys/kthread.h 21 Oct 2007 03:31:40 -0000 1.10 +++ sys/sys/kthread.h 26 Oct 2007 07:50:40 -0000 @@ -42,13 +42,38 @@ struct proc **global_procpp; /* ptr to proc ptr save area */ }; -void kproc_shutdown(void *, int); -void kproc_start(const void *); + /* A kernel thread descriptor; used to start "internal" daemons. */ +struct kthread_desc { + char *arg0; /* arg 0 (for 'ps' listing) */ + void (*func)(void); /* "main" for kernel thread */ + struct thread **global_threadpp; /* ptr to thread ptr save area */ +}; + int kproc_create(void (*)(void *), void *, struct proc **, int flags, int pages, const char *, ...) __printflike(6, 7); void kproc_exit(int) __dead2; int kproc_resume(struct proc *); +void kproc_shutdown(void *, int); +void kproc_start(const void *); int kproc_suspend(struct proc *, int); void kproc_suspend_check(struct proc *); + +/* create a thread inthe given process. create the process if needed */ +int kproc_kthread_add(void (*)(void *), void *, + struct proc **, + struct thread **, + int flags, int pages, + char * procname, const char *, ...) __printflike(8, 9); + +int kthread_add(void (*)(void *), void *, + struct proc *, struct thread **, + int flags, int pages, const char *, ...) __printflike(7, 8); +void kthread_exit(int) __dead2; +int kthread_resume(struct thread *); +void kthread_shutdown(void *, int); +void kthread_start(const void *); +int kthread_suspend(struct thread *, int); +void kthread_suspend_check(struct thread *); + #endif /* !_SYS_KTHREAD_H_ */ Index: sys/sys/proc.h =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/sys/proc.h,v retrieving revision 1.491 diff -u -r1.491 proc.h --- sys/sys/proc.h 21 Sep 2007 04:10:23 -0000 1.491 +++ sys/sys/proc.h 26 Oct 2007 07:50:40 -0000 @@ -322,7 +322,7 @@ #define TDF_IDLETD 0x00000020 /* This is a per-CPU idle thread. */ #define TDF_SELECT 0x00000040 /* Selecting; wakeup/waiting danger. */ #define TDF_SLEEPABORT 0x00000080 /* sleepq_abort was called. */ -#define TDF_UNUSEDx100 0x00000100 /* --available-- */ +#define TDF_KTH_SUSP 0x00000100 /* kthread is suspended */ #define TDF_UBORROWING 0x00000200 /* Thread is borrowing user pri. */ #define TDF_BOUNDARY 0x00000400 /* Thread suspended at user boundary */ #define TDF_ASTPENDING 0x00000800 /* Thread has some asynchronous events. */ @@ -348,7 +348,7 @@ /* * "Private" flags kept in td_pflags: - * These are only accessed by curthread and thus need no locking. + * These are only written by curthread and thus need no locking. */ #define TDP_OLDMASK 0x00000001 /* Need to restore mask after suspend. */ #define TDP_INKTR 0x00000002 /* Thread is currently in KTR code. */ @@ -371,6 +371,7 @@ #define TDP_NORUNNINGBUF 0x00040000 /* Ignore runningbufspace check */ #define TDP_WAKEUP 0x00080000 /* Don't sleep in umtx cond_wait */ #define TDP_INBDFLUSH 0x00100000 /* Already in BO_BDFLUSH, do not recurse */ +#define TDP_KTHREAD 0x00200000 /* This is an official kernel thread */ /* * Reasons that the current thread can not be run yet.