/* decrement reference count and release the handler if reached 0 */ static void ucs_async_handler_put(ucs_async_handler_t *handler) { if (ucs_atomic_fadd32(&handler->refcount, -1) > 1) { return; } ucs_debug("release async handler " UCS_ASYNC_HANDLER_FMT, UCS_ASYNC_HANDLER_ARG(handler)); ucs_free(handler); }
ucs_status_t uct_mm_ep_atomic_fadd32(uct_ep_h tl_ep, uint32_t add, uint64_t remote_addr, uct_rkey_t rkey, uint32_t *result, uct_completion_t *comp) { uint32_t *ptr = (uint32_t *)(rkey + remote_addr); *result = ucs_atomic_fadd32(ptr, add); uct_mm_trace_data(remote_addr, rkey, "ATOMIC_FADD32 [add %"PRIu32" result %"PRIu32"]", add, *result); return UCS_OK; }
/* add new handler to the table */ static ucs_status_t ucs_async_handler_add(int min_id, int max_id, ucs_async_handler_t *handler) { int hash_extra_status; ucs_status_t status; khiter_t hash_it; int i, id; pthread_rwlock_wrlock(&ucs_async_global_context.handlers_lock); handler->id = -1; ucs_assert_always(handler->refcount == 1); /* * Search for an empty key in the range [min_id, max_id) * ucs_async_global_context.handler_id is used to generate "unique" keys. */ for (i = min_id; i < max_id; ++i) { id = min_id + (ucs_atomic_fadd32(&ucs_async_global_context.handler_id, 1) % (max_id - min_id)); hash_it = kh_put(ucs_async_handler, &ucs_async_global_context.handlers, id, &hash_extra_status); if (hash_extra_status == -1) { ucs_error("Failed to add async handler " UCS_ASYNC_HANDLER_FMT " to hash", UCS_ASYNC_HANDLER_ARG(handler)); status = UCS_ERR_NO_MEMORY; goto out_unlock; } else if (hash_extra_status != 0) { handler->id = id; ucs_assert(id != -1); break; } } if (handler->id == -1) { ucs_error("Cannot add async handler %s() - id range [%d..%d) is full", ucs_debug_get_symbol_name(handler->cb), min_id, max_id); status = UCS_ERR_ALREADY_EXISTS; goto out_unlock; } ucs_assert_always(!ucs_async_handler_kh_is_end(hash_it)); kh_value(&ucs_async_global_context.handlers, hash_it) = handler; ucs_debug("added async handler " UCS_ASYNC_HANDLER_FMT " to hash", UCS_ASYNC_HANDLER_ARG(handler)); status = UCS_OK; out_unlock: pthread_rwlock_unlock(&ucs_async_global_context.handlers_lock); return status; }