librdmacm: use comp_channel to enhance scalability.
authorshefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 11 Mar 2009 22:14:37 +0000 (22:14 +0000)
committershefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 11 Mar 2009 22:14:37 +0000 (22:14 +0000)
Use the COMP_CHANNEL abstraction as a common framework for event
reporting and to provide better scalability.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@2027 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

ulp/librdmacm/examples/cmatose/cmatose.c
ulp/librdmacm/include/rdma/rdma_cma.h
ulp/librdmacm/src/cma.cpp

index 7f32f27..b9a8232 100644 (file)
@@ -433,7 +433,7 @@ static int connect_events(void)
                        cma_handler(event->id, event);\r
                        rdma_ack_cm_event(event);\r
                } else {\r
-                       printf("cmatose: failure in rdma_get_cm_event in connect events\n");\r
+                       printf("cmatose:rdma_get_cm_event connect events error 0x%x\n", err);\r
                        ret = err;\r
                }\r
        }\r
@@ -452,7 +452,7 @@ static int disconnect_events(void)
                        cma_handler(event->id, event);\r
                        rdma_ack_cm_event(event);\r
                } else {\r
-                       printf("cmatose: failure in rdma_get_cm_event in disconnect events\n");\r
+                       printf("cmatose: rdma_get_cm_event disconnect events error 0x%x\n", err);\r
                        ret = err;\r
                }\r
        }\r
@@ -537,7 +537,7 @@ static int run_server(void)
                goto out;\r
        }\r
 \r
-       ret = rdma_listen(listen_id, 0);\r
+       ret = rdma_listen(listen_id, connections);\r
        if (ret) {\r
                printf("cmatose: failure trying to listen: 0x%x\n", ret);\r
                goto out;\r
index 3a5a4bb..c665dcd 100644 (file)
@@ -121,7 +121,7 @@ struct rdma_route
 \r
 struct rdma_event_channel\r
 {\r
-       uint32_t                timeout;\r
+       COMP_CHANNEL            channel;\r
 };\r
 \r
 struct rdma_cm_id\r
@@ -133,13 +133,12 @@ struct rdma_cm_id
        struct rdma_route                       route;\r
        enum rdma_port_space            ps;\r
        uint8_t                                         port_num;\r
+       COMP_ENTRY                                      comp_entry;\r
 \r
        union {\r
                IWVConnectEndpoint              *connect;\r
                IWVDatagramEndpoint             *datagram;\r
        }       ep;\r
-       OVERLAPPED                                      overlap;\r
-       uint32_t                                        events_completed;\r
 };\r
 \r
 struct rdma_conn_param\r
index 91b059a..934e2f2 100644 (file)
 \r
 #include <rdma/rdma_cma.h>\r
 #include <infiniband/verbs.h>\r
+#include <comp_channel.h>\r
 #include <iba/ibat.h>\r
 #include "cma.h"\r
+#include "..\..\..\etc\user\comp_channel.cpp"\r
 \r
-IWVProvider *prov;\r
-__declspec(dllexport)\r
-IWVProvider *ibv_get_winverbs(void);\r
+static struct ibv_windata windata;\r
 \r
 enum cma_state\r
 {\r
@@ -64,22 +64,12 @@ struct cma_id_private
 {\r
        struct rdma_cm_id                       id;\r
        enum cma_state                          state;\r
-       int                                                     channel_index;\r
        struct cma_device                       *cma_dev;\r
        int                                                     backlog;\r
        int                                                     index;\r
        struct rdma_cm_id                       **req_list;\r
 };\r
 \r
-struct cma_event_channel\r
-{\r
-       struct rdma_event_channel       channel;\r
-       CRITICAL_SECTION                        lock;\r
-       struct cma_id_private           *id[MAXIMUM_WAIT_OBJECTS];\r
-       HANDLE                                          event[MAXIMUM_WAIT_OBJECTS];\r
-       int                                                     count;\r
-};\r
-\r
 struct cma_device\r
 {\r
        struct ibv_context      *verbs;\r
@@ -107,9 +97,9 @@ static void ucma_cleanup(void)
                delete cma_dev_array;\r
                cma_dev_cnt = 0;\r
        }\r
-       if (prov != NULL) {\r
-               prov->Release();\r
-               prov = NULL;\r
+       if (windata.prov != NULL) {\r
+               ibv_release_windata(&windata, IBV_WINDATA_VERSION);\r
+               windata.prov = NULL;\r
        }\r
 }\r
 \r
@@ -125,9 +115,8 @@ static int ucma_init(void)
                goto out;\r
        }\r
 \r
