DEV_REFTHREAD(9)

πŸ“¦
version 15.1 Β· 2 versions
, in freebsd 15.1

okay bestie, welcome to DEV_REFTHREAD(9) β€” your Kernel Developer's Manual page about not getting owned by a device that yeets itself out of existence while you're still talking to it. it's giving safe device access realness, and the whole trio is dev_refthread, devvn_refthread, and dev_relthread. πŸ’…

🌸 NAME 🌸

dev_refthread, devvn_refthread, dev_relthread β€” safely access device methods. that's the whole vibe: these are the functions that help you touch devices safely. periodt.

✨ SYNOPSIS ✨

the signature lineup, exactly as printed, no edits:

#include <sys/param.h>
#include <sys/conf.h>

struct cdevsw *
dev_refthread(struct cdev *dev, int *ref);

struct cdevsw *
devvn_refthread(struct vnode *vp, struct cdev **devp, int *ref);

void
dev_relthread(struct cdev *dev, int ref);

πŸ’– DESCRIPTION πŸ’–

okay so dev_refthread() β€” or its sibling devvn_refthread() β€” plus dev_relthread() are the routines that give you a safe way to access devfs(4) devices that might get concurrently destroyed by destroy_dev() (e.g., removable media). iconic behavior, honestly.

if successful, dev_refthread() and devvn_refthread() acquire a "thread reference" to the associated struct cdev and return a non-NULL pointer to the cdev's struct cdevsw method table. for the duration of that reference, the cdev's associated private data and method table object are valid. destruction of the cdev sleeps until the thread reference is released. no cap, it literally waits.

a reference cannot prevent media removal. it is an implementation detail of individual drivers how method calls from callers with dev_refthread() references are handled when the device is pending destruction. a common behavior for disk devices is to return the ENXIO status, but that is not required by this KPI.

the devvn_refthread() variant of dev_refthread() extracts the struct cdev pointer out of the VCHR vnode(9) automatically before performing the same actions as dev_refthread(). additionally, a pointer to the struct cdev is returned to the caller via *devp. and devvn_refthread() correctly handles possible parallel reclamation of the vnode. she's careful like that πŸ¦‹

dev_relthread() is used to release a reference to a struct cdev. dev_relthread() must only be invoked when the associated invocation of dev_refthread() or devvn_refthread() returned a non-NULL struct cdevsw *. do not freestyle this one, bestie.

🧚 CONTEXT 🧚

struct cdev objects have two reference counts: si_refcount and si_threadcount. the dev_refthread(), devvn_refthread(), and dev_relthread() functions manipulate the si_threadcount.

the si_threadcount reference guarantees the liveness of the struct cdev object. the other si_refcount reference provides only the weaker guarantee that the memory backing the struct cdev has not been freed. it's giving strong guarantee vs. weaker guarantee, iykyk.

🌈 RETURN VALUES 🌈

if dev_refthread() or devvn_refthread() are unsuccessful, they return NULL.

if these routines are unsuccessful, they do not increment the struct cdev si_threadcount and do not initialize the value pointed to by the *ref parameter in any way. so yeah, don't assume *ref got touched 😭

πŸ¦‹ SEE ALSO πŸ¦‹

go read these too, bestie:

πŸ’… CAVEATS πŸ’…

do not invoke dev_relthread() unless the matching refthread routine succeeded! for real, this is the caveat πŸ’€

xoxo, Debian, August 29, 2018 β€” signing off from DEV_REFTHREAD(9) πŸ’–πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from
  • freebsd 15.1: base 15.1
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms