#ifndef UCS_ASYNC_H_
#define UCS_ASYNC_H_
#include "thread.h"
#include "signal.h"
#include "async_fwd.h"
#include <ucs/sys/compiler_def.h>
#include <ucs/datastruct/mpmc.h>
#include <ucs/time/time.h>
#include <ucs/debug/log.h>
BEGIN_C_DECLS
#define UCS_ASYNC_EVENT_DUMMY 0
struct ucs_async_context {
union {
ucs_async_thread_context_t thread;
ucs_async_signal_context_t signal;
int poll_block;
};
ucs_async_mode_t mode;
volatile uint32_t num_handlers;
ucs_mpmc_queue_t missed;
ucs_time_t last_wakeup;
};
void ucs_async_global_init();
void ucs_async_global_cleanup();
ucs_status_t ucs_async_context_init(ucs_async_context_t *async,
ucs_async_mode_t mode);
void ucs_async_context_cleanup(ucs_async_context_t *async);
int ucs_async_is_from_async(const ucs_async_context_t *async);
static inline int ucs_async_check_miss(ucs_async_context_t *async)
{
if (ucs_unlikely(!ucs_mpmc_queue_is_empty(&async->missed))) {
__ucs_async_poll_missed(async);
return 1;
} else if (ucs_unlikely(async->mode == UCS_ASYNC_MODE_POLL)) {
ucs_async_poll(async);
return 1;
}
return 0;
}
static inline int ucs_async_is_blocked(const ucs_async_context_t *async)
{
if (async->mode == UCS_ASYNC_MODE_THREAD_SPINLOCK) {
return ucs_recursive_spinlock_is_held(&async->thread.spinlock);
} else if (async->mode == UCS_ASYNC_MODE_THREAD_MUTEX) {
return ucs_recursive_mutex_is_blocked(&async->thread.mutex);
} else if (async->mode == UCS_ASYNC_MODE_SIGNAL) {
return UCS_ASYNC_SIGNAL_IS_RECURSIVELY_BLOCKED(async);
}
return async->poll_block > 0;
}
#define UCS_ASYNC_BLOCK(_async) \
do { \
if ((_async)->mode == UCS_ASYNC_MODE_THREAD_SPINLOCK) { \
ucs_recursive_spin_lock(&(_async)->thread.spinlock); \
} else if ((_async)->mode == UCS_ASYNC_MODE_THREAD_MUTEX) { \
ucs_recursive_mutex_block(&(_async)->thread.mutex); \
} else if ((_async)->mode == UCS_ASYNC_MODE_SIGNAL) { \
UCS_ASYNC_SIGNAL_BLOCK(_async); \
} else { \
++(_async)->poll_block; \
} \
} while(0)
#define UCS_ASYNC_UNBLOCK(_async) \
do { \
if ((_async)->mode == UCS_ASYNC_MODE_THREAD_SPINLOCK) { \
ucs_recursive_spin_unlock(&(_async)->thread.spinlock); \
} else if ((_async)->mode == UCS_ASYNC_MODE_THREAD_MUTEX) { \
ucs_recursive_mutex_unblock(&(_async)->thread.mutex); \
} else if ((_async)->mode == UCS_ASYNC_MODE_SIGNAL) { \
UCS_ASYNC_SIGNAL_UNBLOCK(_async); \
} else { \
--(_async)->poll_block; \
} \
} while (0)
#define UCS_ASYNC_THREAD_LOCK_TYPE (RUNNING_ON_VALGRIND ? \
UCS_ASYNC_MODE_THREAD_MUTEX : UCS_ASYNC_MODE_THREAD_SPINLOCK)
END_C_DECLS
#endif