[SDP] Implementation of overlapped send (Rev 817)
authortzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 19 Dec 2005 08:49:41 +0000 (08:49 +0000)
committertzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 19 Dec 2005 08:49:41 +0000 (08:49 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@205 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

16 files changed:
ulp/sdp/include/SdpShared.h
ulp/sdp/kernel/Precompile.h
ulp/sdp/kernel/SdpArp.cpp
ulp/sdp/kernel/SdpArp.h
ulp/sdp/kernel/SdpBufferPool.cpp
ulp/sdp/kernel/SdpBufferPool.h
ulp/sdp/kernel/SdpDriver.cpp
ulp/sdp/kernel/SdpGenUtils.cpp
ulp/sdp/kernel/SdpGenUtils.h
ulp/sdp/kernel/SdpLock.h
ulp/sdp/kernel/SdpRecvPool.cpp
ulp/sdp/kernel/SdpSocket.cpp
ulp/sdp/kernel/SdpSocket.h
ulp/sdp/kernel/SdpUserFile.cpp
ulp/sdp/kernel/SdpUserFile.h
ulp/sdp/todo

index 6f7374e..317ddef 100644 (file)
@@ -50,6 +50,7 @@
 #define IOCTL_WSP_ACCEPT        CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
 #define IOCTL_WSP_GET_XXX_NAME  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
 #define IOCTL_WSP_CLOSE_SOCKET  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
+#define IOCTL_WSP_USER_THREAD   CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80A, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
 \r
 \r
 // Data structures that are used for connect\r
index 6b54a42..f4d0707 100644 (file)
@@ -41,8 +41,7 @@ class SdpSocket;
 class SdpArp;\r
 \r
 #include "ib_al.h"\r
-#include "..\..\ipoib\ip_addresses_shared.h"\r
-\r
+#include "..\..\..\inc\iba\ib_at_ioctl.h"\r
 #include "sdpMsgs.h"\r
 #include "SdpGenUtils.h"\r
 #include "SdpTrace.h"\r
index eedf8cf..7555600 100644 (file)
@@ -46,7 +46,7 @@ SdpArp::Init(PDRIVER_OBJECT  DriverObject)
 \r
     OBJECT_ATTRIBUTES objectAttributes;\r
 \r
-    RtlInitUnicodeString( &DevName1, IPOIB_DEV_NAME );\r
+    RtlInitUnicodeString( &DevName1, IBAT_DEV_NAME );\r
 \r
     InitializeObjectAttributes( &objectAttributes,\r
                                 &DevName1,\r
@@ -138,20 +138,19 @@ SdpArp::SourcePortGidFromIP(
     IO_STATUS_BLOCK    ioStatus;\r
     char temp [1000]; // BUGBUG: Handle the case of more IPs\r
     \r
-    IOCTL_IPOIB_PORTS_IN ipoib_ports_in;\r
-    IOCTL_IPOIB_PORTS_OUT *pipoib_ports_out;\r
-    IPOIB_AT_PORT_RECORD *ports_records;\r
+    IOCTL_IBAT_PORTS_IN ipoib_ports_in;\r
+    IOCTL_IBAT_PORTS_OUT *pipoib_ports_out;\r
+    IBAT_PORT_RECORD *ports_records;\r
 \r
-    ipoib_ports_in.Version = IPOIB_IOCTL_VERSION;\r
-    ipoib_ports_in.Size = sizeof temp;\r
+    ipoib_ports_in.Version = IBAT_IOCTL_VERSION;\r
 \r
-    pipoib_ports_out = (IOCTL_IPOIB_PORTS_OUT *)temp;\r
+    pipoib_ports_out = (IOCTL_IBAT_PORTS_OUT *)temp;\r
 \r
     ASSERT(m_DeviceObject != NULL);\r
 \r
     KeInitializeEvent(&event, NotificationEvent, FALSE);\r
     irp = IoBuildDeviceIoControlRequest(\r
-                IOCTL_IPOIB_PORTS ,\r
+                IOCTL_IBAT_PORTS ,\r
                 m_DeviceObject,\r
                 &ipoib_ports_in,\r
                 sizeof ipoib_ports_in,\r
@@ -180,7 +179,7 @@ SdpArp::SourcePortGidFromIP(
         SDP_PRINT(SDP_ERR, SDP_ARP, ("IoCallDriver failed rc = 0x%x\n", rc ));        \r
         goto Cleanup;\r
     }\r
-    if (pipoib_ports_out->Size != 0) {\r
+    if (pipoib_ports_out->Size > sizeof temp) {\r
         // The number of bytes that we have allocated wasn't enough\r
         SDP_PRINT(SDP_ERR, SDP_ARP, ("pipoib_ports_out.Size = %d\n", pipoib_ports_out->Size ));\r
         rc = STATUS_INSUFFICIENT_RESOURCES;\r
@@ -201,7 +200,7 @@ Cleanup:
 NTSTATUS\r
 SdpArp::SourcePortGidFromPorts(\r
     IN  ULONG  SourceAddr, \r
-    IN  IOCTL_IPOIB_PORTS_OUT *pPorts, \r
+    IN  IOCTL_IBAT_PORTS_OUT *pPorts, \r
     OUT ib_net64_t *SrcPortGuid,\r
     OUT ib_net64_t *SrcCaGuid\r
     )\r
@@ -212,14 +211,14 @@ SdpArp::SourcePortGidFromPorts(
     PIRP               irp;\r
     IO_STATUS_BLOCK    ioStatus;\r
     \r
-    unsigned int i = 0, j = 0;\r
+    int i = 0, j = 0;\r
 \r
-    struct IOCTL_IPOIB_IP_ADDRESSES_IN addresses_in;\r
-    struct IOCTL_IPOIB_IP_ADDRESSES_OUT *addresses_out;\r
+    IOCTL_IBAT_IP_ADDRESSES_IN addresses_in;\r
+    IOCTL_IBAT_IP_ADDRESSES_OUT *addresses_out;\r
     char temp[1000];\r
-    addresses_out = (struct IOCTL_IPOIB_IP_ADDRESSES_OUT *)temp;\r
+    addresses_out = (IOCTL_IBAT_IP_ADDRESSES_OUT *)temp;\r
 \r
-    addresses_in.Version = IPOIB_IOCTL_VERSION;\r
+    addresses_in.Version = IBAT_IOCTL_VERSION;\r
 \r
     for (i = 0 ; i < pPorts->NumPorts; i++) {\r
         SDP_PRINT(SDP_TRACE, SDP_SOCKET, (\r
@@ -233,7 +232,7 @@ SdpArp::SourcePortGidFromPorts(
 \r
         KeInitializeEvent(&event, NotificationEvent, FALSE);\r
         irp = IoBuildDeviceIoControlRequest(\r
-                    IOCTL_IPOIB_IP_ADDRESSES ,\r
+                    IOCTL_IBAT_IP_ADDRESSES ,\r
                     m_DeviceObject,\r
                     &addresses_in,\r
                     sizeof addresses_in,\r
@@ -262,7 +261,7 @@ SdpArp::SourcePortGidFromPorts(
             SDP_PRINT(SDP_ERR, SDP_ARP, ("IoCallDriver failed rc = 0x%x\n", rc ));        \r
             goto Cleanup;\r
         }\r
-        if (addresses_out->Size != 0) {\r
+        if (addresses_out->Size > sizeof temp) {\r
         // The number of bytes that we have allocated wasn't enough\r
             SDP_PRINT(SDP_ERR, SDP_ARP, ("addresses_out.Size = %d\n", addresses_out->Size ));\r
             rc = STATUS_INSUFFICIENT_RESOURCES;\r
@@ -272,10 +271,10 @@ SdpArp::SourcePortGidFromPorts(
 \r
 \r
         // We now have the addreses, we can check if this is what we need\r
-        for (j = 0 ; j < addresses_out->NumIps; j++) {\r
+        for (j = 0 ; j < addresses_out->AddressCount; j++) {\r
             ULONG *pIp;\r
-            ASSERT(addresses_out->Addreses[j].IpVersion == 4);\r
-            pIp = (ULONG *) (&addresses_out->Addreses[j].Data[12]);\r
+            ASSERT(addresses_out->Address[j].IpVersion == 4);\r
+            pIp = (ULONG *) (&addresses_out->Address[j].Address[12]);\r
             if (*pIp == CL_NTOH32(SourceAddr)) {\r
                 SDP_PRINT(SDP_TRACE, SDP_ARP, \r
                     ("Found the IP: ca guid = 0x%I64x port guid=0x%I64x\n", \r
@@ -290,6 +289,13 @@ SdpArp::SourcePortGidFromPorts(
 \r
     }\r
     // If we have reached here the data was not found\r
+    SDP_PRINT(SDP_WARN, SDP_ARP, \r
+        ("HCA not found for ip=%d.%d.%d.%d\n",        \r
+        (SourceAddr & 0xff000000) >> 24,\r
+        (SourceAddr & 0xff0000) >> 16,\r
+        (SourceAddr & 0xff00) >> 8 ,        \r
+        SourceAddr & 0xff\r
+        ));\r
     rc = STATUS_NOT_FOUND;\r
 \r
 Cleanup:\r
@@ -300,27 +306,32 @@ Cleanup:
 \r
 NTSTATUS \r
 SdpArp::DestPortGidFromMac(\r
+    IN  ib_net64_t  SrcPortGuid,\r
     IN  MAC_ADDR  DestMac, \r
     OUT ib_gid_t   *pDestPortGid)\r
 {\r
-    SDP_PRINT(SDP_TRACE, SDP_SOCKET,("MAC = ????"));\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET,("MAC = ????\n"));\r
     NTSTATUS rc = STATUS_SUCCESS;\r
 \r
     KEVENT             event;\r
     PIRP               irp;\r
     IO_STATUS_BLOCK    ioStatus;\r
 \r
-    IOCTL_IPOIB_MAC_2_GID_IN ipoib_mac2gid_in;\r
-    IOCTL_IPOIB_MAC_2_GID_OUT ipoib_mac2gid_out;\r
+    IOCTL_IBAT_MAC_TO_GID_IN ipoib_mac2gid_in;\r
+    IOCTL_IBAT_MAC_TO_GID_OUT ipoib_mac2gid_out;\r
 \r
     C_ASSERT(MAC_ADDR_SIZE == sizeof (ipoib_mac2gid_in.DestMac));\r
+    ipoib_mac2gid_in.Version = IBAT_IOCTL_VERSION;\r
+    ipoib_mac2gid_in.PortGuid = SrcPortGuid;\r
     memcpy(ipoib_mac2gid_in.DestMac, DestMac, MAC_ADDR_SIZE);\r
+    \r
+\r
 \r
     ASSERT(m_DeviceObject != NULL);\r
 \r
     KeInitializeEvent(&event, NotificationEvent, FALSE);\r
     irp = IoBuildDeviceIoControlRequest(\r
-                IOCTL_IPOIB_MAC_2_GID ,\r
+                IOCTL_IBAT_MAC_TO_GID ,\r
                 m_DeviceObject,\r
                 &ipoib_mac2gid_in,\r
                 sizeof ipoib_mac2gid_in,\r
index 2ce7064..ec7e0b2 100644 (file)
@@ -73,7 +73,8 @@ public:
         OUT ib_net64_t *SrcCaGuid\r
         );\r
     NTSTATUS DestPortGidFromMac(\r
-        IN  MAC_ADDR  DestMac, \r
+        IN  ib_net64_t  SrcPortGuid,\r
+        IN  MAC_ADDR    DestMac, \r
         OUT ib_gid_t   *pDestPortGid);\r
 \r
 /* \r
@@ -104,7 +105,7 @@ Synchronously query the SA for a GUID. (started from wsd - query_pr)
     NTSTATUS\r
     SourcePortGidFromPorts(\r
         IN  ULONG  SourceAddr, \r
-        IN  IOCTL_IPOIB_PORTS_OUT *pPorts, \r
+        IN  IOCTL_IBAT_PORTS_OUT *pPorts,  \r
         OUT ib_net64_t *SrcPortGuid,\r
         OUT ib_net64_t *SrcCaGuid\r
         );\r
index 3b40eef..f8ccc62 100644 (file)
@@ -96,6 +96,7 @@ BufferDescriptor::DeAllocateBuffer(BufferDescriptor *pBufferDescriptor, int Tag)
     ExFreePoolWithTag(pBufferDescriptor, Tag);\r
 \r
 }\r
+\r
 /*\r
     Currently the implmentation of shutdown should allow it to work, even without\r
     init being called\r
@@ -104,10 +105,8 @@ BufferPool::BufferPool()
 {\r
     m_SendSeq = 0;\r
     m_AdvtSeq = 0;\r
-    m_ClientBeingServed = false;\r
     m_CurrentlySentBuffers = 0;\r
     m_CurrentlyAllocated = 0;\r
-    m_ClientWaiting = false;\r
     m_PostCreditsWhenCan = false;\r
     m_CreditsCurrentlyPosted = false;\r
     m_CreditdBufferDescriptor = NULL;\r
@@ -131,7 +130,6 @@ BufferPool::Init(
     m_MaxBuffers = MaxBuffers;\r
     m_MaxConcurrentSends = MaxConcurrentSends;\r
     m_MaxMessageSize = MaxMessageSize;        \r
-    KeInitializeEvent(&m_WaitingClients, NotificationEvent, FALSE);\r
     ASSERT(pd != NULL);\r
     m_pd = pd;\r
     ASSERT(qp != NULL);    \r
@@ -139,6 +137,10 @@ BufferPool::Init(
     ASSERT(lkey != NULL);\r
     m_lkey = lkey;\r
     m_pSdpSocket = pSdpSocket;\r
+    m_CallBackPending = false;\r
+\r
+    \r
+\r
     return STATUS_SUCCESS;\r
 }\r
 \r
@@ -156,55 +158,32 @@ BufferPool::Init(
 */\r
 NTSTATUS \r
 BufferPool::GetBuffer(\r
-    BufferDescriptor **ppBufferDescriptor,    \r
-    KEVENT **ppEvent,\r
-    bool FirstBuffer\r
+    BufferDescriptor **ppBufferDescriptor\r
     )\r
 {\r
-    SDP_PRINT(SDP_DEBUG, SDP_BUFFER_POOL, ("this = 0x%p FirstBuffer = %s\n",this,\r
-        FirstBuffer ? "TRUE" : "FALSE"));\r
+    SDP_PRINT(SDP_DEBUG, SDP_BUFFER_POOL, ("this = 0x%p \n",this));\r
     AssertLocked();\r
 \r
     NTSTATUS rc = STATUS_SUCCESS;\r
     *ppBufferDescriptor = NULL;\r
 \r
-    if (m_ClientBeingServed == true && (FirstBuffer != false)) {\r
-        // The request can not be staisfied right now. We need to hold it\r
-        // until our request is being freed\r
-        // BUGBUG: iMPLMENT: create event and put it in the queue\r
-        // This might only happen when there are two threads calling us\r
-        ASSERT(FALSE);\r
-        return STATUS_UNEXPECTED_IO_ERROR;\r
-    }\r
-\r
-    if (FirstBuffer == true) {\r
-        m_ClientBeingServed = true; \r
-    }\r
-\r
-    // Can we supply a buffer right now ?\r
-   if (m_CurrentlySentBuffers < m_MaxConcurrentSends) {\r
-        // yes, supply a buffer\r
-        if (m_FreePackets.Size() > 0) {\r
-            LIST_ENTRY *item = m_FreePackets.RemoveHeadList();\r
-            *ppBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
-            goto Cleanup;\r
-        } else if (m_CurrentlyAllocated < m_MaxBuffers) {\r
-            // we need to alocate a new buffer\r
-            rc = BufferDescriptor::AllocateBuffer(ppBufferDescriptor, m_MaxMessageSize, SEND_BUFFERS_ALLOCATION_TAG);\r
-            if (!NT_SUCCESS(rc)) {\r
-                SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("AllocateBuffer failed rc = 0x%x\n", rc ));\r
-                ASSERT(*ppBufferDescriptor == NULL);\r
-                goto Cleanup;\r
-            }\r
-            m_CurrentlyAllocated++;\r
+    if (m_FreePackets.Size() > 0) {\r
+        LIST_ENTRY *item = m_FreePackets.RemoveHeadList();\r
+        *ppBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
+        goto Cleanup;\r
+    } else if (m_CurrentlyAllocated < m_MaxBuffers) {\r
+        // we need to alocate a new buffer\r
+        rc = BufferDescriptor::AllocateBuffer(ppBufferDescriptor, m_MaxMessageSize, SEND_BUFFERS_ALLOCATION_TAG);\r
+        if (!NT_SUCCESS(rc)) {\r
+            SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("AllocateBuffer failed rc = 0x%x\n", rc ));\r
+            ASSERT(*ppBufferDescriptor == NULL);\r
             goto Cleanup;\r
-        }        \r
-    } \r
-    // No buffers available, we have to wait\r
-    ASSERT(m_ClientWaiting == false);\r
-    KeClearEvent(&m_WaitingClients);\r
-    m_ClientWaiting = true;\r
-    *ppEvent = &m_WaitingClients;\r
+        }\r
+        m_CurrentlyAllocated++;\r
+        goto Cleanup;\r
+    }        \r
+    // No buffers available, we return NULL\r
+    ASSERT(*ppBufferDescriptor == NULL);\r
 \r
 Cleanup:    \r
     return rc;\r
@@ -226,6 +205,12 @@ BufferPool::AddBufferToQueuedList(BufferDescriptor *pBufferDescriptor)
     ASSERT(pBufferDescriptor->GetFlags() == 0 || \r
            pBufferDescriptor->GetFlags() == DISCONNECT_MESSAGE);\r
 \r
+    // Assert that we are not sending an empty buffer\r
+    if (pBufferDescriptor->DataSize == 0) {\r
+        msg_hdr_bsdh *pHeader = (msg_hdr_bsdh *) pBufferDescriptor->pBuffer;\r
+        ASSERT(pHeader->mid == SDP_MID_DISCONNECT );\r
+    }\r
+\r
     m_QueuedPackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
     rc = SendBuffersIfCan();\r
     if (!NT_SUCCESS(rc)) {\r
@@ -238,20 +223,6 @@ Cleanup:
 \r
 }\r
 \r
-/* \r
-    This function is being called by a client that has asked for some buffers\r
-    when he has recieved all it's data\r
-*/\r
-VOID \r
-BufferPool::AllowOthersToGet()\r
-{\r
-    ASSERT(m_ClientBeingServed == true);\r
-    m_ClientBeingServed = false;\r
-\r
-    // BUGBUG: this means that we should free the next waiter (Once we support more\r
-    // than one thread).\r
-}\r
-\r
 /*\r
     called when a send packet has finished.\r
 */\r
@@ -267,8 +238,7 @@ BufferPool::ReturnBuffer(BufferDescriptor *pBufferDescriptor)
 \r
 #if DBG    \r
     if (m_CurrentlySentBuffers == 1) {\r
-        SDP_PRINT(SDP_WARN, SDP_PERFORMANCE, ("Currently no packets are bing sent m_ClientWaiting = %s\n", \r
-                m_ClientWaiting ? "true" : "false"));        \r
+        SDP_PRINT(SDP_WARN, SDP_PERFORMANCE, ("Currently no packets are bing sent\n"));        \r
     }\r
 #endif\r
     ASSERT( pBufferDescriptor->GetFlags() == CREDIT_UPDATE ||\r
@@ -294,23 +264,183 @@ BufferPool::ReturnBuffer(BufferDescriptor *pBufferDescriptor)
         }\r
     } else {\r
         m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
-        // Is there a client waiting ?\r
-        if ( m_ClientWaiting) {\r
-            KeSetEvent( &m_WaitingClients, IO_NO_INCREMENT, FALSE );\r
-            m_ClientWaiting = false;        \r
+        // We have to ask for another thread to do the job, as\r
+        // we might be in a DPC context\r
+\r
+        // Ask for a new callback only in the following conditions:\r
+            // 1) There is no request on the way AND\r
+            // 2) There is a buffer that can be used AND\r
+            // 3) We have enough free space to complete a packet\r
+            // 4) We have gone under some threshold\r
+// TODO: 4 above, didn't seem to have a real influance, so it is not in\r
+// the code now. It should be testsed in the future.\r
+            if (!m_CallBackPending && (m_UserPackets.Size() > 0)) {\r
+            // Now testing 3,4\r
+\r
+            LIST_ENTRY *item = m_UserPackets.Head();\r
+            IRP * pIrp = CONTAINING_RECORD(item, IRP ,Tail.Overlay.ListEntry);\r
+            \r
+            if ((RemainingToCopy(pIrp) < m_MaxMessageSize * m_FreePackets.Size())) {\r
+                rc = m_pSdpSocket->RequestCallBack();\r
+                if (!NT_SUCCESS(rc)) {\r
+                    SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("PostCredits failed rc = 0x%x\n", rc ));\r
+                    goto Cleanup;\r
+                }        \r
+                m_CallBackPending = true;\r
+            }\r
         }\r
+\r
         if (DissconnectMessage) {\r
             SDP_PRINT(SDP_TRACE, SDP_BUFFER_POOL, ("We have recieved a DissconnectMessage complition\n" ));\r
             m_pSdpSocket->DisconectSentEvent();\r
         }\r
     }\r
-Cleanup:    \r
+Cleanup:\r
+    ASSERT(m_CurrentlySentBuffers != 0);\r
     m_CurrentlySentBuffers--;\r
-    ASSERT(m_CurrentlySentBuffers >= 0);\r
 \r
     return rc;\r
 }\r
 \r
+NTSTATUS \r
+BufferPool::AddToUserBuffers(\r
+                        bool *pCopied, \r
+                        bool ForceCopy,\r
+                        char *pData, \r
+                        uint32_t BufferSize, \r
+                        uint32_t Coppied, \r
+                        IRP* pIrp\r
+                        )\r
+{\r
+    SDP_PRINT(SDP_DEBUG, SDP_BUFFER_POOL, ("this = 0x%p \n",this));\r
+    AssertLocked();\r
+    NTSTATUS rc = STATUS_SUCCESS;\r
+\r
+    if ((m_UserPackets.Size() == 0) && (ForceCopy == false) ){\r
+        *pCopied = false;\r
+        goto Cleanup;\r
+    }\r
+\r
+    // We have to queue this IRP (following logic from sample)\r
+    ASSERT(pData != NULL);\r
+    SetBufferSize(pIrp, BufferSize);\r
+    SetUserBuffer(pIrp, pData);\r
+    SetCoppied(pIrp,Coppied);\r
+    SetSocket(pIrp,m_pSdpSocket);\r
+\r
+\r
+    ASSERT(m_UserPackets.Size()==0);\r
+    IoMarkIrpPending(pIrp);\r
+    m_UserPackets.InsertTailList(&pIrp->Tail.Overlay.ListEntry);\r
+    *pCopied = true;\r
+    // We mark the IRP as pending\r
+    pIrp->IoStatus.Status = STATUS_PENDING;\r
+    rc = STATUS_PENDING;\r
+\r
+Cleanup:\r
+\r
+    \r
+#if 0\r
+The above code should be activated if we want to allow returning offsetof\r
+the user mode thread as fast as possible.\r
+\r
+    if (m_CallBackPending == false) {\r
+        NTSTATUS rc1 = m_pSdpSocket->RequestCallBack();\r
+        if (!NT_SUCCESS(rc1)) {\r
+            SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("PostCredits failed rc = 0x%x\n", rc ));\r
+            ASSERT(FALSE);\r
+        }        \r
+        m_CallBackPending = true;\r
+    }\r
+#endif\r
+    \r
+    ASSERT(rc == STATUS_PENDING || rc == STATUS_SUCCESS);\r
+    return rc;\r
+}\r
+\r
+\r
+NTSTATUS \r
+BufferPool::UsersThreadCallBack()\r
+{\r
+    SDP_PRINT(SDP_DEBUG, SDP_BUFFER_POOL, ("this = 0x%p \n",this));\r
+    AssertLocked();\r
+    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);\r
+    IRP *pIrp = NULL;\r
+    LIST_ENTRY *item;\r
+    \r
+    NTSTATUS rc = STATUS_SUCCESS, rc1;\r
+    BufferDescriptor *pBufferDescriptor = NULL;\r
+    ASSERT(m_CallBackPending == true);\r
+    ASSERT(m_UserPackets.Size() > 0 );\r
+\r
+    m_CallBackPending = false;\r
+\r
+    while (m_UserPackets.Size() > 0) {\r
+        rc = GetBuffer(&pBufferDescriptor);\r
+        if (!NT_SUCCESS(rc)) {\r
+            SDP_PRINT(SDP_ERR, SDP_SOCKET, ("GetBuffer failed rc = 0x%x\n", rc ));\r
+            goto Cleanup;\r
+        }\r
+\r
+        if (pBufferDescriptor == NULL) {\r
+            // We don't have a new buffer any more, we just\r
+            // wait for a new packet to be freed\r
+            ASSERT(rc == STATUS_SUCCESS);\r
+            goto Cleanup;\r
+        }\r
+\r
+        item = m_UserPackets.Head();\r
+\r
+        pIrp = CONTAINING_RECORD(item, IRP ,Tail.Overlay.ListEntry);\r
+\r
+        // copy the data from the user mode to the buffers \r
+        ULONG CopySize =  pBufferDescriptor->BufferSize - sizeof msg_hdr_bsdh;\r
+        CopySize = min(CopySize, RemainingToCopy(pIrp));\r
+        \r
+        rc = pBufferDescriptor->WriteData((CHAR *)GetUserBuffer(pIrp) + GetCoppied(pIrp), CopySize);\r
+        if (!NT_SUCCESS(rc)) {\r
+            SDP_PRINT(SDP_ERR, SDP_SOCKET, ("pBufferDescriptor->WriteData failed rc = 0x%x\n", rc ));\r
+            // free the buffer that you have\r
+            rc1 = ReturnBuffer(pBufferDescriptor);\r
+            ASSERT(NT_SUCCESS(rc1));\r
+            goto Cleanup;\r
+        }\r
+        // Update the user buffer\r
+        SetCoppied(pIrp, GetCoppied(pIrp) + CopySize);\r
+        \r
+        // send the data to the buffer\r
+        pBufferDescriptor->SetMid(SDP_MID_DATA);\r
+        rc = AddBufferToQueuedList(pBufferDescriptor);\r
+        if (!NT_SUCCESS(rc)) {\r
+            SDP_PRINT(SDP_ERR, SDP_SOCKET, ("AddBufferToQueuedList failed rc = 0x%x\n", rc ));\r
+            // free the buffer that you have\r
+            rc1 = ReturnBuffer(pBufferDescriptor);\r
+            ASSERT(NT_SUCCESS(rc1));\r
+            goto Cleanup;\r
+        }\r
+\r
+        if (RemainingToCopy(pIrp) == 0) {\r
+            // We have finished with this users packet, we should\r
+            // compleate the IRP\r
+\r
+            WspSendOut *pWspSendOut = (WspSendOut *) pIrp->AssociatedIrp.SystemBuffer;\r
+            m_UserPackets.RemoveHeadList();\r
+\r
+            pIrp->IoStatus.Status = STATUS_SUCCESS;\r
+            pIrp->IoStatus.Information = sizeof (WspSendOut);\r
+            pWspSendOut->Errno = 0;\r
+            pWspSendOut->NumberOfBytesSent = GetBufferSize(pIrp);\r
+            IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);\r
+\r
+        }\r
+    }\r
+\r
+Cleanup:\r
+\r
+    return rc;\r
+}\r
+\r
+\r
 /*\r
     This function goes over the list of packets that we can send, and sends\r
     them. It is called under the lock, and might be called also from a DPC\r
@@ -334,8 +464,6 @@ BufferPool::SendBuffersIfCan()
         }        \r
     }\r
 \r
-\r
-\r
     while ((m_QueuedPackets.Size() > 0) && \r
            (m_CurrentlySentBuffers < m_MaxConcurrentSends) &&\r
            (m_rRecvBuf > 2)) {\r
@@ -365,16 +493,11 @@ Cleanup:
 VOID \r
 BufferPool::CloseSocket()\r
 {\r
-    SDP_PRINT(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p m_WaitingClients = %s\n",\r
-    m_ClientWaiting ? "true" : "false"));\r
+    SDP_PRINT(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p \n"));\r
     AssertLocked();\r
 \r
-    if (m_ClientWaiting) {\r
-        KeSetEvent( &m_WaitingClients, IO_NO_INCREMENT, FALSE );\r
-        m_ClientWaiting = false;\r
-    }\r
-    // The next time our client will try to get data, he will get \r
-    // the error \r
+    //??? Should we do something here \r
+\r
 }\r
 \r
 \r
@@ -388,9 +511,11 @@ VOID
 BufferPool::ShutDown()\r
 {\r
     SDP_PRINT(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p \n",this));\r
-    //???? AssertLocked();\r
+\r
+    //AssertLocked();\r
     BufferDescriptor *pBufferDescriptor = NULL;\r
     LIST_ENTRY *item = NULL;\r
+    IRP *pIrp = NULL;\r
 \r
     while (m_FreePackets.Size() > 0 ) {\r
         item = m_FreePackets.RemoveHeadList();\r
@@ -404,6 +529,14 @@ BufferPool::ShutDown()
         BufferDescriptor::DeAllocateBuffer(pBufferDescriptor, SEND_BUFFERS_ALLOCATION_TAG);\r
     }\r
 \r
+    while (m_UserPackets.Size() > 0 ) {\r
+        item = m_UserPackets.RemoveHeadList();\r
+        pIrp = CONTAINING_RECORD(item, IRP ,Tail.Overlay.ListEntry);\r
+        pIrp->IoStatus.Status = STATUS_CANCELLED;\r
+        pIrp->IoStatus.Information = 0;\r
+        IoCompleteRequest (pIrp, IO_NO_INCREMENT);\r
+    }\r
+\r
     if(m_CreditdBufferDescriptor != NULL) {\r
         BufferDescriptor::DeAllocateBuffer(m_CreditdBufferDescriptor, SEND_BUFFERS_ALLOCATION_TAG);\r
         m_CreditdBufferDescriptor = NULL;\r
@@ -426,6 +559,7 @@ BufferPool::SendBuffer(BufferDescriptor *pBufferDescriptor)
     pHeader->seq_ack = m_pSdpSocket->m_RecvBufferPool.GetRecvSeq();\r
     m_AdvtSeq = pHeader->seq_ack;// Currently only for debug\r
     pHeader->flags = SDP_MSG_FLAG_NON_FLAG;\r
+\r
     /*\r
      * endian swap\r
      */\r
index fb546dd..f7f7989 100644 (file)
@@ -33,8 +33,6 @@
 #ifndef H_SDP_BUFFER_POOL_H\r
 #define H_SDP_BUFFER_POOL_H \r
 \r
-\r
-\r
 // This is simply a wrapper to the LIST_ENTRY class that allows \r
 // easier work with this list\r
 class LinkedList {\r
@@ -87,7 +85,6 @@ public:
         size--;\r
     }\r
     \r
-\r
 private:\r
     int size;\r
     LIST_ENTRY m_Data;\r
@@ -167,6 +164,54 @@ public:
 \r
 };\r
 \r
+\r
+// We will define 4 pointers to store send data for the IRP:\r
+// This will have to change one day()\r
+// The users data\r
+\r
+inline VOID SetUserBuffer(IRP *pIrp, VOID * p) {\r
+    pIrp->Tail.Overlay.DriverContext[0] = (VOID *)p;\r
+}\r
+inline VOID* GetUserBuffer(IRP *pIrp) {\r
+    return (pIrp->Tail.Overlay.DriverContext[0]);\r
+}\r
+\r
+inline VOID SetBufferSize(IRP *pIrp, uint32_t i) {\r
+    pIrp->Tail.Overlay.DriverContext[1] = (VOID *)(UINT_PTR)i;\r
+}\r
+inline uint32_t GetBufferSize(IRP *pIrp) {\r
+    return (uint32_t)(UINT_PTR) (pIrp->Tail.Overlay.DriverContext[1]);\r
+}\r
+\r
+inline VOID SetCoppied(IRP *pIrp, uint32_t i) {\r
+    pIrp->Tail.Overlay.DriverContext[2] = (VOID *)(UINT_PTR)i;\r
+    ASSERT(i <= GetBufferSize(pIrp));\r
+}\r
+inline uint32_t GetCoppied(IRP *pIrp) {\r
+    return (uint32_t)(UINT_PTR) (pIrp->Tail.Overlay.DriverContext[2]);\r
+}\r
+\r
+/* \r
+    BUGBUG:\r
+    As I intend to change this in any case, \r
+    I will not use Referance count on the socket\r
+    here.\r
+*/    // ???????????????????\r
+inline void SetSocket(IRP *pIrp, SdpSocket *pSdpSocket) {\r
+    pIrp->Tail.Overlay.DriverContext[3] = pSdpSocket;\r
+}\r
+\r
+inline SdpSocket *GetSocket(IRP *pIrp) {\r
+    return (SdpSocket *)pIrp->Tail.Overlay.DriverContext[3];\r
+}\r
+\r
+inline uint32_t RemainingToCopy(IRP *pIrp) {\r
+    uint32_t Coppied = GetCoppied(pIrp);\r
+    uint32_t BufferSize = GetBufferSize(pIrp);\r
+    ASSERT(BufferSize >= Coppied);\r
+    return BufferSize - Coppied;\r
+}\r
+\r
 class BufferPool {\r
 \r
 public:\r
@@ -184,17 +229,21 @@ public:
         );\r
 \r
     NTSTATUS GetBuffer(\r
-        BufferDescriptor ** ppBufferDescriptor, \r
-        KEVENT **ppEvent,\r
-        bool FirstBuffer\r
+        BufferDescriptor ** ppBufferDescriptor\r
         );\r
 \r
     NTSTATUS AddBufferToQueuedList(BufferDescriptor *pBufferDescriptor);    \r
 \r
-    VOID AllowOthersToGet();    \r
-\r
     NTSTATUS ReturnBuffer(BufferDescriptor *pBufferDescriptor);\r
 \r
+    NTSTATUS AddToUserBuffers(bool *pCopied, bool ForceCopy,char *pData, uint32_t BufferSize, uint32_t Coppied, IRP* pIrp);\r
+\r
+    VOID RemoveFromUserBuffers(PIRP pIrp) {\r
+        m_UserPackets.RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);\r
+    }\r
+\r
+    NTSTATUS UsersThreadCallBack();\r
+\r
     NTSTATUS SendBuffersIfCan();\r
 \r
     VOID CloseSocket();\r
@@ -222,20 +271,24 @@ private:
     NTSTATUS SendBuffer(BufferDescriptor *pBufferDescriptor);\r
 \r
     // Global data about this connection\r
-    int m_MaxBuffers;           // The maximum number of buffers that we allow for this QP (to be allocated)\r
-    int m_MaxConcurrentSends;   // The total numbers of sends that are allowd for the QP\r
-    int m_MaxMessageSize;       // The maximum buffer size that we allow\r
-\r
-    int m_CurrentlySentBuffers; // Number of buffers that we have sent, and didn't get an ack yet\r
-    int m_CurrentlyAllocated;   // The number of buffers that we have allocated\r
+    uint32_t m_MaxBuffers;           // The maximum number of buffers that we allow for this QP (to be allocated)\r
+    uint32_t m_MaxConcurrentSends;   // The total numbers of sends that are allowd for the QP\r
+    uint32_t m_MaxMessageSize;       // The maximum buffer size that we allow\r
 \r
-    bool m_ClientBeingServed;   // true if we have already started giving buffers to a client\r
+    uint32_t m_CurrentlySentBuffers; // Number of buffers that we have sent, and didn't get an ack yet\r
+    uint32_t m_CurrentlyAllocated;   // The number of buffers that we have allocated\r
 \r
     LinkedList m_FreePackets; // This packets are free and might be used\r
     LinkedList m_QueuedPackets; // This packets were filled with data and should be sent\r
+\r
+\r
+//?????\r
+    public:\r
+    LinkedList m_UserPackets; // This is a list of user packets that we should send\r
+\r
     \r
 \r
-    // TODO: A queue of events for threads that are waiting for buffers.\r
+private: //?????????    \r
 \r
     // IBAL constants from the main socket structure \r
     // TODO: Should they stay here and be used like this ?\r
@@ -244,8 +297,6 @@ private:
     net32_t                            m_lkey;\r
 \r
     // A list of events that the users has to wait on. ???? currently only one\r
-    KEVENT m_WaitingClients; // switch to a linked list\r
-    bool   m_ClientWaiting;\r
 \r
     uint32_t m_SendSeq; //sequence number of last message sent (send_seq in linux)\r
     uint32_t m_AdvtSeq; // sequence number of last message acknowledged (advt_seq in linux)\r
@@ -264,6 +315,8 @@ private:
     bool m_PostCreditsWhenCan;\r
     bool m_CreditsCurrentlyPosted;\r
     BufferDescriptor *m_CreditdBufferDescriptor;\r
+    bool m_CallBackPending; // Set to true if we have requesetd a callback from \r
+                            // the users thread\r
 \r
 VOID AssertLocked();\r
 \r
index 07a3db9..1158527 100644 (file)
@@ -92,7 +92,7 @@ extern "C" NTSTATUS DriverEntry (
 \r
     // fill the device functions\r
     pDriverObject->DriverUnload = DriverUnload;\r
-    pDriverObject->FastIoDispatch = NULL;\r
+    pDriverObject->FastIoDispatch =  NULL;\r
     pDriverObject->DriverStartIo = NULL;\r
     for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {\r
         pDriverObject->MajorFunction[i] = SdpDriver::Dispatch;\r
@@ -492,7 +492,7 @@ SdpDriver::DispatchDeviceIoControl(
                 SDP_PRINT(SDP_ERR, SDP_DRIVER, ("new SdpSocket failed rc = 0x%x\n", rc ));        \r
                 goto Cleanup;\r
             }\r
-            rc = pSdpSocket->Init(&wspSocketIn, pWspSocketOut);\r
+            rc = pSdpSocket->Init(&wspSocketIn, pWspSocketOut, pSdpUserFile);\r
             if (!NT_SUCCESS(rc)) {\r
                 SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpSocket->Init failed rc = 0x%x\n", rc ));\r
                 goto Cleanup;\r
@@ -548,7 +548,7 @@ SdpDriver::DispatchDeviceIoControl(
                pWspSendOut->Errno = WSAENOTSOCK;\r
                goto Cleanup;\r
             }\r
-            rc = pSdpSocket->WSPSend(&wspSendIn, pWspSendOut);\r
+            rc = pSdpSocket->WSPSend(&wspSendIn, pWspSendOut, pIrp);\r
             if (!NT_SUCCESS(rc)) {\r
                 SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpSocket->WSPSend failed rc = 0x%x\n", rc ));        \r
                 goto Cleanup;\r
@@ -689,8 +689,6 @@ SdpDriver::DispatchDeviceIoControl(
             }\r
         }\r
         break;\r
-        \r
-\r
         case IOCTL_WSP_CLOSE_SOCKET :\r
         {\r
             SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("IOCTL_WSP_CLOSE_SOCKET recieved\n" ));   \r
@@ -709,18 +707,21 @@ SdpDriver::DispatchDeviceIoControl(
                goto Cleanup;\r
             }\r
             rc = pSdpSocket->WSPCloseSocket(&wspSocketCloseIn, pWspSocketCloseOut);\r
-            // After closing a socket we "unlink" the kernel object, and it won't\r
-            // be accessable for the user. (currently succesfull or not)\r
-            // BUGBUG: Change this behavior while the linger don't linger staff is fixed\r
-            pSdpUserFile->RemoveSocket(pSdpSocket); // Must succed\r
-            // BUGBUG: are we taking the socket from the correct place\r
-            // It is possible that not, but the chanses of an error seems small\r
             if (!NT_SUCCESS(rc)) {\r
                 SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpSocket->WSPCloseSocket failed rc = 0x%x\n", rc ));        \r
                 goto Cleanup; \r
             }\r
         }\r
         break;\r
+\r
+        case IOCTL_WSP_USER_THREAD :\r
+        {\r
+            SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("IOCTL_WSP_USER_THREAD recieved\n" ));   \r
+            pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
+\r
+            /* Ignore Error = */ pSdpUserFile->UsersThread();\r
+        }\r
+        break;\r
         \r
     default:\r
         // This is an unrecgnized IOCTL\r
index 8a2ddcf..651fb54 100644 (file)
@@ -32,6 +32,8 @@
 \r
 #include "Precompile.h"\r
 \r
+//#define DONT_COPY_DATA\r
+\r
 USHORT ntohs(USHORT in)\r
 {\r
     return ((in & 0xff) << 8) | ((in & 0xff00) >> 8);\r
@@ -122,7 +124,13 @@ CopyFromUser(
     __try\r
     {\r
         ProbeForRead( (void*)p_src, count, 1 );\r
+#ifdef DONT_COPY_DATA        \r
+        if (count < 1000){\r
+            RtlCopyMemory( p_dest, p_src, count );\r
+        }\r
+#else\r
         RtlCopyMemory( p_dest, p_src, count );\r
+#endif\r
         return STATUS_SUCCESS;\r
     }\r
     __except(EXCEPTION_EXECUTE_HANDLER)\r
@@ -147,7 +155,13 @@ CopyToUser(
     __try\r
     {\r
         ProbeForWrite( p_dest, count, 1 );\r
+#ifdef DONT_COPY_DATA        \r
+        if (count < 1000){\r
+            RtlCopyMemory( p_dest, p_src, count );\r
+        }\r
+#else\r
         RtlCopyMemory( p_dest, p_src, count );\r
+#endif\r
         return CL_SUCCESS;\r
     }\r
     __except(EXCEPTION_EXECUTE_HANDLER)\r
index 8440ba5..4b655fd 100644 (file)
@@ -176,8 +176,8 @@ int IbalToWsaError(const    ib_api_status_t ib_status );
 #define WSAESTALE               (WSABASEERR+70)\r
 #define WSAEREMOTE              (WSABASEERR+71)\r
 \r
-\r
-\r
-\r
+// Used for IRP cancell\r
+#define ERROR_OPERATION_ABORTED 995L\r
+#define WSA_OPERATION_ABORTED   (ERROR_OPERATION_ABORTED)\r
 \r
 #endif // _SDP_GEN_UTILS_H\r
index b5c7208..4f8d122 100644 (file)
@@ -125,7 +125,7 @@ public:
     bool Lock(bool Force = false) {\r
         KIRQL  OldIrql;\r
         int OldFlags = 0;\r
-        NTSTATUS rc = STATUS_SUCCESS;\r
+        NTSTATUS rc = STATUS_SUCCESS, rc1 = STATUS_SUCCESS;\r
         ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);\r
         bool Locked = false;\r
         bool WaitedOnLock = false;\r
@@ -158,13 +158,18 @@ public:
             ASSERT(m_NumberOfClientWaiting >= 0);            \r
             KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
             rc = HandleFlags(OldFlags);\r
+            if(!NT_SUCCESS(rc)) {\r
+                SDP_PRINT(SDP_ERR, SDP_LOCK, ("HandleFlags failed rc = 0x%x\n", rc ));\r
+            }\r
             if ((Force == false) && \r
                  (!NT_SUCCESS(rc) ||\r
                   (m_flags & ERROR_SIGNALLED) ||\r
-                  (!NT_SUCCESS(rc = m_CheckSocketState(m_pSdpSocket)))\r
+                  (!NT_SUCCESS(rc1 = m_CheckSocketState(m_pSdpSocket)))\r
                  )) {\r
                 // We have to signal the error to the calling side\r
-                SDP_PRINT(SDP_ERR, SDP_LOCK, ("HandleFlags failed rc = 0x%x\n", rc ));\r
+                if(!NT_SUCCESS(rc1)) {\r
+                    SDP_PRINT(SDP_ERR, SDP_LOCK, ("m_CheckSocketState failed rc1 = 0x%x\n", rc1 ));\r
+                }\r
                 Locked = false;\r
                 KeAcquireSpinLock(&m_SpinLock, &OldIrql);\r
                 m_InUse = false;\r
index 661cac5..f0442e4 100644 (file)
@@ -145,8 +145,10 @@ RecvPool::RecievedBuffer(BufferDescriptor *pBufferDescriptor, bool error)
         (int)pHeader->seq_ack));\r
     m_pSdpSocket->m_SendBufferPool.SetRemoteRecvBuf(rRecvBuf);\r
 \r
-    // m_DisConnRecieved is the last message that should be recieved\r
-    ASSERT(m_DisConnRecieved == false); // BUGBUG: do a real check here\r
+    // m_DisConnRecieved is the last "real" message that should be recieved\r
+    // we might still get credits update\r
+    ASSERT(m_DisConnRecieved == false ||\r
+            (pHeader->mid == SDP_MID_DATA && pHeader->size == sizeof msg_hdr_bsdh)); // BUGBUG: do a real check here\r
 \r
     // ???? Handle more state changes here ????\r
     if (pHeader->mid != SDP_MID_DATA) {\r
index 362dcda..bf0d37e 100644 (file)
@@ -155,6 +155,8 @@ SdpSocket::SdpSocket()
     m_CloseSocketCalled = false;\r
     m_ShutdownCalled = false;\r
     m_DisconnectConnectionRecieved = false;\r
+    m_pSdpUserFile = NULL;\r
+    InitializeListHead(&m_CallBackRequestList);\r
     \r
 }\r
 \r
@@ -167,7 +169,8 @@ VOID SdpSocket::AssertLocked()
 \r
 NTSTATUS SdpSocket::Init(\r
     WspSocketIn *pSocketInParam, \r
-    WspSocketOut *pSocketOutParam)\r
+    WspSocketOut *pSocketOutParam,\r
+    SdpUserFile *pSdpUserFile)\r
 {\r
     NTSTATUS rc = STATUS_SUCCESS;\r
     SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p\n", this));\r
@@ -190,6 +193,10 @@ NTSTATUS SdpSocket::Init(
         rc = STATUS_NO_MEMORY;\r
         goto Cleanup;\r
     }\r
+\r
+    m_pSdpUserFile = pSdpUserFile;\r
+    m_pSdpUserFile->AddRef();\r
+    \r
     \r
 Cleanup:\r
     return rc;\r
@@ -200,25 +207,26 @@ NTSTATUS SdpSocket::AcceptRequests()
 {\r
     // Check if our state allows us to handle send/recv/accept ...\r
     if (m_ShutdownCalled) return STATUS_SHUTDOWN_IN_PROGRESS;\r
-    if (m_CloseSocketCalled) return STATUS_SHUTDOWN_IN_PROGRESS;\r
+    if (m_CloseSocketCalled) return STATUS_HANDLES_CLOSED;  // Not the exact code\r
+                                                            // But it seems relatively closest\r
     return STATUS_SUCCESS;\r
 }\r
 \r
 NTSTATUS SdpSocket::WSPSend(\r
         WspSendIn    *pWspSendIn,\r
-        WspSendOut   *pWspSendOut\r
+        WspSendOut   *pWspSendOut,\r
+        IRP          *pIrp\r
         )\r
 {    \r
     SDP_PRINT(SDP_DEBUG, SDP_SOCKET, ("this = 0x%p size = %d \n",this, pWspSendIn->BufferSize));\r
 \r
     NTSTATUS rc = STATUS_SUCCESS;    \r
-    NTSTATUS rc1; // used only to check that there are no more errors on the \r
-                  // return path\r
     BufferDescriptor * pBufferDescriptor = NULL;\r
     bool First = true;\r
     ULONG Coppied = 0;\r
-    bool Locked = false;\r
     PRKEVENT  pBuffersEvent = NULL;\r
+    bool BufferCopied;\r
+    NTSTATUS rc1;\r
 \r
     // For zero bytes send we currently don't do anything and return with status \r
     // success\r
@@ -227,67 +235,84 @@ NTSTATUS SdpSocket::WSPSend(
         goto Cleanup;\r
     }\r
 \r
-    while (Coppied < pWspSendIn->BufferSize) {\r
-        if ((Locked == false) && !m_Lock.Lock()) {\r
-            SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Failed to lock this = 0x%p \n",this));\r
-            rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
-            goto Cleanup;\r
-        }\r
-        Locked = true;\r
-        ASSERT(pBuffersEvent == NULL);\r
+    if (!m_Lock.Lock()) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Failed to lock this = 0x%p \n",this));\r
+        rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
+        goto Cleanup;\r
+    }\r
 \r
-        if ((m_state != SS_CONNECTED)) {\r
-            // We can not send now.\r
-            SDP_PRINT(SDP_WARN, SDP_SOCKET, ("Can't send now, m_state = %s\n",\r
-                SS2String(m_state)\r
-            ));\r
-            rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
-            pWspSendOut->Errno = WSAENOTCONN;\r
-                \r
-            m_Lock.Unlock(); // Error ignored as this is already an error pass\r
-            Locked = false;\r
+    if ((m_state != SS_CONNECTED)) {\r
+        // We can not send now.\r
+        SDP_PRINT(SDP_WARN, SDP_SOCKET, ("Can't send now, m_state = %s\n",\r
+            SS2String(m_state)\r
+        ));\r
+        rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
+        pWspSendOut->Errno = WSAENOTCONN;\r
+            \r
+        m_Lock.Unlock(); // Error ignored as this is already an error pass\r
+        goto Cleanup;\r
+    }\r
+\r
+    // Check if there is already data in the queue, if yes we just \r
+    // increase the queue and leave.\r
+\r
+    ASSERT(!m_CloseSocketCalled);\r
+    rc = m_SendBufferPool.AddToUserBuffers(&BufferCopied, false , pWspSendIn->pData, pWspSendIn->BufferSize,Coppied, pIrp);\r
+    ASSERT(rc == STATUS_PENDING || rc == STATUS_SUCCESS);\r
+    if (rc == STATUS_PENDING) {\r
+        ASSERT(BufferCopied);\r
+        // TODO: We already took the lock, and we are in the right context,\r
+        // We should probably do some work there\r
+        // Data was already copied to the buffer we are done.\r
+        rc = m_Lock.Unlock();\r
+        if (!NT_SUCCESS(rc)) {\r
+            // No need to complete the IRP, as it will be be deleted\r
+            // when all other IRPs will be\r
+            SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc ));\r
             goto Cleanup;\r
         }\r
+        // This IRP will be pending (make sure to change this after the unlock)\r
+        rc = STATUS_PENDING;\r
+\r
+        goto Cleanup;\r
+    } \r
+\r
+    ASSERT(rc == STATUS_SUCCESS);\r
+    ASSERT(BufferCopied == false);\r
+    // We now try to copy the data to the internal buffers\r
+\r
+    while (Coppied < pWspSendIn->BufferSize) {\r
 \r
-        rc = m_SendBufferPool.GetBuffer(&pBufferDescriptor, &pBuffersEvent, First);\r
+        rc = m_SendBufferPool.GetBuffer(&pBufferDescriptor);\r
         if (!NT_SUCCESS(rc)) {\r
             SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_SendBufferPool.GetBuffer failed rc = 0x%x\n", rc ));\r
             m_Lock.Unlock(); // Error ignored as this is already an error pass\r
-            Locked = false;\r
             goto Cleanup;\r
         }\r
-        First = false;\r
-        \r
-        if (pBuffersEvent != NULL) {\r
-            // We are told to wait on this event\r
+\r
+        if (pBufferDescriptor == NULL) {\r
+            // We don't have a new buffer any more, we store the remaining\r
+            // buffer and quit\r
+            rc = m_SendBufferPool.AddToUserBuffers(\r
+                                            &BufferCopied, \r
+                                            true , \r
+                                            pWspSendIn->pData, \r
+                                            pWspSendIn->BufferSize,\r
+                                            Coppied,\r
+                                            pIrp);\r
+            ASSERT(rc == STATUS_PENDING);\r
+            ASSERT(BufferCopied == true);\r
+\r
             rc = m_Lock.Unlock();\r
-            Locked = false;\r
             if (!NT_SUCCESS(rc)) {\r
                 SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc ));\r
+                // No need to complete the IRP, as it will be be deleted\r
+                // when all other IRPs will be\r
                 goto Cleanup;\r
             }\r
-\r
-            rc = MyKeWaitForSingleObject(\r
-                pBuffersEvent,\r
-                UserRequest,\r
-                UserMode,\r
-                FALSE,\r
-                NULL\r
-                );    \r
-            pBuffersEvent = NULL;\r
-            if (( rc == STATUS_ALERTED ) ||( rc == STATUS_USER_APC )) {\r
-                // BUGBUG: Think what to do here, we should be able to stop the\r
-                // connect, and quit (probably shutdown should be enough)\r
-                SDP_PRINT(SDP_WARN, SDP_SOCKET, ("MyKeWaitForSingleObject was alerted rc = 0x%x\n", rc ));\r
-                rc = STATUS_UNEXPECTED_IO_ERROR;\r
-                //pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
-                Shutdown();\r
-                goto Cleanup;\r
-            }\r
-            // try getting the buffer again\r
-            continue;\r
+            rc = STATUS_PENDING;// This IRP will be pending (make sure to change this after the unlock)\r
+            goto Cleanup;\r
         }\r
-\r
         // copy the data from the user mode to the buffers \r
         ULONG CopySize =  pBufferDescriptor->BufferSize - sizeof msg_hdr_bsdh;\r
         CopySize = min(CopySize, pWspSendIn->BufferSize - Coppied);\r
@@ -315,23 +340,29 @@ NTSTATUS SdpSocket::WSPSend(
             goto Cleanup;\r
         }\r
     }\r
-    ASSERT(Locked == true);\r
+    \r
     rc = m_Lock.Unlock();\r
     if (!NT_SUCCESS(rc)) {\r
         SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc ));\r
         goto Cleanup;\r
     }\r
-    \r
-    m_SendBufferPool.AllowOthersToGet();\r
-   \r
+\r
 Cleanup:\r
     if (NT_SUCCESS(rc) ) {\r
-        pWspSendOut->Errno = 0;\r
-        ASSERT(pWspSendIn->BufferSize == Coppied);\r
-        pWspSendOut->NumberOfBytesSent = Coppied;\r
+        ASSERT((rc == STATUS_SUCCESS) || (rc == STATUS_PENDING));\r
+        if (rc != STATUS_PENDING) {\r
+            pWspSendOut->Errno = 0;\r
+            ASSERT(pWspSendIn->BufferSize == Coppied);\r
+            pWspSendOut->NumberOfBytesSent = Coppied;\r
+        }\r
     } else {\r
         // Make sure that we have the error setted\r
+        Shutdown();\r
         ASSERT(pWspSendOut->Errno != 0); // BUGBUG: Need to make sure that this\r
+        if(pWspSendOut->Errno == 0) {\r
+            // Some default value\r
+            pWspSendOut->Errno = WSAENOBUFS;\r
+        }\r
         SDP_PRINT(SDP_WARN, SDP_SOCKET, ("this = 0x%p rc = 0x%x\n",this, rc));\r
         // is indeed the case.\r
     }\r
@@ -544,7 +575,7 @@ NTSTATUS SdpSocket::WSPConnect(
         goto Cleanup;\r
     }        \r
 \r
-    rc = g_pSdpDriver->m_pSdpArp->DestPortGidFromMac(pWspConnectIn->DestMac, &DestPortGid);\r
+    rc = g_pSdpDriver->m_pSdpArp->DestPortGidFromMac(m_SrcPortGuid, pWspConnectIn->DestMac, &DestPortGid);\r
     if (!NT_SUCCESS(rc)) {\r
         SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->DestPortGidFromIP failed rc = 0x%x\n", rc ));\r
         pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
@@ -1066,7 +1097,13 @@ SdpSocket::WSPCloseSocket(
     SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p state = %s \n",this, SS2String(m_state)));\r
     OBJECT_ATTRIBUTES   attr;\r
     HANDLE  ThreadHandle;\r
-\r
+    bool sleep = false;\r
+restart:\r
+    \r
+    if (sleep) {\r
+        Sleep(1*1000*1000);//???????\r
+    }\r
+    sleep = true;\r
 \r
     if (!m_Lock.Lock()) {\r
         SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Failed to lock this = 0x%p \n",this));\r
@@ -1084,6 +1121,13 @@ SdpSocket::WSPCloseSocket(
         goto Cleanup;\r
     }\r
 \r
+\r
+    //?????????\r
+    if (m_SendBufferPool.m_UserPackets.Size() > 0) {\r
+        m_Lock.Unlock();\r
+        goto restart;\r
+    }\r
+\r
     // This will force that no more calls will be allowed\r
     ASSERT(m_CloseSocketCalled == FALSE); // If this is not the case \r
     // We shouldn't be able to take the lock\r
@@ -1152,7 +1196,7 @@ SdpSocket::WSPCloseSocket(
     m_pCloseSocketThread = NULL; // Will be delated when the callback thread is deleted\r
 \r
     rc = m_Lock.Unlock();\r
-    if (rc == STATUS_SHUTDOWN_IN_PROGRESS) {\r
+    if (rc == STATUS_HANDLES_CLOSED) {\r
         // shutdown in progress is fine since we have started the shutdown ...\r
         rc = STATUS_SUCCESS;\r
     }\r
@@ -1262,7 +1306,7 @@ NTSTATUS SdpSocket::CmSendRTU()
 \r
     int MaxMessageSize = min(m_hello_ack.hah.l_rcv_size, MAX_SEND_BUFFER_SIZE);\r
 \r
-    rc = m_SendBufferPool.Init(MAX_SEND_PACKETS, QP_ATTRIB_SQ_DEPTH, MaxMessageSize, m_pd, m_qp, m_lkey, this);\r
+    rc = m_SendBufferPool.Init(MAX_SEND_PACKETS, SDP_QP_ATTRIB_SQ_DEPTH, MaxMessageSize, m_pd, m_qp, m_lkey, this);\r
     if (!NT_SUCCESS(rc)) {\r
         SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_SendBufferPool.Init failed rc = 0x%x\n", rc ));\r
         goto Cleanup;\r
@@ -1428,7 +1472,7 @@ SdpSocket::CmReqCallback(IN   ib_cm_req_rec_t *p_cm_req_rec)
     WspSocketIn SocketInParam;\r
     WspSocketOut SocketOutParam;\r
     SocketInParam.dwFlags = 0;        \r
-    rc = pNewSocket->Init(&SocketInParam, &SocketOutParam);\r
+    rc = pNewSocket->Init(&SocketInParam, &SocketOutParam, m_pSdpUserFile);\r
     if (!NT_SUCCESS(rc)) {\r
         SDP_PRINT(SDP_ERR, SDP_SOCKET, ("pNewSocket.Init() failed rc = 0x%x\n", rc ));\r
         goto ErrorLocked;\r
@@ -1498,7 +1542,7 @@ SdpSocket::CmReqCallback(IN   ib_cm_req_rec_t *p_cm_req_rec)
     // We will now call init on the sender and the reciever\r
     int MaxMessageSize = min(msg_hello->hh.l_rcv_size, MAX_SEND_BUFFER_SIZE);\r
 \r
-    rc = pNewSocket->m_SendBufferPool.Init(MAX_SEND_PACKETS, QP_ATTRIB_SQ_DEPTH, MaxMessageSize, pNewSocket->m_pd, pNewSocket->m_qp, pNewSocket->m_lkey, pNewSocket);\r
+    rc = pNewSocket->m_SendBufferPool.Init(MAX_SEND_PACKETS, SDP_QP_ATTRIB_SQ_DEPTH, MaxMessageSize, pNewSocket->m_pd, pNewSocket->m_qp, pNewSocket->m_lkey, pNewSocket);\r
     if (!NT_SUCCESS(rc)) {\r
         SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_SendBufferPool.Init failed rc = 0x%x\n", rc ));\r
         goto ErrorLocked;\r
@@ -1753,10 +1797,10 @@ SdpSocket::CmDreqCallback(IN   ib_cm_dreq_rec_t *p_cm_dreq_rec)
 \r
 \r
     // Take the lock and verify the state\r
-    Locked = m_Lock.Lock();\r
+    rc = m_Lock.LockRc();\r
     // BUGBUG: It seems that even when the lock fails we should send\r
     // drep\r
-    if (!Locked) {\r
+    if (!NT_SUCCESS(rc)) {\r
         SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Lock failed rc = 0x%x\n", rc ));\r
         goto Cleanup;\r
     }\r
@@ -1958,15 +2002,16 @@ NTSTATUS SdpSocket::send_cb()
 {\r
     SDP_PRINT(SDP_DEBUG, SDP_SOCKET, ("called this =0x%p\n", this));\r
     NTSTATUS rc = STATUS_SUCCESS, rc1 = STATUS_SUCCESS, rc2 = STATUS_SUCCESS;\r
+    AssertLocked();\r
     ib_api_status_t     ib_status;\r
     ib_wc_t  *p_wc, *p_free;\r
     size_t              i;\r
     BufferDescriptor *pBufferDescriptor = NULL;\r
 \r
-    for( i = 0; i < QP_ATTRIB_SQ_DEPTH; i++ ) {\r
+    for( i = 0; i < SDP_QP_ATTRIB_SQ_DEPTH; i++ ) {\r
         m_SendComplitionWC[i].p_next = &m_SendComplitionWC[i + 1];\r
     }\r
-    m_SendComplitionWC[QP_ATTRIB_SQ_DEPTH - 1].p_next = NULL;\r
+    m_SendComplitionWC[SDP_QP_ATTRIB_SQ_DEPTH - 1].p_next = NULL;\r
 \r
     do \r
     {\r
@@ -2127,7 +2172,7 @@ NTSTATUS SdpSocket::CreateQp()
     }\r
 \r
     /* Allocate send CQ. */\r
-    cq_create.size = QP_ATTRIB_SQ_DEPTH;\r
+    cq_create.size = SDP_QP_ATTRIB_SQ_DEPTH;\r
     cq_create.pfn_comp_cb = SdpSocket::__send_cb1;\r
 \r
     ib_status = ib_create_cq(\r
@@ -2150,7 +2195,7 @@ NTSTATUS SdpSocket::CreateQp()
     qp_create.rq_depth = QP_ATTRIB_RQ_DEPTH;\r
     qp_create.rq_sge = QP_ATTRIB_RQ_SGE;       /* To support buffers spanning pages. */\r
     qp_create.h_rq_cq = m_rcq;\r
-    qp_create.sq_depth = QP_ATTRIB_SQ_DEPTH;\r
+    qp_create.sq_depth = SDP_QP_ATTRIB_SQ_DEPTH;\r
     //TODO: Figure out the right number of SGE entries for sends.\r
     qp_create.sq_sge = QP_ATTRIB_SQ_SGE;\r
     qp_create.h_sq_cq = m_scq;\r
@@ -2318,6 +2363,41 @@ VOID SdpSocket::CreateCmRequest(
     cm_req->pfn_cm_rep_cb = cm_rep_callback;\r
 }\r
 \r
+\r
+VOID SdpSocket::UsersThreadCallBack(bool Send)\r
+{\r
+    NTSTATUS rc = STATUS_SUCCESS;\r
+\r
+    if (!m_Lock.Lock()) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Failed to lock this = 0x%p \n",this));\r
+        // Error is ignored, as it is a callback path, socket is already at an error state\r
+        goto Cleanup;\r
+    }\r
+    if (Send) {\r
+        InitializeListHead(&m_CallBackRequestList);\r
+        rc = m_SendBufferPool.UsersThreadCallBack();\r
+        if (!NT_SUCCESS(rc)) {        \r
+            SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_SendBufferPool.UsersThreadCallBack failed this = 0x%p, rc = 0x%x \n",\r
+                this, rc));\r
+            m_Lock.Unlock(); // Error is ignored, as this is already an error path\r
+            Shutdown();\r
+            goto Cleanup;\r
+        }\r
+        \r
+    }\r
+\r
+    rc = m_Lock.Unlock(); // Error is ignored, as it is a callback path \r
+    if (!NT_SUCCESS(rc)) {        \r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock failed this = 0x%p, rc = 0x%x \n",\r
+            this, rc));\r
+        Shutdown();\r
+        goto Cleanup;\r
+    }\r
+\r
+Cleanup:\r
+    return;\r
+}\r
+\r
 // static\r
 VOID SdpSocket::ShutdownCB(VOID* pContext)\r
 {\r
@@ -2485,12 +2565,16 @@ VOID SdpSocket::Shutdown()
         delete m_pCloseSocketThread;\r
         m_pCloseSocketThread = NULL;\r
     }\r
-    \r
 \r
     // Now that all ibal operations have finished we can free the memory\r
     m_SendBufferPool.ShutDown();\r
     m_RecvBufferPool.ShutDown();\r
 \r
+    if (m_pSdpUserFile != NULL) {\r
+        m_pSdpUserFile->RemoveSocket(this);\r
+        m_pSdpUserFile->Release();\r
+        m_pSdpUserFile = NULL;\r
+    }\r
 \r
 /*\r
     Memory reagion probably cleans when the other handles are closed\r
index 808aa2b..3b1dbf4 100644 (file)
@@ -43,13 +43,12 @@ It keeps a list of all the objects so we know when to remove them.
 \r
 const int MAX_SEND_BUFFER_SIZE          = 1*4096; // This is the maximum send packet size\r
 \r
-// BUGBUG: Check why changing this param crushes the system\r
 const int MAX_RECV_BUFFER_SIZE          = 1*4096; // This is the maximum send packet size\r
 const int MAX_SEND_PACKETS              = 200;    // This is the maximum number of packets allocated per send\r
 const int MAX_RECV_PACKETS              = 200;    // This is the maximum number of packets allocated per send\r
                                   \r
 \r
-const short QP_ATTRIB_SQ_DEPTH =               64;\r
+const short SDP_QP_ATTRIB_SQ_DEPTH     =               64;\r
 const short QP_ATTRIB_SQ_SGE   =       1;      /* Set based on inline data requirements */\r
 //#define QP_ATTRIB_RESPONDER_RESOURCES        4\r
 const short QP_ATTRIB_INITIATOR_DEPTH = 4;\r
@@ -142,7 +141,7 @@ private:
     KEVENT                  m_ShutdownCompleteEvent;\r
     KEVENT                  m_DisconectSentEvent;\r
 \r
-    ib_wc_t                 m_SendComplitionWC[QP_ATTRIB_SQ_DEPTH];\r
+    ib_wc_t                 m_SendComplitionWC[SDP_QP_ATTRIB_SQ_DEPTH];\r
     ib_wc_t                 m_RecvComplitionWC[QP_ATTRIB_RQ_DEPTH];\r
 \r
     // The following three falgs are used to shutdown a socket\r
@@ -150,7 +149,9 @@ private:
     bool                    m_ShutdownCalled;\r
     bool                    m_DisconnectConnectionRecieved;\r
 \r
-    ThreadHandle*           m_pCloseSocketThread;    \r
+    ThreadHandle*           m_pCloseSocketThread;\r
+\r
+    SdpUserFile             *m_pSdpUserFile;\r
 \r
     static VOID __send_cb1(\r
         IN  const   ib_cq_handle_t  h_cq,\r
@@ -166,6 +167,8 @@ public:
     RecvPool                m_RecvBufferPool;\r
     ConnectionList          m_ConnectionList;\r
 \r
+    LIST_ENTRY m_CallBackRequestList;// Used by the call back request thread to hold the request\r
+\r
     \r
     SdpSocket();\r
 \r
@@ -175,7 +178,8 @@ public:
 \r
     NTSTATUS Init(\r
         WspSocketIn     *pSocketInParam, \r
-        WspSocketOut    *pSocketOutParam\r
+        WspSocketOut    *pSocketOutParam,\r
+        SdpUserFile     *pSdpUserFile\r
         );\r
 \r
     NTSTATUS WSPConnect(\r
@@ -185,7 +189,8 @@ public:
 \r
     NTSTATUS WSPSend(\r
         WspSendIn    *pWspSendIn,\r
-        WspSendOut   *pWspSendOut\r
+        WspSendOut   *pWspSendOut,\r
+        IRP          *pIrp          \r
         );    \r
 \r
     NTSTATUS WSPRecv(\r
@@ -244,6 +249,14 @@ public:
         USHORT DestPort\r
     );\r
 \r
+    NTSTATUS RequestCallBack() {\r
+        AssertLocked();\r
+        ASSERT(IsListEmpty(&m_CallBackRequestList));\r
+        return m_pSdpUserFile->RequestCallBack(&m_CallBackRequestList);\r
+    }\r
+\r
+    VOID UsersThreadCallBack(bool Send);\r
+\r
     VOID CmRepCallback(IN   ib_cm_rep_rec_t *p_cm_rep_rec);\r
     VOID CmReqCallback(IN   ib_cm_req_rec_t *p_cm_req_rec);\r
     VOID CmRtuCallback(IN   ib_cm_rtu_rec_t *p_cm_rtu_rec);\r
index 898b32f..5a62b45 100644 (file)
@@ -36,19 +36,21 @@ SdpUserFile::SdpUserFile()
 {\r
     InitializeListHead(&m_SocketsList);\r
     m_shutdown = false;\r
+    m_NumberOfUserThreads = 0;\r
 }\r
 \r
 NTSTATUS SdpUserFile::Init()\r
 {\r
-    KeInitializeSpinLock(&m_Lock);\r
     InitializeListHead(&m_SocketsList);\r
+    KeInitializeEvent(&m_UsersCallEvent, SynchronizationEvent  , FALSE );\r
     m_shutdown = false;\r
-\r
+    KeInitializeSpinLock(&m_Lock);\r
     return STATUS_SUCCESS;\r
 }\r
 \r
 void SdpUserFile::Shutdown()\r
 {   \r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("Called this = 0x%p \n",this));\r
     // go over the entire list, and release it's objects\r
     CSpinLockWrapper Lock(m_Lock);\r
     Lock.Lock();\r
@@ -57,6 +59,22 @@ void SdpUserFile::Shutdown()
         Lock.Unlock();\r
         return;\r
     }\r
+    m_shutdown = true;\r
+\r
+    // Go over the list of callbacks that you have to make and remove \r
+    // them.\r
+    while (m_UsersCallList.Size() > 0) {\r
+        PLIST_ENTRY pTemp = m_UsersCallList.RemoveHeadList();\r
+        SdpSocket * pSdpSocket = CONTAINING_RECORD(pTemp, SdpSocket , m_CallBackRequestList);\r
+\r
+        // Don't call release with the lock being hold\r
+        Lock.Unlock();\r
+        pSdpSocket->Release();\r
+        // It seems that we shoule be protected by the m_shutdown\r
+        // flag, but will take the lock just in case\r
+        Lock.Lock();\r
+    }\r
+    \r
     while (!IsListEmpty(&m_SocketsList)) {\r
         PLIST_ENTRY pTemp = RemoveHeadList(&m_SocketsList);\r
         SdpSocket *pSdpSocket = CONTAINING_RECORD(pTemp, SdpSocket, m_UserFileList );\r
@@ -68,9 +86,11 @@ void SdpUserFile::Shutdown()
         // It seems that we shoule be protected by the m_shutdown\r
         // flag, but will take the lock just in case\r
         Lock.Lock();\r
-\r
     }\r
+    \r
     Lock.Unlock();\r
+    // Free the users thread\r
+    KePulseEvent(&m_UsersCallEvent,IO_NO_INCREMENT ,FALSE);   \r
 }\r
 \r
 NTSTATUS SdpUserFile::AddSocket(SdpSocket *pSdpSocket)\r
@@ -143,4 +163,98 @@ SdpSocket *SdpUserFile::SocketByPointer(VOID *Socket)
     return pSdpSocket;\r
 }\r
 \r
+NTSTATUS \r
+SdpUserFile::RequestCallBack(LIST_ENTRY *pList)\r
+{\r
+    NTSTATUS rc = STATUS_SUCCESS;\r
+    CSpinLockWrapper Lock(m_Lock);\r
+    SdpSocket *pSdpSocket = NULL;\r
+    \r
+    pSdpSocket = CONTAINING_RECORD(pList, SdpSocket , m_CallBackRequestList);\r
+    // Take the lock and add the wanted event\r
+    Lock.Lock();\r
+    if (m_shutdown) {\r
+        Lock.Unlock();\r
+        return STATUS_SHUTDOWN_IN_PROGRESS;\r
+    }\r
+    pSdpSocket->AddRef();\r
 \r
+    ASSERT(IsListEmpty(pList));\r
+    m_UsersCallList.InsertTailList(pList);\r
+\r
+    Lock.Unlock();\r
+    // Make sure someone tries to read our objects\r
+    KeSetEvent(&m_UsersCallEvent,IO_NETWORK_INCREMENT ,FALSE);\r
+    return rc;\r
+\r
+}\r
+\r
+/*\r
+    This function is being called by a thread that reaches us from \r
+    the user, and is responisble for copying data from user buffers\r
+    to kernel memory.\r
+\r
+    Only in the case of shutdown, the thread will exit.\r
+    Since we only do the cleanup of the SdpUserFile on IRP_MJ_CLOSE\r
+    there is no feer of working on a removed object.\r
+*/\r
+\r
+NTSTATUS \r
+SdpUserFile::UsersThread()\r
+{\r
+    NTSTATUS rc = STATUS_SUCCESS;\r
+    CSpinLockWrapper Lock(m_Lock);\r
+    LIST_ENTRY *item = NULL;\r
+    SdpSocket *pSdpSocket = NULL;\r
+    bool ShutdownCalled = false; // This will only change from false\r
+                                 // to true\r
+    long NumberOfThreads = InterlockedIncrement(&m_NumberOfUserThreads);\r
+    if(NumberOfThreads != 1) {\r
+        // It seems that more than one uesr is here, don't let him\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("More than one user thread !!! \n"));\r
+        ASSERT(FALSE);\r
+        return STATUS_ACCESS_DENIED;\r
+    }\r
+                                 \r
+    int count = 0;                                 \r
+    while (true) {\r
+        // Take the lock, and see the state:\r
+        Lock.Lock();\r
+        ShutdownCalled = m_shutdown;\r
+        // Process all data that exists\r
+        if(m_UsersCallList.Size() > 0) {\r
+            item = m_UsersCallList.RemoveHeadList();\r
+            pSdpSocket = CONTAINING_RECORD(item, SdpSocket , m_CallBackRequestList);\r
+\r
+            Lock.Unlock();\r
+\r
+            // Do the call back \r
+            if (!ShutdownCalled) {\r
+                pSdpSocket->UsersThreadCallBack(true);\r
+            } else {\r
+                //Currently, we don't call on shutdown.\r
+            }\r
+\r
+            // Release everything\r
+            pSdpSocket->Release();\r
+            continue;\r
+        }\r
+        if (ShutdownCalled) {\r
+            // Is there some other thread that is hidding ? Shouldn't happen\r
+            // but we can't trust the user\r
+            KePulseEvent(&m_UsersCallEvent,IO_NO_INCREMENT ,FALSE);\r
+            Lock.Unlock();\r
+            return STATUS_SUCCESS;\r
+        }\r
+        // Wait for a new event to arrive\r
+        Lock.Unlock();\r
+        rc = MyKeWaitForSingleObject(&m_UsersCallEvent, UserRequest, UserMode, TRUE, NULL);\r
+        \r
+        if (rc == STATUS_USER_APC ) {\r
+            SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Worker thread has recieved a user APC, shuting down the process \n"));\r
+            Shutdown();\r
+            return STATUS_SUCCESS;\r
+        }\r
+    }\r
+\r
+}\r
index c115de6..1726312 100644 (file)
@@ -41,8 +41,6 @@ It keeps a list of all the objects so we know when to remove them.
 #ifndef _SDP_USER_FILE_H\r
 #define _SDP_USER_FILE_H\r
 \r
-\r
-\r
 class SdpUserFile : public RefCountImpl {\r
 private: \r
     KSPIN_LOCK  m_Lock;\r
@@ -50,7 +48,12 @@ private:
 \r
 // BUGBUG: Use something more effiecent for this storage\r
     LIST_ENTRY m_SocketsList; \r
-    \r
+\r
+    LinkedList m_UsersCallList; // This list holds all the requests of users for callback\r
+    KEVENT m_UsersCallEvent;    // The users thread waits on this event\r
+\r
+    volatile long m_NumberOfUserThreads;// Make sure that there is only one user thread\r
+\r
 public:\r
 \r
     SdpUserFile();\r
@@ -64,6 +67,12 @@ public:
 \r
     VOID RemoveSocket(SdpSocket *pSdpSocket);\r
 \r
+//    VOID MoveSocketT(SdpSocket *pSdpSocket);\r
+\r
+    NTSTATUS RequestCallBack(LIST_ENTRY *pList);\r
+\r
+    NTSTATUS UsersThread();\r
+\r
 };\r
 \r
 #endif //_SDP_USER_FILE_H\r
index d44cafc..bf3e60e 100644 (file)
@@ -9,12 +9,11 @@ KERNEL MODE:
        1) Clean error path.\r
 \r
     send:\r
-       1) On send: implmeant some kind of a negal algorithm.\r
-       2) On send: Create some kind of mechanism that will allow to recieve complitions on more than\r
+       1) implmeant some kind of a negal algorithm.\r
+       2) Create some kind of mechanism that will allow to recieve complitions on more than\r
        one send.\r
-       3) If possibale, post more than one send.\r
-       4) Consider copying big packets from the DPC handler, instead of using the users thread\r
-           for the copy\r
+       3) If possibale, post more than one send, at a time\r
+    4) [Critical] Use refferance count when queing the socket in an IRP structure.\r
 \r
      recv:\r
        1) Find and fix the race when the socket is being initialized\r
@@ -34,6 +33,14 @@ general:
        Check the ArpCache problems (on a native windows machine) and decide what to do.\r
        \r
 \r
+Overlapped IO:\r
+1) Split to two types of overlapped operations\r
+2) Use referance counting on our type? If not, make sure that the life time of objects is well.\r
+3) Replace InterlockedIncrement with _InterlockedIncrement\r
+4) Make sure that in UserFile module, operations can start only when there is a user mode thread\r
+   that is already waiting.\r
+\r
+\r
 USER MODE:\r
 \r
 * Check the lifetime of the SdpSocket (when is it deleted and so)??\r