mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Merge "named_locks: Use ao2_weakproxy to deal with cleanup from container."
This commit is contained in:
		| @@ -48,7 +48,7 @@ | ||||
|  * To use a named lock: | ||||
|  * 	Call ast_named_lock_get with the appropriate keyspace and key. | ||||
|  * 	Use the standard ao2 lock/unlock functions as needed. | ||||
|  * 	Call ast_named_lock_put when you're finished with it. | ||||
|  * 	Call ao2_cleanup when you're finished with it. | ||||
|  */ | ||||
|  | ||||
| /*! | ||||
| @@ -66,9 +66,6 @@ struct ast_named_lock; | ||||
| struct ast_named_lock *__ast_named_lock_get(const char *filename, int lineno, const char *func, | ||||
| 	enum ast_named_lock_type lock_type, const char *keyspace, const char *key); | ||||
|  | ||||
| int __ast_named_lock_put(const char *filename, int lineno, const char *func, | ||||
| 	struct ast_named_lock *lock); | ||||
|  | ||||
| /*! | ||||
|  * \brief Geta named lock handle | ||||
|  * \since 13.9.0 | ||||
| @@ -92,11 +89,8 @@ int __ast_named_lock_put(const char *filename, int lineno, const char *func, | ||||
|  * \since 13.9.0 | ||||
|  * | ||||
|  * \param lock The pointer to the ast_named_lock structure returned by ast_named_lock_get | ||||
|  * \retval 0 Success | ||||
|  * \retval -1 Failure | ||||
|  */ | ||||
| #define ast_named_lock_put(lock) \ | ||||
| 	__ast_named_lock_put(__FILE__, __LINE__, __PRETTY_FUNCTION__, lock) | ||||
| #define ast_named_lock_put(lock) ao2_cleanup(lock) | ||||
|  | ||||
| /*! | ||||
|  * @} | ||||
|   | ||||
| @@ -35,13 +35,17 @@ ASTERISK_REGISTER_FILE() | ||||
| struct ao2_container *named_locks; | ||||
| #define NAMED_LOCKS_BUCKETS 101 | ||||
|  | ||||
| struct ast_named_lock { | ||||
| struct named_lock_proxy { | ||||
| 	AO2_WEAKPROXY(); | ||||
| 	char key[0]; | ||||
| }; | ||||
|  | ||||
| struct ast_named_lock { | ||||
| }; | ||||
|  | ||||
| static int named_locks_hash(const void *obj, const int flags) | ||||
| { | ||||
| 	const struct ast_named_lock *lock = obj; | ||||
| 	const struct named_lock_proxy *lock = obj; | ||||
|  | ||||
| 	switch (flags & OBJ_SEARCH_MASK) { | ||||
| 	case OBJ_SEARCH_KEY: | ||||
| @@ -57,8 +61,8 @@ static int named_locks_hash(const void *obj, const int flags) | ||||
|  | ||||
| static int named_locks_cmp(void *obj_left, void *obj_right, int flags) | ||||
| { | ||||
| 	const struct ast_named_lock *object_left = obj_left; | ||||
| 	const struct ast_named_lock *object_right = obj_right; | ||||
| 	const struct named_lock_proxy *object_left = obj_left; | ||||
| 	const struct named_lock_proxy *object_right = obj_right; | ||||
| 	const char *right_key = obj_right; | ||||
| 	int cmp; | ||||
|  | ||||
| @@ -98,45 +102,72 @@ int ast_named_locks_init(void) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void named_lock_proxy_cb(void *weakproxy, void *data) | ||||
| { | ||||
| 	ao2_unlink(named_locks, weakproxy); | ||||
| } | ||||
|  | ||||
| struct ast_named_lock *__ast_named_lock_get(const char *filename, int lineno, const char *func, | ||||
| 	enum ast_named_lock_type lock_type, const char *keyspace, const char *key) | ||||
| { | ||||
| 	struct named_lock_proxy *proxy = NULL; | ||||
| 	struct ast_named_lock *lock = NULL; | ||||
| 	int concat_key_buff_len = strlen(keyspace) + strlen(key) + 2; | ||||
| 	char *concat_key = ast_alloca(concat_key_buff_len); | ||||
| 	int keylen = strlen(keyspace) + strlen(key) + 2; | ||||
| 	char *concat_key = ast_alloca(keylen); | ||||
|  | ||||
| 	sprintf(concat_key, "%s-%s", keyspace, key); /* Safe */ | ||||
|  | ||||
| 	ao2_lock(named_locks); | ||||
| 	lock = ao2_find(named_locks, concat_key, OBJ_SEARCH_KEY | OBJ_NOLOCK); | ||||
| 	if (lock) { | ||||
| 	proxy = ao2_find(named_locks, concat_key, OBJ_SEARCH_KEY | OBJ_NOLOCK); | ||||
| 	if (proxy) { | ||||
| 		ao2_unlock(named_locks); | ||||
| 		ast_assert((ao2_options_get(lock) & AO2_ALLOC_OPT_LOCK_MASK) == lock_type); | ||||
| 		return lock; | ||||
| 		lock = __ao2_weakproxy_get_object(proxy, 0, __PRETTY_FUNCTION__, filename, lineno, func); | ||||
|  | ||||
| 		if (lock) { | ||||
| 			/* We have an existing lock and it's not being destroyed. */ | ||||
| 			ao2_ref(proxy, -1); | ||||
| 			ast_assert((ao2_options_get(lock) & AO2_ALLOC_OPT_LOCK_MASK) == lock_type); | ||||
|  | ||||
| 			return lock; | ||||
| 		} | ||||
|  | ||||
| 		/* the old proxy is being destroyed, clean list before creating/adding new one */ | ||||
| 		ao2_lock(named_locks); | ||||
| 		ao2_unlink_flags(named_locks, proxy, OBJ_NOLOCK); | ||||
| 		ao2_ref(proxy, -1); | ||||
| 	} | ||||
|  | ||||
| 	lock = ao2_alloc_options(sizeof(*lock) + concat_key_buff_len, NULL, lock_type); | ||||
| 	if (lock) { | ||||
| 		strcpy(lock->key, concat_key); /* Safe */ | ||||
| 		ao2_link_flags(named_locks, lock, OBJ_NOLOCK); | ||||
| 	proxy = ao2_t_weakproxy_alloc(sizeof(*proxy) + keylen, NULL, concat_key); | ||||
| 	if (!proxy) { | ||||
| 		goto failure_cleanup; | ||||
| 	} | ||||
|  | ||||
| 	lock = __ao2_alloc(sizeof(*lock) + keylen, NULL, lock_type, concat_key, filename, lineno, func); | ||||
| 	if (!lock) { | ||||
| 		goto failure_cleanup; | ||||
| 	} | ||||
|  | ||||
| 	/* We have exclusive access to proxy and lock, no need for locking here. */ | ||||
| 	if (ao2_weakproxy_set_object(proxy, lock, OBJ_NOLOCK)) { | ||||
| 		goto failure_cleanup; | ||||
| 	} | ||||
|  | ||||
| 	if (ao2_weakproxy_subscribe(proxy, named_lock_proxy_cb, NULL, OBJ_NOLOCK)) { | ||||
| 		goto failure_cleanup; | ||||
| 	} | ||||
|  | ||||
| 	strcpy(proxy->key, concat_key); /* Safe */ | ||||
| 	ao2_link_flags(named_locks, proxy, OBJ_NOLOCK); | ||||
| 	ao2_unlock(named_locks); | ||||
| 	ao2_t_ref(proxy, -1, "Release allocation reference"); | ||||
|  | ||||
| 	return lock; | ||||
| } | ||||
|  | ||||
| int __ast_named_lock_put(const char *filename, int lineno, const char *func, | ||||
| 	struct ast_named_lock *lock) | ||||
| { | ||||
| 	if (!lock) { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	ao2_lock(named_locks); | ||||
| 	if (ao2_ref(lock, -1) == 2) { | ||||
| 		ao2_unlink_flags(named_locks, lock, OBJ_NOLOCK); | ||||
| 	} | ||||
| failure_cleanup: | ||||
| 	ao2_unlock(named_locks); | ||||
|  | ||||
| 	return 0; | ||||
| 	ao2_cleanup(proxy); | ||||
| 	ao2_cleanup(lock); | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user