libibverbs: use comp_channel to enhance scalability
[mirror/winof/.git] / ulp / libibverbs / src / verbs.cpp
index a25d430..ca80d1a 100644 (file)
@@ -1,7 +1,7 @@
 /*\r
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.\r
  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.\r
- * Copyright (c) 2008 Intel Corporation.  All rights reserved.\r
+ * Copyright (c) 2008-2009 Intel Corporation.  All rights reserved.\r
  *\r
  * This software is available to you under the OpenIB.org BSD license\r
  * below:\r
 #include <stdio.h>\r
 \r
 #include <infiniband/verbs.h>\r
+#include <comp_channel.h>\r
 #include "ibverbs.h"\r
 \r
-struct verbs_cq\r
-{\r
-       struct ibv_cq                           cq;\r
-       int                                                     channel_index;\r
-};\r
-\r
-struct verbs_comp_channel\r
-{\r
-       struct ibv_comp_channel         channel;\r
-       CRITICAL_SECTION                        lock;\r
-       struct verbs_cq                         *cq[MAXIMUM_WAIT_OBJECTS];\r
-       HANDLE                                          event[MAXIMUM_WAIT_OBJECTS];\r
-       int                                                     count;\r
-};\r
-\r
 __declspec(dllexport)\r
 int ibv_rate_to_mult(enum ibv_rate rate)\r
 {\r
@@ -64,7 +50,7 @@ int ibv_rate_to_mult(enum ibv_rate rate)
        case IBV_RATE_60_GBPS:  return 24;\r
        case IBV_RATE_80_GBPS:  return 32;\r
        case IBV_RATE_120_GBPS: return 48;\r
-       default:           return -1;\r
+       default:                                return -1;\r
        }\r
 }\r
 \r
@@ -322,124 +308,60 @@ int ibv_dereg_mr(struct ibv_mr *mr)
 __declspec(dllexport)\r
 struct ibv_comp_channel *ibv_create_comp_channel(struct ibv_context *context)\r
 {\r
-       struct verbs_comp_channel *vchan;\r
+       struct ibv_comp_channel *channel;\r
 \r
-       vchan = new struct verbs_comp_channel;\r
-       if (vchan == NULL) {\r
+       channel = new struct ibv_comp_channel;\r
+       if (channel == NULL) {\r
                return NULL;\r
        }\r
 \r
-       InitializeCriticalSection(&vchan->lock);\r
-       vchan->count = 0;\r
-       vchan->channel.context = context;\r
-       vchan->channel.timeout = INFINITE;\r
-\r
-       return &vchan->channel;\r
+       CompChannelInit(&comp_mgr, &channel->comp_channel, INFINITE);\r
+       channel->context = context;\r
+       return channel;\r
 }\r
 \r
 __declspec(dllexport)\r
 int ibv_destroy_comp_channel(struct ibv_comp_channel *channel)\r
 {\r
-       struct verbs_comp_channel *vchan;\r
-\r
-       vchan = CONTAINING_RECORD(channel, struct verbs_comp_channel, channel);\r
-       if (vchan->count > 0) {\r
-               return -1;\r
-       }\r
-\r
-       DeleteCriticalSection(&vchan->lock);    \r
-       delete vchan;\r
+       CompChannelCleanup(&channel->comp_channel);\r
+       delete channel;\r
        return 0;\r
 }\r
 \r
-static int ibv_comp_channel_insert_cq(struct ibv_comp_channel *channel,\r
-                                                                         struct verbs_cq *cq)\r
-{\r
-       struct verbs_comp_channel *vchan;\r
-       int ret = 0;\r
-\r
-       vchan = CONTAINING_RECORD(channel, struct verbs_comp_channel, channel);\r
-\r
-       EnterCriticalSection(&vchan->lock);\r
-       if (vchan->count == MAXIMUM_WAIT_OBJECTS) {\r
-               ret = -1;\r
-               goto out;\r
-       }\r
-\r
-       vchan->cq[vchan->count] = cq;\r
-       vchan->event[vchan->count] = cq->cq.overlap.hEvent;\r
-       cq->channel_index = vchan->count++;\r
-out:\r
-       LeaveCriticalSection(&vchan->lock);\r
-       return ret;\r
-}\r
-\r
-/*\r
- * TODO: we cannot call ibv_comp_channel_remove_cq() while another\r
- * thread is calling ibv_get_cq_event().  If this is needed, then we\r
- * need to halt the ibv_get_cq_event() thread, modify the event list,\r
- * then restart the ibv_get_cq_event() thread.\r
- */\r
-static void ibv_comp_channel_remove_cq(struct ibv_comp_channel *channel,\r
-                                                                          struct verbs_cq *cq)\r
-{\r
-       struct verbs_comp_channel *vchan;\r
-\r
-       vchan = CONTAINING_RECORD(channel, struct verbs_comp_channel, channel);\r
-\r
-       EnterCriticalSection(&vchan->lock);\r
-       vchan->count--;\r
-       vchan->cq[cq->channel_index] = vchan->cq[vchan->count];\r
-       vchan->event[cq->channel_index] = vchan->event[vchan->count];\r
-       vchan->cq[cq->channel_index]->channel_index = cq->channel_index;\r
-       LeaveCriticalSection(&vchan->lock);\r
-}\r
-\r
 __declspec(dllexport)\r
 struct ibv_cq *ibv_create_cq(struct ibv_context *context, int cqe, void *cq_context,\r
                                                         struct ibv_comp_channel *channel, int comp_vector)\r
 {\r
-       struct verbs_cq *vcq;\r
+       struct ibv_cq *cq;\r
        HRESULT hr;\r
        SIZE_T entries;\r
 \r
-       vcq = new struct verbs_cq;\r
-       if (vcq == NULL) {\r
+       cq = new struct ibv_cq;\r
+       if (cq == NULL) {\r
                return NULL;\r
        }\r
 \r
-       vcq->cq.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
-       if (vcq->cq.overlap.hEvent == NULL) {\r
-               goto err1;\r
-       }\r
-\r
-       vcq->cq.context = context;\r
-       vcq->cq.channel = channel;\r
-       vcq->cq.cq_context = cq_context;\r
-       vcq->cq.comp_events_completed = 0;\r
+       cq->context = context;\r
+       cq->channel = channel;\r
+       cq->cq_context = cq_context;\r
 \r
        entries = cqe;\r
-       hr = context->cmd_if->CreateCompletionQueue(&entries, &vcq->cq.handle);\r
+       hr = context->cmd_if->CreateCompletionQueue(&entries, &cq->handle);\r
        if (FAILED(hr)) {\r
-               goto err2;\r
+               goto err;\r
        }\r
 \r
        if (channel != NULL) {\r
-               hr = ibv_comp_channel_insert_cq(channel, vcq);\r
-               if (FAILED(hr)) {\r
-                       goto err3;\r
-               }\r
+               CompEntryInit(&channel->comp_channel, &cq->comp_entry);\r
+       } else {\r
+               memset(&cq->comp_entry, 0, sizeof cq->comp_entry);\r
        }\r
 \r
-       vcq->cq.cqe = (uint32_t) entries;\r
-       return &vcq->cq;\r
+       cq->cqe = (uint32_t) entries;\r
+       return cq;\r
 \r
-err3:\r
-       vcq->cq.handle->Release();\r
-err2:\r
-       CloseHandle(vcq->cq.overlap.hEvent);\r
-err1:\r
-       delete vcq;\r
+err:\r
+       delete cq;\r
        return NULL;\r
 }\r
 \r
@@ -460,8 +382,9 @@ __declspec(dllexport)
 int ibv_req_notify_cq(struct ibv_cq *cq, int solicited_only)\r
 {\r
        HRESULT hr;\r
+\r
        hr = cq->handle->Notify(solicited_only ? WvCqSolicited : WvCqNextCompletion,\r
-                                                       &cq->overlap);\r
+                                                       &cq->comp_entry.Overlap);\r
        if (SUCCEEDED(hr) || hr == WV_IO_PENDING) {\r
                return 0;\r
        } else {\r
@@ -486,19 +409,12 @@ int ibv_poll_cq(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc)
 __declspec(dllexport)\r
 int ibv_destroy_cq(struct ibv_cq *cq)\r
 {\r
-       struct verbs_cq *vcq;\r
-\r
-       vcq = CONTAINING_RECORD(cq, struct verbs_cq, cq);\r
-\r
        cq->handle->CancelOverlappedRequests();\r
 \r
        if (cq->channel != NULL) {\r
-               ibv_comp_channel_remove_cq(cq->channel, vcq);\r
+               CompChannelRemoveEntry(&cq->channel->comp_channel, &cq->comp_entry);\r
        }\r
 \r
-       while (cq->comp_events_completed > 0)\r
-               ; /* twiddle thumbs */\r
-\r
        cq->handle->Release();\r
        delete cq;\r
        return 0;\r
@@ -508,42 +424,21 @@ __declspec(dllexport)
 int ibv_get_cq_event(struct ibv_comp_channel *channel,\r
                                         struct ibv_cq **cq, void **cq_context)\r
 {\r
-       struct verbs_comp_channel *vchan;\r
-       struct verbs_cq *vcq;\r
-       HRESULT hr;\r
+       COMP_ENTRY *entry;\r
+       DWORD ret;\r
 \r
-       vchan = CONTAINING_RECORD(channel, struct verbs_comp_channel, channel);\r
-       hr = WaitForMultipleObjects(vchan->count, vchan->event, FALSE,\r
-                                                               vchan->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->comp_channel, &entry);\r
+       if (!ret) {\r
+               *cq = CONTAINING_RECORD(entry, struct ibv_cq, comp_entry);\r
+               *cq_context = (*cq)->cq_context;\r
        }\r
 \r
-       EnterCriticalSection(&vchan->lock);\r
-       vcq = vchan->cq[hr];\r
-       vcq->cq.comp_events_completed++;\r
-       LeaveCriticalSection(&vchan->lock);\r
-\r
-       *cq = &vcq->cq;\r
-       *cq_context = vcq->cq.cq_context;\r
-       return 0;\r
+       return ret;\r
 }\r
 \r
 __declspec(dllexport)\r
 void ibv_ack_cq_events(struct ibv_cq *cq, unsigned int nevents)\r
 {\r
-       struct verbs_comp_channel *vchan;\r
-\r
-       if (cq->channel == NULL) {\r
-               return;\r
-       }\r
-\r
-       vchan = CONTAINING_RECORD(cq->channel, struct verbs_comp_channel, channel);\r
-       EnterCriticalSection(&vchan->lock);\r
-       cq->comp_events_completed -= nevents;\r
-       LeaveCriticalSection(&vchan->lock);\r
 }\r
 \r
 __declspec(dllexport)\r