+static int
+sysctl_handle_kern_threadname( __unused struct sysctl_oid *oidp, __unused void *arg1,
+ __unused int arg2, struct sysctl_req *req)
+{
+ int error;
+ struct uthread *ut = get_bsdthread_info(current_thread());
+ user_addr_t oldp=0, newp=0;
+ size_t *oldlenp=NULL;
+ size_t newlen=0;
+
+ oldp = req->oldptr;
+ oldlenp = &(req->oldlen);
+ newp = req->newptr;
+ newlen = req->newlen;
+
+ /* We want the current length, and maybe the string itself */
+ if(oldlenp) {
+ /* if we have no thread name yet tell'em we want MAXTHREADNAMESIZE - 1 */
+ size_t currlen = MAXTHREADNAMESIZE - 1;
+
+ if(ut->pth_name)
+ /* use length of current thread name */
+ currlen = strlen(ut->pth_name);
+ if(oldp) {
+ if(*oldlenp < currlen)
+ return ENOMEM;
+ /* NOTE - we do not copy the NULL terminator */
+ if(ut->pth_name) {
+ error = copyout(ut->pth_name,oldp,currlen);
+ if(error)
+ return error;
+ }
+ }
+ /* return length of thread name minus NULL terminator (just like strlen) */
+ req->oldidx = currlen;
+ }
+
+ /* We want to set the name to something */
+ if(newp)
+ {
+ if(newlen > (MAXTHREADNAMESIZE - 1))
+ return ENAMETOOLONG;
+ if(!ut->pth_name)
+ {
+ ut->pth_name = (char*)kalloc( MAXTHREADNAMESIZE );
+ if(!ut->pth_name)
+ return ENOMEM;
+ }
+ bzero(ut->pth_name, MAXTHREADNAMESIZE);
+ error = copyin(newp, ut->pth_name, newlen);
+ if(error)
+ return error;
+ }
+
+ return 0;
+}
+
+SYSCTL_PROC(_kern, KERN_THREADNAME, threadname, CTLFLAG_ANYBODY | CTLTYPE_STRING | CTLFLAG_RW, 0, 0, sysctl_handle_kern_threadname,"A","");
+