--- /usr/src/sys/kern/kern_descrip.c	Mon Mar 19 01:22:08 2007
+++ kern_descrip.c	Mon Mar 26 18:12:42 2007
@@ -59,6 +59,7 @@
 #include <sys/namei.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
+#include <sys/refcount.h>
 #include <sys/resourcevar.h>
 #include <sys/signalvar.h>
 #include <sys/socketvar.h>
@@ -140,9 +141,6 @@
 struct mtx sigio_lock;		/* mtx to protect pointers to sigio */
 void	(*mq_fdclose)(struct thread *td, int fd, struct file *fp);
 
-/* A mutex to protect the association between a proc and filedesc. */
-static struct mtx	fdesc_mtx;
-
 /*
  * Find the first zero bit in the given bitmap, starting at low and not
  * exceeding size - 1.
@@ -1399,8 +1397,8 @@
 	}
 
 	/* Create the file descriptor table. */
-	newfdp->fd_fd.fd_refcnt = 1;
-	newfdp->fd_fd.fd_holdcnt = 1;
+	refcount_init(&newfdp->fd_fd.fd_refcnt, 1);
+	refcount_init(&newfdp->fd_fd.fd_holdcnt, 1);
 	newfdp->fd_fd.fd_cmask = CMASK;
 	newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
 	newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
@@ -1415,25 +1413,18 @@
 {
 	struct filedesc *fdp;
 
-	mtx_lock(&fdesc_mtx);
 	fdp = p->p_fd;
 	if (fdp != NULL)
-		fdp->fd_holdcnt++;
-	mtx_unlock(&fdesc_mtx);
+		refcount_acquire(&fdp->fd_holdcnt);
 	return (fdp);
 }
 
 static void
 fddrop(struct filedesc *fdp)
 {
-	int i;
 
-	mtx_lock(&fdesc_mtx);
-	i = --fdp->fd_holdcnt;
-	mtx_unlock(&fdesc_mtx);
-	if (i > 0)
+	if (!refcount_release(&fdp->fd_holdnct))
 		return;
-
 	mtx_destroy(&fdp->fd_mtx);
 	FREE(fdp, M_FILEDESC);
 }
@@ -1444,9 +1435,8 @@
 struct filedesc *
 fdshare(struct filedesc *fdp)
 {
-	FILEDESC_LOCK_FAST(fdp);
-	fdp->fd_refcnt++;
-	FILEDESC_UNLOCK_FAST(fdp);
+
+	refcount_acquire(&fdp->fd_refcnt);
 	return (fdp);
 }
 
@@ -1457,16 +1447,13 @@
 fdunshare(struct proc *p, struct thread *td)
 {
 
-	FILEDESC_LOCK_FAST(p->p_fd);
-	if (p->p_fd->fd_refcnt > 1) {
+	if (refcount_value(&p->p_fd->fd_refcnt) > 1) {
 		struct filedesc *tmp;
 
-		FILEDESC_UNLOCK_FAST(p->p_fd);
 		tmp = fdcopy(p->p_fd);
 		fdfree(td);
 		p->p_fd = tmp;
-	} else
-		FILEDESC_UNLOCK_FAST(p->p_fd);
+	}
 }
 
 /*
@@ -1612,10 +1599,7 @@
 		if (fdtol != NULL)
 			FREE(fdtol, M_FILEDESC_TO_LEADER);
 	}
-	FILEDESC_LOCK_FAST(fdp);
-	i = --fdp->fd_refcnt;
-	FILEDESC_UNLOCK_FAST(fdp);
-	if (i > 0)
+	if (!refcount_release(&fdp->fd_refcnt))
 		return;
 	/*
 	 * We are the last reference to the structure, so we can
@@ -1628,10 +1612,7 @@
 	}
 	FILEDESC_LOCK(fdp);
 
-	/* XXX This should happen earlier. */
-	mtx_lock(&fdesc_mtx);
 	td->td_proc->p_fd = NULL;
-	mtx_unlock(&fdesc_mtx);
 
 	if (fdp->fd_nfiles > NDFILE)
 		FREE(fdp->fd_ofiles, M_FILEDESC);
@@ -1817,7 +1798,8 @@
 	fdp = td->td_proc->p_fd;
 	if (fdp == NULL)
 		return (0);
-	KASSERT(fdp->fd_refcnt == 1, ("the fdtable should not be shared"));
+	KASSERT(refcount_value(&fdp->fd_refcnt) == 1,
+	    ("the fdtable should not be shared"));
 	devnull = -1;
 	error = 0;
 	for (i = 0; i < 3; i++) {
@@ -2460,7 +2442,8 @@
 		if (fdp == NULL)
 			continue;
 		FILEDESC_LOCK_FAST(fdp);
-		for (n = 0; fdp->fd_refcnt > 0 && n < fdp->fd_nfiles; ++n) {
+		for (n = 0; refcount_value(&fdp->fd_refcnt) &&
+		    n < fdp->fd_nfiles; ++n) {
 			if ((fp = fdp->fd_ofiles[n]) == NULL)
 				continue;
 			xf.xf_fd = n;
@@ -2604,7 +2587,6 @@
 	    NULL, NULL, UMA_ALIGN_PTR, 0);
 	sx_init(&filelist_lock, "filelist lock");
 	mtx_init(&sigio_lock, "sigio lock", NULL, MTX_DEF);
-	mtx_init(&fdesc_mtx, "fdesc", NULL, MTX_DEF);
 }
 SYSINIT(select, SI_SUB_LOCK, SI_ORDER_FIRST, filelistinit, NULL)
 
--- /usr/src/sys/sys/filedesc.h	Wed Oct  4 07:24:42 2006
+++ filedesc.h	Mon Mar 26 09:01:17 2007
@@ -58,8 +58,8 @@
 	int	fd_lastfile;		/* high-water mark of fd_ofiles */
 	int	fd_freefile;		/* approx. next free file */
 	u_short	fd_cmask;		/* mask for file creation */
-	u_short	fd_refcnt;		/* thread reference count */
-	u_short	fd_holdcnt;		/* hold count on structure + mutex */
+	u_int	fd_refcnt;		/* thread reference count */
+	u_int	fd_holdcnt;		/* hold count on structure */
 
 	struct	mtx fd_mtx;		/* protects members of this struct */
 	int	fd_locked;		/* long lock flag */
--- /usr/src/sys/sys/refcount.h	Wed Oct  4 07:24:43 2006
+++ refcount.h	Mon Mar 26 08:55:43 2007
@@ -56,4 +56,11 @@
 	return (atomic_fetchadd_int(count, -1) == 1);
 }
 
+static __inline u_int
+refcount_value(volatile u_int *count)
+{
+
+	return (*count);
+}
+
 #endif	/* ! __SYS_REFCOUNT_H__ */
