#include "dapl_osd.h"
#include "dapl.h"
#include "dapl_hca_util.h"
#include "dapl_ia_util.h"
#include "dapl_rmr_util.h"
#include "dapl_lmr_util.h"
#include "dapl_pz_util.h"
#include "dapl_ep_util.h"
#include "dapl_cr_util.h"
#include "dapl_evd_util.h"
#include "dapl_sp_util.h"
#include "dapl_adapter_util.h"
#include "dapl_provider.h"
#include "dapl_hash.h"
#include "dapl_debug.h"
#include <sys/time.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
static void dapls_osd_fork_cleanup(void);
void
dapl_os_init()
{
int status;
status = pthread_atfork(NULL, NULL, dapls_osd_fork_cleanup);
if (status != 0) {
dapl_dbg_log(DAPL_DBG_TYPE_WARN,
"WARNING: pthread_atfork %d\n", status);
}
}
DAT_RETURN
dapl_os_get_time(
OUT DAPL_OS_TIMEVAL * loc)
{
struct timeval tv;
struct timezone tz;
(void) gettimeofday(&tv, &tz);
*loc = ((DAT_UINT64)(tv.tv_sec) * 1000000L) + (DAT_UINT64) tv.tv_usec;
return (DAT_SUCCESS);
}
int
dapl_os_get_env_bool(
char *env_str)
{
char *env_var;
env_var = getenv(env_str);
if (env_var != NULL) {
return (1);
}
return (0);
}
int
dapl_os_get_env_val(
char *env_str,
int def_val)
{
char *env_var;
env_var = getenv(env_str);
if (env_var != NULL) {
def_val = strtol(env_var, NULL, 0);
}
return (def_val);
}
DAT_RETURN
dapl_os_wait_object_init(
IN DAPL_OS_WAIT_OBJECT *wait_obj)
{
wait_obj->signaled = DAT_FALSE;
if (0 != pthread_cond_init(&wait_obj->cv, NULL)) {
return (DAT_ERROR(DAT_INTERNAL_ERROR, 0));
}
(void) pthread_mutex_init(&wait_obj->lock, NULL);
return (DAT_SUCCESS);
}
DAT_RETURN
dapl_os_wait_object_wait(
IN DAPL_OS_WAIT_OBJECT *wait_obj,
IN DAT_TIMEOUT timeout_val)
{
DAT_RETURN dat_status;
int pthread_status;
struct timespec future;
dat_status = DAT_SUCCESS;
pthread_status = 0;
if (timeout_val != DAT_TIMEOUT_INFINITE) {
struct timeval now;
struct timezone tz;
unsigned int microsecs;
(void) gettimeofday(&now, &tz);
microsecs = now.tv_usec + (timeout_val % 1000000);
if (microsecs > 1000000) {
now.tv_sec = now.tv_sec + timeout_val / 1000000 + 1;
now.tv_usec = microsecs - 1000000;
} else {
now.tv_sec = now.tv_sec + timeout_val / 1000000;
now.tv_usec = microsecs;
}
future.tv_sec = now.tv_sec;
future.tv_nsec = now.tv_usec * 1000;
(void) pthread_mutex_lock(&wait_obj->lock);
while (wait_obj->signaled == DAT_FALSE && pthread_status == 0) {
pthread_status = pthread_cond_timedwait(
&wait_obj->cv, &wait_obj->lock, &future);
}
if (pthread_status == 0) {
wait_obj->signaled = DAT_FALSE;
}
(void) pthread_mutex_unlock(&wait_obj->lock);
} else {
(void) pthread_mutex_lock(&wait_obj->lock);
while (wait_obj->signaled == DAT_FALSE && pthread_status == 0) {
pthread_status = pthread_cond_wait(
&wait_obj->cv, &wait_obj->lock);
}
if (pthread_status == 0) {
wait_obj->signaled = DAT_FALSE;
}
(void) pthread_mutex_unlock(&wait_obj->lock);
}
if (ETIMEDOUT == pthread_status) {
dat_status = DAT_ERROR(DAT_TIMEOUT_EXPIRED, 0);
} else if (0 != pthread_status) {
dat_status = DAT_ERROR(DAT_INTERNAL_ERROR, 0);
}
return (dat_status);
}
DAT_RETURN
dapl_os_wait_object_wakeup(
IN DAPL_OS_WAIT_OBJECT *wait_obj)
{
(void) pthread_mutex_lock(&wait_obj->lock);
wait_obj->signaled = DAT_TRUE;
(void) pthread_mutex_unlock(&wait_obj->lock);
if (0 != pthread_cond_signal(&wait_obj->cv)) {
return (DAT_ERROR(DAT_INTERNAL_ERROR, 0));
}
return (DAT_SUCCESS);
}
DAT_RETURN
dapl_os_wait_object_destroy(
IN DAPL_OS_WAIT_OBJECT *wait_obj)
{
if (0 != pthread_cond_destroy(&wait_obj->cv)) {
return (DAT_ERROR(DAT_INTERNAL_ERROR, 0));
}
if (0 != pthread_mutex_destroy(&wait_obj->lock)) {
return (DAT_ERROR(DAT_INTERNAL_ERROR, 0));
}
return (DAT_SUCCESS);
}
void
dapls_osd_fork_cleanup(void)
{
DAPL_PROVIDER_LIST_NODE *cur_node;
DAPL_HCA *hca_ptr;
DAPL_IA *ia_ptr;
DAPL_LMR *lmr_ptr;
DAPL_RMR *rmr_ptr;
DAPL_PZ *pz_ptr;
DAPL_CR *cr_ptr;
DAPL_EP *ep_ptr;
DAPL_EVD *evd_ptr;
DAT_EP_PARAM *param;
DAPL_SP *sp_ptr;
while (NULL != g_dapl_provider_list.head) {
cur_node = g_dapl_provider_list.head;
g_dapl_provider_list.head = cur_node->next;
hca_ptr = (DAPL_HCA *) cur_node->data.extension;
while (!dapl_llist_is_empty(&hca_ptr->ia_list_head)) {
ia_ptr = (DAPL_IA *)
dapl_llist_peek_head(&hca_ptr->ia_list_head);
while (!dapl_llist_is_empty(&ia_ptr->rmr_list_head)) {
rmr_ptr = (DAPL_RMR *)
dapl_llist_peek_head(&ia_ptr->
rmr_list_head);
if (rmr_ptr->param.lmr_triplet.
virtual_address != 0) {
dapl_os_atomic_dec(&rmr_ptr->
lmr->lmr_ref_count);
rmr_ptr->param.lmr_triplet.
virtual_address = 0;
}
dapl_os_atomic_dec(&rmr_ptr->pz->pz_ref_count);
dapl_ia_unlink_rmr(rmr_ptr->header.owner_ia,
rmr_ptr);
dapl_rmr_dealloc(rmr_ptr);
}
while (!dapl_llist_is_empty(&ia_ptr->rsp_list_head)) {
sp_ptr = (DAPL_SP *) dapl_llist_peek_head(
&ia_ptr->rsp_list_head);
dapl_os_atomic_dec(&((DAPL_EVD *)sp_ptr->
evd_handle)->evd_ref_count);
dapls_ia_unlink_sp(ia_ptr, sp_ptr);
dapls_sp_free_sp(sp_ptr);
}
while (!dapl_llist_is_empty(&ia_ptr->ep_list_head)) {
ep_ptr = (DAPL_EP *) dapl_llist_peek_head(
&ia_ptr->ep_list_head);
param = &ep_ptr->param;
if (param->pz_handle != NULL) {
dapl_os_atomic_dec(&((DAPL_PZ *)param->
pz_handle)->pz_ref_count);
}
if (param->recv_evd_handle != NULL) {
dapl_os_atomic_dec(&((DAPL_EVD *)param->
recv_evd_handle)->evd_ref_count);
}
if (param->request_evd_handle) {
dapl_os_atomic_dec(&((DAPL_EVD *)param->
request_evd_handle)->evd_ref_count);
}
if (param->connect_evd_handle != NULL) {
dapl_os_atomic_dec(&((DAPL_EVD *)param->
connect_evd_handle)->evd_ref_count);
}
dapl_ia_unlink_ep(ia_ptr, ep_ptr);
dapl_ep_dealloc(ep_ptr);
}
while (!dapl_llist_is_empty(&ia_ptr->lmr_list_head)) {
lmr_ptr = (DAPL_LMR *) dapl_llist_peek_head(
&ia_ptr->lmr_list_head);
(void) dapls_hash_remove(lmr_ptr->header.
owner_ia->hca_ptr->lmr_hash_table,
lmr_ptr->param.lmr_context, NULL);
pz_ptr = (DAPL_PZ *) lmr_ptr->param.pz_handle;
dapl_os_atomic_dec(&pz_ptr->pz_ref_count);
dapl_ia_unlink_lmr(lmr_ptr->header.owner_ia,
lmr_ptr);
dapl_lmr_dealloc(lmr_ptr);
}
while (!dapl_llist_is_empty(&ia_ptr->psp_list_head)) {
sp_ptr = (DAPL_SP *) dapl_llist_peek_head(
&ia_ptr->psp_list_head);
while (!dapl_llist_is_empty(&sp_ptr->
cr_list_head)) {
cr_ptr = (DAPL_CR *)
dapl_llist_peek_head(
&sp_ptr->cr_list_head);
dapl_sp_remove_cr(sp_ptr, cr_ptr);
dapls_cr_free(cr_ptr);
}
dapls_ia_unlink_sp(ia_ptr, sp_ptr);
dapl_os_atomic_dec(&((DAPL_EVD *)sp_ptr->
evd_handle)->evd_ref_count);
dapls_sp_free_sp(sp_ptr);
}
while (!dapl_llist_is_empty(&ia_ptr->pz_list_head)) {
pz_ptr = (DAPL_PZ *)
dapl_llist_peek_head(&ia_ptr->pz_list_head);
dapl_ia_unlink_pz(pz_ptr->header.owner_ia,
pz_ptr);
dapl_pz_dealloc(pz_ptr);
}
while (!dapl_llist_is_empty(&ia_ptr->evd_list_head)) {
evd_ptr = (DAPL_EVD *) dapl_llist_peek_head(
&ia_ptr->evd_list_head);
dapl_ia_unlink_evd(evd_ptr->header.owner_ia,
evd_ptr);
evd_ptr->ib_cq_handle = IB_INVALID_HANDLE;
(void) dapls_evd_dealloc(evd_ptr);
}
dapl_hca_unlink_ia(ia_ptr->hca_ptr, ia_ptr);
ia_ptr->async_error_evd = NULL;
dapls_ia_free(ia_ptr);
}
dapl_os_free(cur_node, sizeof (DAPL_PROVIDER_LIST_NODE));
}
}