1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 21:57:35 +00:00

Kernel: Tidy up sys$select() to make it more readable.

This commit is contained in:
Andreas Kling 2019-06-06 17:46:41 +02:00
parent 6e4f0b3cc5
commit bf905225e7
2 changed files with 45 additions and 73 deletions

View file

@ -1294,10 +1294,17 @@ int Process::sys$sleep(unsigned seconds)
return 0; return 0;
} }
void kgettimeofday(timeval& tv) timeval kgettimeofday()
{ {
timeval tv;
tv.tv_sec = RTC::boot_time() + PIT::seconds_since_boot(); tv.tv_sec = RTC::boot_time() + PIT::seconds_since_boot();
tv.tv_usec = PIT::ticks_this_second() * 1000; tv.tv_usec = PIT::ticks_this_second() * 1000;
return tv;
}
void kgettimeofday(timeval& tv)
{
tv = kgettimeofday();
} }
int Process::sys$gettimeofday(timeval* tv) int Process::sys$gettimeofday(timeval* tv)
@ -1744,106 +1751,72 @@ clock_t Process::sys$times(tms* times)
int Process::sys$select(const Syscall::SC_select_params* params) int Process::sys$select(const Syscall::SC_select_params* params)
{ {
// FIXME: Return -EINTR if a signal is caught.
// FIXME: Return -EINVAL if timeout is invalid.
if (!validate_read_typed(params)) if (!validate_read_typed(params))
return -EFAULT; return -EFAULT;
if (params->writefds && !validate_read_typed(params->writefds)) if (params->writefds && !validate_write_typed(params->writefds))
return -EFAULT; return -EFAULT;
if (params->readfds && !validate_read_typed(params->readfds)) if (params->readfds && !validate_write_typed(params->readfds))
return -EFAULT; return -EFAULT;
if (params->exceptfds && !validate_read_typed(params->exceptfds)) if (params->exceptfds && !validate_write_typed(params->exceptfds))
return -EFAULT; return -EFAULT;
if (params->timeout && !validate_read_typed(params->timeout)) if (params->timeout && !validate_read_typed(params->timeout))
return -EFAULT; return -EFAULT;
int nfds = params->nfds; if (params->nfds < 0)
fd_set* writefds = params->writefds; return -EINVAL;
fd_set* readfds = params->readfds;
fd_set* exceptfds = params->exceptfds;
auto* timeout = params->timeout;
// FIXME: Implement exceptfds support. if (params->timeout && (params->timeout->tv_sec || params->timeout->tv_usec)) {
(void)exceptfds; auto now = kgettimeofday();
AK::timeval_add(&now, params->timeout, &current->m_select_timeout);
if (timeout && (timeout->tv_sec || timeout->tv_usec)) {
struct timeval now;
kgettimeofday(now);
AK::timeval_add(&now, timeout, &current->m_select_timeout);
current->m_select_has_timeout = true; current->m_select_has_timeout = true;
} else { } else {
current->m_select_has_timeout = false; current->m_select_has_timeout = false;
} }
if (nfds < 0) auto transfer_fds = [&] (auto* fds, auto& vector) -> int {
return -EINVAL;
// FIXME: Return -EINTR if a signal is caught.
// FIXME: Return -EINVAL if timeout is invalid.
auto transfer_fds = [this, nfds] (fd_set* set, auto& vector) -> int {
vector.clear_with_capacity(); vector.clear_with_capacity();
if (!set) if (!fds)
return 0; return 0;
auto bitmap = Bitmap::wrap((byte*)set, FD_SETSIZE); for (int fd = 0; fd < params->nfds; ++fd) {
for (int i = 0; i < nfds; ++i) { if (FD_ISSET(fd, fds)) {
if (bitmap.get(i)) { if (!file_descriptor(fd))
if (!file_descriptor(i))
return -EBADF; return -EBADF;
vector.append(i); vector.append(fd);
} }
} }
return 0; return 0;
}; };
if (int error = transfer_fds(params->writefds, current->m_select_write_fds))
int error = 0;
error = transfer_fds(writefds, current->m_select_write_fds);
if (error)
return error; return error;
error = transfer_fds(readfds, current->m_select_read_fds); if (int error = transfer_fds(params->readfds, current->m_select_read_fds))
if (error)
return error; return error;
error = transfer_fds(exceptfds, current->m_select_exceptional_fds); if (int error = transfer_fds(params->exceptfds, current->m_select_exceptional_fds))
if (error)
return error; return error;
#if defined(DEBUG_IO) || defined(DEBUG_POLL_SELECT) #if defined(DEBUG_IO) || defined(DEBUG_POLL_SELECT)
dbgprintf("%s<%u> selecting on (read:%u, write:%u), timeout=%p\n", name().characters(), pid(), current->m_select_read_fds.size(), current->m_select_write_fds.size(), timeout); dbgprintf("%s<%u> selecting on (read:%u, write:%u), timeout=%p\n", name().characters(), pid(), current->m_select_read_fds.size(), current->m_select_write_fds.size(), params->timeout);
#endif #endif
if (!timeout || current->m_select_has_timeout) if (!params->timeout || current->m_select_has_timeout)
current->block(Thread::State::BlockedSelect); current->block(Thread::State::BlockedSelect);
int markedfds = 0; int marked_fd_count = 0;
auto mark_fds = [&] (auto* fds, auto& vector, auto should_mark) {
if (readfds) { if (!fds)
memset(readfds, 0, sizeof(fd_set)); return;
auto bitmap = Bitmap::wrap((byte*)readfds, FD_SETSIZE); FD_ZERO(fds);
for (int fd : current->m_select_read_fds) { for (int fd : vector) {
auto* descriptor = file_descriptor(fd); if (auto* descriptor = file_descriptor(fd); descriptor && should_mark(*descriptor)) {
if (!descriptor) FD_SET(fd, fds);
continue; ++marked_fd_count;
if (descriptor->can_read()) {
bitmap.set(fd, true);
++markedfds;
} }
} }
} };
mark_fds(params->readfds, current->m_select_read_fds, [] (auto& descriptor) { return descriptor.can_read(); });
if (writefds) { mark_fds(params->writefds, current->m_select_write_fds, [] (auto& descriptor) { return descriptor.can_write(); });
memset(writefds, 0, sizeof(fd_set)); // FIXME: We should also mark params->exceptfds as appropriate.
auto bitmap = Bitmap::wrap((byte*)writefds, FD_SETSIZE); return marked_fd_count;
for (int fd : current->m_select_write_fds) {
auto* descriptor = file_descriptor(fd);
if (!descriptor)
continue;
if (descriptor->can_write()) {
bitmap.set(fd, true);
++markedfds;
}
}
}
// FIXME: Check for exceptional conditions.
return markedfds;
} }
int Process::sys$poll(pollfd* fds, int nfds, int timeout) int Process::sys$poll(pollfd* fds, int nfds, int timeout)
@ -1869,9 +1842,7 @@ int Process::sys$poll(pollfd* fds, int nfds, int timeout)
timeout -= 1000; timeout -= 1000;
} }
tvtimeout.tv_usec = timeout * 1000; tvtimeout.tv_usec = timeout * 1000;
auto now = kgettimeofday();
struct timeval now;
kgettimeofday(now);
AK::timeval_add(&now, &tvtimeout, &current->m_select_timeout); AK::timeval_add(&now, &tvtimeout, &current->m_select_timeout);
current->m_select_has_timeout = true; current->m_select_has_timeout = true;
} else { } else {

View file

@ -22,6 +22,7 @@ class Region;
class VMObject; class VMObject;
class ProcessTracer; class ProcessTracer;
timeval kgettimeofday();
void kgettimeofday(timeval&); void kgettimeofday(timeval&);
class Process : public InlineLinkedListNode<Process> class Process : public InlineLinkedListNode<Process>