Exemplo n.º 1
0
/*
 * prop_object_release_emergency
 *	A direct free with prop_object_release failed.
 *	Walk down the tree until a leaf is found and
 *	free that. Do not recurse to avoid stack overflows.
 *
 *	This is a slow edge condition, but necessary to
 *	guarantee that an object can always be freed.
 */
static void
prop_object_release_emergency(prop_object_t obj)
{
	struct _prop_object *po;
	prop_object_t parent = NULL;
	uint32_t ocnt;

	for (;;) {
		po = obj;
		_PROP_ASSERT(obj);

		_PROP_REFCNT_LOCK();
    		ocnt = po->po_refcnt--;
		_PROP_REFCNT_UNLOCK();

		_PROP_ASSERT(ocnt != 0);
		if (ocnt != 1)
			break;

		_PROP_ASSERT(po->po_type);		
		if ((po->po_type->pot_free)(NULL, &obj) ==
						_PROP_OBJECT_FREE_DONE)
			break;

		parent = po;
		_PROP_REFCNT_LOCK();
		++po->po_refcnt;
		_PROP_REFCNT_UNLOCK();
	}
	_PROP_ASSERT(parent);
	/* One object was just freed. */
	po = parent;
	(*po->po_type->pot_emergency_free)(parent);
}
Exemplo n.º 2
0
/*
 * prop_object_release --
 *	Decrement the reference count on an object.
 *
 *	Free the object if we are releasing the final
 *	reference.
 */
void
prop_object_release(prop_object_t obj)
{
	struct _prop_object *po;
	struct _prop_stack stack;
	void (*unlock)(void); 
	int ret;
	uint32_t ocnt;

	_prop_stack_init(&stack);

	do {
		do {
			po = obj;
			_PROP_ASSERT(obj);

			if (po->po_type->pot_lock != NULL)
				po->po_type->pot_lock();

			/* Save pointer to object unlock function */
			unlock = po->po_type->pot_unlock;
			
			_PROP_REFCNT_LOCK();
			ocnt = po->po_refcnt--;
			_PROP_REFCNT_UNLOCK();

			_PROP_ASSERT(ocnt != 0);
			if (ocnt != 1) {
				ret = 0;
				if (unlock != NULL)
					unlock();
				break;
			}
			
			ret = (po->po_type->pot_free)(&stack, &obj);

			if (unlock != NULL)
				unlock();

			if (ret == _PROP_OBJECT_FREE_DONE)
				break;
			
			_PROP_REFCNT_LOCK();
			++po->po_refcnt;
			_PROP_REFCNT_UNLOCK();
		} while (ret == _PROP_OBJECT_FREE_RECURSE);
		if (ret == _PROP_OBJECT_FREE_FAILED)
			prop_object_release_emergency(obj);
	} while (_prop_stack_pop(&stack, &obj, NULL, NULL, NULL));
}
Exemplo n.º 3
0
/*
 * prop_object_release_emergency
 *	A direct free with prop_object_release failed.
 *	Walk down the tree until a leaf is found and
 *	free that. Do not recurse to avoid stack overflows.
 *
 *	This is a slow edge condition, but necessary to
 *	guarantee that an object can always be freed.
 */
static void
prop_object_release_emergency(prop_object_t obj)
{
	struct _prop_object *po;
	void (*unlock)(void);
	prop_object_t parent = NULL;
	uint32_t ocnt;

	for (;;) {
		po = obj;
		_PROP_ASSERT(obj);

		if (po->po_type->pot_lock != NULL)
		po->po_type->pot_lock();

		/* Save pointerto unlock function */
		unlock = po->po_type->pot_unlock;
		
		_PROP_REFCNT_LOCK();
    		ocnt = po->po_refcnt--;
		_PROP_REFCNT_UNLOCK();

		_PROP_ASSERT(ocnt != 0);
		if (ocnt != 1) {
			if (unlock != NULL)
				unlock();
			break;
		}
		
		_PROP_ASSERT(po->po_type);		
		if ((po->po_type->pot_free)(NULL, &obj) ==
		    _PROP_OBJECT_FREE_DONE) {
			if (unlock != NULL)
				unlock();
			break;
		}

		if (unlock != NULL)
			unlock();
		
		parent = po;
		_PROP_REFCNT_LOCK();
		++po->po_refcnt;
		_PROP_REFCNT_UNLOCK();
	}
	_PROP_ASSERT(parent);
	/* One object was just freed. */
	po = parent;
	(*po->po_type->pot_emergency_free)(parent);
}
Exemplo n.º 4
0
/*
 * prop_object_retain --
 *	Increment the reference count on an object.
 */
void
prop_object_retain(prop_object_t obj)
{
	struct _prop_object *po = obj;
	uint32_t ocnt;

	_PROP_REFCNT_LOCK();
	ocnt = po->po_refcnt++;
	_PROP_REFCNT_UNLOCK();

	_PROP_ASSERT(ocnt != 0xffffffffU);
}