Example #1
0
int
osd_register(u_int type, osd_destructor_t destructor, osd_method_t *methods)
{
	void *newptr;
	u_int i, m;

	KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));

	/*
	 * If no destructor is given, use default one. We need to use some
	 * destructor, because NULL destructor means unused slot.
	 */
	if (destructor == NULL)
		destructor = osd_default_destructor;

	sx_xlock(&osd_module_lock[type]);
	/*
	 * First, we try to find unused slot.
	 */
	for (i = 0; i < osd_nslots[type]; i++) {
		if (osd_destructors[type][i] == NULL) {
			OSD_DEBUG("Unused slot found (type=%u, slot=%u).",
			    type, i);
			break;
		}
	}
	/*
	 * If no unused slot was found, allocate one.
	 */
	if (i == osd_nslots[type]) {
		osd_nslots[type]++;
		if (osd_nmethods[type] != 0)
			osd_methods[type] = realloc(osd_methods[type],
			    sizeof(osd_method_t) * osd_nslots[type] *
			    osd_nmethods[type], M_OSD, M_WAITOK);
		newptr = malloc(sizeof(osd_destructor_t) * osd_nslots[type],
		    M_OSD, M_WAITOK);
		rm_wlock(&osd_object_lock[type]);
		bcopy(osd_destructors[type], newptr,
		    sizeof(osd_destructor_t) * i);
		free(osd_destructors[type], M_OSD);
		osd_destructors[type] = newptr;
		rm_wunlock(&osd_object_lock[type]);
		OSD_DEBUG("New slot allocated (type=%u, slot=%u).",
		    type, i + 1);
	}

	osd_destructors[type][i] = destructor;
	if (osd_nmethods[type] != 0) {
		for (m = 0; m < osd_nmethods[type]; m++)
			osd_methods[type][i * osd_nmethods[type] + m] =
			    methods != NULL ? methods[m] : NULL;
	}
	sx_xunlock(&osd_module_lock[type]);
	return (i + 1);
}
Example #2
0
void
osd_deregister(u_int type, u_int slot)
{
	struct osd *osd, *tosd;

	KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
	KASSERT(slot > 0, ("Invalid slot."));
	KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot."));

	sx_xlock(&osd_module_lock[type]);
	rm_wlock(&osd_object_lock[type]);
	/*
	 * Free all OSD for the given slot.
	 */
	mtx_lock(&osd_list_lock[type]);
	LIST_FOREACH_SAFE(osd, &osd_list[type], osd_next, tosd)
		do_osd_del(type, osd, slot, 1);
	mtx_unlock(&osd_list_lock[type]);
	/*
	 * Set destructor to NULL to free the slot.
	 */
	osd_destructors[type][slot - 1] = NULL;
	if (slot == osd_nslots[type]) {
		osd_nslots[type]--;
		osd_destructors[type] = realloc(osd_destructors[type],
		    sizeof(osd_destructor_t) * osd_nslots[type], M_OSD,
		    M_NOWAIT | M_ZERO);
		if (osd_nmethods[type] != 0)
			osd_methods[type] = realloc(osd_methods[type],
			    sizeof(osd_method_t) * osd_nslots[type] *
			    osd_nmethods[type], M_OSD, M_NOWAIT | M_ZERO);
		/*
		 * We always reallocate to smaller size, so we assume it will
		 * always succeed.
		 */
		KASSERT(osd_destructors[type] != NULL &&
		    (osd_nmethods[type] == 0 || osd_methods[type] != NULL),
		    ("realloc() failed"));
		OSD_DEBUG("Deregistration of the last slot (type=%u, slot=%u).",
		    type, slot);
	} else {
		OSD_DEBUG("Slot deregistration (type=%u, slot=%u).",
		    type, slot);
	}
	rm_wunlock(&osd_object_lock[type]);
	sx_xunlock(&osd_module_lock[type]);
}
Example #3
0
static uintptr_t
unlock_rm(struct lock_object *lock)
{
	struct thread *td;
	struct pcpu *pc;
	struct rmlock *rm;
	struct rm_queue *queue;
	struct rm_priotracker *tracker;
	uintptr_t how;

	rm = (struct rmlock *)lock;
	tracker = NULL;
	how = 0;
	rm_assert(rm, RA_LOCKED | RA_NOTRECURSED);
	if (rm_wowned(rm))
		rm_wunlock(rm);
	else {
		/*
		 * Find the right rm_priotracker structure for curthread.
		 * The guarantee about its uniqueness is given by the fact
		 * we already asserted the lock wasn't recursively acquired.
		 */
		critical_enter();
		td = curthread;
		pc = pcpu_find(curcpu);
		for (queue = pc->pc_rm_queue.rmq_next;
		    queue != &pc->pc_rm_queue; queue = queue->rmq_next) {
			tracker = (struct rm_priotracker *)queue;
				if ((tracker->rmp_rmlock == rm) &&
				    (tracker->rmp_thread == td)) {
					how = (uintptr_t)tracker;
					break;
				}
		}
		KASSERT(tracker != NULL,
		    ("rm_priotracker is non-NULL when lock held in read mode"));
		critical_exit();
		rm_runlock(rm, tracker);
	}
	return (how);
}