libibverbs: use comp_channel to enhance scalability
authorshefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 11 Mar 2009 22:07:21 +0000 (22:07 +0000)
committershefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 11 Mar 2009 22:07:21 +0000 (22:07 +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@2025 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

ulp/libibverbs/include/infiniband/verbs.h
ulp/libibverbs/src/Sources
ulp/libibverbs/src/device.cpp
ulp/libibverbs/src/ibv_exports.src
ulp/libibverbs/src/ibverbs.h
ulp/libibverbs/src/verbs.cpp

index c849d75..6841463 100644 (file)
@@ -37,6 +37,8 @@
 \r
 #include <windows.h>\r
 #include <rdma\winverbs.h>\r
+#include <errno.h>\r
+#include <comp_channel.h>\r
 \r
 #ifdef __cplusplus\r
 extern "C" {\r
@@ -51,6 +53,16 @@ typedef unsigned __int16     uint16_t;
 typedef unsigned __int32       uint32_t;\r
 typedef unsigned __int64       uint64_t;\r
 \r
+#define EOVERFLOW              WV_BUFFER_OVERFLOW\r
+#define EISCONN                        WV_CONNECTION_ACTIVE\r
+#define ECONNREFUSED   WV_CONNECTION_REFUSED\r
+#define ETIMEDOUT              WV_TIMEOUT\r
+#define ENETUNREACH            WV_HOST_UNREACHABLE\r
+#define EADDRINUSE             WV_ADDRESS_ALREADY_EXISTS\r
+#define EALREADY               WV_IO_PENDING\r
+#define EAFNOSUPPORT   WV_INVALID_ADDRESS\r
+#define EWOULDBLOCK            WV_DEVICE_BUSY\r
+\r
 union ibv_gid\r
 {\r
        uint8_t                 raw[16];\r
@@ -636,8 +648,8 @@ struct ibv_qp
 \r
 struct ibv_comp_channel\r
 {\r
-       struct ibv_context     *context;\r
-       uint32_t                                timeout;\r
+       struct ibv_context              *context;\r
+       COMP_CHANNEL                    comp_channel;\r
 };\r
 \r
 struct ibv_cq\r
@@ -646,9 +658,8 @@ struct ibv_cq
        struct ibv_comp_channel *channel;\r
        void                                    *cq_context;\r
        IWVCompletionQueue              *handle;\r
-       OVERLAPPED                              overlap;\r
        int                                             cqe;\r
-       uint32_t                                comp_events_completed;\r
+       COMP_ENTRY                              comp_entry;\r
 };\r
 \r
 struct ibv_ah\r
@@ -678,7 +689,7 @@ struct ibv_context
 {\r
        struct ibv_device               *device;\r
        IWVDevice                               *cmd_if;\r
-       uint32_t                                timeout;\r
+       COMP_CHANNEL                    channel;\r
 };\r
 \r
 /**\r
@@ -1103,6 +1114,23 @@ const char *ibv_port_state_str(enum ibv_port_state port_state);
 __declspec(dllexport)\r
 const char *ibv_event_type_str(enum ibv_event_type event);\r
 \r
+/*\r
+ * Windows specific structures and interfaces\r
+ */\r
+struct ibv_windata\r
+{\r
+       IWVProvider             *prov;\r
+       COMP_MANAGER    *comp_mgr;\r
+};\r
+\r
+#define IBV_WINDATA_VERSION 1\r
+\r
+__declspec(dllexport)\r
+int ibv_get_windata(struct ibv_windata *windata, int version);\r
+\r
+__declspec(dllexport)\r
+void ibv_release_windata(struct ibv_windata *windata, int version);\r
+\r
 #ifdef __cplusplus\r
 }\r
 #endif\r
index aef0946..ee9e40b 100644 (file)
@@ -14,7 +14,7 @@ DLLDEF = $(OBJ_PATH)\$O\ibv_exports.def
 !endif\r
 \r
 DLLENTRY = DllMain\r
-USE_MSVCRT=1\r
+USE_MSVCRT = 1\r
 \r
 SOURCES = \\r
        ibverbs.rc              \\r
index af63338..58a2ec5 100644 (file)
 #include <stdio.h>\r
 #include <infiniband/verbs.h>\r
 #include <rdma/winverbs.h>\r
+#include "..\..\..\etc\user\comp_channel.cpp"\r
 \r
 IWVProvider *prov;\r
+COMP_MANAGER comp_mgr;\r
 \r
 struct verbs_device\r
 {\r
@@ -43,35 +45,53 @@ struct verbs_device
 \r
 struct verbs_port\r
 {\r
-       OVERLAPPED                      overlap;\r
+       COMP_ENTRY                      comp_entry;\r
        DWORD                           event_flag;\r
+       uint8_t                         port_num;\r
 };\r
 \r
-#define EVENT_PORT_NONE        0xFF\r
-\r
 struct verbs_context\r
 {\r
        struct ibv_context      context;\r
        struct verbs_device     device;\r
-       HANDLE                          *event;\r
        struct verbs_port       *port;\r
-       uint8_t                         event_port_index;\r
+       verbs_port                      *event_port;\r
 };\r
 \r
-__declspec(dllexport)\r
-IWVProvider *ibv_get_winverbs(void)\r
+static int ibv_init(void)\r
 {\r
        HRESULT hr;\r
 \r
        if (prov == NULL) {\r
                hr = WvGetObject(IID_IWVProvider, (LPVOID*) &prov);\r
                if (FAILED(hr)) {\r
-                       return NULL;\r
+                       return -1;\r
                }\r
+               CompManagerOpen(&comp_mgr);\r
+               CompManagerMonitor(&comp_mgr, prov->GetFileHandle(), 0);\r
+       }\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int ibv_get_windata(struct ibv_windata *windata, int version)\r
+{\r
+       int ret;\r
+\r
+       if (version != IBV_WINDATA_VERSION || ibv_init()) {\r
+               return -1;\r
        }\r
 \r
        prov->AddRef();\r
-       return prov;\r
+       windata->prov = prov;\r
+       windata->comp_mgr = &comp_mgr;\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+void ibv_release_windata(struct ibv_windata *windata, int version)\r
+{\r
+       windata->prov->Release();\r
 }\r
 \r
 __declspec(dllexport)\r
@@ -84,11 +104,8 @@ struct ibv_device **ibv_get_device_list(int *num)
        SIZE_T size, cnt;\r
        HRESULT hr;\r
 \r
-       if (prov == NULL) {\r
-               hr = WvGetObject(IID_IWVProvider, (LPVOID*) &prov);\r
-               if (FAILED(hr)) {\r
-                       goto err1;\r
-               }       \r
+       if (ibv_init()) {\r
+               goto err1;\r
        }\r
 \r
        cnt = 0;\r
@@ -179,45 +196,30 @@ struct ibv_context *ibv_open_device(struct ibv_device *device)
                return NULL;\r
        }\r
        memcpy(&vcontext->device, vdev, sizeof(struct verbs_device));\r
-       vcontext->event_port_index = EVENT_PORT_NONE;\r
-       vcontext->context.timeout = INFINITE;\r
+       vcontext->event_port = NULL;\r
+       CompChannelInit(&comp_mgr, &vcontext->context.channel, INFINITE);\r
 \r
        vcontext->port = new struct verbs_port[vdev->phys_port_cnt];\r
        if (vcontext->port == NULL) {\r
                goto err1;\r
        }\r
 \r
-       vcontext->event = new HANDLE[vdev->phys_port_cnt];\r
-       if (vcontext->event == NULL) {\r
-               goto err2;\r
-       }\r
-\r
        hr = prov->OpenDevice(vdev->guid, &vcontext->context.cmd_if);\r
        if (FAILED(hr)) {\r
-               goto err3;\r
+               goto err2;\r
        }\r
 \r
        for (i = 0; i < vdev->phys_port_cnt; i++) {\r
-               vcontext->event[i] = CreateEvent(NULL, FALSE, FALSE, NULL);\r
-               if (vcontext->event[i] == NULL) {\r
-                       goto err4;\r
-               }\r
-               vcontext->port[i].overlap.hEvent = vcontext->event[i];\r
+               vcontext->port[i].port_num = (uint8_t) i + 1;\r
                vcontext->port[i].event_flag = 0;\r
-\r
-               vcontext->context.cmd_if->Notify((UINT8) i + 1,\r
-                                                                                &vcontext->port[i].overlap,\r
+               CompEntryInit(&vcontext->context.channel, &vcontext->port[i].comp_entry);\r
+               vcontext->context.cmd_if->Notify(vcontext->port[i].port_num,\r
+                                                                                &vcontext->port[i].comp_entry.Overlap,\r
                                                                                 &vcontext->port[i].event_flag);\r
        }\r
 \r
        return &vcontext->context;\r
 \r
-err4:\r
-       while (--i >= 0) {\r
-               CloseHandle(vcontext->event[i]);\r
-       }\r
-err3:\r
-       delete vcontext->event;\r
 err2:\r
        delete vcontext->port;\r
 err1:\r
@@ -235,11 +237,10 @@ int ibv_close_device(struct ibv_context *context)
        context->cmd_if->CancelOverlappedRequests();\r
 \r
        for (i = 0; i < vcontext->device.phys_port_cnt; i++) {\r
-               CloseHandle(vcontext->event[i]);\r
+               CompChannelRemoveEntry(&context->channel, &vcontext->port[i].comp_entry);\r
        }\r
 \r
        context->cmd_if->Release();\r
-       delete vcontext->event;\r
        delete vcontext->port;\r
        delete vcontext;\r
        return 0;\r
@@ -250,7 +251,7 @@ static enum ibv_event_type ibv_get_port_event_state(struct verbs_context *vconte
        WV_PORT_ATTRIBUTES attr;\r
        HRESULT hr;\r
 \r
-       hr = vcontext->context.cmd_if->QueryPort(vcontext->event_port_index + 1, &attr);\r
+       hr = vcontext->context.cmd_if->QueryPort(vcontext->event_port->port_num, &attr);\r
        if (FAILED(hr)) {\r
                return IBV_EVENT_PORT_ERR;\r
        }\r
@@ -265,8 +266,8 @@ static int ibv_report_port_event(struct verbs_context *vcontext,
        struct verbs_port *port;\r
        int ret = 0;\r
 \r
-       port = &vcontext->port[vcontext->event_port_index];\r
-       event->element.port_num = vcontext->event_port_index + 1;\r
+       port = vcontext->event_port;\r
+       event->element.port_num = port->port_num;\r
 \r
        if (port->event_flag & WV_EVENT_ERROR) {\r
                event->event_type = IBV_EVENT_DEVICE_FATAL;\r
@@ -289,9 +290,10 @@ static int ibv_report_port_event(struct verbs_context *vcontext,
        }\r
        \r
        if (port->event_flag == 0) {\r
-               vcontext->context.cmd_if->Notify(vcontext->event_port_index + 1,\r
-                                                                                &port->overlap, &port->event_flag);\r
-               vcontext->event_port_index = EVENT_PORT_NONE;\r
+               vcontext->context.cmd_if->Notify(vcontext->event_port->port_num,\r
+                                                                                &port->comp_entry.Overlap,\r
+                                                                                &port->event_flag);\r
+               vcontext->event_port = NULL;\r
        }\r
        return ret;\r
 }\r
@@ -301,26 +303,23 @@ int ibv_get_async_event(struct ibv_context *context,
                                                struct ibv_async_event *event)\r
 {\r
        struct verbs_context *vcontext;\r
-       HRESULT hr;\r
-       int i;\r
+       COMP_ENTRY *entry;\r
+       int ret;\r
 \r
        vcontext = CONTAINING_RECORD(context, struct verbs_context, context);\r
-       if (vcontext->event_port_index != EVENT_PORT_NONE) {\r
+       if (vcontext->event_port) {\r
                if (ibv_report_port_event(vcontext, event) == 0) {\r
                        return 0;\r
                }\r
        }\r
 \r
-       hr = WaitForMultipleObjects(vcontext->device.phys_port_cnt,\r
-                                                               vcontext->event, FALSE, context->timeout);\r
-       if (hr == WAIT_TIMEOUT) {\r
-               return hr;\r
-       } else if (hr == WAIT_FAILED) {\r
-               return HRESULT_FROM_WIN32(GetLastError());\r
+       ret = CompChannelPoll(&context->channel, &entry);\r
+       if (!ret) {\r
+               vcontext->event_port = CONTAINING_RECORD(entry, struct verbs_port, comp_entry);\r
+               ret = ibv_report_port_event(vcontext, event);\r
        }\r
 \r
-       vcontext->event_port_index = (UINT8) hr;\r
-       return ibv_report_port_event(vcontext, event);\r
+       return ret;\r
 }\r
 \r
 __declspec(dllexport)\r
index 4698d94..63f274e 100644 (file)
@@ -51,4 +51,6 @@ ibv_detach_mcast
 ibv_node_type_str\r
 ibv_port_state_str\r
 ibv_event_type_str\r
+ibv_get_windata\r
+ibv_release_windata\r
 #endif\r
index 834b178..baf012c 100644 (file)
@@ -1,6 +1,5 @@
 /*\r
- * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.\r
- * Copyright (c) 2007 Cisco Systems, Inc.  All rights reserved.\r
+ * Copyright (c) 2009 Intel Corp, Inc.  All rights reserved.\r
  *\r
  * This software is available to you under the OpenIB.org BSD license\r
  * below:\r
@@ -31,6 +30,8 @@
 #ifndef IB_VERBS_H\r
 #define IB_VERBS_H\r
 \r
+extern COMP_MANAGER comp_mgr;\r
+\r
 __inline void* __cdecl operator new(size_t size)\r
 {\r
        return HeapAlloc(GetProcessHeap(), 0, size);\r
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