Changeset 44487 in vbox for trunk/src/VBox/Runtime/r3/os2
- Timestamp:
- Jan 31, 2013 12:37:42 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 83507
- Location:
- trunk/src/VBox/Runtime/r3/os2
- Files:
-
- 1 deleted
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/os2/pipe-os2.cpp
r44462 r44487 763 763 if (RT_FAILURE(rc)) 764 764 return rc; 765 765 766 rc = rtPipeOs2EnsureSem(pThis); 767 if (RT_SUCCESS(rc) && cMillies > 0) 768 { 769 /* Stop polling attempts if we might block. */ 770 if (pThis->hPollSet == NIL_RTPOLLSET) 771 pThis->hPollSet = (RTPOLLSET)(uintptr_t)0xbeef0042; 772 else 773 rc = VERR_WRONG_ORDER; 774 } 766 775 if (RT_SUCCESS(rc)) 767 776 { … … 771 780 * Check the handle state. 772 781 */ 782 APIRET orc; 783 if (cMillies > 0) 784 { 785 ULONG ulIgnore; 786 orc = DosResetEventSem(pThis->hev, &ulIgnore); 787 AssertMsg(orc == NO_ERROR || orc == ERROR_ALREADY_RESET, ("%d\n", orc)); 788 } 789 773 790 PIPESEMSTATE aStates[4]; RT_ZERO(aStates); 774 APIRETorc = DosQueryNPipeSemState((HSEM)pThis->hev, &aStates[0], sizeof(aStates));791 orc = DosQueryNPipeSemState((HSEM)pThis->hev, &aStates[0], sizeof(aStates)); 775 792 if (orc != NO_ERROR) 776 793 { … … 789 806 Assert(aStates[i].fStatus == NPSS_WSPACE || aStates[i].fStatus == NPSS_RDATA || aStates[i].fStatus == NPSS_EOI); 790 807 if ( aStates[i].fStatus != NPSS_EOI 791 && aStates[ 0].usAvail > 0)808 && aStates[i].usAvail > 0) 792 809 break; 793 810 … … 822 839 if (rc == VERR_BROKEN_PIPE) 823 840 pThis->fBrokenPipe = true; 841 if (cMillies > 0) 842 pThis->hPollSet = NIL_RTPOLLSET; 824 843 } 825 844 … … 860 879 861 880 862 #if 0 863 /** 864 * Internal RTPollSetAdd helper that returns the handle that should be added to 865 * the pollset. 866 * 867 * @returns Valid handle on success, INVALID_HANDLE_VALUE on failure. 868 * @param hPipe The pipe handle. 869 * @param fEvents The events we're polling for. 870 * @param ph where to put the primary handle. 871 */ 872 int rtPipePollGetHandle(RTPIPE hPipe, uint32_t fEvents, PHANDLE ph) 881 int rtPipePollGetHandle(RTPIPE hPipe, uint32_t fEvents, PRTHCINTPTR phNative) 873 882 { 874 883 RTPIPEINTERNAL *pThis = hPipe; … … 876 885 AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE); 877 886 878 AssertReturn(!(fEvents & RTPOLL_EVT_READ) || pThis->fRead,VERR_INVALID_PARAMETER);887 AssertReturn(!(fEvents & RTPOLL_EVT_READ) || pThis->fRead, VERR_INVALID_PARAMETER); 879 888 AssertReturn(!(fEvents & RTPOLL_EVT_WRITE) || !pThis->fRead, VERR_INVALID_PARAMETER); 880 889 881 /* Later: Try register an event handle with the pipe like on OS/2, there is 882 a file control for doing this obviously intended for the OS/2 subsys. 883 The question is whether this still exists on Vista and W7. */ 884 *ph = pThis->Overlapped.hEvent; 885 return VINF_SUCCESS; 890 int rc = RTCritSectEnter(&pThis->CritSect); 891 if (RT_SUCCESS(rc)) 892 { 893 rc = rtPipeOs2EnsureSem(pThis); 894 if (RT_SUCCESS(rc)) 895 *phNative = (RTHCINTPTR)pThis->hev; 896 RTCritSectLeave(&pThis->CritSect); 897 } 898 return rc; 886 899 } 887 900 … … 893 906 * @param pThis The pipe handle. 894 907 * @param fEvents The desired events. 908 * @param fResetEvtSem Whether to reset the event semaphore. 895 909 */ 896 static uint32_t rtPipePollCheck(RTPIPEINTERNAL *pThis, uint32_t fEvents) 897 { 910 static uint32_t rtPipePollCheck(RTPIPEINTERNAL *pThis, uint32_t fEvents, bool fResetEvtSem) 911 { 912 /* 913 * Reset the event semaphore if we're gonna wait. 914 */ 915 APIRET orc; 916 ULONG ulIgnore; 917 if (fResetEvtSem) 918 { 919 orc = DosResetEventSem(pThis->hev, &ulIgnore); 920 AssertMsg(orc == NO_ERROR || orc == ERROR_ALREADY_RESET, ("%d\n", orc)); 921 } 922 923 /* 924 * Check for events. 925 */ 898 926 uint32_t fRetEvents = 0; 899 927 if (pThis->fBrokenPipe) … … 901 929 else if (pThis->fRead) 902 930 { 903 if (!pThis->fIOPending) 904 { 905 DWORD cbAvailable; 906 if (PeekNamedPipe(pThis->hPipe, NULL, 0, NULL, &cbAvailable, NULL)) 907 { 908 if ( (fEvents & RTPOLL_EVT_READ) 909 && cbAvailable > 0) 910 fRetEvents |= RTPOLL_EVT_READ; 911 } 912 else 913 { 914 if (GetLastError() == ERROR_BROKEN_PIPE) 915 pThis->fBrokenPipe = true; 931 ULONG cbActual = 0; 932 ULONG ulState = 0; 933 AVAILDATA Avail = { 0, 0 }; 934 orc = DosPeekNPipe(pThis->hPipe, NULL, 0, &cbActual, &Avail, &ulState); 935 if (orc != NO_ERROR) 936 { 937 fRetEvents |= RTPOLL_EVT_ERROR; 938 if (orc == ERROR_BROKEN_PIPE || orc == ERROR_PIPE_NOT_CONNECTED) 939 pThis->fBrokenPipe = true; 940 } 941 else if (Avail.cbpipe > 0) 942 fRetEvents |= RTPOLL_EVT_READ; 943 else if (ulState != NP_STATE_CONNECTED) 944 { 945 fRetEvents |= RTPOLL_EVT_ERROR; 946 pThis->fBrokenPipe = true; 947 } 948 } 949 else 950 { 951 PIPESEMSTATE aStates[4]; RT_ZERO(aStates); 952 orc = DosQueryNPipeSemState((HSEM)pThis->hev, &aStates[0], sizeof(aStates)); 953 if (orc == NO_ERROR) 954 { 955 int i = 0; 956 while (aStates[i].fStatus == NPSS_RDATA) 957 i++; 958 if (aStates[i].fStatus == NPSS_CLOSE) 959 { 916 960 fRetEvents |= RTPOLL_EVT_ERROR; 917 } 918 } 919 } 920 else 921 { 922 if (pThis->fIOPending) 923 { 924 rtPipeWriteCheckCompletion(pThis); 925 if (pThis->fBrokenPipe) 926 fRetEvents |= RTPOLL_EVT_ERROR; 927 } 928 if ( !pThis->fIOPending 929 && !fRetEvents) 930 { 931 FILE_PIPE_LOCAL_INFORMATION Info; 932 if (rtPipeQueryInfo(pThis, &Info)) 933 { 934 /* Check for broken pipe. */ 935 if (Info.NamedPipeState == FILE_PIPE_CLOSING_STATE) 936 { 937 fRetEvents = RTPOLL_EVT_ERROR; 938 pThis->fBrokenPipe = true; 939 } 940 941 /* Check if there is available buffer space. */ 942 if ( !fRetEvents 943 && (fEvents & RTPOLL_EVT_WRITE) 944 && ( Info.WriteQuotaAvailable > 0 945 || Info.OutboundQuota == 0) 946 ) 947 fRetEvents |= RTPOLL_EVT_WRITE; 948 } 949 else if (fEvents & RTPOLL_EVT_WRITE) 961 pThis->fBrokenPipe = true; 962 } 963 else if ( aStates[i].fStatus == NPSS_WSPACE 964 && aStates[i].usAvail > 0) 950 965 fRetEvents |= RTPOLL_EVT_WRITE; 951 966 } 952 } 953 954 return fRetEvents; 955 } 956 957 958 /** 959 * Internal RTPoll helper that polls the pipe handle and, if @a fNoWait is 960 * clear, starts whatever actions we've got running during the poll call. 961 * 962 * @returns 0 if no pending events, actions initiated if @a fNoWait is clear. 963 * Event mask (in @a fEvents) and no actions if the handle is ready 964 * already. 965 * UINT32_MAX (asserted) if the pipe handle is busy in I/O or a 966 * different poll set. 967 * 968 * @param hPipe The pipe handle. 969 * @param hPollSet The poll set handle (for access checks). 970 * @param fEvents The events we're polling for. 971 * @param fFinalEntry Set if this is the final entry for this handle 972 * in this poll set. This can be used for dealing 973 * with duplicate entries. 974 * @param fNoWait Set if it's a zero-wait poll call. Clear if 975 * we'll wait for an event to occur. 976 */ 967 else 968 { 969 fRetEvents |= RTPOLL_EVT_ERROR; 970 if (orc == ERROR_BROKEN_PIPE || orc == ERROR_PIPE_NOT_CONNECTED) 971 pThis->fBrokenPipe = true; 972 } 973 } 974 975 return fRetEvents & (fEvents | RTPOLL_EVT_ERROR); 976 } 977 978 977 979 uint32_t rtPipePollStart(RTPIPE hPipe, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait) 978 980 { 979 /** @todo All this polling code could be optimized to make fewer system980 * calls; like for instance the ResetEvent calls. */981 981 RTPIPEINTERNAL *pThis = hPipe; 982 982 AssertPtrReturn(pThis, UINT32_MAX); … … 989 989 uint32_t fRetEvents; 990 990 if ( pThis->cUsers == 0 991 || pThis->hPollSet == hPollSet) 992 { 993 /* Check what the current events are. */ 994 fRetEvents = rtPipePollCheck(pThis, fEvents); 995 if ( !fRetEvents 996 && !fNoWait) 997 { 998 /* Make sure the event semaphore has been reset. */ 999 if (!pThis->fIOPending) 1000 { 1001 rc = ResetEvent(pThis->Overlapped.hEvent); 1002 Assert(rc == TRUE); 1003 } 1004 1005 /* Kick off the zero byte read thing if applicable. */ 1006 if ( !pThis->fIOPending 1007 && pThis->fRead 1008 && (fEvents & RTPOLL_EVT_READ) 1009 ) 1010 { 1011 DWORD cbRead = 0; 1012 if (ReadFile(pThis->hPipe, pThis->abBuf, 0, &cbRead, &pThis->Overlapped)) 1013 fRetEvents = rtPipePollCheck(pThis, fEvents); 1014 else if (GetLastError() == ERROR_IO_PENDING) 1015 { 1016 pThis->fIOPending = true; 1017 pThis->fZeroByteRead = true; 1018 } 1019 else 1020 fRetEvents = RTPOLL_EVT_ERROR; 1021 } 1022 1023 /* If we're still set for the waiting, record the poll set and 1024 mark the pipe used. */ 1025 if (!fRetEvents) 1026 { 1027 pThis->cUsers++; 1028 pThis->hPollSet = hPollSet; 1029 } 991 || pThis->hPollSet == NIL_RTPOLLSET) 992 { 993 fRetEvents = rtPipePollCheck(pThis, fEvents, fNoWait); 994 if (!fRetEvents && !fNoWait) 995 { 996 /* Mark the set busy while waiting. */ 997 pThis->cUsers++; 998 pThis->hPollSet = hPollSet; 1030 999 } 1031 1000 } … … 1041 1010 1042 1011 1043 /**1044 * Called after a WaitForMultipleObjects returned in order to check for pending1045 * events and stop whatever actions that rtPipePollStart() initiated.1046 *1047 * @returns Event mask or 0.1048 *1049 * @param hPipe The pipe handle.1050 * @param fEvents The events we're polling for.1051 * @param fFinalEntry Set if this is the final entry for this handle1052 * in this poll set. This can be used for dealing1053 * with duplicate entries. Only keep in mind that1054 * this method is called in reverse order, so the1055 * first call will have this set (when the entire1056 * set was processed).1057 * @param fHarvestEvents Set if we should check for pending events.1058 */1059 1012 uint32_t rtPipePollDone(RTPIPE hPipe, uint32_t fEvents, bool fFinalEntry, bool fHarvestEvents) 1060 1013 { … … 1068 1021 Assert(pThis->cUsers > 0); 1069 1022 1070 1071 /* Cancel the zero byte read. */1072 uint32_t fRetEvents = 0;1073 if (pThis->fZeroByteRead)1074 {1075 CancelIo(pThis->hPipe);1076 DWORD cbRead = 0;1077 if ( !GetOverlappedResult(pThis->hPipe, &pThis->Overlapped, &cbRead, TRUE /*fWait*/)1078 && GetLastError() != ERROR_OPERATION_ABORTED)1079 fRetEvents = RTPOLL_EVT_ERROR;1080 1081 pThis->fIOPending = false;1082 pThis->fZeroByteRead = false;1083 }1084 1085 1023 /* harvest events. */ 1086 fRetEvents |= rtPipePollCheck(pThis, fEvents);1024 uint32_t fRetEvents = rtPipePollCheck(pThis, fEvents, false); 1087 1025 1088 1026 /* update counters. */ 1089 1027 pThis->cUsers--; 1090 if (!pThis->cUsers) 1091 pThis->hPollSet = NIL_RTPOLLSET; 1028 pThis->hPollSet = NIL_RTPOLLSET; 1092 1029 1093 1030 RTCritSectLeave(&pThis->CritSect); 1094 1031 return fRetEvents; 1095 1032 } 1096 #endif
Note:
See TracChangeset
for help on using the changeset viewer.