/* internally to wait for one object. Also used as a shortcut to wait on events and semaphores */ static int _DkObjectWaitOne (PAL_HANDLE handle, PAL_NUM timeout) { /* only for all these handle which has a file descriptor, or a eventfd. events and semaphores will skip this part */ if (HANDLE_HDR(handle)->flags & HAS_FDS) { struct pollfd fds[MAX_FDS]; int off[MAX_FDS]; int nfds = 0; for (int i = 0 ; i < MAX_FDS ; i++) { int events = 0; if ((HANDLE_HDR(handle)->flags & RFD(i)) && !(HANDLE_HDR(handle)->flags & ERROR(i))) events |= POLLIN; if ((HANDLE_HDR(handle)->flags & WFD(i)) && !(HANDLE_HDR(handle)->flags & WRITEABLE(i)) && !(HANDLE_HDR(handle)->flags & ERROR(i))) events |= POLLOUT; if (events) { fds[nfds].fd = handle->generic.fds[i]; fds[nfds].events = events|POLLHUP|POLLERR; fds[nfds].revents = 0; off[nfds] = i; nfds++; } } if (!nfds) return -PAL_ERROR_TRYAGAIN; int64_t waittime = timeout; int ret = ocall_poll(fds, nfds, timeout != NO_TIMEOUT ? &waittime : NULL); if (IS_ERR(ret)) return unix_to_pal_error(ERRNO(ret)); if (!ret) return -PAL_ERROR_TRYAGAIN; for (int i = 0 ; i < nfds ; i++) { if (!fds[i].revents) continue; if (fds[i].revents & POLLOUT) HANDLE_HDR(handle)->flags |= WRITEABLE(off[i]); if (fds[i].revents & (POLLHUP|POLLERR)) HANDLE_HDR(handle)->flags |= ERROR(off[i]); } return 0; } const struct handle_ops * ops = HANDLE_OPS(handle); if (!ops || !ops->wait) return -PAL_ERROR_NOTSUPPORT; return ops->wait(handle, timeout); }
int _DkObjectClose (PAL_HANDLE objectHandle) { if (!objectHandle || UNKNOWN_HANDLE(objectHandle)) return -PAL_ERROR_INVAL; if (atomic_dec_and_test_nonnegative(&objectHandle->__in.ref)) return 0; const struct handle_ops * ops = HANDLE_OPS(objectHandle); /* if the operation 'close' is defined, call the function. */ if (ops && ops->close) return ops->close(objectHandle); free(objectHandle); return 0; }
/* internally to wait for one object. Also used as a shortcut to wait on events and semaphores */ static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout) { /* only for all these handle which has a file descriptor, or a eventfd. events and semaphores will skip this part */ if (handle->__in.flags & HAS_FDS) { struct pollfd fds[MAX_FDS]; int off[MAX_FDS]; int nfds = 0; for (int i = 0 ; i < MAX_FDS ; i++) { int events = 0; if ((handle->__in.flags & RFD(i)) && !(handle->__in.flags & ERROR(i))) events |= POLLIN; if ((handle->__in.flags & WFD(i)) && !(handle->__in.flags & WRITEABLE(i)) && !(handle->__in.flags & ERROR(i))) events |= POLLOUT; if (events) { fds[nfds].fd = handle->__in.fds[i]; fds[nfds].events = events|POLLHUP|POLLERR; fds[nfds].revents = 0; off[nfds] = i; nfds++; } } if (!nfds) return -PAL_ERROR_TRYAGAIN; int ret = INLINE_SYSCALL(poll, 3, &fds, nfds, timeout ? timeout : -1); if (IS_ERR(ret)) switch (ERRNO(ret)) { case EINTR: return -PAL_ERROR_INTERRUPTED; default: return unix_to_pal_error(ERRNO(ret)); } if (!ret) return -PAL_ERROR_TRYAGAIN; for (int i = 0 ; i < nfds ; i++) { if (!fds[i].revents) continue; if (fds[i].revents & POLLOUT) handle->__in.flags |= WRITEABLE(off[i]); if (fds[i].revents & (POLLHUP|POLLERR)) handle->__in.flags |= ERROR(off[i]); } return 0; } const struct handle_ops * ops = HANDLE_OPS(handle); if (!ops->wait) return -PAL_ERROR_NOTSUPPORT; return ops->wait(handle, timeout); }