int32_t SystemNative_Poll(PollEvent* pollEvents, uint32_t eventCount, int32_t milliseconds, uint32_t* triggered) { if (pollEvents == NULL || triggered == NULL) { return Error_EFAULT; } if (milliseconds < -1) { return Error_EINVAL; } size_t bufferSize; if (!multiply_s(sizeof(struct pollfd), (size_t)eventCount, &bufferSize)) { return SystemNative_ConvertErrorPlatformToPal(EOVERFLOW); } int useStackBuffer = bufferSize <= 2048; struct pollfd* pollfds = (struct pollfd*)(useStackBuffer ? alloca(bufferSize) : malloc(bufferSize)); if (pollfds == NULL) { return Error_ENOMEM; } for (uint32_t i = 0; i < eventCount; i++) { const PollEvent* event = &pollEvents[i]; pollfds[i].fd = event->FileDescriptor; // we need to do this for platforms like AIX where PAL_POLL* doesn't // match up to their reality; this is PollEvent -> system polling switch (event->Events) { case PAL_POLLIN: pollfds[i].events = POLLIN; break; case PAL_POLLPRI: pollfds[i].events = POLLPRI; break; case PAL_POLLOUT: pollfds[i].events = POLLOUT; break; case PAL_POLLERR: pollfds[i].events = POLLERR; break; case PAL_POLLHUP: pollfds[i].events = POLLHUP; break; case PAL_POLLNVAL: pollfds[i].events = POLLNVAL; break; default: pollfds[i].events = event->Events; break; } pollfds[i].revents = 0; } int rv; while ((rv = poll(pollfds, (nfds_t)eventCount, milliseconds)) < 0 && errno == EINTR); if (rv < 0) { if (!useStackBuffer) { free(pollfds); } *triggered = 0; return SystemNative_ConvertErrorPlatformToPal(errno); } for (uint32_t i = 0; i < eventCount; i++) { const struct pollfd* pfd = &pollfds[i]; assert(pfd->fd == pollEvents[i].FileDescriptor); assert(pfd->events == pollEvents[i].Events); // same as the other switch, just system -> PollEvent switch (pfd->revents) { case POLLIN: pollEvents[i].TriggeredEvents = PAL_POLLIN; break; case POLLPRI: pollEvents[i].TriggeredEvents = PAL_POLLPRI; break; case POLLOUT: pollEvents[i].TriggeredEvents = PAL_POLLOUT; break; case POLLERR: pollEvents[i].TriggeredEvents = PAL_POLLERR; break; case POLLHUP: pollEvents[i].TriggeredEvents = PAL_POLLHUP; break; case POLLNVAL: pollEvents[i].TriggeredEvents = PAL_POLLNVAL; break; default: pollEvents[i].TriggeredEvents = (int16_t)pfd->revents; break; } } *triggered = (uint32_t)rv; if (!useStackBuffer) { free(pollfds); } return Error_SUCCESS; }
extern "C" Error SystemNative_Poll(PollEvent* pollEvents, uint32_t eventCount, int32_t milliseconds, uint32_t* triggered) { if (pollEvents == nullptr || triggered == nullptr) { return PAL_EFAULT; } if (milliseconds < -1) { return PAL_EINVAL; } size_t bufferSize; if (!multiply_s(sizeof(pollfd), static_cast<size_t>(eventCount), &bufferSize)) { return SystemNative_ConvertErrorPlatformToPal(EOVERFLOW); } bool useStackBuffer = bufferSize <= 2048; pollfd* pollfds = reinterpret_cast<pollfd*>(useStackBuffer ? alloca(bufferSize) : malloc(bufferSize)); if (pollfds == nullptr) { return PAL_ENOMEM; } for (uint32_t i = 0; i < eventCount; i++) { const PollEvent& event = pollEvents[i]; pollfds[i] = { .fd = event.FileDescriptor, .events = event.Events, .revents = 0 }; } int rv; while (CheckInterrupted(rv = poll(pollfds, static_cast<nfds_t>(eventCount), milliseconds))); if (rv < 0) { if (!useStackBuffer) { free(pollfds); } *triggered = 0; return SystemNative_ConvertErrorPlatformToPal(errno); } for (uint32_t i = 0; i < eventCount; i++) { const pollfd& pfd = pollfds[i]; assert(pfd.fd == pollEvents[i].FileDescriptor); assert(pfd.events == pollEvents[i].Events); pollEvents[i].TriggeredEvents = static_cast<PollEvents>(pfd.revents); } *triggered = static_cast<uint32_t>(rv); if (!useStackBuffer) { free(pollfds); } return PAL_SUCCESS; } extern "C" int32_t SystemNative_PosixFAdvise(intptr_t fd, int64_t offset, int64_t length, FileAdvice advice) { #if HAVE_POSIX_ADVISE int32_t result; while (CheckInterrupted( result = #if HAVE_POSIX_FADVISE64 posix_fadvise64( #else posix_fadvise( #endif ToFileDescriptor(fd), offset, length, advice))); return result; #else // Not supported on this platform. Caller can ignore this failure since it's just a hint. (void)fd, (void)offset, (void)length, (void)advice; return ENOTSUP; #endif }