Beispiel #1
0
static int
kobj_class_compile1(kobj_class_t cls, int mflags)
{
	kobj_ops_t ops;

	KOBJ_ASSERT(MA_NOTOWNED);

	ops = malloc(sizeof(struct kobj_ops), M_KOBJ, mflags);
	if (ops == NULL)
		return (ENOMEM);

	/*
	 * We may have lost a race for kobj_class_compile here - check
	 * to make sure someone else hasn't already compiled this
	 * class.
	 */
	KOBJ_LOCK();
	if (cls->ops) {
		KOBJ_UNLOCK();
		free(ops, M_KOBJ);
		return (0);
	}
	kobj_class_compile_common(cls, ops);
	KOBJ_UNLOCK();
	return (0);
}
Beispiel #2
0
void
kobj_init(kobj_t obj, kobj_class_t cls)
{
	KOBJ_ASSERT(MA_NOTOWNED);
  retry:
	KOBJ_LOCK();

	/*
	 * Consider compiling the class' method table.
	 */
	if (!cls->ops) {
		/*
		 * kobj_class_compile doesn't want the lock held
		 * because of the call to malloc - we drop the lock
		 * and re-try.
		 */
		KOBJ_UNLOCK();
		kobj_class_compile(cls);
		goto retry;
	}

	kobj_init_common(obj, cls);

	KOBJ_UNLOCK();
}
Beispiel #3
0
void
kobj_class_compile(kobj_class_t cls)
{
	kobj_ops_t ops;

	KOBJ_ASSERT(MA_NOTOWNED);

	/*
	 * Allocate space for the compiled ops table.
	 */
	ops = malloc(sizeof(struct kobj_ops), M_KOBJ, M_NOWAIT);
	if (!ops)
		panic("%s: out of memory", __func__);

	KOBJ_LOCK();
	
	/*
	 * We may have lost a race for kobj_class_compile here - check
	 * to make sure someone else hasn't already compiled this
	 * class.
	 */
	if (cls->ops) {
		KOBJ_UNLOCK();
		free(ops, M_KOBJ);
		return;
	}

	kobj_class_compile_common(cls, ops);
	KOBJ_UNLOCK();
}
Beispiel #4
0
void
kobj_class_free(kobj_class_t cls)
{
	void* ops = NULL;

	KOBJ_ASSERT(MA_NOTOWNED);
	KOBJ_LOCK();

	/*
	 * Protect against a race between kobj_create and
	 * kobj_delete.
	 */
	if (cls->refs == 0) {
		/*
		 * For now we don't do anything to unregister any methods
		 * which are no longer used.
		 */

		/*
		 * Free memory and clean up.
		 */
		ops = cls->ops;
		cls->ops = NULL;
	}
	
	KOBJ_UNLOCK();

	if (ops)
		free(ops, M_KOBJ);
}
void
kobj_class_free(kobj_class_t cls)
{
	int i;
	kobj_method_t *m;
	void* ops = NULL;

	KOBJ_ASSERT(MA_NOTOWNED);
	KOBJ_LOCK();

	/*
	 * Protect against a race between kobj_create and
	 * kobj_delete.
	 */
	if (cls->refs == 0) {
		/*
		 * Unregister any methods which are no longer used.
		 */
		for (i = 0, m = cls->methods; m->desc; i++, m++)
			kobj_unregister_method(m->desc);

		/*
		 * Free memory and clean up.
		 */
		ops = cls->ops;
		cls->ops = NULL;
	}
	
	KOBJ_UNLOCK();

	if (ops)
		free(ops, M_KOBJ);
}
Beispiel #6
0
static int
kobj_init1(kobj_t obj, kobj_class_t cls, int mflags)
{
	int error;

	KOBJ_LOCK();
	while (cls->ops == NULL) {
		/*
		 * kobj_class_compile doesn't want the lock held
		 * because of the call to malloc - we drop the lock
		 * and re-try.
		 */
		KOBJ_UNLOCK();
		error = kobj_class_compile1(cls, mflags);
		if (error != 0)
			return (error);
		KOBJ_LOCK();
	}
	kobj_init_common(obj, cls);
	KOBJ_UNLOCK();
	return (0);
}
void
kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops)
{

	KOBJ_ASSERT(MA_NOTOWNED);

	/*
	 * Increment refs to make sure that the ops table is not freed.
	 */
	KOBJ_LOCK();

	cls->refs++;
	kobj_class_compile_common(cls, ops);

	KOBJ_UNLOCK();
}
Beispiel #8
0
void
kobj_delete(kobj_t obj, struct malloc_type *mtype)
{
	kobj_class_t cls = obj->ops->cls;
	int refs;

	/*
	 * Consider freeing the compiled method table for the class
	 * after its last instance is deleted. As an optimisation, we
	 * should defer this for a short while to avoid thrashing.
	 */
	KOBJ_ASSERT(MA_NOTOWNED);
	KOBJ_LOCK();
	cls->refs--;
	refs = cls->refs;
	KOBJ_UNLOCK();

	if (!refs)
		kobj_class_free(cls);

	obj->ops = NULL;
	if (mtype)
		free(obj, mtype);
}