-       prov = ibv_get_winverbs();\r
-       if (prov == NULL) {\r
-               ret = -1;\r
+       ret = ibv_get_windata(&windata, IBV_WINDATA_VERSION);\r
+       if (ret) {\r
                goto err;\r
        }\r
 \r
@@ -211,75 +200,26 @@ void rdma_free_devices(struct ibv_context **list)
 __declspec(dllexport)\r
 struct rdma_event_channel *rdma_create_event_channel(void)\r
 {\r
-       struct cma_event_channel *chan;\r
+       struct rdma_event_channel *channel;\r
 \r
        if (!cma_dev_cnt && ucma_init()) {\r
                return NULL;\r
        }\r
 \r
-       chan = new struct cma_event_channel;\r
-       if (chan == NULL) {\r
+       channel = new struct rdma_event_channel;\r
+       if (channel == NULL) {\r
                return NULL;\r
        }\r
 \r
-       InitializeCriticalSection(&chan->lock);\r
-       chan->count = 0;\r
-       chan->channel.timeout = INFINITE;\r
-\r
-       return &chan->channel;\r
+       CompChannelInit(windata.comp_mgr, &channel->channel, INFINITE);\r
+       return channel;\r
 }\r
 \r
 __declspec(dllexport)\r
 void rdma_destroy_event_channel(struct rdma_event_channel *channel)\r
 {\r
-       struct cma_event_channel *chan;\r
-\r
-       chan = CONTAINING_RECORD(channel, struct cma_event_channel, channel);\r
-       DeleteCriticalSection(&chan->lock);     \r
-       delete chan;\r
-}\r
-\r
-static int cma_event_channel_insert_id(struct rdma_event_channel *channel,\r
-                                                                          struct cma_id_private *id_priv)\r
-{\r
-       struct cma_event_channel *chan;\r
-       int ret = 0;\r
-\r
-       chan = CONTAINING_RECORD(channel, struct cma_event_channel, channel);\r
-\r
-       EnterCriticalSection(&chan->lock);\r
-       if (chan->count == MAXIMUM_WAIT_OBJECTS) {\r
-               ret = -1;\r
-               goto out;\r
-       }\r
-\r
-       chan->id[chan->count] = id_priv;\r
-       chan->event[chan->count] = id_priv->id.overlap.hEvent;\r
-       id_priv->channel_index = chan->count++;\r
-out:\r
-       LeaveCriticalSection(&chan->lock);\r
-       return ret;\r
-}\r
-\r
-/*\r
- * TODO: we cannot call cma_event_channel_remove_id() while another\r
- * thread is calling rdma_get_event().  If this is needed, then we\r
- * need to halt the rdma_get_event() thread, modify the event list,\r
- * then restart the rdma_get_event() thread.\r
- */\r
-static void cma_event_channel_remove_id(struct rdma_event_channel *channel,\r
-                                                                               struct cma_id_private *id_priv)\r
-{\r
-       struct cma_event_channel *chan;\r
-\r
-       chan = CONTAINING_RECORD(channel, struct cma_event_channel, channel);\r
-\r
-       EnterCriticalSection(&chan->lock);\r
-       chan->count--;\r
-       chan->id[id_priv->channel_index] = chan->id[chan->count];\r
-       chan->event[id_priv->channel_index] = chan->event[chan->count];\r
-       chan->id[id_priv->channel_index]->channel_index = id_priv->channel_index;\r
-       LeaveCriticalSection(&chan->lock);\r
+       CompChannelCleanup(&channel->channel);\r
+       delete channel;\r
 }\r
 \r
 __declspec(dllexport)\r
@@ -301,43 +241,26 @@ int rdma_create_id(struct rdma_event_channel *channel,
        }\r
 \r
        RtlZeroMemory(id_priv, sizeof(struct cma_id_private));\r
-       id_priv->id.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
-       if (id_priv->id.overlap.hEvent == NULL) {\r
-               goto err1;\r
-       }\r
-\r
        id_priv->id.context = context;\r
        id_priv->id.channel = channel;\r
        id_priv->id.ps = ps;\r
+       CompEntryInit(&channel->channel, &id_priv->id.comp_entry);\r
 \r
        if (ps == RDMA_PS_TCP) {\r
-               hr = prov->CreateConnectEndpoint(&id_priv->id.ep.connect);\r
+               hr = windata.prov->CreateConnectEndpoint(&id_priv->id.ep.connect);\r
        } else {\r
-               hr = prov->CreateDatagramEndpoint(&id_priv->id.ep.datagram);\r
+               hr = windata.prov->CreateDatagramEndpoint(&id_priv->id.ep.datagram);\r
        }\r
        if (FAILED(hr)) {\r
-               goto err2;\r
-       }\r
-\r
-       hr = cma_event_channel_insert_id(channel, id_priv);\r
-       if (FAILED(hr)) {\r
-               goto err3;\r
+               goto err;\r
        }\r
 \r
        *id = &id_priv->id;\r
        return 0;\r
 \r
-err3:\r
-       if (ps == RDMA_PS_TCP) {\r
-               id_priv->id.ep.connect->Release();\r
-       } else {\r
-               id_priv->id.ep.datagram->Release();\r
-       }\r
-err2:\r
-       CloseHandle(id_priv->id.overlap.hEvent);\r
-err1:\r
+err:\r
        delete id_priv;\r
-       return -1;\r
+       return hr;\r
 }\r
 \r
 static void ucma_destroy_listen(struct cma_id_private *id_priv)\r
@@ -354,7 +277,7 @@ static void ucma_destroy_listen(struct cma_id_private *id_priv)
 __declspec(dllexport)\r
 int rdma_destroy_id(struct rdma_cm_id *id)\r
 {\r
-       struct cma_id_private   *id_priv;\r
+       struct cma_id_private *id_priv;\r
 \r
        id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
        if (id->ps == RDMA_PS_TCP) {\r
@@ -363,7 +286,7 @@ int rdma_destroy_id(struct rdma_cm_id *id)
                id->ep.datagram->CancelOverlappedRequests();\r
        }\r
 \r
-       cma_event_channel_remove_id(id->channel, id_priv);\r
+       CompChannelRemoveEntry(&id->channel->channel, &id->comp_entry);\r
 \r
        if (id_priv->backlog > 0) {\r
                ucma_destroy_listen(id_priv);\r
@@ -538,7 +461,8 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
        RtlCopyMemory(&id->route.addr.dst_addr, dst_addr, ucma_addrlen(dst_addr));\r
        id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
        id_priv->state = cma_addr_resolve;\r
-       SetEvent(id->overlap.hEvent);\r
+\r
+       CompEntryPost(&id->comp_entry);\r
        return 0;\r
 }\r
 \r
@@ -563,7 +487,8 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
 \r
        id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
        id_priv->state = cma_route_resolve;\r
-       SetEvent(id->overlap.hEvent);\r
+\r
+       CompEntryPost(&id->comp_entry);\r
        return 0;\r
 }\r
 \r
@@ -583,7 +508,7 @@ static int ucma_modify_qp_init(struct cma_id_private *id_priv, struct ibv_qp *qp
                return hr;\r
        }\r
 \r
-       qp_attr.pkey_index = (uint16_t) index;\r
+       qp_attr.pkey_index = index;\r
        return ibv_modify_qp(qp, &qp_attr, (enum ibv_qp_attr_mask)\r
                                                 (IBV_QP_STATE | IBV_QP_PKEY_INDEX | IBV_QP_PORT));\r
 }\r
