aboutsummaryrefslogtreecommitdiff
path: root/sys/sys
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2021-01-28 23:27:44 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2021-01-29 11:23:43 +0000
commiteaad8d1303da500ed691bd774742a4555a05e729 (patch)
tree216991c09e5d80b94c432ceefdabed26eb9dfa1b /sys/sys
parentabd619045a54c73f41a95b3e038a5ba083391400 (diff)
downloadsrc-eaad8d1303da500ed691bd774742a4555a05e729.tar.gz
src-eaad8d1303da500ed691bd774742a4555a05e729.zip
fd: add fget_only_user
This can be used by single-threaded processes which don't share a file descriptor table to access their file objects without having to reference them. For example select consumers tend to match the requirement and have several file descriptors to inspect.
Diffstat (limited to 'sys/sys')
-rw-r--r--sys/sys/filedesc.h12
1 files changed, 12 insertions, 0 deletions
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 9b65c7a66054..890232b7f160 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -177,6 +177,11 @@ struct filedesc_to_leader {
SX_NOTRECURSED)
#define FILEDESC_UNLOCK_ASSERT(fdp) sx_assert(&(fdp)->fd_sx, SX_UNLOCKED)
+#define FILEDESC_IS_ONLY_USER(fdp) ({ \
+ struct filedesc *_fdp = (fdp); \
+ MPASS(curproc->p_fd == _fdp); \
+ (curproc->p_numthreads == 1 && refcount_load(&_fdp->fd_refcnt) == 1); \
+})
#else
/*
@@ -272,6 +277,13 @@ int fget_unlocked_seq(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
struct file **fpp, seqc_t *seqp);
int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
struct file **fpp);
+/* Return a file pointer without a ref. FILEDESC_IS_ONLY_USER must be true. */
+int fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
+ struct file **fpp);
+#define fput_only_user(fdp, fp) ({ \
+ MPASS(FILEDESC_IS_ONLY_USER(fdp)); \
+ MPASS(refcount_load(&fp->f_count) > 0); \
+})
/* Requires a FILEDESC_{S,X}LOCK held and returns without a ref. */
static __inline struct file *