prio.c (6750B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "primpl.h" 7 8 #include <string.h> /* for memset() */ 9 10 /************************************************************************/ 11 12 PRLock* _pr_flock_lock; 13 PRCondVar* _pr_flock_cv; 14 15 #ifdef WINCE 16 /* 17 * There are no stdin, stdout, stderr in Windows CE. INVALID_HANDLE_VALUE 18 * should cause all I/O functions on the handle to fail. 19 */ 20 # define STD_INPUT_HANDLE ((DWORD) - 10) 21 # define STD_OUTPUT_HANDLE ((DWORD) - 11) 22 # define STD_ERROR_HANDLE ((DWORD) - 12) 23 24 static HANDLE GetStdHandle(DWORD nStdHandle) { 25 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 26 return INVALID_HANDLE_VALUE; 27 } 28 #endif 29 30 void _PR_InitIO(void) { 31 const PRIOMethods* methods = PR_GetFileMethods(); 32 33 _PR_InitFdCache(); 34 35 _pr_flock_lock = PR_NewLock(); 36 _pr_flock_cv = PR_NewCondVar(_pr_flock_lock); 37 38 #ifdef WIN32 39 _pr_stdin = PR_AllocFileDesc((PROsfd)GetStdHandle(STD_INPUT_HANDLE), methods); 40 _pr_stdout = 41 PR_AllocFileDesc((PROsfd)GetStdHandle(STD_OUTPUT_HANDLE), methods); 42 _pr_stderr = 43 PR_AllocFileDesc((PROsfd)GetStdHandle(STD_ERROR_HANDLE), methods); 44 # ifdef WINNT 45 _pr_stdin->secret->md.sync_file_io = PR_TRUE; 46 _pr_stdout->secret->md.sync_file_io = PR_TRUE; 47 _pr_stderr->secret->md.sync_file_io = PR_TRUE; 48 # endif 49 #else 50 _pr_stdin = PR_AllocFileDesc(0, methods); 51 _pr_stdout = PR_AllocFileDesc(1, methods); 52 _pr_stderr = PR_AllocFileDesc(2, methods); 53 #endif 54 _PR_MD_INIT_FD_INHERITABLE(_pr_stdin, PR_TRUE); 55 _PR_MD_INIT_FD_INHERITABLE(_pr_stdout, PR_TRUE); 56 _PR_MD_INIT_FD_INHERITABLE(_pr_stderr, PR_TRUE); 57 58 _PR_MD_INIT_IO(); 59 } 60 61 void _PR_CleanupIO(void) { 62 PR_FreeFileDesc(_pr_stdin); 63 _pr_stdin = NULL; 64 PR_FreeFileDesc(_pr_stdout); 65 _pr_stdout = NULL; 66 PR_FreeFileDesc(_pr_stderr); 67 _pr_stderr = NULL; 68 69 if (_pr_flock_cv) { 70 PR_DestroyCondVar(_pr_flock_cv); 71 _pr_flock_cv = NULL; 72 } 73 if (_pr_flock_lock) { 74 PR_DestroyLock(_pr_flock_lock); 75 _pr_flock_lock = NULL; 76 } 77 78 _PR_CleanupFdCache(); 79 } 80 81 PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd) { 82 PRFileDesc* result = NULL; 83 PR_ASSERT((int)osfd >= PR_StandardInput && osfd <= PR_StandardError); 84 85 if (!_pr_initialized) { 86 _PR_ImplicitInitialization(); 87 } 88 89 switch (osfd) { 90 case PR_StandardInput: 91 result = _pr_stdin; 92 break; 93 case PR_StandardOutput: 94 result = _pr_stdout; 95 break; 96 case PR_StandardError: 97 result = _pr_stderr; 98 break; 99 default: 100 (void)PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 101 } 102 return result; 103 } 104 105 PR_IMPLEMENT(PRFileDesc*) 106 PR_AllocFileDesc(PROsfd osfd, const PRIOMethods* methods) { 107 PRFileDesc* fd; 108 109 #ifdef XP_UNIX 110 /* 111 * Assert that the file descriptor is small enough to fit in the 112 * fd_set passed to select 113 */ 114 PR_ASSERT(osfd < FD_SETSIZE); 115 #endif 116 fd = _PR_Getfd(); 117 if (fd) { 118 /* Initialize the members of PRFileDesc and PRFilePrivate */ 119 fd->methods = methods; 120 fd->secret->state = _PR_FILEDESC_OPEN; 121 fd->secret->md.osfd = osfd; 122 #if defined(_WIN64) 123 fd->secret->alreadyConnected = PR_FALSE; 124 fd->secret->overlappedActive = PR_FALSE; 125 #endif 126 _PR_MD_INIT_FILEDESC(fd); 127 } else { 128 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 129 } 130 131 return fd; 132 } 133 134 PR_IMPLEMENT(void) PR_FreeFileDesc(PRFileDesc* fd) { 135 PR_ASSERT(fd); 136 _PR_Putfd(fd); 137 } 138 139 #if defined(_WIN64) && defined(WIN95) 140 141 PRFileDescList* _fd_waiting_for_overlapped_done = NULL; 142 PRLock* _fd_waiting_for_overlapped_done_lock = NULL; 143 144 void CheckOverlappedPendingSocketsAreDone() { 145 if (!_fd_waiting_for_overlapped_done_lock || 146 !_fd_waiting_for_overlapped_done) { 147 return; 148 } 149 150 PR_Lock(_fd_waiting_for_overlapped_done_lock); 151 152 PRFileDescList* cur = _fd_waiting_for_overlapped_done; 153 PRFileDescList* previous = NULL; 154 while (cur) { 155 PR_ASSERT(cur->fd->secret->overlappedActive); 156 PRFileDesc* fd = cur->fd; 157 DWORD rvSent; 158 if (GetOverlappedResult((HANDLE)fd->secret->md.osfd, &fd->secret->ol, 159 &rvSent, FALSE) == TRUE) { 160 fd->secret->overlappedActive = PR_FALSE; 161 PR_LOG(_pr_io_lm, PR_LOG_MIN, 162 ("CheckOverlappedPendingSocketsAreDone GetOverlappedResult " 163 "succeeded\n")); 164 } else { 165 DWORD err = WSAGetLastError(); 166 PR_LOG(_pr_io_lm, PR_LOG_MIN, 167 ("CheckOverlappedPendingSocketsAreDone GetOverlappedResult failed " 168 "%d\n", 169 err)); 170 if (err != ERROR_IO_INCOMPLETE) { 171 fd->secret->overlappedActive = PR_FALSE; 172 } 173 } 174 175 if (!fd->secret->overlappedActive) { 176 _PR_MD_CLOSE_SOCKET(fd->secret->md.osfd); 177 fd->secret->state = _PR_FILEDESC_CLOSED; 178 # ifdef _PR_HAVE_PEEK_BUFFER 179 if (fd->secret->peekBuffer) { 180 PR_ASSERT(fd->secret->peekBufSize > 0); 181 PR_DELETE(fd->secret->peekBuffer); 182 fd->secret->peekBufSize = 0; 183 fd->secret->peekBytes = 0; 184 } 185 # endif 186 187 PR_FreeFileDesc(fd); 188 189 if (previous) { 190 previous->next = cur->next; 191 } else { 192 _fd_waiting_for_overlapped_done = cur->next; 193 } 194 PRFileDescList* del = cur; 195 cur = cur->next; 196 PR_Free(del); 197 } else { 198 previous = cur; 199 cur = cur->next; 200 } 201 } 202 203 PR_Unlock(_fd_waiting_for_overlapped_done_lock); 204 } 205 #endif 206 207 /* 208 ** Wait for some i/o to finish on one or more more poll descriptors. 209 */ 210 PR_IMPLEMENT(PRInt32) 211 PR_Poll(PRPollDesc* pds, PRIntn npds, PRIntervalTime timeout) { 212 #if defined(_WIN64) && defined(WIN95) 213 // For each iteration check if TFO overlapped IOs are down. 214 CheckOverlappedPendingSocketsAreDone(); 215 #endif 216 217 return (_PR_MD_PR_POLL(pds, npds, timeout)); 218 } 219 220 /* 221 ** Set the inheritance attribute of a file descriptor. 222 */ 223 PR_IMPLEMENT(PRStatus) PR_SetFDInheritable(PRFileDesc* fd, PRBool inheritable) { 224 #if defined(XP_UNIX) || defined(WIN32) 225 /* 226 * Only a non-layered, NSPR file descriptor can be inherited 227 * by a child process. 228 */ 229 if (fd->identity != PR_NSPR_IO_LAYER) { 230 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 231 return PR_FAILURE; 232 } 233 if (fd->secret->inheritable != inheritable) { 234 if (_PR_MD_SET_FD_INHERITABLE(fd, inheritable) == PR_FAILURE) { 235 return PR_FAILURE; 236 } 237 fd->secret->inheritable = inheritable; 238 } 239 return PR_SUCCESS; 240 #else 241 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 242 return PR_FAILURE; 243 #endif 244 } 245 246 /* 247 ** This function only has a useful implementation in the debug build of 248 ** the pthreads version. 249 */ 250 PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc* debug_out, const char* msg) { 251 /* do nothing */ 252 } /* PT_FPrintStats */