static int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *timeout) { struct timespec timenow; struct timespec sleepytime; unsigned long long diff; int retcode; /* This is just to avoid a completely busy wait */ clock_gettime(CLOCK_MONOTONIC, &timenow); diff = ts_difftime(&timenow, timeout); sleepytime.tv_sec = diff / 1000000000LL; sleepytime.tv_nsec = diff % 1000000000LL; while ((retcode = pthread_mutex_trylock(mutex)) == EBUSY) { clock_gettime(CLOCK_MONOTONIC, &timenow); if (ts_difftime(timeout, &timenow) >= 0) { return ETIMEDOUT; } nanosleep(&sleepytime, NULL); } return retcode; }
static int pthread_timedjoin_np(pthread_t td, void **res, struct timespec *timeout) { struct timespec timenow; struct timespec sleepytime; /* This is just to avoid a completely busy wait */ sleepytime.tv_sec = 0; sleepytime.tv_nsec = 10000000; /* 10ms */ do { if (pthread_kill(td, 0)) return pthread_join(td, res); nanosleep(&sleepytime, NULL); clock_gettime(CLOCK_MONOTONIC, &timenow); if (ts_difftime(timeout, &timenow) >= 0) { return ETIMEDOUT; } } while (TRUE); return ETIMEDOUT; }
static int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *timeout) #endif { struct timespec timenow; struct timespec sleepytime; int retcode; /* This is just to avoid a completely busy wait */ sleepytime.tv_sec = 0; sleepytime.tv_nsec = 10000000; /* 10ms */ while ((retcode = pthread_mutex_trylock (mutex)) == EBUSY) { clock_gettime(CLOCK_MONOTONIC, &timenow); if (ts_difftime(timeout, &timenow) >= 0) { return ETIMEDOUT; } nanosleep (&sleepytime, NULL); } return retcode; }
DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds) { struct timespec starttime; struct timespec timenow; unsigned long long diff; DWORD signalled; DWORD polled; DWORD *poll_map; BOOL *signalled_idx; int fd = -1; int index; int status; ULONG Type; PVOID Object; #ifdef HAVE_POLL_H struct pollfd *pollfds; #else int maxfd; fd_set fds; struct timeval timeout; #endif if (!nCount || (nCount > MAXIMUM_WAIT_OBJECTS)) { WLog_ERR(TAG, "invalid handles count(%d)", nCount); return WAIT_FAILED; } if (bWaitAll) { signalled_idx = alloca(nCount * sizeof(BOOL)); memset(signalled_idx, FALSE, nCount * sizeof(BOOL)); poll_map = alloca(nCount * sizeof(DWORD)); memset(poll_map, 0, nCount * sizeof(DWORD)); } #ifdef HAVE_POLL_H pollfds = alloca(nCount * sizeof(struct pollfd)); #endif signalled = 0; do { if (bWaitAll && (dwMilliseconds != INFINITE)) clock_gettime(CLOCK_MONOTONIC, &starttime); #ifndef HAVE_POLL_H maxfd = 0; FD_ZERO(&fds); ZeroMemory(&timeout, sizeof(timeout)); #endif polled = 0; for (index = 0; index < nCount; index++) { if (bWaitAll) { if (signalled_idx[index]) continue; poll_map[polled] = index; } if (!winpr_Handle_GetInfo(lpHandles[index], &Type, &Object)) { WLog_ERR(TAG, "invalid event file descriptor"); return WAIT_FAILED; } fd = winpr_Handle_getFd(Object); if (fd == -1) { WLog_ERR(TAG, "invalid file descriptor"); return WAIT_FAILED; } #ifdef HAVE_POLL_H pollfds[polled].fd = fd; pollfds[polled].events = POLLIN; pollfds[polled].revents = 0; #else FD_SET(fd, &fds); if (fd > maxfd) maxfd = fd; #endif polled++; } #ifdef HAVE_POLL_H do { status = poll(pollfds, polled, dwMilliseconds); } while (status < 0 && errno == EINTR); #else if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) { timeout.tv_sec = dwMilliseconds / 1000; timeout.tv_usec = (dwMilliseconds % 1000) * 1000; } do { status = select(maxfd + 1, &fds, 0, 0, (dwMilliseconds == INFINITE) ? NULL : &timeout); } while (status < 0 && errno == EINTR); #endif if (status < 0) { #ifdef HAVE_POLL_H WLog_ERR(TAG, "poll() failure [%d] %s", errno, strerror(errno)); #else WLog_ERR(TAG, "select() failure [%d] %s", errno, strerror(errno)); #endif return WAIT_FAILED; } if (status == 0) return WAIT_TIMEOUT; if (bWaitAll && (dwMilliseconds != INFINITE)) { clock_gettime(CLOCK_MONOTONIC, &timenow); diff = ts_difftime(&timenow, &starttime); if (diff / 1000 > dwMilliseconds) return WAIT_TIMEOUT; else dwMilliseconds -= (diff / 1000); } for (index = 0; index < polled; index++) { DWORD idx; if (bWaitAll) idx = poll_map[index]; else idx = index; if (!winpr_Handle_GetInfo(lpHandles[idx], &Type, &Object)) { WLog_ERR(TAG, "invalid hHandle."); return WAIT_FAILED; } fd = winpr_Handle_getFd(lpHandles[idx]); if (fd == -1) { WLog_ERR(TAG, "invalid file descriptor"); return WAIT_FAILED; } #ifdef HAVE_POLL_H if (pollfds[index].revents & POLLIN) #else if (FD_ISSET(fd, &fds)) #endif { DWORD rc = winpr_Handle_cleanup(lpHandles[idx]); if (rc != WAIT_OBJECT_0) return rc; if (bWaitAll) { signalled_idx[idx] = TRUE; /* Continue checks from last position. */ for (; signalled < nCount; signalled++) { if (!signalled_idx[signalled]) break; } } if (!bWaitAll) return (WAIT_OBJECT_0 + index); if (bWaitAll && (signalled >= nCount)) return (WAIT_OBJECT_0); } } } while (bWaitAll); WLog_ERR(TAG, "failed (unknown error)"); return WAIT_FAILED; }
DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds) { struct timespec starttime; struct timespec timenow; unsigned long long diff; DWORD signalled; DWORD polled; DWORD* poll_map = NULL; BOOL* signalled_idx = NULL; int fd = -1; DWORD index; int status; ULONG Type; BOOL signal_handled = FALSE; WINPR_HANDLE* Object; #ifdef HAVE_POLL_H struct pollfd* pollfds; #else int maxfd; fd_set rfds; fd_set wfds; struct timeval timeout; #endif if (!nCount || (nCount > MAXIMUM_WAIT_OBJECTS)) { WLog_ERR(TAG, "invalid handles count(%"PRIu32")", nCount); return WAIT_FAILED; } if (bWaitAll) { signalled_idx = alloca(nCount * sizeof(BOOL)); memset(signalled_idx, FALSE, nCount * sizeof(BOOL)); poll_map = alloca(nCount * sizeof(DWORD)); memset(poll_map, 0, nCount * sizeof(DWORD)); } #ifdef HAVE_POLL_H pollfds = alloca(nCount * sizeof(struct pollfd)); #endif signalled = 0; do { #ifndef HAVE_POLL_H fd_set* prfds = NULL; fd_set* pwfds = NULL; maxfd = 0; FD_ZERO(&rfds); FD_ZERO(&wfds); ZeroMemory(&timeout, sizeof(timeout)); #endif if (bWaitAll && (dwMilliseconds != INFINITE)) clock_gettime(CLOCK_MONOTONIC, &starttime); polled = 0; for (index = 0; index < nCount; index++) { if (bWaitAll) { if (signalled_idx[index]) continue; poll_map[polled] = index; } if (!winpr_Handle_GetInfo(lpHandles[index], &Type, &Object)) { WLog_ERR(TAG, "invalid event file descriptor"); SetLastError(ERROR_INVALID_HANDLE); return WAIT_FAILED; } fd = winpr_Handle_getFd(Object); if (fd == -1) { WLog_ERR(TAG, "invalid file descriptor"); SetLastError(ERROR_INVALID_HANDLE); return WAIT_FAILED; } #ifdef HAVE_POLL_H pollfds[polled].fd = fd; pollfds[polled].events = handle_mode_to_pollevent(Object->Mode); pollfds[polled].revents = 0; #else FD_SET(fd, &rfds); FD_SET(fd, &wfds); if (Object->Mode & WINPR_FD_READ) prfds = &rfds; if (Object->Mode & WINPR_FD_WRITE) pwfds = &wfds; if (fd > maxfd) maxfd = fd; #endif polled++; } #ifdef HAVE_POLL_H do { status = poll(pollfds, polled, dwMilliseconds); } while (status < 0 && errno == EINTR); #else if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) { timeout.tv_sec = dwMilliseconds / 1000; timeout.tv_usec = (dwMilliseconds % 1000) * 1000; } do { status = select(maxfd + 1, prfds, pwfds, 0, (dwMilliseconds == INFINITE) ? NULL : &timeout); } while (status < 0 && errno == EINTR); #endif if (status < 0) { #ifdef HAVE_POLL_H WLog_ERR(TAG, "poll() handle %d (%"PRIu32") failure [%d] %s", index, nCount, errno, strerror(errno)); #else WLog_ERR(TAG, "select() handle %d (%"PRIu32") failure [%d] %s", index, nCount, errno, strerror(errno)); #endif winpr_log_backtrace(TAG, WLOG_ERROR, 20); SetLastError(ERROR_INTERNAL_ERROR); return WAIT_FAILED; } if (status == 0) return WAIT_TIMEOUT; if (bWaitAll && (dwMilliseconds != INFINITE)) { clock_gettime(CLOCK_MONOTONIC, &timenow); diff = ts_difftime(&timenow, &starttime); if (diff / 1000 > dwMilliseconds) return WAIT_TIMEOUT; else dwMilliseconds -= (diff / 1000); } signal_handled = FALSE; for (index = 0; index < polled; index++) { DWORD idx; BOOL signal_set = FALSE; if (bWaitAll) idx = poll_map[index]; else idx = index; if (!winpr_Handle_GetInfo(lpHandles[idx], &Type, &Object)) { WLog_ERR(TAG, "invalid hHandle."); SetLastError(ERROR_INVALID_HANDLE); return WAIT_FAILED; } fd = winpr_Handle_getFd(lpHandles[idx]); if (fd == -1) { WLog_ERR(TAG, "invalid file descriptor"); SetLastError(ERROR_INVALID_HANDLE); return WAIT_FAILED; } #ifdef HAVE_POLL_H signal_set = pollfds[index].revents & pollfds[index].events; #else if (Object->Mode & WINPR_FD_READ) signal_set = FD_ISSET(fd, &rfds) ? 1 : 0; if (Object->Mode & WINPR_FD_WRITE) signal_set |= FD_ISSET(fd, &wfds) ? 1 : 0; #endif if (signal_set) { DWORD rc = winpr_Handle_cleanup(lpHandles[idx]); if (rc != WAIT_OBJECT_0) return rc; if (bWaitAll) { signalled_idx[idx] = TRUE; /* Continue checks from last position. */ for (; signalled < nCount; signalled++) { if (!signalled_idx[signalled]) break; } } if (!bWaitAll) return (WAIT_OBJECT_0 + index); if (signalled >= nCount) return (WAIT_OBJECT_0); signal_handled = TRUE; } } } while (bWaitAll || !signal_handled); WLog_ERR(TAG, "failed (unknown error)"); SetLastError(ERROR_INTERNAL_ERROR); return WAIT_FAILED; }