Add cdevsw->d_purge() support.

This device method shall wake up any threads sleeping in the device driver
and make the depart the drivers code for good.
This commit is contained in:
Poul-Henning Kamp 2004-09-27 06:18:25 +00:00
parent c7f4c39534
commit 743cd76a73
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=135843
2 changed files with 21 additions and 11 deletions

View File

@ -551,11 +551,11 @@ make_dev_alias(struct cdev *pdev, const char *fmt, ...)
static void
idestroy_dev(struct cdev *dev)
{
if (!(dev->si_flags & SI_NAMED)) {
printf( "WARNING: Driver mistake: destroy_dev on %d/%d\n",
major(dev), minor(dev));
panic("don't do that");
}
struct cdevsw *csw;
KASSERT(dev->si_flags & SI_NAMED,
("WARNING: Driver mistake: destroy_dev on %d/%d\n",
major(dev), minor(dev)));
devfs_destroy(dev);
@ -578,6 +578,19 @@ idestroy_dev(struct cdev *dev)
dev->si_flags &= ~SI_CLONELIST;
}
csw = dev->si_devsw;
dev->si_devsw = NULL;
while (csw->d_purge != NULL && dev->si_threadcount) {
printf("Purging %lu threads from %s\n",
dev->si_threadcount, devtoname(dev));
csw->d_purge(dev);
msleep(csw, &devmtx, PRIBIO, "devprg", hz/10);
}
dev->si_drv1 = 0;
dev->si_drv2 = 0;
bzero(&dev->__si_u, sizeof(dev->__si_u));
if (!(dev->si_flags & SI_ALIAS)) {
/* Remove from cdevsw list */
LIST_REMOVE(dev, si_list);
@ -588,11 +601,8 @@ idestroy_dev(struct cdev *dev)
LIST_REMOVE(dev, si_hash);
}
dev->si_drv1 = 0;
dev->si_drv2 = 0;
dev->si_devsw = NULL;
bzero(&dev->__si_u, sizeof(dev->__si_u));
dev->si_flags &= ~SI_ALIAS;
if (dev->si_refcount > 0) {
LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list);
} else {

View File

@ -149,8 +149,8 @@ typedef int d_poll_t(struct cdev *dev, int events, struct thread *td);
typedef int d_kqfilter_t(struct cdev *dev, struct knote *kn);
typedef int d_mmap_t(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr,
int nprot);
typedef void d_purge_t(struct cdev *dev);
typedef int d_spare1_t(struct cdev *dev);
typedef int d_spare2_t(struct cdev *dev);
typedef int dumper_t(
@ -214,7 +214,7 @@ struct cdevsw {
d_strategy_t *d_strategy;
dumper_t *d_dump;
d_kqfilter_t *d_kqfilter;
d_spare1_t *d_spare1;
d_purge_t *d_purge;
d_spare2_t *d_spare2;
/* These fields should not be messed with by drivers */