#include <mach/mach_types.h>
#include <mach/vm_prot.h>
#include <vm/vm_kern.h>
+#include <sys/stat.h>
#include <vm/vm_map.h>
#include <sys/systm.h>
+#include <kern/assert.h>
#include <sys/conf.h>
#include <sys/proc_internal.h>
#include <sys/buf.h> /* for SET */
/* XXX most of these just exist to export; there's no good header for them*/
void pcb_synch(void);
-void tbeproc(void *);
+TAILQ_HEAD(,devsw_lock) devsw_locks;
+lck_mtx_t devsw_lock_list_mtx;
+lck_grp_t *devsw_lock_grp;
/* Just to satisfy pstat command */
int dmmin, dmmax, dmtext;
* else see whether the index is free
* return the major number that is free else -1
*
+ * if index is negative, we start
+ * looking for a free slot at the absolute value of index,
+ * instead of starting at 0
*/
int
bdevsw_isfree(int index)
{
struct bdevsw *devsw;
- if (index == -1) {
- devsw = bdevsw;
- for(index=0; index < nblkdev; index++, devsw++) {
- if(memcmp((char *)devsw,
- (char *)&nobdev,
- sizeof(struct bdevsw)) == 0)
- break;
+
+ if (index < 0) {
+ if (index == -1)
+ index = 1; /* start at 1 to avoid collision with volfs (Radar 2842228) */
+ else
+ index = -index; /* start at least this far up in the table */
+ devsw = &bdevsw[index];
+ for(; index < nblkdev; index++, devsw++) {
+ if(memcmp((char *)devsw,
+ (char *)&nobdev,
+ sizeof(struct bdevsw)) == 0)
+ break;
}
- } else {
- /* NB: Not used below unless index is in range */
- devsw = &bdevsw[index];
}
-
+ devsw = &bdevsw[index];
if ((index < 0) || (index >= nblkdev) ||
(memcmp((char *)devsw,
(char *)&nobdev,
* if index is -1, find a free slot to add
* else see whether the slot is free
* return the major number that is used else -1
+ *
+ * if index is negative, we start
+ * looking for a free slot at the absolute value of index,
+ * instead of starting at 0
*/
int
bdevsw_add(int index, struct bdevsw * bsw)
{
- struct bdevsw *devsw;
-
- if (index == -1) {
- devsw = &bdevsw[1]; /* Start at slot 1 - this is a hack to fix the index=1 hack */
- /* yes, start at 1 to avoid collision with volfs (Radar 2842228) */
- for(index=1; index < nblkdev; index++, devsw++) {
- if(memcmp((char *)devsw,
- (char *)&nobdev,
- sizeof(struct bdevsw)) == 0)
- break;
- }
- }
- devsw = &bdevsw[index];
- if ((index < 0) || (index >= nblkdev) ||
- (memcmp((char *)devsw,
- (char *)&nobdev,
- sizeof(struct bdevsw)) != 0)) {
+ index = bdevsw_isfree(index);
+ if (index < 0) {
return(-1);
}
bdevsw[index] = *bsw;
return(index);
}
-/*
+/*
* if the slot has the same bsw, then remove
* else -1
*/
* if index is -1, return a free slot if avaliable
* else see whether the index is free
* return the major number that is free else -1
+ *
+ * if index is negative, we start
+ * looking for a free slot at the absolute value of index,
+ * instead of starting at 0
*/
int
cdevsw_isfree(int index)
{
struct cdevsw *devsw;
- if (index == -1) {
- devsw = cdevsw;
- for(index=0; index < nchrdev; index++, devsw++) {
- if(memcmp((char *)devsw,
- (char *)&nocdev,
- sizeof(struct cdevsw)) == 0)
- break;
+ if (index < 0) {
+ if (index == -1)
+ index = 0;
+ else
+ index = -index; /* start at least this far up in the table */
+ devsw = &cdevsw[index];
+ for(; index < nchrdev; index++, devsw++) {
+ if(memcmp((char *)devsw,
+ (char *)&nocdev,
+ sizeof(struct cdevsw)) == 0)
+ break;
}
}
devsw = &cdevsw[index];
* else see whether the slot is free
* return the major number that is used else -1
*
+ * if index is negative, we start
+ * looking for a free slot at the absolute value of index,
+ * instead of starting at 0
+ *
* NOTE: In practice, -1 is unusable, since there are kernel internal
* devices that call this function with absolute index values,
* which will stomp on free-slot based assignments that happen
- * before them. Therefore, if index is negative, we start
- * looking for a free slot at the absolute value of index,
- * instead of starting at 0 (lets out slot 1, but that's one
- * of the problem slots down low - the vndevice). -12 is
- * currently a safe starting point.
+ * before them. -24 is currently a safe starting point.
*/
int
cdevsw_add(int index, struct cdevsw * csw)
{
- struct cdevsw *devsw;
-
+ index = cdevsw_isfree(index);
if (index < 0) {
- if (index == -1)
- index = 0; /* historical behaviour; XXX broken */
- else
- index = -index; /* start at least this far up in the table */
- devsw = &cdevsw[index];
- for(; index < nchrdev; index++, devsw++) {
- if(memcmp((char *)devsw,
- (char *)&nocdev,
- sizeof(struct cdevsw)) == 0)
- break;
- }
- }
- devsw = &cdevsw[index];
- if ((index < 0) || (index >= nchrdev) ||
- (memcmp((char *)devsw,
- (char *)&nocdev,
- sizeof(struct cdevsw)) != 0)) {
return(-1);
}
cdevsw[index] = *csw;
return(index);
}
/*
- * if the index has the same bsw, then remove
+ * if the slot has the same csw, then remove
* else -1
*/
int
return(-1);
}
cdevsw[index] = nocdev;
+ cdevsw_flags[index] = 0;
return(index);
}
return (index);
}
-#include <pexpert/pexpert.h> /* for PE_parse_boot_arg */
-
-void
-tbeproc(void *procp)
+int
+cdevsw_setkqueueok(int index, struct cdevsw *csw, int use_offset)
{
- struct proc *p = procp;
+ struct cdevsw *devsw;
+ uint64_t flags = CDEVSW_SELECT_KQUEUE;
- if (p)
- OSBitOrAtomic(P_TBE, &p->p_flag);
- return;
+ devsw = &cdevsw[index];
+ if ((index < 0) || (index >= nchrdev) ||
+ (memcmp((char *)devsw,
+ (char *)csw,
+ sizeof(struct cdevsw)) != 0)) {
+ return(-1);
+ }
+
+ if (use_offset) {
+ flags |= CDEVSW_USE_OFFSET;
+ }
+
+ cdevsw_flags[index] = flags;
+ return 0;
}
+#include <pexpert/pexpert.h> /* for PE_parse_boot_arg */
+
/*
* Copy the "hostname" variable into a caller-provided buffer
* Returns: 0 for success, ENAMETOOLONG for insufficient buffer space.
}
}
+void
+devsw_lock(dev_t dev, int mode)
+{
+ devsw_lock_t newlock, tmplock;
+ int res;
+
+ assert(0 <= major(dev) && major(dev) < nchrdev);
+ assert(mode == S_IFCHR || mode == S_IFBLK);
+
+ MALLOC(newlock, devsw_lock_t, sizeof(struct devsw_lock), M_TEMP, M_WAITOK | M_ZERO);
+ newlock->dl_dev = dev;
+ newlock->dl_thread = current_thread();
+ newlock->dl_mode = mode;
+
+ lck_mtx_lock_spin(&devsw_lock_list_mtx);
+retry:
+ TAILQ_FOREACH(tmplock, &devsw_locks, dl_list) {
+ if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
+ res = msleep(tmplock, &devsw_lock_list_mtx, PVFS, "devsw_lock", NULL);
+ assert(res == 0);
+ goto retry;
+ }
+ }
+
+ TAILQ_INSERT_TAIL(&devsw_locks, newlock, dl_list);
+ lck_mtx_unlock(&devsw_lock_list_mtx);
+
+}
+void
+devsw_unlock(dev_t dev, int mode)
+{
+ devsw_lock_t tmplock;
+
+ assert(0 <= major(dev) && major(dev) < nchrdev);
+
+ lck_mtx_lock_spin(&devsw_lock_list_mtx);
+
+ TAILQ_FOREACH(tmplock, &devsw_locks, dl_list) {
+ if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
+ break;
+ }
+ }
+
+ if (tmplock == NULL) {
+ panic("Trying to unlock, and couldn't find lock.");
+ }
+
+ if (tmplock->dl_thread != current_thread()) {
+ panic("Trying to unlock, but I don't hold the lock.");
+ }
+
+ wakeup(tmplock);
+ TAILQ_REMOVE(&devsw_locks, tmplock, dl_list);
+
+ lck_mtx_unlock(&devsw_lock_list_mtx);
+
+ FREE(tmplock, M_TEMP);
+}
+
+void
+devsw_init()
+{
+ devsw_lock_grp = lck_grp_alloc_init("devsw", NULL);
+ assert(devsw_lock_grp != NULL);
+
+ lck_mtx_init(&devsw_lock_list_mtx, devsw_lock_grp, NULL);
+ TAILQ_INIT(&devsw_locks);
+}