@@ -689,7 +614,7 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
 \r
        id_priv->state = cma_active_connect;\r
        hr = id->ep.connect->Connect(id->qp->conn_handle, &id->route.addr.dst_addr,\r
-                                                                &attr, &id->overlap);\r
+                                                                &attr, &id->comp_entry.Overlap);\r
        if (FAILED(hr) && hr != WV_IO_PENDING) {\r
                id_priv->state = cma_route_resolve;\r
                return hr;\r
@@ -715,13 +640,16 @@ static int ucma_get_request(struct cma_id_private *listen, int index)
 \r
        if (listen->id.ps == RDMA_PS_TCP) {\r
                hr = listen->id.ep.connect->GetRequest(id_priv->id.ep.connect,\r
-                                                                                          &id_priv->id.overlap);\r
+                                                                                          &id_priv->id.comp_entry.Overlap);\r
        } else {\r
                hr = listen->id.ep.datagram->GetRequest(id_priv->id.ep.datagram,\r
-                                                                                               &id_priv->id.overlap);\r
+                                                                                               &id_priv->id.comp_entry.Overlap);\r
+       }\r
+       if (FAILED(hr) && hr != WV_IO_PENDING) {\r
+               return hr;\r
        }\r
 \r
-       return (FAILED(hr) && hr != WV_IO_PENDING) ? hr : 0;\r
+       return 0;\r
 }\r
 \r
 __declspec(dllexport)\r
