2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief select() implementation
|
|
|
|
* \author Christian Prochaska
|
2016-12-13 17:09:35 +01:00
|
|
|
* \author Christian Helmuth
|
|
|
|
* \author Emery Hemingway
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
* \author Norman Feske
|
2011-12-22 16:19:25 +01:00
|
|
|
* \date 2010-01-21
|
|
|
|
*
|
|
|
|
* the 'select()' implementation is partially based on the lwip version as
|
|
|
|
* implemented in 'src/api/sockets.c'
|
2016-12-13 17:09:35 +01:00
|
|
|
*
|
|
|
|
* Note what POSIX states about select(): File descriptors associated with
|
|
|
|
* regular files always select true for ready to read, ready to write, and
|
|
|
|
* error conditions.
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2016-12-13 17:09:35 +01:00
|
|
|
* Copyright (C) 2010-2017 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
/* Genode includes */
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
#include <base/log.h>
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
#include <base/exception.h>
|
2016-12-13 17:09:35 +01:00
|
|
|
#include <util/reconstructible.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
/* Libc includes */
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <libc-plugin/plugin_registry.h>
|
|
|
|
#include <libc-plugin/plugin.h>
|
2017-02-14 22:26:03 +01:00
|
|
|
#include <libc/select.h>
|
|
|
|
#include <stdlib.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <sys/select.h>
|
2012-05-24 15:26:59 +02:00
|
|
|
#include <signal.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
/* libc-internal includes */
|
|
|
|
#include <internal/init.h>
|
|
|
|
#include <internal/suspend.h>
|
|
|
|
#include <internal/resume.h>
|
|
|
|
#include <internal/select.h>
|
2016-12-13 17:09:35 +01:00
|
|
|
|
|
|
|
namespace Libc {
|
|
|
|
struct Select_cb;
|
2017-02-14 22:26:03 +01:00
|
|
|
struct Select_cb_list;
|
2016-12-13 17:09:35 +01:00
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
static Libc::Suspend *_suspend_ptr;
|
|
|
|
static Libc::Resume *_resume_ptr;
|
|
|
|
static Libc::Select *_select_ptr;
|
|
|
|
|
|
|
|
|
|
|
|
void Libc::init_select(Suspend &suspend, Resume &resume, Select &select)
|
|
|
|
{
|
|
|
|
_suspend_ptr = &suspend;
|
|
|
|
_resume_ptr = &resume;
|
|
|
|
_select_ptr = &select;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
void (*libc_select_notify)() __attribute__((weak));
|
|
|
|
|
|
|
|
|
|
|
|
/** Description for a task waiting in select */
|
2016-12-13 17:09:35 +01:00
|
|
|
struct Libc::Select_cb
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2017-02-14 22:26:03 +01:00
|
|
|
Select_cb *next = nullptr;
|
2016-12-13 17:09:35 +01:00
|
|
|
|
|
|
|
int const nfds;
|
|
|
|
int nready = 0;
|
|
|
|
fd_set readfds;
|
|
|
|
fd_set writefds;
|
|
|
|
fd_set exceptfds;
|
|
|
|
|
|
|
|
Select_cb(int nfds, fd_set const &readfds, fd_set const &writefds, fd_set const &exceptfds)
|
|
|
|
:
|
|
|
|
nfds(nfds), readfds(readfds), writefds(writefds), exceptfds(exceptfds)
|
|
|
|
{ }
|
2011-12-22 16:19:25 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-02-14 22:26:03 +01:00
|
|
|
struct Libc::Select_cb_list
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2017-02-14 22:26:03 +01:00
|
|
|
Genode::Lock _mutex;
|
|
|
|
Select_cb *_first = nullptr;
|
|
|
|
|
|
|
|
struct Guard : Genode::Lock::Guard
|
|
|
|
{
|
2019-09-16 13:52:39 +02:00
|
|
|
Select_cb_list *l;
|
2017-02-14 22:26:03 +01:00
|
|
|
|
|
|
|
Guard(Select_cb_list &list) : Genode::Lock::Guard(list._mutex), l(&list) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
void unsynchronized_insert(Select_cb *scb)
|
|
|
|
{
|
|
|
|
scb->next = _first;
|
|
|
|
_first = scb;
|
|
|
|
}
|
|
|
|
|
|
|
|
void insert(Select_cb *scb)
|
|
|
|
{
|
|
|
|
Guard guard(*this);
|
|
|
|
unsynchronized_insert(scb);
|
|
|
|
}
|
|
|
|
|
|
|
|
void remove(Select_cb *scb)
|
|
|
|
{
|
|
|
|
Guard guard(*this);
|
|
|
|
|
|
|
|
/* address of pointer to next allows to change the head */
|
|
|
|
for (Select_cb **next = &_first; *next; next = &(*next)->next) {
|
|
|
|
if (*next == scb) {
|
|
|
|
*next = scb->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FUNC>
|
|
|
|
void for_each(FUNC const &func)
|
|
|
|
{
|
|
|
|
Guard guard(*this);
|
|
|
|
|
|
|
|
for (Select_cb *scb = _first; scb; scb = scb->next)
|
|
|
|
func(*scb);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/** The global list of tasks waiting for select */
|
2019-09-16 13:52:39 +02:00
|
|
|
static Libc::Select_cb_list &select_cb_list()
|
|
|
|
{
|
|
|
|
static Libc::Select_cb_list inst;
|
|
|
|
return inst;
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
/**
|
|
|
|
* Poll plugin select() functions
|
|
|
|
*
|
|
|
|
* We iterate over all file descriptors in each list and count the number of
|
|
|
|
* ready descriptors. Output file-descriptor sets are cleared by this function
|
|
|
|
* (according to POSIX).
|
|
|
|
*/
|
|
|
|
static int selscan(int nfds,
|
|
|
|
fd_set *in_readfds, fd_set *in_writefds, fd_set *in_exceptfds,
|
|
|
|
fd_set *out_readfds, fd_set *out_writefds, fd_set *out_exceptfds)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
int nready = 0;
|
|
|
|
|
|
|
|
/* zero timeout for polling of the plugins' select() functions */
|
2016-12-13 17:09:35 +01:00
|
|
|
struct timeval tv_0 = { 0, 0 };
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/* temporary fd sets that are passed to the plugins */
|
2016-12-13 17:09:35 +01:00
|
|
|
int plugin_nready;
|
2011-12-22 16:19:25 +01:00
|
|
|
fd_set plugin_readfds;
|
|
|
|
fd_set plugin_writefds;
|
|
|
|
fd_set plugin_exceptfds;
|
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
/* clear fd sets */
|
|
|
|
if (out_readfds) FD_ZERO(out_readfds);
|
|
|
|
if (out_writefds) FD_ZERO(out_writefds);
|
|
|
|
if (out_exceptfds) FD_ZERO(out_exceptfds);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
for (Libc::Plugin *plugin = Libc::plugin_registry()->first();
|
|
|
|
plugin;
|
|
|
|
plugin = plugin->next()) {
|
2011-12-22 16:19:25 +01:00
|
|
|
if (plugin->supports_select(nfds, in_readfds, in_writefds, in_exceptfds, &tv_0)) {
|
|
|
|
|
|
|
|
plugin_readfds = *in_readfds;
|
|
|
|
plugin_writefds = *in_writefds;
|
|
|
|
plugin_exceptfds = *in_exceptfds;
|
|
|
|
|
|
|
|
plugin_nready = plugin->select(nfds, &plugin_readfds, &plugin_writefds, &plugin_exceptfds, &tv_0);
|
|
|
|
|
|
|
|
if (plugin_nready > 0) {
|
|
|
|
for (int libc_fd = 0; libc_fd < nfds; libc_fd++) {
|
|
|
|
if (out_readfds && FD_ISSET(libc_fd, &plugin_readfds)) {
|
|
|
|
FD_SET(libc_fd, out_readfds);
|
|
|
|
}
|
|
|
|
if (out_writefds && FD_ISSET(libc_fd, &plugin_writefds)) {
|
|
|
|
FD_SET(libc_fd, out_writefds);
|
|
|
|
}
|
|
|
|
if (out_exceptfds && FD_ISSET(libc_fd, &plugin_exceptfds)) {
|
|
|
|
FD_SET(libc_fd, out_exceptfds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nready += plugin_nready;
|
|
|
|
} else if (plugin_nready < 0) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("plugin->select() returned error value ", plugin_nready);
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nready;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* this function gets called by plugin backends when file descripors become ready */
|
|
|
|
static void select_notify()
|
|
|
|
{
|
2016-12-13 17:09:35 +01:00
|
|
|
bool resume_all = false;
|
2011-12-22 16:19:25 +01:00
|
|
|
fd_set tmp_readfds, tmp_writefds, tmp_exceptfds;
|
|
|
|
|
|
|
|
/* check for each waiting select() function if one of its fds is ready now
|
2016-12-13 17:09:35 +01:00
|
|
|
* and if so, wake all up */
|
2017-02-14 22:26:03 +01:00
|
|
|
|
2019-09-16 13:52:39 +02:00
|
|
|
select_cb_list().for_each([&] (Libc::Select_cb &scb) {
|
2017-02-14 22:26:03 +01:00
|
|
|
scb.nready = selscan(scb.nfds,
|
|
|
|
&scb.readfds, &scb.writefds, &scb.exceptfds,
|
|
|
|
&tmp_readfds, &tmp_writefds, &tmp_exceptfds);
|
|
|
|
if (scb.nready > 0) {
|
|
|
|
scb.readfds = tmp_readfds;
|
|
|
|
scb.writefds = tmp_writefds;
|
|
|
|
scb.exceptfds = tmp_exceptfds;
|
2016-12-13 17:09:35 +01:00
|
|
|
|
|
|
|
resume_all = true;
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
2017-02-14 22:26:03 +01:00
|
|
|
});
|
2011-12-22 16:19:25 +01:00
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
if (resume_all) {
|
|
|
|
struct Missing_call_of_init_select : Genode::Exception { };
|
|
|
|
if (!_resume_ptr)
|
|
|
|
throw Missing_call_of_init_select();
|
|
|
|
|
|
|
|
_resume_ptr->resume_all();
|
|
|
|
}
|
2016-12-13 17:09:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-23 12:30:18 +02:00
|
|
|
static inline void print(Genode::Output &output, timeval *tv)
|
2016-12-13 17:09:35 +01:00
|
|
|
{
|
|
|
|
if (!tv) {
|
|
|
|
print(output, "nullptr");
|
|
|
|
} else {
|
|
|
|
print(output, "{");
|
|
|
|
print(output, tv->tv_sec);
|
|
|
|
print(output, ",");
|
|
|
|
print(output, tv->tv_usec);
|
|
|
|
print(output, "}");
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-04-26 12:47:33 +02:00
|
|
|
extern "C" __attribute__((weak))
|
|
|
|
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|
|
|
struct timeval *tv)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
fd_set in_readfds, in_writefds, in_exceptfds;
|
2016-12-13 17:09:35 +01:00
|
|
|
|
|
|
|
Genode::Constructible<Libc::Select_cb> select_cb;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/* initialize the select notification function pointer */
|
|
|
|
if (!libc_select_notify)
|
|
|
|
libc_select_notify = select_notify;
|
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
if (readfds) in_readfds = *readfds; else FD_ZERO(&in_readfds);
|
|
|
|
if (writefds) in_writefds = *writefds; else FD_ZERO(&in_writefds);
|
|
|
|
if (exceptfds) in_exceptfds = *exceptfds; else FD_ZERO(&in_exceptfds);
|
|
|
|
|
|
|
|
{
|
2017-02-14 22:26:03 +01:00
|
|
|
/*
|
2017-04-24 15:03:25 +02:00
|
|
|
* We use the guard directly to atomically check if any descripor is
|
|
|
|
* ready, but insert into select-callback list otherwise.
|
2017-02-14 22:26:03 +01:00
|
|
|
*/
|
2019-09-16 13:52:39 +02:00
|
|
|
Libc::Select_cb_list::Guard guard(select_cb_list());
|
2016-12-13 17:09:35 +01:00
|
|
|
|
|
|
|
int const nready = selscan(nfds,
|
|
|
|
&in_readfds, &in_writefds, &in_exceptfds,
|
|
|
|
readfds, writefds, exceptfds);
|
|
|
|
|
|
|
|
/* return if any descripor is ready */
|
|
|
|
if (nready)
|
|
|
|
return nready;
|
|
|
|
|
|
|
|
/* return on zero-timeout */
|
|
|
|
if (tv && (tv->tv_sec) == 0 && (tv->tv_usec == 0))
|
2011-12-22 16:19:25 +01:00
|
|
|
return 0;
|
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
/* suspend as we don't have any immediate events */
|
|
|
|
|
|
|
|
select_cb.construct(nfds, in_readfds, in_writefds, in_exceptfds);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2019-09-16 13:52:39 +02:00
|
|
|
select_cb_list().unsynchronized_insert(&(*select_cb));
|
2016-12-13 17:09:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
struct Timeout
|
|
|
|
{
|
|
|
|
timeval const *_tv;
|
|
|
|
bool const valid { _tv != nullptr };
|
2019-04-09 15:46:36 +02:00
|
|
|
Genode::uint64_t duration {
|
|
|
|
valid ? (Genode::uint64_t)_tv->tv_sec*1000 + _tv->tv_usec/1000 : 0UL };
|
2016-12-13 17:09:35 +01:00
|
|
|
|
2018-12-03 14:37:54 +01:00
|
|
|
bool expired() const { return valid && duration == 0; };
|
2016-12-13 17:09:35 +01:00
|
|
|
|
|
|
|
Timeout(timeval *tv) : _tv(tv) { }
|
|
|
|
} timeout { tv };
|
|
|
|
|
2017-02-20 13:30:36 +01:00
|
|
|
struct Check : Libc::Suspend_functor {
|
|
|
|
struct Timeout *timeout;
|
|
|
|
Libc::Select_cb *select_cb;
|
|
|
|
|
|
|
|
Check(Timeout *timeout, Libc::Select_cb * select_cb)
|
|
|
|
: timeout(timeout), select_cb(select_cb) { }
|
|
|
|
|
|
|
|
bool suspend() override {
|
|
|
|
return !timeout->expired() && select_cb->nready == 0; }
|
|
|
|
} check ( &timeout, &*select_cb );
|
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
{
|
|
|
|
struct Missing_call_of_init_select : Genode::Exception { };
|
|
|
|
if (!_suspend_ptr)
|
|
|
|
throw Missing_call_of_init_select();
|
|
|
|
}
|
|
|
|
|
2017-02-20 13:30:36 +01:00
|
|
|
while (!timeout.expired() && select_cb->nready == 0)
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
timeout.duration = _suspend_ptr->suspend(check, timeout.duration);
|
2016-12-13 17:09:35 +01:00
|
|
|
|
2019-09-16 13:52:39 +02:00
|
|
|
select_cb_list().remove(&(*select_cb));
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
if (timeout.expired())
|
|
|
|
return 0;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
/* not timed out -> results have been stored in select_cb by select_notify() */
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
if (readfds) *readfds = select_cb->readfds;
|
|
|
|
if (writefds) *writefds = select_cb->writefds;
|
|
|
|
if (exceptfds) *exceptfds = select_cb->exceptfds;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-12-13 17:09:35 +01:00
|
|
|
return select_cb->nready;
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
2012-05-24 15:26:59 +02:00
|
|
|
|
2019-04-26 12:47:33 +02:00
|
|
|
extern "C" __attribute__((alias("select")))
|
|
|
|
int __sys_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|
|
|
struct timeval *tv);
|
2016-08-16 15:44:42 +02:00
|
|
|
|
2019-04-26 12:47:33 +02:00
|
|
|
extern "C" __attribute__((alias("select")))
|
|
|
|
int _select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|
|
|
struct timeval *tv);
|
2016-08-16 15:44:42 +02:00
|
|
|
|
|
|
|
|
2019-04-26 12:47:33 +02:00
|
|
|
extern "C" __attribute__((weak))
|
|
|
|
int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|
|
|
const struct timespec *timeout, const sigset_t *sigmask)
|
2012-05-24 15:26:59 +02:00
|
|
|
{
|
2014-09-09 14:32:31 +02:00
|
|
|
struct timeval tv;
|
2012-05-24 15:26:59 +02:00
|
|
|
sigset_t origmask;
|
|
|
|
int nready;
|
|
|
|
|
|
|
|
if (timeout) {
|
|
|
|
tv.tv_usec = timeout->tv_nsec / 1000;
|
|
|
|
tv.tv_sec = timeout->tv_sec;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sigmask)
|
|
|
|
sigprocmask(SIG_SETMASK, sigmask, &origmask);
|
|
|
|
nready = select(nfds, readfds, writefds, exceptfds, &tv);
|
|
|
|
if (sigmask)
|
|
|
|
sigprocmask(SIG_SETMASK, &origmask, NULL);
|
|
|
|
|
|
|
|
return nready;
|
|
|
|
}
|
2016-08-16 15:44:42 +02:00
|
|
|
|
2019-04-26 12:47:33 +02:00
|
|
|
extern "C" __attribute__((alias("pselect")))
|
|
|
|
int __sys_pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|
|
|
const struct timespec *timeout, const sigset_t *sigmask);
|
2017-02-14 22:26:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
/****************************************
|
|
|
|
** Select handler for libc components **
|
|
|
|
****************************************/
|
|
|
|
|
|
|
|
int Libc::Select_handler_base::select(int nfds, fd_set &readfds,
|
|
|
|
fd_set &writefds, fd_set &exceptfds)
|
|
|
|
{
|
|
|
|
fd_set in_readfds, in_writefds, in_exceptfds;
|
|
|
|
|
|
|
|
/* initialize the select notification function pointer */
|
|
|
|
if (!libc_select_notify)
|
|
|
|
libc_select_notify = select_notify;
|
|
|
|
|
|
|
|
in_readfds = readfds;
|
|
|
|
in_writefds = writefds;
|
|
|
|
in_exceptfds = exceptfds;
|
|
|
|
|
|
|
|
/* remove potentially enqueued callback from list */
|
|
|
|
if (_select_cb->constructed())
|
2019-09-16 13:52:39 +02:00
|
|
|
select_cb_list().remove(&(**_select_cb));
|
2017-02-14 22:26:03 +01:00
|
|
|
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We use the guard directly to atomically check is any descripor is
|
|
|
|
* ready, and insert into select-callback list otherwise.
|
|
|
|
*/
|
2019-09-16 13:52:39 +02:00
|
|
|
Libc::Select_cb_list::Guard guard(select_cb_list());
|
2017-02-14 22:26:03 +01:00
|
|
|
|
|
|
|
int const nready = selscan(nfds,
|
|
|
|
&in_readfds, &in_writefds, &in_exceptfds,
|
|
|
|
&readfds, &writefds, &exceptfds);
|
|
|
|
|
|
|
|
/* return if any descripor is ready */
|
|
|
|
if (nready)
|
|
|
|
return nready;
|
|
|
|
|
|
|
|
/* suspend as we don't have any immediate events */
|
|
|
|
|
2017-03-02 14:57:15 +01:00
|
|
|
_select_cb->construct(nfds, in_readfds, in_writefds, in_exceptfds);
|
2017-02-14 22:26:03 +01:00
|
|
|
|
2019-09-16 13:52:39 +02:00
|
|
|
select_cb_list().unsynchronized_insert(&(**_select_cb));
|
2017-02-14 22:26:03 +01:00
|
|
|
}
|
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
struct Missing_call_of_init_select : Exception { };
|
|
|
|
if (!_select_ptr)
|
|
|
|
throw Missing_call_of_init_select();
|
|
|
|
|
|
|
|
_select_ptr->schedule_select(*this);
|
2017-02-14 22:26:03 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Libc::Select_handler_base::dispatch_select()
|
|
|
|
{
|
|
|
|
Select_handler_cb &select_cb = *_select_cb;
|
|
|
|
|
|
|
|
if (select_cb->nready == 0) return;
|
|
|
|
|
2019-09-16 13:52:39 +02:00
|
|
|
select_cb_list().remove(&(*select_cb));
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
|
|
|
|
if (_select_ptr)
|
|
|
|
_select_ptr->deschedule_select();
|
2017-02-14 22:26:03 +01:00
|
|
|
|
|
|
|
select_ready(select_cb->nready, select_cb->readfds,
|
|
|
|
select_cb->writefds, select_cb->exceptfds);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Libc::Select_handler_base::Select_handler_base()
|
|
|
|
:
|
|
|
|
_select_cb((Select_handler_cb*)malloc(sizeof(*_select_cb)))
|
|
|
|
{ }
|
|
|
|
|
|
|
|
Libc::Select_handler_base::~Select_handler_base()
|
|
|
|
{ }
|