process acounting (pstats/p_ru) needs to be moved to lwp proposed structure of kinfo_proc (compare freebsd's kinfo_proc): /* * KERN_PROC subtype ops return arrays of augmented proc structures: */ struct kinfo_proc { size_t ki_len; /* complete length of this structure */ int ki_type; /* KI_TYPE_PROC */ /* proc information */ int ki_pflags; sigset_t ki_siglist; struct timeval ki_start; char ki_comm[MAXCOMLEN+1]; /* cred information */ uid_t ki_uid; short ki_ngroups; gid_t ki_groups[NGROUPS]; uid_t ki_ruid; uid_t ki_svuid; gid_t ki_rgid; gid_t ki_svgid; struct procsig ki_procsig; /* shared signal structure */ struct vmspace ki_vm; /* address space */ struct pstats ki_stats; /* process stats */ u_int64_t ki_uticks; /* time accouting */ u_int64_t ki_sticks; u_int64_t ki_iticks; int ki_cpuid; /* last scheduled on cpu */ pid_t ki_pid; /* process id */ pid_t ki_ppid; /* parent process id */ pid_t ki_pgid; /* process group id */ short ki_jobc; /* job control counter */ dev_t ki_tdev; /* controlling tty dev */ pid_t ki_tpgid; /* tty process group id */ struct session *ki_tsess; /* tty session pointer */ segsz_t ki_xsize; /* text size */ short ki_xrssize; /* text rss */ short ki_xccount; /* text references */ short ki_xswrss; long ki_flag; #define EPROC_CTTY 0x01 /* controlling tty vnode active */ #define EPROC_SLEADER 0x02 /* session leader */ char ki_login[roundup(MAXLOGNAME, sizeof(long))]; /* setlogin() name */ int ki_jailid; }; void fill_kinfo_proc (struct proc *, struct kinfo_proc *); Points regarding how to export lwp info: * Export it separately from the processes, like having a kvm_getlwps which takes, among other things, a PID as argument. * Pro: you don't clutter struct kinfo_proc with lwp references * Con: if you want to get info about all lwps, you have to first get all the PIDs, then get the lwps of each proc which means many more calls uses of kinfo_proc: /repos/src/dragonfly/src/bin/ps/ps.c: 90: static const char *getfmt (char **(*)(kvm_t *, const struct kinfo_proc *, int), /repos/src/dragonfly/src/bin/ps/ps.c: 116: struct kinfo_proc *kp; /repos/src/dragonfly/src/bin/ps/ps.c: 519: getfmt(char **(*fn) (kvm_t *, const struct kinfo_proc *, int), KINFO *ki, char /repos/src/dragonfly/src/bin/ps/ps.h: 54: struct kinfo_proc *ki_p; /* proc structure */ /repos/src/dragonfly/src/contrib/cvs-1.12/src/update.c: 78: static int get_linkinfo_proc( void *_callerdat, struct _finfo * ); /repos/src/dragonfly/src/contrib/cvs-1.12/src/update.c: 507: (get_linkinfo_proc, NULL, NULL, NULL, NULL, /repos/src/dragonfly/src/contrib/cvs-1.12/src/update.c: 540: * The get_linkinfo_proc callback adds each file to the hardlist /repos/src/dragonfly/src/contrib/cvs-1.12/src/update.c: 545: get_linkinfo_proc (void *callerdat, struct file_info *finfo) /repos/src/dragonfly/src/contrib/ipfilter/ipsend/sock.c: 98: static struct kinfo_proc *getproc __P((void)); /repos/src/dragonfly/src/contrib/ipfilter/ipsend/sock.c: 252: static struct kinfo_proc *getproc() /repos/src/dragonfly/src/contrib/ipfilter/ipsend/sock.c: 254: static struct kinfo_proc kp; /repos/src/dragonfly/src/contrib/ipfilter/ipsend/sock.c: 281: struct kinfo_proc *p; /repos/src/dragonfly/src/lib/libc/gen/sysctl.3: 166: struct kinfo_proc kp; /repos/src/dragonfly/src/lib/libc/gen/sysctl.3: 424: .Va struct kinfo_proc /repos/src/dragonfly/src/lib/libkcore/kcore.h: 75: struct kinfo_proc; /repos/src/dragonfly/src/lib/libkcore/kcore.h: 87: int kcore_get_procs(struct kcore_data *kc, struct kinfo_proc **procs, /repos/src/dragonfly/src/lib/libkcore/kcore_file.c: 56: struct kinfo_proc *procs, *oprocs; /repos/src/dragonfly/src/lib/libkcore/kcore_proc.c: 52: kcore_get_procs(struct kcore_data *kc, struct kinfo_proc **procs, size_t *len) /repos/src/dragonfly/src/lib/libkcore/kcore_proc.c: 54: struct kinfo_proc *p; /repos/src/dragonfly/src/lib/libkcore/kcore_proc.c: 69: *procs = malloc(sizeof(struct kinfo_proc) * nlen); /repos/src/dragonfly/src/lib/libkcore/kcore_proc.c: 72: memcpy(*procs, p, sizeof(struct kinfo_proc) * nlen); /repos/src/dragonfly/src/lib/libkvm/kvm.h: 51: struct kinfo_proc; /repos/src/dragonfly/src/lib/libkvm/kvm.h: 70: char **kvm_getargv (kvm_t *, const struct kinfo_proc *, int); /repos/src/dragonfly/src/lib/libkvm/kvm.h: 71: char **kvm_getenvv (kvm_t *, const struct kinfo_proc *, int); /repos/src/dragonfly/src/lib/libkvm/kvm.h: 75: struct kinfo_proc * /repos/src/dragonfly/src/lib/libkvm/kvm_getprocs.3: 56: .Ft struct kinfo_proc * /repos/src/dragonfly/src/lib/libkvm/kvm_getprocs.3: 59: .Fn kvm_getargv "kvm_t *kd" "const struct kinfo_proc *p" "int nchr" /repos/src/dragonfly/src/lib/libkvm/kvm_getprocs.3: 61: .Fn kvm_getenvv "kvm_t *kd" "const struct kinfo_proc *p" "int nchr" /repos/src/dragonfly/src/lib/libkvm/kvm_getprocs.3: 100: The processes are returned as a contiguous array of kinfo_proc structures. /repos/src/dragonfly/src/lib/libkvm/kvm_private.h: 56: struct kinfo_proc *procbase; /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 98: struct kinfo_proc *bp, int maxcnt) /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 256: struct kinfo_proc *bp = kd->procbase; /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 279: struct kinfo_proc * /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 306: kd->procbase = (struct kinfo_proc *) /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 317: if (size % sizeof(struct kinfo_proc) != 0) { /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 320: size, sizeof(struct kinfo_proc)); /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 323: nprocs = size / sizeof(struct kinfo_proc); /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 343: size = nprocs * sizeof(struct kinfo_proc); /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 344: kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size); /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 351: size = nprocs * sizeof(struct kinfo_proc); /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 585: struct kinfo_proc kp; /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 601: kvm_doargv(kvm_t *kd, const struct kinfo_proc *kp, int nchr, /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 644: kvm_getargv(kvm_t *kd, const struct kinfo_proc *kp, int nchr) /repos/src/dragonfly/src/lib/libkvm/kvm_proc.c: 703: kvm_getenvv(kvm_t *kd, const struct kinfo_proc *kp, int nchr) /repos/src/dragonfly/src/sys/kern/kern_proc.c: 782: error = SYSCTL_OUT(req, 0, sizeof (struct kinfo_proc) * 5); /repos/src/dragonfly/src/sys/sys/user.h: 48: * unless they really, really, really need kinfo_proc. /repos/src/dragonfly/src/sys/sys/user.h: 106: struct kinfo_proc { /repos/src/dragonfly/src/sys/sys/user.h: 158: struct kinfo_proc u_kproc; /* proc + eproc */ /repos/src/dragonfly/src/usr.bin/fstat/fstat.c: 139: void dofiles(struct kinfo_proc *kp); /repos/src/dragonfly/src/usr.bin/fstat/fstat.c: 140: void dommap(struct kinfo_proc *kp); /repos/src/dragonfly/src/usr.bin/fstat/fstat.c: 156: struct kinfo_proc *p, *plast; /repos/src/dragonfly/src/usr.bin/fstat/fstat.c: 301: dofiles(struct kinfo_proc *kp) /repos/src/dragonfly/src/usr.bin/fstat/fstat.c: 392: dommap(struct kinfo_proc *kp) /repos/src/dragonfly/src/usr.bin/gcore/extern.h: 42: void md_core(kvm_t *, int, struct kinfo_proc *); /repos/src/dragonfly/src/usr.bin/gcore/gcore.c: 72: static void core(int, int, struct kinfo_proc *); /repos/src/dragonfly/src/usr.bin/gcore/gcore.c: 90: struct kinfo_proc *ki = NULL; /repos/src/dragonfly/src/usr.bin/gcore/gcore.c: 210: core(int efd, int fd, struct kinfo_proc *ki) /repos/src/dragonfly/src/usr.bin/gcore/md-nop.c: 46: md_core(kvm_t *kd, int fd, struct kinfo_proc *ki) /repos/src/dragonfly/src/usr.bin/gcore/md-sparc.c: 81: md_core(kvm_t *kd, int fd, struct kinfo_proc *ki) /repos/src/dragonfly/src/usr.bin/killall/killall.c: 102: struct kinfo_proc *procs = NULL, *newprocs; /repos/src/dragonfly/src/usr.bin/killall/killall.c: 295: if (size % sizeof(struct kinfo_proc) != 0) { /repos/src/dragonfly/src/usr.bin/killall/killall.c: 297: size, sizeof(struct kinfo_proc)); /repos/src/dragonfly/src/usr.bin/killall/killall.c: 301: nprocs = size / sizeof(struct kinfo_proc); /repos/src/dragonfly/src/usr.bin/pkill/pkill.c: 89: struct kinfo_proc *plist; /repos/src/dragonfly/src/usr.bin/pkill/pkill.c: 112: void killact(struct kinfo_proc *, int); /repos/src/dragonfly/src/usr.bin/pkill/pkill.c: 113: void grepact(struct kinfo_proc *, int); /repos/src/dragonfly/src/usr.bin/pkill/pkill.c: 126: void (*action)(struct kinfo_proc *, int); /repos/src/dragonfly/src/usr.bin/pkill/pkill.c: 127: struct kinfo_proc *kp; /repos/src/dragonfly/src/usr.bin/pkill/pkill.c: 450: killact(struct kinfo_proc *kp, int dummy __unused) /repos/src/dragonfly/src/usr.bin/pkill/pkill.c: 460: grepact(struct kinfo_proc *kp, int printdelim) /repos/src/dragonfly/src/usr.bin/sockstat/sockstat.c: 418: static struct kinfo_proc proc; /repos/src/dragonfly/src/usr.bin/systat/pigs.c: 63: struct kinfo_proc *pt_kp; /repos/src/dragonfly/src/usr.bin/systat/pigs.c: 184: struct kinfo_proc *kpp; /repos/src/dragonfly/src/usr.bin/top/machine.c: 77: struct kinfo_proc **next_proc; /* points to next valid proc pointer */ /repos/src/dragonfly/src/usr.bin/top/machine.c: 175: static struct kinfo_proc *pbase; /repos/src/dragonfly/src/usr.bin/top/machine.c: 176: static struct kinfo_proc **pref; /repos/src/dragonfly/src/usr.bin/top/machine.c: 454: register struct kinfo_proc **prefp; /repos/src/dragonfly/src/usr.bin/top/machine.c: 455: register struct kinfo_proc *pp; /repos/src/dragonfly/src/usr.bin/top/machine.c: 468: pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *) /repos/src/dragonfly/src/usr.bin/top/machine.c: 521: qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *), compare); /repos/src/dragonfly/src/usr.bin/top/machine.c: 538: struct kinfo_proc *pp; /repos/src/dragonfly/src/usr.bin/top/machine.c: 748: register struct kinfo_proc *p1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 749: register struct kinfo_proc *p2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 754: p1 = *(struct kinfo_proc **) pp1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 755: p2 = *(struct kinfo_proc **) pp2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 787: register struct kinfo_proc *p1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 788: register struct kinfo_proc *p2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 793: p1 = *(struct kinfo_proc **) pp1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 794: p2 = *(struct kinfo_proc **) pp2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 812: register struct kinfo_proc *p1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 813: register struct kinfo_proc *p2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 818: p1 = *(struct kinfo_proc **) pp1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 819: p2 = *(struct kinfo_proc **) pp2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 837: register struct kinfo_proc *p1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 838: register struct kinfo_proc *p2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 843: p1 = *(struct kinfo_proc **) pp1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 844: p2 = *(struct kinfo_proc **) pp2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 864: register struct kinfo_proc *p1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 865: register struct kinfo_proc *p2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 870: p1 = *(struct kinfo_proc **) pp1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 871: p2 = *(struct kinfo_proc **) pp2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 889: register struct kinfo_proc *p1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 890: register struct kinfo_proc *p2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 895: p1 = *(struct kinfo_proc **) pp1; /repos/src/dragonfly/src/usr.bin/top/machine.c: 896: p2 = *(struct kinfo_proc **) pp2; /repos/src/dragonfly/src/usr.bin/top/machine.c: 926: register struct kinfo_proc **prefp; /repos/src/dragonfly/src/usr.bin/top/machine.c: 927: register struct kinfo_proc *pp; /repos/src/dragonfly/src/usr.bin/w/w.c: 106: struct kinfo_proc *kp; /* `most interesting' proc */ /repos/src/dragonfly/src/usr.bin/w/w.c: 108: struct kinfo_proc *dkp; /* debug option proc list */ /repos/src/dragonfly/src/usr.bin/w/w.c: 111: #define debugproc(p) *((struct kinfo_proc **)&(p)->kp_eproc.e_spare[0]) /repos/src/dragonfly/src/usr.bin/w/w.c: 123: struct kinfo_proc *kp; /repos/src/dragonfly/src/usr.bin/w/w.c: 124: struct kinfo_proc *dkp; /repos/src/dragonfly/src/usr.bin/w/w.c: 298: * list using kinfo_proc kp_eproc.e_spare /* * Same shit for lwps as for procs. * Don't mind the non-matching variable names and types. */ struct kinfo_lwp { size_t kil_len; /* length of our structure */ int kil_type; /* KI_TYPE_LWP */ pid_t kil_proc; /* our associated proc pid */ lwpid_t kil_tid; /* our thread id */ int kil_flags; /* P_ flags */ /* accounting */ uint64_t kil_cpticks; /* sched ticks (quantums?) used */ sigset_t kil_siglist; /* just the siglist, maybe the mask later on */ char kil_wmesg; /* pull this from the associated thread thingamabob */ struct thread kil_thread; /* associated thread struct stuff crap thing */ } void fill_kinfo_lwp(struct lwp *, struct kinfo_lwp *); /* * Fill in a struct kinfo_lwp. */ void fill_kinfo_lwp(struct lwp_t *lwp, struct kinfo_lwp *kilp) { bzero(kilp, sizeof(*kilp)); kilp->kil_proc = lwp->lwp_proc->p_pid; kilp->kil_tid = lwp->lwp_tid; kilp->kil_flag = lwp->lwp_flag; kilp->kil_cpticks = (uint64_t)lwp->lwp_cpticks; kilp->kil_siglist = lwp->lwp_siglist; if (lwp->lwp_thread->td_wmesg) { strncpy(kilp->kil_wmesg, lwp->lwp_thread->td_wmesg, WMESGLEN); kilp->kil_wmesg[WMESGLEN] = 0; } bcopy(lwp->lwp_thread, kilp->kil_thread, sizeof(lwp->lwp_thread)); }