Userspace initially didn't have any sort of mechanism to handle
device hotplug (either removing or inserting a device).
This meant that after a short term of scanning all known devices, by
fetching device events (DeviceEvent packets) from /dev/devctl, we
basically never try to read it again after SystemServer initialization
code.
To accommodate hotplug needs, we change SystemServer by ensuring it will
generate a known set of device nodes at their location during the its
main initialization code. This includes devices like /dev/mem, /dev/zero
and /dev/full, etc.
The actual responsible userspace program to handle hotplug events is a
new userspace program called DeviceMapper, with following key points:
- Its current task is to to constantly read the /dev/devctl device node.
Because we already created generic devices, we only handle devices
that are dynamically-generated in nature, like storage devices, audio
channels, etc.
- Since dynamically-generated device nodes could have an infinite minor
numbers, but major numbers are decoded to a device type, we create an
internal registry based on two structures - DeviceNodeFamily, and
RegisteredDeviceNode. DeviceNodeFamily objects are attached in the
main logic code, when handling a DeviceEvent device insertion packet.
A DeviceNodeFamily object has an internal HashTable to hold objects of
RegisteredDeviceNode class.
- Because some device nodes could still share the same major number (TTY
and serial TTY devices), we have two modes of allocation - limited
allocation (so a range is defined for a major number), or infinite
range. Therefore, two (or more) separate DeviceNodeFamily objects can
can exist albeit sharing the same major number, but they are required
to allocate from a different minor numbers' range to ensure there are
no collisions.
- As for KCOV, we handle this device differently. In case the user
compiled the kernel with such support - this happens to be a singular
device node that we usually don't need, so it's dynamically-generated
too, and because it has only one instance, we don't register it in our
internal registry to not make it complicated needlessly.
The Kernel code is modified to allow proper blocking in case of no
events in the DeviceControlDevice class, because otherwise we will need
to poll periodically the device to check if a new event is available,
which would waste CPU time for no good reason.
This change ensures that code in the Service class doesn't try to check
the g_system_mode variable, but instead is asked on whether it supports
a given system mode string value.
Also, don't assume that we should create sockets for any new Service
instance, but instead do that only if the Service should run in the
current system mode.
Just a small cleanup to ensure we can get these pieces of code out to
other files and still have the main.cpp file organized.
The populate_devtmpfs_char_devices_based_on_sysfs() method is removed
because we can simply create the /dev/devctl device node without looking
at the SysFS. This assumed-to-exist device node will be used later on in
an event loop to handle hotplug events.
Except one instance where it is required for interfacing with LibGUI
Also changed an instance of west const to east because the clang-format
commit hook required it.
Before page_did_create_main_document() only initialized ConsoleClient
for top-level browsing context which means that nested browsing context
could not print into the console.
With this change, ConsoleClient is initialized for documents created
for nested browsing context too. One ConsoleClient is shared between
all browsing contexts within the same page.
With signed 32-bit time_t, the type of time_t + m_ttl is unsigned int,
which results in -Werror=sign-compare. Fix this by explicitly casting
it back to time_t.
The Hurd has sin_len, just like the BSDs.
This happened to hit a clang-format bug, and we have been advised
to disable clang-format for this block of code for now.
Without using PATH_MAX :^)
To read a symlink, we can just open its file with O_NOLINK and read its
contents. To get the executable path, we could read the /proc/self/exe
link like the Linux version does; but that relies on procfs being
mounted. Instead, we could do what procfs itself does to get the path:
ask the proc server about it.
On FreeBSD and GNU/Hurd, SHM_ANON is a nice way to create anonymous
files using the usual shm_open() API. This is a lot like the fallback
shm_open() branch that follows, except we don't have to fool around
with choosing a unique name (with retrying) and unlinking the file
afterwards; it just does the right thing. Isn't this nice?
The Hurd supports sending file descriptors over local sockets using
the SCM_RIGHTS / cmsg mechanism just like the other systems. It doesn't
have anything like ucred/PEERCRED, though.
This is defined when building on GNU/Hurd, the GNU operating system with
the Hurd as its kernel (as it was designed originally, before Linux and
GNU/Linux came to be).
Also, define the corresponding part of User-Agent.
If SO_TIMESTAMP is unsupported, we won't be able to determine
kernelspace-to-userspace latency. But other than that, things should
still build and work.
(It's a separate question of what "kernelspace-to-userspace latency"
even means on a microkernel system, where the network card drivers, the
network stack, and ntpquery(1) are all running as userspace programs.)
Also, don't fail completely if settting receive timeout fails.