/*---------------------------------------------------------------------------*/ void xio_context_destroy(struct xio_context *ctx) { int i; xio_observable_notify_all_observers(&ctx->observable, XIO_CONTEXT_EVENT_CLOSE, NULL); xio_observable_unreg_all_observers(&ctx->observable); for (i = 0; i < XIO_STAT_LAST; i++) if (ctx->stats.name[i]) kfree(ctx->stats.name[i]); xio_workqueue_destroy(ctx->workqueue); /* can free only xio created loop */ if (ctx->flags != XIO_LOOP_USER_LOOP) xio_ev_loop_destroy(ctx->ev_loop); ctx->ev_loop = NULL; if (ctx->ctx_dentry) { debugfs_remove_recursive(ctx->ctx_dentry); ctx->ctx_dentry = NULL; } kfree(ctx); }
/*---------------------------------------------------------------------------*/ static void *portal_server_cb(void *data) { struct hw_thread_data *tdata = data; cpu_set_t cpuset; struct xio_context *ctx; struct xio_server *server; char str[128]; int i; /* set affinity to thread */ CPU_ZERO(&cpuset); CPU_SET(tdata->affinity, &cpuset); pthread_setaffinity_np(tdata->thread_id, sizeof(cpu_set_t), &cpuset); /* open default event loop */ tdata->loop = xio_ev_loop_init(); /* create thread context for the client */ ctx = xio_ctx_open(NULL, tdata->loop, 0); /* bind a listener server to a portal/url */ printf("thread [%d] - listen:%s\n", tdata->affinity, tdata->portal); server = xio_bind(ctx, &portal_server_ops, tdata->portal, NULL, 0, tdata); if (server == NULL) goto cleanup; sprintf(str,"hello world header response from thread %d", tdata->affinity); /* create "hello world" message */ for (i = 0; i <QUEUE_DEPTH; i++) { tdata->rsp[i].out.header.iov_base = strdup(str); tdata->rsp[i].out.header.iov_len = strlen(tdata->rsp[i].out.header.iov_base); } /* the default xio supplied main loop */ xio_ev_loop_run(tdata->loop); /* normal exit phase */ fprintf(stdout, "exit signaled\n"); /* detach the server */ xio_unbind(server); /* free the message */ for (i = 0; i <QUEUE_DEPTH; i++) free(tdata->rsp[i].out.header.iov_base); cleanup: /* free the context */ xio_ctx_close(ctx); /* destroy the default loop */ xio_ev_loop_destroy(tdata->loop); return NULL; }
/*---------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { struct xio_server *server; /* server portal */ struct hw_server_data server_data; char url[256]; struct xio_context *ctx; void *loop; int i; uint16_t port = atoi(argv[2]); memset(&server_data, 0, sizeof(server_data)); /* open default event loop */ loop = xio_ev_loop_init(); /* create thread context for the client */ ctx = xio_ctx_open(NULL, loop, 0); /* create url to connect to */ sprintf(url, "rdma://%s:%d", argv[1], port); /* bind a listener server to a portal/url */ server = xio_bind(ctx, &server_ops, url, NULL, 0, &server_data); if (server == NULL) goto cleanup; /* spawn portals */ for (i = 0; i < MAX_THREADS; i++) { server_data.tdata[i].affinity = i+1; port += 1; sprintf(server_data.tdata[i].portal, "rdma://%s:%d", argv[1], port); pthread_create(&server_data.tdata[i].thread_id, NULL, portal_server_cb, &server_data.tdata[i]); } xio_ev_loop_run(loop); /* normal exit phase */ fprintf(stdout, "exit signaled\n"); /* join the threads */ for (i = 0; i < MAX_THREADS; i++) pthread_join(server_data.tdata[i].thread_id, NULL); /* free the server */ xio_unbind(server); cleanup: /* free the context */ xio_ctx_close(ctx); /* destroy the default loop */ xio_ev_loop_destroy(&loop); return 0; }
/*---------------------------------------------------------------------------*/ void xio_destroy_context_continue(struct work_struct *work) { xio_work_handle_t *xio_work; struct xio_context *ctx; int i; xio_work = container_of(work, xio_work_handle_t, work); ctx = container_of(xio_work, struct xio_context, destroy_ctx_work); if (ctx->run_private) ERROR_LOG("not all observers finished! run_private=%d\n", ctx->run_private); xio_observable_notify_all_observers(&ctx->observable, XIO_CONTEXT_EVENT_POST_CLOSE, NULL); if (!xio_observable_is_empty(&ctx->observable)) ERROR_LOG("context destroy: observers leak - %p\n", ctx); xio_observable_unreg_all_observers(&ctx->observable); for (i = 0; i < XIO_STAT_LAST; i++) kfree(ctx->stats.name[i]); xio_workqueue_destroy(ctx->workqueue); xio_objpool_destroy(ctx->msg_pool); /* can free only xio created loop */ if (ctx->flags != XIO_LOOP_USER_LOOP) xio_ev_loop_destroy(ctx->ev_loop); ctx->ev_loop = NULL; XIO_OBSERVABLE_DESTROY(&ctx->observable); xio_ctx_task_pools_destroy(ctx); if (ctx->mempool) { xio_mempool_destroy(ctx->mempool); ctx->mempool = NULL; } kfree(ctx); }
static void *worker_thread(void *data) { struct thread_data *tdata = data; cpu_set_t cpuset; struct xio_session **sessions = NULL; struct xio_context *ctx; struct session_data *session_data = NULL; int j = 0, n = 0; struct timespec start, end; void *loop = NULL; double *sec = NULL; /* set affinity to thread */ CPU_ZERO(&cpuset); CPU_SET(tdata->affinity, &cpuset); pthread_setaffinity_np(tdata->thread_id, sizeof(cpu_set_t), &cpuset); /* open default event loop */ loop = xio_ev_loop_init(); if (loop == NULL) { fprintf(stderr, "Failed to allocate event loop\n"); return (void*)(-1); } /* create thread context for the client */ ctx= xio_ctx_open(NULL, loop, 0); if(ctx == NULL) { fprintf(stderr, "Failed to allocate thread context\n"); xio_ev_loop_destroy(&loop); return (void*)-1; } session_data = malloc(tdata->num_sessions*sizeof(struct session_data)); sessions = malloc(tdata->num_sessions*sizeof(struct sessions *)); if( session_data == NULL || sessions == NULL ) { fprintf(stderr, "Allocation failed\n"); xio_ctx_close(ctx); xio_ev_loop_destroy(&loop); if(session_data) { free(session_data); } if(sessions) { free(sessions); } return (void*)-1; } for(n = 0; n < tdata->num_sessions; n++) { tdata->loop = loop; session_data[n].tdata = tdata; } /* client session attributes */ struct xio_session_attr attr = { &ses_ops, /* callbacks structure */ NULL, /* no need to pass the server private data */ 0 }; if(clock_gettime(CLOCK_MONOTONIC, &start)) { fprintf(stderr, "clock_gettime() failed, errno = %d\n", errno); } for (j = 0; j< NUM_ITER; j++) { for(n = 0; n < tdata->num_sessions; n++) { sessions[n] = xio_session_open(XIO_SESSION_REQ, &attr, tdata->url, 0, 0, &session_data[n]); /* connect the session */ //fprintf(stderr, "Connect Session\n"); session_data[n].conn = xio_connect(sessions[n], ctx, 0, &session_data[n]); } /* the default xio supplied main loop */ xio_ev_loop_run(loop); } if(clock_gettime(CLOCK_MONOTONIC, &end)) { fprintf(stderr, "clock_gettime() failed, errno = %d\n", errno); } /* normal exit phase */ fprintf(stdout, "exit signaled\n"); /* free the context */ xio_ctx_close(ctx); /* destroy the default loop */ xio_ev_loop_destroy(&loop); sec = malloc(sizeof(double)); *sec = (double)(((end.tv_sec * 1000000000 + end.tv_nsec) - (start.tv_sec * 1000000000 - start.tv_nsec))/NUM_ITER)/1000000000; fprintf(stdout, "THREAD [ %lu ] It took %lf sec for %d sessions\n", tdata->thread_id, *sec, tdata->num_sessions); free(session_data); free(sessions); return ((void *)sec); }