*/
static Atomic_uint32 hgfsHandleCounter = {0};
-/*
- * Number of outstanding asynchronous operations.
- */
-static Atomic_uint32 gHgfsAsyncCounter = {0};
-static MXUserExclLock *gHgfsAsyncLock;
-static MXUserCondVar *gHgfsAsyncVar;
-
static HgfsServerMgrCallbacks *gHgfsMgrData = NULL;
/* Allocate/Add sessions helper functions. */
+static void
+HgfsServerAsyncInfoIncCount(HgfsAsyncRequestInfo *info);
static Bool
HgfsServerAllocateSession(HgfsTransportSessionInfo *transportSession,
HgfsSessionInfo **session);
static Bool HgfsPacketSend(HgfsPacket *packet,
HgfsTransportSessionInfo *transportSession,
+ HgfsSessionInfo *session,
HgfsSendFlags flags);
/*
goto exit;
}
- if (!HgfsPacketSend(input->packet, input->transportSession, 0)) {
+ if (!HgfsPacketSend(input->packet,
+ input->transportSession,
+ input->session,
+ 0)) {
/* Send failed. Drop the reply. */
Log("%s: Error sending reply\n", __FUNCTION__);
}
*/
HSPU_PutMetaPacket(packet, transportSession->channelCbTable);
input->request = NULL;
- Atomic_Inc(&gHgfsAsyncCounter);
+ HgfsServerAsyncInfoIncCount(&input->session->asyncRequestsInfo);
/* Remove pending requests during poweroff. */
Poll_Callback(POLL_CS_MAIN,
* Initialize the globals for handling the active shared folders.
*/
- gHgfsAsyncLock = NULL;
- gHgfsAsyncVar = NULL;
- Atomic_Write(&gHgfsAsyncCounter, 0);
-
DblLnkLst_Init(&gHgfsSharedFoldersList);
gHgfsSharedFoldersLock = MXUser_CreateExclLock("sharedFoldersLock",
RANK_hgfsSharedFolders);
- gHgfsAsyncLock = MXUser_CreateExclLock("asyncLock",
- RANK_hgfsSharedFolders);
-
- gHgfsAsyncVar = MXUser_CreateCondVarExclLock(gHgfsAsyncLock);
if (!HgfsPlatformInit()) {
LOG(4, ("Could not initialize server platform specific \n"));
gHgfsSharedFoldersLock = NULL;
}
- if (NULL != gHgfsAsyncLock) {
- MXUser_DestroyExclLock(gHgfsAsyncLock);
- gHgfsAsyncLock = NULL;
- }
-
- if (NULL != gHgfsAsyncVar) {
- MXUser_DestroyCondVar(gHgfsAsyncVar);
- gHgfsAsyncVar = NULL;
- }
-
HgfsPlatformDestroy();
/*
}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerAsyncInfoInit --
+ *
+ * Initialize the async request info for a session.
+ *
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsServerAsyncInfoInit(HgfsAsyncRequestInfo *info) // IN/OUT: info
+{
+ Atomic_Write(&info->requestCount, 0);
+ info->lock = MXUser_CreateExclLock("asyncLock",
+ RANK_hgfsSharedFolders);
+ info->requestCountIsZero = MXUser_CreateCondVarExclLock(info->lock);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerAsyncInfoExit --
+ *
+ * Destroy the async request info for a session session.
+ *
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsServerAsyncInfoExit(HgfsAsyncRequestInfo *info) // IN/OUT: info
+{
+ ASSERT(Atomic_Read(&info->requestCount) == 0);
+ if (NULL != info->lock) {
+ MXUser_DestroyExclLock(info->lock);
+ info->lock = NULL;
+ }
+
+ if (NULL != info->requestCountIsZero) {
+ MXUser_DestroyCondVar(info->requestCountIsZero);
+ info->requestCountIsZero = NULL;
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerAsyncWaitForAllRequestsDone --
+ *
+ * Wait for all the async info requests to be done.
+ *
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsServerAsyncWaitForAllRequestsDone(HgfsAsyncRequestInfo *info) // IN: info
+{
+ MXUser_AcquireExclLock(info->lock);
+ while (Atomic_Read(&info->requestCount)) {
+ MXUser_WaitCondVarExclLock(info->lock, info->requestCountIsZero);
+ }
+ MXUser_ReleaseExclLock(info->lock);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerAsyncSignalAllRequestsDone --
+ *
+ * Signal that all the async info requests are done.
+ *
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsServerAsyncSignalAllRequestsDone(HgfsAsyncRequestInfo *info) // IN: info
+{
+ MXUser_AcquireExclLock(info->lock);
+ MXUser_BroadcastCondVar(info->requestCountIsZero);
+ MXUser_ReleaseExclLock(info->lock);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerAsyncInfoDecCount --
+ *
+ * Decrement the async info request count for a session.
+ *
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsServerAsyncInfoDecCount(HgfsAsyncRequestInfo *info) // IN/OUT: info
+{
+ if (Atomic_ReadDec32(&info->requestCount) == 1) {
+ HgfsServerAsyncSignalAllRequestsDone(info);
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerAsyncInfoIncCount --
+ *
+ * Increment the async info request count for a session.
+ *
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsServerAsyncInfoIncCount(HgfsAsyncRequestInfo *info) // IN/OUT: info
+{
+ Atomic_Inc(&info->requestCount);
+}
+
+
/*
*-----------------------------------------------------------------------------
*
DblLnkLst_LinkLast(&session->searchFreeList,
&session->searchArray[i].links);
}
+ /* Initialize the async request info.*/
+ HgfsServerAsyncInfoInit(&session->asyncRequestsInfo);
/* Get common to all sessions capabiities. */
HgfsServerGetDefaultCapabilities(session->hgfsSessionCapabilities,
MXUser_DestroyExclLock(session->searchArrayLock);
MXUser_DestroyExclLock(session->fileIOLock);
+ /* Teardown the async request info.*/
+ HgfsServerAsyncInfoExit(&session->asyncRequestsInfo);
+
free(session);
}
HgfsNotify_Deactivate(HGFS_NOTIFY_REASON_SERVER_SYNC, session);
}
- /*
- * XXX - TODO move these globals into the session!
- * Wait for outstanding asynchronous requests to complete.
- */
- MXUser_AcquireExclLock(gHgfsAsyncLock);
- while (Atomic_Read(&gHgfsAsyncCounter)) {
- MXUser_WaitCondVarExclLock(gHgfsAsyncLock, gHgfsAsyncVar);
- }
- MXUser_ReleaseExclLock(gHgfsAsyncLock);
+ HgfsServerAsyncWaitForAllRequestsDone(&session->asyncRequestsInfo);
break;
case HGFS_QUIESCE_THAW:
}
-/*
- *----------------------------------------------------------------------------
- *
- * HgfsNotifyPacketSent --
- *
- * Decrements counter of outstanding asynchronous packets
- * and signal conditional variable when the counter
- * becomes 0.
- *
- * Results:
- * TRUE on success, FALSE on error.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------------
- */
-
-static void
-HgfsNotifyPacketSent(void)
-{
- if (Atomic_ReadDec32(&gHgfsAsyncCounter) == 1) {
- MXUser_AcquireExclLock(gHgfsAsyncLock);
- MXUser_BroadcastCondVar(gHgfsAsyncVar);
- MXUser_ReleaseExclLock(gHgfsAsyncLock);
- }
-}
-
-
/*
*----------------------------------------------------------------------------
*
*/
static Bool
-HgfsPacketSend(HgfsPacket *packet, // IN/OUT: Hgfs Packet
- HgfsTransportSessionInfo *transportSession, // IN: session info
- HgfsSendFlags flags) // IN: flags for how to process
+HgfsPacketSend(HgfsPacket *packet, // IN/OUT: Hgfs Packet
+ HgfsTransportSessionInfo *transportSession, // IN: transport
+ HgfsSessionInfo *session, // IN: session info
+ HgfsSendFlags flags) // IN: send flags
{
Bool result = FALSE;
- Bool notificationNeeded = (0 != (packet->state & HGFS_STATE_CLIENT_REQUEST) &&
+ Bool asyncClientRequest = (0 != (packet->state & HGFS_STATE_CLIENT_REQUEST) &&
0 != (packet->state & HGFS_STATE_ASYNC_REQUEST));
ASSERT(packet);
flags);
}
- if (notificationNeeded) {
- HgfsNotifyPacketSent();
+ if (asyncClientRequest) {
+ ASSERT(session);
+ HgfsServerAsyncInfoDecCount(&session->asyncRequestsInfo);
}
return result;
}
goto exit;
}
- if (!HgfsPacketSend(packet, session->transportSession, 0)) {
+ if (!HgfsPacketSend(packet,
+ session->transportSession,
+ session,
+ 0)) {
LOG(4, ("%s: failed to send notification to the host\n", __FUNCTION__));
goto exit;
}