#ifndef _WIN32 #include #include "pollset.h" #include #include #include #include "../log.h" #define TAG WINPR_TAG("sync.pollset") #ifdef WINPR_HAVE_POLL_H static INT16 handle_mode_to_pollevent(ULONG mode) { INT16 event = 0; if (mode & WINPR_FD_READ) event |= POLLIN; if (mode & WINPR_FD_WRITE) event |= POLLOUT; return event; } #endif BOOL pollset_init(WINPR_POLL_SET* set, size_t nhandles) { WINPR_ASSERT(set); #ifdef WINPR_HAVE_POLL_H if (nhandles > MAXIMUM_WAIT_OBJECTS) { set->isStatic = FALSE; set->pollset = calloc(nhandles, sizeof(*set->pollset)); if (!set->pollset) return FALSE; } else { set->pollset = set->staticSet; set->isStatic = TRUE; } #else set->fdIndex = calloc(nhandles, sizeof(*set->fdIndex)); if (!set->fdIndex) return FALSE; FD_ZERO(&set->rset_base); FD_ZERO(&set->rset); FD_ZERO(&set->wset_base); FD_ZERO(&set->wset); set->maxFd = 0; set->nread = set->nwrite = 0; #endif set->size = nhandles; set->fillIndex = 0; return TRUE; } void pollset_uninit(WINPR_POLL_SET* set) { WINPR_ASSERT(set); #ifdef WINPR_HAVE_POLL_H if (!set->isStatic) free(set->pollset); #else free(set->fdIndex); #endif } void pollset_reset(WINPR_POLL_SET* set) { WINPR_ASSERT(set); #ifndef WINPR_HAVE_POLL_H FD_ZERO(&set->rset_base); FD_ZERO(&set->wset_base); set->maxFd = 0; set->nread = set->nwrite = 0; #endif set->fillIndex = 0; } BOOL pollset_add(WINPR_POLL_SET* set, int fd, ULONG mode) { WINPR_ASSERT(set); #ifdef WINPR_HAVE_POLL_H struct pollfd* item = NULL; if (set->fillIndex == set->size) return FALSE; item = &set->pollset[set->fillIndex]; item->fd = fd; item->revents = 0; item->events = handle_mode_to_pollevent(mode); #else FdIndex* fdIndex = &set->fdIndex[set->fillIndex]; if (mode & WINPR_FD_READ) { FD_SET(fd, &set->rset_base); set->nread++; } if (mode & WINPR_FD_WRITE) { FD_SET(fd, &set->wset_base); set->nwrite++; } if (fd > set->maxFd) set->maxFd = fd; fdIndex->fd = fd; fdIndex->mode = mode; #endif set->fillIndex++; return TRUE; } int pollset_poll(WINPR_POLL_SET* set, DWORD dwMilliseconds) { WINPR_ASSERT(set); int ret = 0; UINT64 dueTime = 0; UINT64 now = 0; now = GetTickCount64(); if (dwMilliseconds == INFINITE) dueTime = 0xFFFFFFFFFFFFFFFF; else dueTime = now + dwMilliseconds; #ifdef WINPR_HAVE_POLL_H int timeout = 0; do { if (dwMilliseconds == INFINITE) timeout = -1; else timeout = (int)(dueTime - now); ret = poll(set->pollset, set->fillIndex, timeout); if (ret >= 0) return ret; if (errno != EINTR) return -1; now = GetTickCount64(); } while (now < dueTime); #else do { struct timeval staticTimeout; struct timeval* timeout; fd_set* rset = NULL; fd_set* wset = NULL; if (dwMilliseconds == INFINITE) { timeout = NULL; } else { long waitTime = (long)(dueTime - now); timeout = &staticTimeout; timeout->tv_sec = waitTime / 1000; timeout->tv_usec = (waitTime % 1000) * 1000; } if (set->nread) { rset = &set->rset; memcpy(rset, &set->rset_base, sizeof(*rset)); } if (set->nwrite) { wset = &set->wset; memcpy(wset, &set->wset_base, sizeof(*wset)); } ret = select(set->maxFd + 1, rset, wset, NULL, timeout); if (ret >= 0) return ret; if (errno != EINTR) return -1; now = GetTickCount64(); } while (now < dueTime); FD_ZERO(&set->rset); FD_ZERO(&set->wset); #endif return 0; /* timeout */ } BOOL pollset_isSignaled(WINPR_POLL_SET* set, size_t idx) { WINPR_ASSERT(set); if (idx > set->fillIndex) { WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); return FALSE; } #ifdef WINPR_HAVE_POLL_H return !!(set->pollset[idx].revents & set->pollset[idx].events); #else FdIndex* fdIndex = &set->fdIndex[idx]; if (fdIndex->fd < 0) return FALSE; if ((fdIndex->mode & WINPR_FD_READ) && FD_ISSET(fdIndex->fd, &set->rset)) return TRUE; if ((fdIndex->mode & WINPR_FD_WRITE) && FD_ISSET(fdIndex->fd, &set->wset)) return TRUE; return FALSE; #endif } BOOL pollset_isReadSignaled(WINPR_POLL_SET* set, size_t idx) { WINPR_ASSERT(set); if (idx > set->fillIndex) { WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); return FALSE; } #ifdef WINPR_HAVE_POLL_H return !!(set->pollset[idx].revents & POLLIN); #else FdIndex* fdIndex = &set->fdIndex[idx]; if (fdIndex->fd < 0) return FALSE; return FD_ISSET(fdIndex->fd, &set->rset); #endif } BOOL pollset_isWriteSignaled(WINPR_POLL_SET* set, size_t idx) { WINPR_ASSERT(set); if (idx > set->fillIndex) { WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); return FALSE; } #ifdef WINPR_HAVE_POLL_H return !!(set->pollset[idx].revents & POLLOUT); #else FdIndex* fdIndex = &set->fdIndex[idx]; if (fdIndex->fd < 0) return FALSE; return FD_ISSET(fdIndex->fd, &set->wset); #endif } #endif