| 1092 | } |
| 1093 | |
| 1094 | static void |
| 1095 | destroy_devl(struct cdev *dev) |
| 1096 | { |
| 1097 | struct cdevsw *csw; |
| 1098 | struct cdev_privdata *p; |
| 1099 | struct cdev_priv *cdp; |
| 1100 | |
| 1101 | dev_lock_assert_locked(); |
| 1102 | KASSERT(dev->si_flags & SI_NAMED, |
| 1103 | ("WARNING: Driver mistake: destroy_dev on %d\n", dev2unit(dev))); |
| 1104 | KASSERT((dev->si_flags & SI_ETERNAL) == 0, |
| 1105 | ("WARNING: Driver mistake: destroy_dev on eternal %d\n", |
| 1106 | dev2unit(dev))); |
| 1107 | |
| 1108 | cdp = cdev2priv(dev); |
| 1109 | if ((cdp->cdp_flags & CDP_UNREF_DTR) == 0) { |
| 1110 | /* |
| 1111 | * Avoid race with dev_rel(), e.g. from the populate |
| 1112 | * loop. If CDP_UNREF_DTR flag is set, the reference |
| 1113 | * to be dropped at the end of destroy_devl() was |
| 1114 | * already taken by delist_dev_locked(). |
| 1115 | */ |
| 1116 | dev_refl(dev); |
| 1117 | |
| 1118 | devfs_destroy(dev); |
| 1119 | } |
| 1120 | |
| 1121 | /* Remove name marking */ |
| 1122 | dev->si_flags &= ~SI_NAMED; |
| 1123 | |
| 1124 | /* If we are a child, remove us from the parents list */ |
| 1125 | if (dev->si_flags & SI_CHILD) { |
| 1126 | LIST_REMOVE(dev, si_siblings); |
| 1127 | dev->si_flags &= ~SI_CHILD; |
| 1128 | } |
| 1129 | |
| 1130 | /* Kill our children */ |
| 1131 | while (!LIST_EMPTY(&dev->si_children)) |
| 1132 | destroy_devl(LIST_FIRST(&dev->si_children)); |
| 1133 | |
| 1134 | /* Remove from clone list */ |
| 1135 | if (dev->si_flags & SI_CLONELIST) { |
| 1136 | LIST_REMOVE(dev, si_clone); |
| 1137 | dev->si_flags &= ~SI_CLONELIST; |
| 1138 | } |
| 1139 | |
| 1140 | mtx_lock(&cdp->cdp_threadlock); |
| 1141 | csw = dev->si_devsw; |
| 1142 | dev->si_devsw = NULL; /* already NULL for SI_ALIAS */ |
| 1143 | while (csw != NULL && csw->d_purge != NULL && dev->si_threadcount) { |
| 1144 | csw->d_purge(dev); |
| 1145 | mtx_unlock(&cdp->cdp_threadlock); |
| 1146 | msleep(csw, &devmtx, PRIBIO, "devprg", hz/10); |
| 1147 | mtx_lock(&cdp->cdp_threadlock); |
| 1148 | if (dev->si_threadcount) |
| 1149 | printf("Still %lu threads in %s\n", |
| 1150 | dev->si_threadcount, devtoname(dev)); |
| 1151 | } |
no test coverage detected