Index: include/unistd.h =================================================================== --- include/unistd.h +++ include/unistd.h @@ -571,6 +571,7 @@ void *setmode(const char *); int setpgrp(pid_t, pid_t); /* obsoleted by setpgid() */ void setproctitle(const char *_fmt, ...) __printf0like(1, 2); +void setproctitle_fast(const char *_fmt, ...) __printf0like(1, 2); int setresgid(gid_t, gid_t, gid_t); int setresuid(uid_t, uid_t, uid_t); int setrgid(gid_t); Index: lib/libc/gen/setproctitle.3 =================================================================== --- lib/libc/gen/setproctitle.3 +++ lib/libc/gen/setproctitle.3 @@ -31,12 +31,18 @@ .In unistd.h .Ft void .Fn setproctitle "const char *fmt" "..." +.Ft void +.Fn setproctitle_fast "const char *fmt" "..." .Sh DESCRIPTION The .Fn setproctitle library routine sets the process title that appears on the .Xr ps 1 -command. +command. The +.Fn setproctitle_fast +variant is optimized for high frequency updates, but may make the +.Xr ps 1 +command slightly slower. .Pp The title is set from the executable's name, followed by the result of a @@ -96,6 +102,10 @@ function first appeared in .Fx 2.2 . +The +.Fn setproctitle_fast +function first appeared in +.Fx 12 . Other operating systems have similar functions. .Sh AUTHORS Index: lib/libc/gen/setproctitle.c =================================================================== --- lib/libc/gen/setproctitle.c +++ lib/libc/gen/setproctitle.c @@ -55,8 +55,8 @@ #define SPT_BUFSIZE 2048 /* from other parts of sendmail */ -void -setproctitle(const char *fmt, ...) +static inline char * +setproctitle_internal(const char *fmt, va_list ap) { static struct ps_strings *ps_strings; static char *buf = NULL; @@ -67,27 +67,23 @@ char **nargvp; int nargc; int i; - va_list ap; size_t len; unsigned long ul_ps_strings; - int oid[4]; if (buf == NULL) { buf = malloc(SPT_BUFSIZE); if (buf == NULL) - return; + return NULL; nargv[0] = buf; } if (obuf == NULL ) { obuf = malloc(SPT_BUFSIZE); if (obuf == NULL) - return; + return NULL; *obuf = '\0'; } - va_start(ap, fmt); - if (fmt) { buf[SPT_BUFSIZE - 1] = '\0'; @@ -114,22 +110,13 @@ kbuf = obuf; } else /* Nothing to restore */ - return; - - va_end(ap); - - /* Set the title into the kernel cached command line */ - oid[0] = CTL_KERN; - oid[1] = KERN_PROC; - oid[2] = KERN_PROC_ARGS; - oid[3] = getpid(); - sysctl(oid, 4, 0, 0, kbuf, strlen(kbuf) + 1); + return NULL; if (ps_strings == NULL) { len = sizeof(ul_ps_strings); if (sysctlbyname("kern.ps_strings", &ul_ps_strings, &len, NULL, 0) == -1) - return; + return NULL; ps_strings = (struct ps_strings *)ul_ps_strings; } @@ -138,7 +125,7 @@ * Should not happen. */ if (ps_strings->ps_argvstr == NULL) - return; + return NULL; /* style #3 */ if (oargc == -1) { @@ -167,4 +154,55 @@ } ps_strings->ps_nargvstr = nargc; ps_strings->ps_argvstr = nargvp; + + return nargvp[0]; +} + +static int fast_update = 0; + +void +setproctitle_fast(const char *fmt, ...) +{ + va_list ap; + char *buf; + int oid[4]; + + va_start(ap, fmt); + buf = setproctitle_internal(fmt, ap); + va_end(ap); + + if (!buf) + return; + + if (!fast_update) { + /* Tell the kernel to start looking in user-space */ + oid[0] = CTL_KERN; + oid[1] = KERN_PROC; + oid[2] = KERN_PROC_ARGS; + oid[3] = getpid(); + sysctl(oid, 4, 0, 0, "", 0); + fast_update = 1; + } +} + +void +setproctitle(const char *fmt, ...) +{ + va_list ap; + char *buf; + int oid[4]; + + va_start(ap, fmt); + buf = setproctitle_internal(fmt, ap); + va_end(ap); + + if (buf) { + /* Set the title into the kernel cached command line */ + oid[0] = CTL_KERN; + oid[1] = KERN_PROC; + oid[2] = KERN_PROC_ARGS; + oid[3] = getpid(); + sysctl(oid, 4, 0, 0, buf, strlen(buf) + 1); + fast_update = 0; + } } Index: sys/kern/kern_proc.c =================================================================== --- sys/kern/kern_proc.c +++ sys/kern/kern_proc.c @@ -1988,11 +1988,20 @@ if (req->newlen > ps_arg_cache_limit - sizeof(struct pargs)) return (ENOMEM); - newpa = pargs_alloc(req->newlen); - error = SYSCTL_IN(req, newpa->ar_args, req->newlen); - if (error != 0) { - pargs_free(newpa); - return (error); + + if (req->newlen == 0) { + /* + * Clear the argument pointer, so that we'll fetch arguments + * with proc_getargv() until further notice. + */ + newpa = NULL; + } else { + newpa = pargs_alloc(req->newlen); + error = SYSCTL_IN(req, newpa->ar_args, req->newlen); + if (error != 0) { + pargs_free(newpa); + return (error); + } } PROC_LOCK(p); pa = p->p_args; Index: usr.bin/top/machine.c =================================================================== --- usr.bin/top/machine.c +++ usr.bin/top/machine.c @@ -950,7 +950,6 @@ } } else { if (pp->ki_flag & P_SYSTEM || - pp->ki_args == NULL || (args = kvm_getargv(kd, pp, cmdlen)) == NULL || !(*args)) { if (ps.thread && pp->ki_flag & P_HADTHREADS &&