From 3dab450860a416318f4975a44933d133725c58bb Mon Sep 17 00:00:00 2001 From: phk Date: Wed, 17 Nov 2004 07:39:58 +0000 Subject: [PATCH] Split the FILEDESC_LOCK in two variants. FILEDESC_LOCK_FAST will just grab the interlocking mutex and hold it. This should be used for simple modifications of a field. FILEDESC_LOCK holds a (homegrown) sleepable lock which should be used where sleeping is required. The homegrown lock will probably be replaced with a generic type of lock once we have found out how that should look. Help and reviews by: rwatson --- sys/sys/filedesc.h | 65 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index d3cb5e2939a8..fe606e31e47f 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -60,12 +61,13 @@ struct filedesc { u_short fd_refcnt; /* reference count */ struct mtx fd_mtx; /* protects members of this struct */ + int fd_locked; /* long lock flag */ + int fd_wanted; /* "" */ struct kqlist fd_kqlist; /* list of kqueues on this filedesc */ int fd_holdleaderscount; /* block fdfree() for shared close() */ int fd_holdleaderswakeup; /* fdfree() needs wakeup */ }; - /* * Structure to keep track of (process leader, struct fildedesc) tuples. * Each process has a pointer to such a structure when detailed tracking @@ -93,14 +95,61 @@ struct filedesc_to_leader { #ifdef _KERNEL /* Lock a file descriptor table. */ -#define FILEDESC_LOCK(fd) mtx_lock(&(fd)->fd_mtx) -#define FILEDESC_UNLOCK(fd) mtx_unlock(&(fd)->fd_mtx) -#define FILEDESC_LOCKED(fd) mtx_owned(&(fd)->fd_mtx) -#define FILEDESC_LOCK_ASSERT(fd, type) mtx_assert(&(fd)->fd_mtx, (type)) -#define FILEDESC_LOCK_DESC "filedesc structure" +#define FILEDESC_LOCK(fd) \ + do { \ + mtx_lock(&(fd)->fd_mtx); \ + (fd)->fd_wanted++; \ + while ((fd)->fd_locked) \ + msleep(&(fd)->fd_locked, &(fd)->fd_mtx, PLOCK, "fdesc", 0); \ + (fd)->fd_locked = 2; \ + (fd)->fd_wanted--; \ + mtx_unlock(&(fd)->fd_mtx); \ + } while (0); -#define FILEDESC_LOCK_FAST(fd) FILEDESC_LOCK(fd); -#define FILEDESC_UNLOCK_FAST(fd) FILEDESC_UNLOCK(fd); +#define FILEDESC_UNLOCK(fd) \ + do { \ + mtx_lock(&(fd)->fd_mtx); \ + KASSERT((fd)->fd_locked == 2, \ + ("fdesc locking mistake %d should be %d", (fd)->fd_locked, 2)); \ + (fd)->fd_locked = 0; \ + if ((fd)->fd_wanted) \ + wakeup(&(fd)->fd_locked); \ + mtx_unlock(&(fd)->fd_mtx); \ + } while (0); + +#define FILEDESC_LOCK_FAST(fd) \ + do { \ + mtx_lock(&(fd)->fd_mtx); \ + (fd)->fd_wanted++; \ + while ((fd)->fd_locked) \ + msleep(&(fd)->fd_locked, &(fd)->fd_mtx, PLOCK, "fdesc", 0); \ + (fd)->fd_locked = 1; \ + (fd)->fd_wanted--; \ + } while (0); + +#define FILEDESC_UNLOCK_FAST(fd) \ + do { \ + KASSERT((fd)->fd_locked == 1, \ + ("fdesc locking mistake %d should be %d", (fd)->fd_locked, 1)); \ + (fd)->fd_locked = 0; \ + if ((fd)->fd_wanted) \ + wakeup(&(fd)->fd_locked); \ + mtx_unlock(&(fd)->fd_mtx); \ + } while (0); + +#ifdef INVARIANT_SUPPORT +#define FILEDESC_LOCK_ASSERT(fd, arg) \ + do { \ + if ((arg) == MA_OWNED) \ + KASSERT((fd)->fd_locked != 0, ("fdesc locking mistake")); \ + else \ + KASSERT((fd)->fd_locked == 0, ("fdesc locking mistake")); \ + } while (0); +#else +#define FILEDESC_LOCK_ASSERT(fd, arg) +#endif + +#define FILEDESC_LOCK_DESC "filedesc structure" struct thread;