@@ -731,7 +659,7 @@ int rdma_listen(struct rdma_cm_id *id, int backlog)
        HRESULT hr;\r
        int i;\r
 \r
-       if (backlog <= 0 || backlog > CMA_DEFAULT_BACKLOG) {\r
+       if (backlog <= 0) {\r
                backlog = CMA_DEFAULT_BACKLOG;\r
        }\r
 \r
@@ -784,7 +712,8 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
        }\r
 \r
        id_priv->state = cma_accepting;\r
-       hr = id->ep.connect->Accept(id->qp->conn_handle, &attr, &id->overlap);\r
+       hr = id->ep.connect->Accept(id->qp->conn_handle, &attr,\r
+                                                               &id->comp_entry.Overlap);\r
        if (FAILED(hr) && hr != WV_IO_PENDING) {\r
                id_priv->state = cma_disconnected;\r
                return hr;\r
@@ -848,9 +777,10 @@ int rdma_ack_cm_event(struct rdma_cm_event *event)
 static int ucma_process_conn_req(struct cma_event *event)\r
 {\r
        struct cma_id_private *listen;\r
-       HRESULT hr = 0;\r
+       struct cma_event_channel *chan;\r
 \r
        listen = (struct cma_id_private *) event->id_priv->id.context;\r
+       ucma_get_request(listen, event->id_priv->index);\r
 \r
        if (SUCCEEDED(event->event.status)) {\r
                event->event.status = ucma_query_connect(&event->id_priv->id,\r
@@ -860,25 +790,18 @@ static int ucma_process_conn_req(struct cma_event *event)
        if (SUCCEEDED(event->event.status)) {\r
                event->event.event = RDMA_CM_EVENT_CONNECT_REQUEST;\r
                event->id_priv->state = cma_passive_connect;\r
-\r
-               listen->req_list[event->id_priv->index] = NULL;\r
-               ucma_get_request(listen, event->id_priv->index);\r
        } else {\r
-               hr = listen->id.ep.connect->GetRequest(event->id_priv->id.ep.connect,\r
-                                                                                          &event->id_priv->id.overlap);\r
-               if (hr == WV_IO_PENDING) {\r
-                       hr = 0;\r
-               }\r
+               rdma_destroy_id(&event->id_priv->id);\r
        }\r
 \r
-       return hr;\r
+       return event->event.status;\r
 }\r
 \r
 static int ucma_process_conn_resp(struct cma_event *event)\r
 {\r
-       struct rdma_cm_id       *id;\r
-       WV_CONNECT_PARAM        attr;\r
-       HRESULT                         hr;\r
+       struct rdma_cm_id *id;\r
+       WV_CONNECT_PARAM attr;\r
+       HRESULT hr;\r
 \r
        if (FAILED(event->event.status)) {\r
                goto err;\r
@@ -888,7 +811,8 @@ static int ucma_process_conn_resp(struct cma_event *event)
        event->id_priv->state = cma_accepting;\r
 \r
        id = &event->id_priv->id;\r
-       hr = id->ep.connect->Accept(id->qp->conn_handle, &attr, &id->overlap);\r
+       hr = id->ep.connect->Accept(id->qp->conn_handle, &attr,\r
+                                                               &id->comp_entry.Overlap);\r
        if (FAILED(hr) && hr != WV_IO_PENDING) {\r
                event->event.status = hr;\r
                goto err;\r
@@ -906,16 +830,18 @@ err:
 \r
 static void ucma_process_establish(struct cma_event *event)\r
 {\r
+       struct cma_id_private *id_priv = event->id_priv;\r
+\r
        if (SUCCEEDED(event->event.status)) {\r
-               event->event.status = ucma_query_connect(&event->id_priv->id,\r
+               event->event.status = ucma_query_connect(&id_priv->id,\r
                                                                                                 &event->event.param.conn);\r
        }\r
 \r
        if (SUCCEEDED(event->event.status)) {\r
                event->event.event = RDMA_CM_EVENT_ESTABLISHED;\r
-               event->id_priv->state = cma_connected;\r
 \r
-               event->id_priv->id.ep.connect->NotifyDisconnect(&event->id_priv->id.overlap);\r
+               id_priv->state = cma_connected;\r
+               id_priv->id.ep.connect->NotifyDisconnect(&id_priv->id.comp_entry.Overlap);\r
        } else {\r
                event->event.event = RDMA_CM_EVENT_CONNECT_ERROR;\r
                event->id_priv->state = cma_disconnected;\r
@@ -962,12 +888,10 @@ __declspec(dllexport)
 int rdma_get_cm_event(struct rdma_event_channel *channel,\r
                                          struct rdma_cm_event **event)\r
 {\r
-       struct cma_event_channel *chan;\r
        struct cma_event *evt;\r
-       struct cma_id_private *id_priv;\r
        struct rdma_cm_id *id;\r
-       DWORD bytes;\r
-       HRESULT hr;\r
+       COMP_ENTRY *entry;\r
+       DWORD bytes, ret;\r
 \r
        evt = new struct cma_event;\r
        if (evt == NULL) {\r
@@ -977,28 +901,20 @@ int rdma_get_cm_event(struct rdma_event_channel *channel,
        do {\r
                RtlZeroMemory(evt, sizeof(struct cma_event));\r
 \r
-               chan = CONTAINING_RECORD(channel, struct cma_event_channel, channel);\r
-               hr = WaitForMultipleObjects(chan->count, chan->event, FALSE,\r
-                                                                       chan->channel.timeout);\r
-               if (hr == WAIT_TIMEOUT) {\r
-                       return hr;\r
-               } else if (hr == WAIT_FAILED) {\r
-                       return HRESULT_FROM_WIN32(GetLastError());\r
+               ret = CompChannelPoll(&channel->channel, &entry);\r
+               if (ret) {\r
+                       return ret;\r
                }\r
 \r
-               EnterCriticalSection(&chan->lock);\r
-               evt->id_priv = chan->id[hr];\r
-               LeaveCriticalSection(&chan->lock);\r
-\r
-               id = &evt->id_priv->id;\r
+               id = CONTAINING_RECORD(entry, struct rdma_cm_id, comp_entry);\r
+               evt->id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
                evt->event.id = id;\r
                evt->event.param.conn.private_data = evt->private_data;\r
-               if (id->ep.connect->GetOverlappedResult(&id->overlap, &bytes, FALSE) == 0) {\r
-                       evt->event.status = HRESULT_FROM_WIN32(GetLastError());\r
-               }\r
+               evt->event.status = id->ep.connect->\r
+                                                       GetOverlappedResult(&entry->Overlap, &bytes, FALSE);\r
 \r
-               hr = ucma_process_event(evt);\r
-       } while (FAILED(hr));\r
+               ret = ucma_process_event(evt);\r
+       } while (ret);\r
        \r
        *event = &evt->event;\r
        return 0;\r
@@ -1069,16 +985,6 @@ int rdma_set_option(struct rdma_cm_id *id, int level, int optname,
 __declspec(dllexport)\r
 int rdma_migrate_id(struct rdma_cm_id *id, struct rdma_event_channel *channel)\r
 {\r
-       struct cma_id_private *id_priv;\r
-\r
-       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
-       cma_event_channel_remove_id(id->channel, id_priv);\r
-       /*\r
-        * TODO: To support calling this routine while processing events on the old\r
-        * channel, we need to wait for all old events to be acknowledged.\r
-        */\r
        id->channel = channel;\r
-       cma_event_channel_insert_id(channel, id_priv);\r
-\r
        return 0;\r
 }\r