Compare commits

...

247 Commits

Author SHA1 Message Date
Ehmry - ecc9c8b28b ahci: driver improve diagnostic messages for empty ports
Fix 3709
2020-03-22 19:19:29 +05:30
Christian Helmuth cfb49c7316 version: 20.02 2020-02-28 12:19:49 +01:00
Norman Feske a3fad2e171 News item for version 20.02 2020-02-28 12:19:49 +01:00
Norman Feske dd5db8484a Release notes for version 20.02 2020-02-28 12:19:49 +01:00
Christian Helmuth 5affd51250 depot: update recipe hashes 2020-02-28 08:59:43 +01:00
Alexander Boettcher ce27b5ebce tool: support hyphen in depot-user name (depot.inc)
Fixes #3668
2020-02-28 08:58:28 +01:00
Norman Feske fce9cd8c22 sculpt manager: use runtime state report max of 1M
With complex scenarios, supplementing the <report> node with the
attribute 'requested' or 'provides' can easily result in a report of
more than 64K.
2020-02-27 14:47:00 +01:00
Christian Prochaska 8faa916d93 gdb_monitor.run: increase RAM quota
Fixes #3667
2020-02-27 14:47:00 +01:00
Christian Helmuth e52802162c libc: reimplement synchronization primitives
The new implementation relieves the main entrypoint from monitor jobs
for contended lock primitives and is based on custom applicant data
structures, per-lock resp. per-semaphore applicant lists, and a
libc-internal blockade with timeouts based on libc kernel primitives.
2020-02-27 14:47:00 +01:00
Josef Söntgen f3ec246b67 base: remove diagnostic message in destructor
The LOG message in the Signal_handler_thread's destructor is just an
diagnostic leftover.

Fixes #3666.
2020-02-27 14:46:59 +01:00
Christian Prochaska 434c9ceb5d vbox5-nova: document possible 'Blocking_canceled' exception
Fixes #3664
2020-02-27 14:46:59 +01:00
Norman Feske c3fb81d1a1 window_layouter: improve rules formatting
This is a follow-up patch for "window_layouter: add dynamic screen
handling".

Issue #3646
2020-02-27 14:46:59 +01:00
Norman Feske c340f57207 Xml_node: skip leading whitespace in with_raw_node
This patch makes the 'with_raw_node' method more useful in situations
where content of an Xml_node is fed into an Xml_generator, i.e., the
rules report/rom mechanism of the window layouter.
2020-02-27 14:46:59 +01:00
Norman Feske bbe1bf9c3a fs_query.run: increase timeout
This is apparently needed for base-foc on Qemu/x86.
2020-02-27 14:46:59 +01:00
Alexander Boettcher accda1211b mutex: reinit Applicant state in Mutex::acquire()
The applicant_to_wake_up() member must be initialized to 0 to keep the
same semantic as before the change by

"base: add mutex as derivate of lock"

Issue #3662
2020-02-27 14:46:59 +01:00
Norman Feske daee1f4cb8 timer/nova: prevent potential division by zero
This case triggered with the leitzentrale.run script on Qemu.
The frequency value must never initialized with zero.

Fixes #3663
2020-02-27 14:46:59 +01:00
Stefan Kalkowski 87cb10c558 sculpt_manager: accept uplink from "local" network
Be less rigid when checking for available network to support
setups where the uplink or depot repositories are provided by
another source than "wired" or "wifi" NIC services,
e.g., a virtual machine with pass-through network device.
2020-02-27 14:46:59 +01:00
Norman Feske 904651ada9 sculpt: version 20.02 2020-02-27 14:46:59 +01:00
Norman Feske 1d3ce93107 sculpt: leitzentrale user-interface redesign
Issue #3650
2020-02-27 14:46:59 +01:00
Sebastian Sumpf 103dcdeea8 vmm: ARMv8 virtio improvements
net:
* increase queue size to 1024 (more stable on Linux)
* use mac address from Nic session instead of random one
* handle data that is larger than rx descriptor correctly (copy less)
* clear descriptor header (12 bytes) on rx

generic:
* always use 'avail_idx' (tx and rx)
* added barriers when reading/writing queues (TMP)

Ref #3620
2020-02-27 14:46:59 +01:00
Sebastian Sumpf f77531138a vmm: ARMv8 virtio for network and console
Simple console and network implementation of the Virtio protocol.

Fix #3620
2020-02-27 14:46:59 +01:00
Sebastian Sumpf c8b3b060aa vmm: ARMv8 add 'local_address' to Ram_allocator
Ref #3620
2020-02-27 14:46:59 +01:00
Stefan Kalkowski 7780ee6a34 vmm: do not lock inside VMM
We do not use the VMM with several CPUs until now.
On the other hand there is a dead-lock due to the
generic timer calling the cpu handler function explicitly,
which already holds the lock. For the time-being remove the lock.

Ref #3620
2020-02-27 14:46:59 +01:00
Stefan Kalkowski 2e2625e952 vmm: check ring-buffer capacity in pl011 model
Ref #3620
2020-02-27 14:46:58 +01:00
Stefan Kalkowski 55c3eb7c14 vmm: fix GIC interrupt register bit shifts
Ref #3620
2020-02-27 14:46:58 +01:00
Stefan Thöni a7a9855493 base: lay groundwork for base-linux caps change
Include the necessary hooks to introduce file descriptor
based capabilities in base linux.

Issue #3581
2020-02-27 14:46:58 +01:00
Norman Feske 5eaaee0dbe text_area: a simple text viewer / editor
The new text_area component is able to view and edit files.
Internally, it employs a menu_view for the graphics output.

Only basic notepad-like text-editing functions are supported.

At the current time, it is solely meant as a companion of the Sculpt
manager.

Issue #3650
2020-02-27 14:46:58 +01:00
Norman Feske b2bc718c1f fs_query: report 'writeable' attribute for files 2020-02-27 14:46:58 +01:00
Norman Feske 7118ad494c os/vfs.h: add Directory::Entry::rwx accessor 2020-02-27 14:46:58 +01:00
Norman Feske 582e0e718c menu_view: make texture handling more robust
This patch improves the robustness of menu_view when encounting missing
textures, which can happen during development when using styled buttons
and frames. With the patch, menu_view outputs diagnostic messages,
pinpointing the problem.

The patch also updates the texture handling to use the 'File_content'
utility and the VFS for obtaining PNG images.

Issue #3629
2020-02-27 14:46:58 +01:00
Norman Feske 1713583a19 menu_view: basic support for styling labels
This patch allows for the customization of the text color and alpha
value of the label widget by the means of a style-definition file.
The mechanism is exemplified with the new "invisible" label style
that sets the alpha value to zero.

Issue #3629
2020-02-27 14:46:57 +01:00
Norman Feske 38aef49428 menu_view: invisible button style 2020-02-27 14:46:57 +01:00
Alexander Boettcher a9caf3fbe4 base: avoid wrong warning by Mutex::acquire
A _owner is only valid if lock is actually locked.

Issue #3612
2020-02-27 14:46:57 +01:00
Josef Söntgen 80ff844dc2 depot: update public key for cnuke 2020-02-27 14:46:57 +01:00
Josef Söntgen c53be5a3fb os: omit size check on payloadless Block packets
The check is already performed in 'packet_valid' where the conditions
for payloadless packets are already considered.

Fixes #3660.
2020-02-27 14:46:57 +01:00
Josef Söntgen 6addd6cf1e os: fix Node_rwx::rwx
Fixes #3658.
2020-02-27 14:46:57 +01:00
Sebastian Sumpf 3995d2f4a2 part_block: switch to Request_stream and Job APIs
- use Job API as block connection back end
- use Request_stream API as front end
- use Mmio framework for gpt and mbr parsing
- implement sync correctly

fixes #3652
2020-02-27 14:46:57 +01:00
Sebastian Sumpf b95dc611d6 gmp: use architecture specific 'config.h'
Generated a separate 'config.h' for arm, arm_64, x86_32, x86_64 for the
current version (6.1.2) of GMP. This became necessary because
configurations differ for each architecture.

'config.h' generaton on x86_64 host in'gmp-6.1.2' directory:

for x86_64 (native):
! configure

for x86_32:
! configure --host=x86-pc-linux-gnu --build=x86_64-pc-linux-gnu

for arm:
! configure --host=arm-linux-gnu --build=x86_64-pc-linux-gnu \
!  CC=/usr/local/gcc-linaro-arm/bin/arm-linux-gnueabi-gcc ABI=32

for arm_v8:
! configure --host=aarch64-linux-gnu --build=x86_64-pc-linux-gnu \
!  CC=/usr/local/gcc-linaro/bin/aarch64-linux-gnu-gcc ABI=64

issue #3598
2020-02-27 14:46:57 +01:00
Christian Helmuth 4cccf74664 depot: update recipe hashes 2020-02-20 12:11:23 +01:00
Stefan Kalkowski 8cc48d5688 hw: be more accurate in synchronizing ASID/Pages
Fix #3651
2020-02-20 12:11:23 +01:00
Stefan Kalkowski b76bd57ed1 window_layouter: add dynamic screen handling
This commit adds dynamic switching in between different defined
screens via keyboard shortcuts, or by editing the rules file.
In the window_layouter package it defines per default ten screens,
reachable by pressing the screen key along with numbers 0-9.

Fix #3646
2020-02-20 12:11:23 +01:00
Alexander Boettcher 2afc218767 test/registry: measure time used for iteration
Issue #3612
2020-02-20 12:11:22 +01:00
Alexander Boettcher 5bbaa30655 base: use mutex in registry
Issue #3612
2020-02-20 12:11:22 +01:00
Alexander Boettcher 5440cd4b50 base: use blockade in thread
Issue #3612
2020-02-20 12:11:22 +01:00
Alexander Boettcher e686ff78e9 base: add blockade as derivate of lock
Issue #3612
2020-02-20 12:11:22 +01:00
Alexander Boettcher 2bd77722c7 base: use mutex in heap
Issue #3612
2020-02-20 12:11:22 +01:00
Alexander Boettcher 00f69bc70d base: add mutex as derivate of lock
The mutex class is more restrictive in usage compared to
Genode::Lock.

- At initialiation time it is ever unlocked.
- No thread is permitted to lock twice. Warn about it
  in case it happens.
- Only the lock onwer is permitted to unlock the mutex.
  Warn about it and don't unlock the mutex in case it happens.

Issue #3612
2020-02-20 12:11:22 +01:00
Stefan Kalkowski d1609e771a pdf_view: fix typo in pkg runtime requires
Fix #3648
2020-02-20 12:11:22 +01:00
Norman Feske 89f813f113 os: add sandbox lib to api/os 2020-02-20 12:11:22 +01:00
Norman Feske 9b0fbf000e sandbox: support for local state-report handling
Fixes #3647
2020-02-20 12:11:22 +01:00
Stefan Kalkowski 725d16e18e hw: optimize ipc capability allocation
In preparation of ipc receive, by now a bunch of capabilities got
allocated to be ready iin case of capability receiption. After that
unuse slots were freed again. This overhead of senseless (de-)allocations
is replaced in this commit by just restock capability slots that got
used by the last receive.

Fix #3640
2020-02-20 12:11:22 +01:00
Martin Stein e42a205a51 base-hw: Ada-compliant scheduler method signatures
Ref #3308
2020-02-20 12:11:22 +01:00
Martin Stein 0d5f185267 base-hw: no pointers in scheduler interface
Ref #3308
2020-02-20 12:11:22 +01:00
Martin Stein c146a215fb base-hw: cpu scheduler without inheritance
Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein eef7b5e168 base-hw: double list without inheritance
Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein a753b6ce46 base-hw: fix run scripts
Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein 793e12f8f3 base-hw: no error return codes in signaling
Error return codes are used with non-const functions in the signaling modules.
This would have been impractical for the in-place translation of the module to
Ada in the context of the Spunky project. Besides, it is easy to get rid of
them and it makes the execution flow more clear.

Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein 751e6430fa base-hw: obsolete Kernel::Thread::_signal_receiver
Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein 9eb20c2be7 base-hw: no pointer arguments in signaling
Besides reducing the use of pointers in base-hw, this prepares for the in-place
translation of the signaling module to Ada in the context of the Spunky
project.

Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein 5e460394d2 base-hw: do not inherit Kernel::Object
This prevents the use of Kernel::Object as base class for the specific kernel
objects and instead makes it a member of the kernel objects. Besides
simplifying inheritance hierarchies in base-hw, this prepares for the in-place
translation of the signaling module (and others) to Ada in the context of the
Spunky project.

Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein 88043e144a base-hw: no virtual functions in signaling
Besides simplifying the execution flow in the signaling module, this prepares
for the in-place translation of the signaling module to Ada in the context of
the Spunky project.

Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein 3cc7774fe4 base-hw: Ada/SPARK-friendly Ipc_node interface
This prevents the use of C++ features in the public method interface of the
synchronous-IPC module that would be impractical for the in-place
translation of the module into Ada in the context of the Spunky project.

* Get rid of thread accessor.
* Get rid of non-const functions with return values.
* Get rid of pointer return-values.

Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein a04243aaf4 base-hw: remove unused Ipc_node accessor methods
Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein 5a95183c3e base-hw: avoid that Ipc_node inherits
Besides simplifying inheritance hierarchies in base-hw, this prepares for the
in-place translation of the synchronous-IPC module to Ada in the context of the
Spunky project.

Ref #3308
2020-02-20 12:11:21 +01:00
Martin Stein 6a5aa18a7b base-hw: no PD code / virt methods in Ipc_node
This is a simplication of the asyncronous-IPC module of the base-hw kernel.
Besides structuring the code in a cleaner way, it prepares for the in-place
translation of the module into Ada in the context of the Spunky project.

* Get rid of virtual methods in Ipc_node.
* Move all stuff related to protection domains, capabilities, and UTCBs to
  the Thread class. this code might later be moved to a dedicated module, but
  for now it's just fine to have it done by the thread module.

Ref #3308
2020-02-20 12:11:21 +01:00
Christian Prochaska 4b3c40f35b test-tcp_bulk: increase resources
Fixes #3645
2020-02-20 12:11:21 +01:00
Stefan Kalkowski 79fba6c2ac core: add kernel-specific UTCB quota bookkeeping
Fix #859
2020-02-20 12:11:21 +01:00
Tomasz Gajewski 4f217b19a9 hw: add CPU wake up code for rpi3
Moved code waking up processors for Cortex A53 before changing privilege
level because sending events to higher privilege levels is not allowed.

Fixed enable_mmu for Cortex A53 to properly return cpu id.

Fixed starting code for secondary cores to properly initialize stacks.

Added code to wake up secondary cores on rpi3.

Ref #3573
2020-02-20 12:08:17 +01:00
Stefan Kalkowski 202333c881 hw: cortex a9 diagnostic register initialization
We cannot count on the correct initialization of the diagnostic register
of the secondary cores. But the boot core gets initialized by the bootchain,
so we can copy over those values.

Fix #3639
2020-02-20 12:08:17 +01:00
Christian Prochaska 2ce0395fd8 arora.run: fix 'focus' route
Fixes #3637
2020-02-20 12:08:17 +01:00
Ehmry - bbdf181828 core: add support for unlabeled LOG sessions
If the root child requests a LOG service with the label "unlabeled" then
return a LOG session that logs unprefixed messages. This allows a external
test controller to recognize log messages produced by a blessed component.
2020-02-20 12:08:17 +01:00
Norman Feske 0181c6025a menu_view: add <label min_ex=".."> attribute
This new attribute can be used to enforce a minimum width in the unit of
the size of the character 'x'. Furthermore, the patch sets the minimum
height of a label to 0 if no 'text' attribute is present. By combining
both features, the label becomes usable as a horizontal spacer.

Issue #3629
2020-02-20 12:08:17 +01:00
Norman Feske 6eff83c1eb menu_view: invisible frame
Issue #3629
2020-02-20 12:08:17 +01:00
Norman Feske 5aae0f2379 menu_view: support multiple floats within a frame
This patch refines the hover handling such that a float widget never
responds to hovering unless a child is hovered. This way, it becomes
possible to stack multiple float widgets within one frame and still
reach all child widgets.

Issue #3629
2020-02-20 12:08:17 +01:00
Norman Feske 49ae4a834f menu_view: support for displaying text selections
Similarly to the way of how a <cursor> can be defined for a <label>
widget, a selection can be expressed as follows:

  <label ...>
    <selection at="2" length="12"/>
  </label>

Issue #3607
Issue #3629
2020-02-20 12:08:17 +01:00
Norman Feske 5b650434b0 menu_view: unquote label text attribute value
This patch enables the menu view to display '"' characters supplied via
the 'text' attribute of the <label> widget.

Issue #3607
Issue #3629
2020-02-20 12:08:16 +01:00
Norman Feske e612f7cd7d menu_view: add character position to hover report
When setting the <dialog> attribute 'hover_details' to "yes", the hover
report features the character position of a hovered label.

Issue #3607
Issue #3629
2020-02-20 12:08:16 +01:00
Norman Feske 7cc4aa2a28 menu_view: text cursor support
This patch equips the label widget with the ability to display a text
cursor, as illustrated by the following example:

  <label text="...">
    <cursor at="10"/>
  </label>

Issue #3607
Issue #3629
2020-02-20 12:08:16 +01:00
Norman Feske 60f5d0e34a gems/animated_geometry.h: increase value range
The value range supported by the 'Animated_rect' utility is constrained
to 2^11 by the used 32-bit integer type. The interpolation is performed
on fixpoint numbers with a fractional precision of 10 bits. The
non-linear interpolation as performed by the 'Lazy_value' utility
involves squaring the values. Hence, the interpolated integral values
must not exceed 2^11 (2*11 bits for the square plus 10 bit for the
fractional part require 32 bits). This range is too small for
high-resolution displays. Hence this patch replaces the 32-bit integer
type by a 64-bit integer type.

Fixes #3627
2020-02-20 12:08:16 +01:00
Norman Feske 46c5a90ba1 nitpicker_gfx: Text_painter::Font::index_at_xpos
This method is useful for finding the character under a mouse position.
2020-02-20 12:08:16 +01:00
Stefan Kalkowski 1273c573b6 wm: destroy view before newly creating it 2020-02-20 12:08:16 +01:00
Norman Feske 3a2895af19 wm: reset pointer position on leave event
The wm used to remember the last pointer position when observing a leave
event. With such a stale pointer position, the wm would eventually
wrongly create an artifical motion event when a supposedly hovered
window changes its position (during an animated move). This can lead to
the propagation of the stale pointer position to the wm client, which,
in turn, may interpret the outdated position (e.g., the menu view would
report a wrong hover state).

This patch removes the stale state by resetting the '_pointer_pos' when
observing a leave event.

Fixes #3632
2020-02-20 12:08:16 +01:00
Norman Feske 0bffac6c98 nit_fader: make fading steps configurable
Fixes #3633
2020-02-20 12:08:16 +01:00
Norman Feske c25de5dba3 backdrop: make width and height customizable 2020-02-20 12:08:16 +01:00
Norman Feske 60edfa4d77 fs_query: add directory entries to listing report
Fixes #3631
2020-02-20 12:08:16 +01:00
Norman Feske 52e582132f os/vfs.h: handle corner case in join function
When specifying "/" or "" as rel_path to the 'Directory' constructor,
the constructed directory should refer to the same directory. The
implementation of the join utility did not consider this corner case. It
occurred during the attempt to use fs_query with "/" given as path.

This patch also adds a Directory::Entry::dir accessor that returns true
if the entry is a directory.

Fixes #3630
2020-02-20 12:08:16 +01:00
Norman Feske a888041ba4 cached_fs_rom: fix file-handle leak
Fixes #3634
2020-02-20 12:08:16 +01:00
Norman Feske 844af06782 base/buffered_output.h: flush at destruction time
By writing out all dangling characters at destruction time, the
'Buffered_output' utility can be used as a local variable rather
than a long-living object.
2020-02-20 12:08:16 +01:00
Norman Feske 7da3404bd0 pkg/noux-system: increase nit_fb quota
With this change, the window can be maximized on a full-HD screen.
2020-02-20 12:08:16 +01:00
Sid Hussmann 7676f47540 depot_deploy: support heartbeat in deploy config
Issue #3575
2020-02-20 12:08:16 +01:00
Josef Söntgen 9d7a58f6a7 dde_bsd: update audio driver to OpenBSD 6.6
Besides updating to a newer version the update adds the AC97 ICH driver
and addresses shortcomings with the OpenBSD emulation environment:

* Fix 'delay(9)' implementation - it now properly uses 'us' as unit,
  which results on faster initialization of the drivers.

* Fix LOG output that got lost during commit f23579532 and bring over
  the printf implementation from dde_linux for more structured
  printing.

* As said the driver now recognizes the AUICH devices. So far it was
  only tested with the device model in VirtualBox where it produces
  stuttering audio, investigating the cause is still ongoing.

Fixes #3641.
2020-02-20 12:08:16 +01:00
Christian Prochaska 9bd3d2aa5c qt5: use main entrypoint in QPA plugin
Fixes #3644
2020-02-20 12:08:16 +01:00
Christian Prochaska 28e782dda5 qt5: use pthread backend for QThreads
Fixes #3643
2020-02-20 12:08:16 +01:00
Christian Prochaska 597098845c libc: support pthread cleanup handlers
Fixes #3642
2020-02-20 12:08:16 +01:00
Sebastian Sumpf 8a7deae238 ahci: switch to request stream API + structural changes
- Remove dated 'Block::Driver' front end and implement
  'Block::Request_stream' front end
- Remove all dynamic memory allocations but DMA memory allocations
- Remove 'Platform_hba' and implement platform specific functions in
  'spec/<platform>/*'
- Ata and Atapi don't inherit from 'Port' any more, but are a member of
  'Port' as a protocol implementation
- Use platform driver for MMIO mappings (x86)
- Exchange stateful initialization of Ata/Atapi with a sequential
  initialization using 'wait_for_any' and 'retry' patterns
- Fix Atapi initialization by setting the byte count limit
- Set FIS receive base only when Cmd::FRE is disabled and Cmd::FR is 0
- Put everything in namespaces ('Ahci', 'Ata', or 'Atapi')
- Ata decides during read/write operations to use native-command queuing
  or normal DMA requests
- Remove port claiming logic (is now done via 'Constructibles')

fixes #3636
2020-02-20 12:08:16 +01:00
Sebastian Sumpf 73f2c7043c ahci: remove Exynos5 support
Exynos5 support has ceased on Genode

issue #3636
2020-02-10 16:00:41 +01:00
Sebastian Sumpf de24035066 base: add 'wait_for_any' to 'Register_set'
This is the same as 'wait_for' with the difference that 'wait_for_any'
succeeds when *one* condition is met.

issue #3636
2020-02-10 16:00:40 +01:00
Norman Feske 57ea1dbdd3 depot: update recipe hashes 2020-02-10 14:29:06 +01:00
Christian Prochaska 9f73f09cec tcp bulk test: add VFS server tests
Fixes #3611
2020-02-10 14:21:48 +01:00
Martin Stein d56b21d329 nic_router: do not change ethernet header as hub
When forwarding domain-local traffic like a hub, the NIC router shouldn't
modify packets at all.

Fixes #3625
2020-02-10 14:21:47 +01:00
Christian Helmuth 8d60bc11b5 vbox: periodic timer based on absolute timestamps
Before timestamps where calculated as durations since current wakeup
which introduces a systematical drift.
2020-02-10 14:21:47 +01:00
Christian Helmuth 604f4c666b Remove Timed_semaphore from libc incl test package
Issue #3550
2020-02-10 14:21:47 +01:00
Christian Helmuth ff5175ec76 libc: synchronization primitives based on monitor
The libc monitor facility enables the execution of monitor jobs by the
main thread when the monitor pool was charged. In comparison to the
current suspend/resume_all mechanism the main thread iterates over all
job functions in contrast to waking up all threads to check their
conditions by themselves. Threads are only woken up if the completion
condition was met.

This commit is the result of a collaboration with Christian Prochaska.
Many thanks for your support, Christian.

Fixes #3550
2020-02-10 14:21:47 +01:00
Christian Helmuth 6aebd5dd95 libc: append serial number to pthread name
... in pthread_create()

Issue #3550
2020-02-10 14:21:47 +01:00
Christian Helmuth 3d4bed3374 libc: unify semantic of sleep functions
sleep(), usleep(), and nanosleep() now return immediately on
zero-timeout. Also, non-zero timeouts sleep at least 1 ms (the current
minimal timeout in libc), which compensates rounding errors.

Issue #3550
2020-02-10 14:21:47 +01:00
Alexander Boettcher ee7a77643e depot_deploy: support affinity configuration
Fixes #3597
2020-02-10 14:21:47 +01:00
Alexander Boettcher 646d6c368c core: fixup cpu weight on failed thread creation
Fixes #3613
2020-02-07 14:14:20 +01:00
Alexander Boettcher d96e14fe16 sandbox: adjust location size scaling
by incorporating session location

Issue #1412
2020-02-07 14:14:20 +01:00
Alexander Boettcher 3a9d450106 trace: avoid page fault on client calling subjects
Fixes #3608
2020-02-07 14:14:20 +01:00
Martin Stein a73ef9fc06 app/ping: fix destination MAC on ARP replies
The ARP destination MAC was set to the Ethernet source MAC which is not
necessarily the MAC of the other ARP peer. Instead use the ARP source MAC of
the ARP request.
2020-02-04 16:12:04 +01:00
Stefan Kalkowski 3016b64fac mesa: enable ARM-64 port
Fix #3622
2020-02-04 16:10:28 +01:00
Stefan Kalkowski 22498e0b09 os: add backtrace utility for arm_64
Fix #3621
2020-02-04 16:10:22 +01:00
Stefan Kalkowski 79dff674fd gems: add connect facility to tcp_terminal
Instead of listening for new TCP/IP connections only,
the TCP terminal connects to a server when an IP address is
configured in the policy for a terminal client.

Fix #3619
2020-02-04 16:10:09 +01:00
Stefan Kalkowski 56ef7ca9e7 hw: enable ARMv8 performance counter
Fix #3618
2020-02-04 16:05:01 +01:00
Stefan Kalkowski 9db50753f1 libports: add ARMv8 support for libpng
Fix #3617
2020-02-04 16:04:54 +01:00
Stefan Kalkowski e84e1bbf36 dde_linux: optimize refresh routine in imx8_fb_drv
Fix #3616
2020-02-04 16:03:08 +01:00
Stefan Kalkowski fda337a1c0 os: increase throughput of blit for ARM 64-bit
Fix #3615
2020-02-04 16:01:35 +01:00
Stefan Kalkowski f49f91da08 os: increase RAM quota for drivers in fb_bench.run
Enables fb_bench.run script for new imx8 framebuffer driver.

Ref #3615
2020-02-04 15:59:33 +01:00
Christian Helmuth 90535a1401 depot: update recipe hashes 2020-02-04 15:51:10 +01:00
Christian Helmuth 43719b5fd1 libc: fix returned timeout-left value
If the suspend method for the main thread detects that the suspend
condition is false it must return the passed timeout value (not always
0). Otherwise, the caller may incorrectly assume the timeout expired.
2020-02-04 15:51:10 +01:00
Stefan Kalkowski 2a94f8cdb4 depot: update public key for skalk 2020-02-04 15:51:10 +01:00
Christian Helmuth 1e578f1a50 Log key count in input test 2020-02-04 15:51:10 +01:00
Alexander Boettcher a036d2373a x86/ps2: disable devices during commands
Especially the initial reset ended up with an unusable keyboard in rare
cases before. This commit disables keyboard and mouse handling of i8042
during command sequences according to a note from

  https://www.win.tue.nl/~aeb/linux/kbd/scancodes-12.html
2020-02-04 15:51:10 +01:00
Norman Feske a2b303e95a Road map for 2020 2020-02-04 15:51:10 +01:00
Alexander Boettcher 7b964fa700 base: add affinity space info to platform info
Issue #3599
2020-02-04 15:51:10 +01:00
Alexander Boettcher 72f5f9d133 sculpt_manager: apply affinity-space to runtime
Issue #3599
2020-02-04 15:51:10 +01:00
Christian Prochaska 186a6bc080 test-tcp_bulk_lxip: increase timeout value
Fixes #3609
2020-02-04 15:51:10 +01:00
Norman Feske 567d9f7910 Xml_node::Unquoted utility for attribute values
The new utility can be used to revert quoted XML attribute values.
Such quoting is needed whenever an attribute value can contain '"'
characters. E.g., in the menu_view's <label text="..."> widget.

Issue #1757
2020-02-04 15:51:10 +01:00
Norman Feske d70cf314d8 Never throw in 'Attached_rom_dataspace::size'
If the ROM service returned in invalid dataspace, reflect this condition
via a size of zero instead of triggering an exception of type
'Reconstructible<Attached_dataspace>::Deref_unconstructed_object'.

Issue #3606
2020-02-04 15:51:10 +01:00
Norman Feske c6445da654 vfs: watch support for <rom> file system
Fixes #3606
2020-02-04 15:51:10 +01:00
Norman Feske 96cde52838 vfs: make <rom> fs robust against invalid ROMs
An invalid ROM dataspace can occur, for example, when requesting a ROM
from the report_rom service before the first report was posted. Such a
<rom> node can still be useful if it's dynamic. E.g., it can be watched.
Hence, the corner case of an invalid ROM dataspace should be gracefully
handled instead of causing an abort.

Issue #3606
2020-02-04 15:51:09 +01:00
Norman Feske c67a0d3dd8 os/dynamic_rom_session.h: support Xml_generator
This patch adds a special variant of a 'Content_producer' called
'Xml_producer', which allows the direct use of an 'Xml_generator'
for generating the ROM-module content.
2020-02-04 15:51:09 +01:00
Norman Feske 78c0e5f6b6 New sandbox library extracted from init component
This patch extracts the child-management functionality from the init
component into a new library called "sandbox". The library API is
located at 'os/include/os/sandbox.h'.

The sandbox API allows for the interaction of the component with the
sandboxed children by providing locally implemented services. This
mechanism is illustrated by the new test at os/src/test/sandbox.

Issue #3601
2020-02-04 15:51:09 +01:00
Norman Feske f82e7df0ba os/buffered_xml.h: support for generating XML
This patch extends the 'Buffered_xml' utility with a new constructor
that fills the buffer with the output of an 'Xml_generator'. It thereby
presents an easy way to generate XML to be consumed locally.

The patch also add a deprecation mark to the original 'xml' accessor
because copying 'Xml_node' objects (here as return value) is dangerous.
The new 'with_xml_node' method should instead be used to access the XML
content stored in the buffer.

Fixes #3602
2020-02-04 15:51:09 +01:00
Norman Feske 640a001ab6 util/xml_node.h: avoid internal use of exceptions
The XML parser used to rely in C++ exceptions while parsing, which is an
artifact from the initial implementation. This patch reworks the code such
that exceptions are avoided in the common cases.

Fixes #3605
2020-02-04 15:51:09 +01:00
Alexander Boettcher c5c5f8754c test-init: add test to check for affinity warning
Issue #1412
2020-02-04 15:51:09 +01:00
Alexander Boettcher 5be3bf4f26 init: warn about missing affinity-space
if affinity is set by children

Issue #1412
2020-02-04 15:51:09 +01:00
Alexander Boettcher d132fc0a73 init: scale affinity location
Issue #1412
2020-02-04 15:51:09 +01:00
Christian Helmuth 285a33c97d dde_linux: add missing white space in log message 2020-02-04 15:51:09 +01:00
Alexander Boettcher f09ac23144 base: Timestamp type on arm_64 is 64bit 2020-02-04 15:51:09 +01:00
Alexander Boettcher 734752d6b5 base-nova: show size of framebuffer correctly 2020-02-04 15:51:09 +01:00
Christian Prochaska 4fc6c4ff5c test-tcp_bulk_lwip: increase timeout value
Fixes #3604
2020-02-04 15:51:09 +01:00
Christian Prochaska 746d373362 vfs_lxip: classify 'data' file as continuous
Fixes #3603
2020-02-04 15:51:09 +01:00
Alexander Boettcher 2256f5fb4b dde_linux: add dma_wmb/rmb barriers for arm_v6 2020-02-04 15:51:09 +01:00
Christian Prochaska d8e2c95597 vfs server: ensure retry for stalled session
Fixes #3600
2020-02-04 15:51:09 +01:00
Alexander Boettcher 6506240642 dde_linux: add dma_wmb/rmb barriers for arm_v7
and remove re-defined dma_wmb in fec driver
2020-02-04 15:51:09 +01:00
Sebastian Sumpf bd284347da libports: fix undefined reference for gmp on arm_v8
* enable native 'invert_limb' implemenation
* disable native 'udiv_qrnnd' implemenation

fixes #3598
2020-02-04 15:51:08 +01:00
Sebastian Sumpf 3813f9772a libports: add '__gmpn_invert_limb' for arm_v7
Implementation was missing.

issue #3598
2020-02-04 15:51:08 +01:00
Sebastian Sumpf 1902d1a06b hw: do not map boot modules in bootstrap
This commit safes virtual address space.
2020-02-04 15:51:08 +01:00
Josef Söntgen 7ecabb25eb ssh_terminal: address ambigouity of return values
Replace return values with appropiate bool and document two-staged
publickey authentication. This fixes a bug where wrong authentication
attempts are not properly denied.

Issue #3590.
2020-02-04 15:51:08 +01:00
Alexander Boettcher 5b633a83df core: dissolve thread object on failed creation
Fixes #3596
2020-02-04 15:51:08 +01:00
Norman Feske beb8bf498c base-hw: add explicit array-bounds check
This patch rules out out-of-bounds array accesses without inspecting the
caller. It is not a bug fix but adds clarity.
2020-02-04 15:51:08 +01:00
Norman Feske de764d8490 base-hw/muen: add explicit array-bounds check 2020-02-04 15:51:08 +01:00
Norman Feske 5635c1318c base-hw: explicit bounds check in store_apic_id
Avoid relying on the caller regarding the CPU index argument to ease the
reasoning about the code.
2020-02-04 15:51:08 +01:00
Norman Feske 01713c74f9 base-foc: explicit array-index bounds check
Adding an explicit check clarifies at the first glance that the array
bounds are respected without needing knowledge about MAX_CAPS_PER_MSG
and L4_UTCB_GENERIC_DATA_SIZE (used for dimensioning 'mr').
2020-02-04 15:51:08 +01:00
Norman Feske 9ec66f0594 allocator_avl: simplify structure
This patch changes the code of '_alloc_two_blocks_metadata' to not
leak the result of a partial allocation in the out parameters of
the method. This eases the reasoning about the absence of a
use-atfer-free problem (there was none).
2020-02-04 15:51:08 +01:00
Norman Feske 6947bddd3f base: avoid use of memcpy 2020-02-04 15:51:08 +01:00
Norman Feske 37ec636018 test/smp: add missing destruct call 2020-02-04 15:51:08 +01:00
Norman Feske 9bba6613e7 base/affinity.h: simplify member initialization
This is just a minor style improvement.
2020-02-04 15:51:08 +01:00
Christian Prochaska d4f246517c depot: recipe for drivers_interactive-imx8q_evk
Fixes #3595
2020-02-04 15:51:08 +01:00
Stefan Kalkowski 5bfebe7a3f depot: recipe for usb_hid_drv
Fixes #3594
2020-02-04 15:47:27 +01:00
Stefan Kalkowski 3df67362b4 depot: recipe for usb_host_drv
Fixes #3593
2020-02-04 15:47:27 +01:00
Christian Prochaska f1042e7fb1 depot: recipe for imx8_fb_drv
Fixes #3592
2020-02-04 15:47:27 +01:00
Christian Prochaska b29112efdf dde_linux: framebuffer driver for i.MX8 EVK
Fixes #3591
2020-02-04 15:47:27 +01:00
Stefan Kalkowski fe899eecc7 base-linux: fix configurable host toolchain
With the '-x' argument of the 'g++' tool the language gets specified,
therefore it has to be 'c++' furthermore, not CUSTOM_HOST_CXX. Moreover,
when import-lx_hybrid.mk gets evaluated first, global.mk is not included
yet, therefore we cannot eagerly evaluate the CXX_LINK_OPT_NO_PIE variable.

Issue #3466
2020-02-04 15:47:27 +01:00
Norman Feske c2a2ec121f libc-net/resolv: silence warning in 3rd-party code 2020-02-04 15:47:27 +01:00
Norman Feske e1e1fa23b7 zlib: fix compile warning
This patch includes 'unistd.h' to avoid warnings about the implicit
declaration of the functions ‘read’, 'close', and 'write.
2020-02-04 15:47:27 +01:00
Norman Feske aee8d35dc4 libcrypto: suppress warning about unused value 2020-02-04 15:47:27 +01:00
Christian Helmuth 4bbbf5d2e3 dde_linux: reduce compiler warnings 2020-02-04 15:47:27 +01:00
Norman Feske ba7e832c5d ssh_terminal: fix compile warning
server.h:51:12: warning: ‘int write_avail_cb(socket_t, int, void*)’
                declared ‘static’ but never defined [-Wunused-function]

This patch fixes the warning by moving the user of 'write_avail_cb' to
the compliation unit that defines it.
2020-01-03 14:44:31 +01:00
Norman Feske bbfc092a31 core: avoid use of C array as buffer in Log_root 2020-01-03 14:44:15 +01:00
Norman Feske de52cf1cdd core: check return value of map.metadata
Even though the call of map.metadata is known to always return a valid
pointer (because the meta data is assigned in the code just above),
better add an explicit nullptr check.
2020-01-03 14:44:15 +01:00
Norman Feske 783c05fd6c uart/exynos: be explicit about unused return value 2020-01-03 14:44:15 +01:00
Norman Feske 6ae98e2e6d base: mark Parent::Close_result with [[nodiscard]] 2020-01-03 14:44:15 +01:00
Norman Feske ffc099eb54 cxx: add nullptr check in calloc
Even though malloc via the cxx_heap never fails, the implementation of
calloc should better not rely on this assumption.
2020-01-03 14:44:15 +01:00
Christian Helmuth 9321067b68 Remove unused/redundant longlong.h
This was used by an ancient libgmp port - longlong.h is now part of the
GMP sources.
2020-01-03 14:21:41 +01:00
Christian Prochaska 0eaa1f7a08 lx_kit: support enable/disable IRQ and pass IRQ number to handler
Fixes #3589
2020-01-02 15:53:46 +01:00
Christian Helmuth 18f90ca1e3 nova: request stack pointer on page fault
The SP value is part of the Page_fault_info object but was not requested
from the kernel on portal creation.
2020-01-02 15:30:28 +01:00
Christian Helmuth 9a35743df6 Mark packet-stream descriptor head/tail as volatile
`volatile` effectively prevents instruction reordering by the compiler
and fixes an issue with -O3 compiled components.

Note, this commit does not address further arguments regarding memory
barriers and volatile voiced in issue #693.

Issue #693
2019-12-20 14:34:22 +01:00
Christian Helmuth 8d63a3c1f3 Increase timeout of RTC test
It takes its time on sel4 and Qemu.
2019-12-20 14:28:18 +01:00
Alexander Boettcher 1ac33caa90 nova: handle rpc_entrypoint destruction better
Fixes #1921
2019-12-20 11:31:39 +01:00
Alexander Boettcher 1c361bf545 base: add test to destruct entrypoint
Issue #1921
2019-12-20 11:31:27 +01:00
Alexander Boettcher a41dd48986 nova: avoid invalid capability counting overhead
- handle it the same way as done for other kernels

Fixes #3579
2019-12-20 11:29:21 +01:00
Christian Helmuth b931b67cba depot: update recipe hashes 2019-12-19 17:01:43 +01:00
Christian Helmuth 24435e9ca1 Run TCP bulk tests on all Qemu platforms
This explicitly includes ARM32/64.
2019-12-19 17:01:43 +01:00
Alexander Boettcher e54ff599ca base-hw: trace execution time of core threads
Fixes #3572
2019-12-19 17:01:43 +01:00
Sebastian Sumpf 04969b6be0 base-hw: add trace execution time support
This enables the 'top' program on base-hw for debugging issue #3247 on
rpi.

Fixes #3572
2019-12-19 17:01:42 +01:00
Christian Helmuth 1ddf1dbc25 Use ram-block in libc vfs tests on Rpi3 2019-12-19 17:01:42 +01:00
Christian Helmuth 8699f5592f wifi: run wpa_main in pthread 2019-12-19 17:01:42 +01:00
Norman Feske 73d089da36 Quota tweaks for base-sel4 2019-12-19 17:01:42 +01:00
Christian Prochaska c8cd09e72c qt5: don't build qt5_jscore and qt5_webcore for arm_v8a
Fixes #3585
2019-12-19 17:01:42 +01:00
Christian Prochaska be1ef01f10 stdcxx: add symbols needed by dosbox
Fixes #3588
2019-12-19 17:01:42 +01:00
Alexander Boettcher 0a1bc1f4b7 nova: add requesting time of killed SCs
Fixes #3587
2019-12-19 17:01:42 +01:00
Alexander Boettcher bcb7f45201 core: avoid dangling ptr in cpu thread component
if exception is triggered during construction of a thread
2019-12-19 17:01:42 +01:00
Alexander Boettcher 33db0e0d4d base: add uboot for imx8 as port
that contains scripts to download and build uboot

Fixes #3584
2019-12-19 17:01:42 +01:00
Christian Helmuth 504539ad1e vfs/lwip: notify I/O progress on sent packets
Incoming ACK packets for sent data packets may be the only unblocker for
suspended write/send loops. This patch informs VFS users about I/O of
VFS handle on successfully sent packets.
2019-12-19 17:01:42 +01:00
Christian Prochaska a62fce8dc5 sd_card_drv: i.MX8 support
Fixes #3580
2019-12-19 17:01:42 +01:00
Christian Prochaska 81a78cf1d0 usb_host_drv: fix 'matches->compatible' string access
Fixes #3582
2019-12-19 17:01:42 +01:00
Christian Helmuth 283135c9cd test-libc_getenv: allow unrelated content in log pattern 2019-12-19 17:01:42 +01:00
Sebastian Sumpf 22d4d5c1c1 ldso: update link map during respawn
move binary to front of link map after respawn. This is required by GDB
in order to load symbol files correctly.

issue #3481
2019-12-19 17:01:42 +01:00
Sebastian Sumpf 9c372c36c1 libc: thread local errno support
Store errno in pthread objects, return member upon call to '__error()'.
This became necessary in order to make errno thread-safe.

Note, any call to libc code from a non-pthread (beside the first
entrypoint) is not supported.

issue #3568
2019-12-19 17:01:42 +01:00
Sebastian Sumpf 9767c4db0e vfs_lwip/lwip: Lwip::lock for concurrent access
This is required in case the send and receive of IP packets is
performed by multiple thread because lwip is not thread safe.

issue #3568
2019-12-19 17:01:42 +01:00
Alexander Boettcher 9812799b24 seoul: reduce CPU load in graphic mode
- Stop refreshing if all CPUs go to sleep, also in text mode.
- Any input resets update rate to 100Hz in graphic mode, which gets
  decreased step by step down to 25Hz if no input is available (looking video
  without input by user).

Fixes #3576
2019-12-19 17:01:42 +01:00
Alexander Boettcher d385749ead seoul: make vmm memory configurable
- document Genode specific configuration option
2019-12-19 17:01:42 +01:00
Christian Helmuth 23ed5d3936 base-linux: configurable host toolchain
This commit uses CUSTOM_HOST_CC/CUSTOM_HOST_CXX instead of hardcoded
commands and introduces HOST_DEV_PREFIX.

Original patch by Roman Iten and Pirmin Duss.

Issue #3466
2019-12-19 17:01:42 +01:00
Christian Helmuth cebc963396 Cleanup linux_rtc_drv and lx_fs target.mk
Original patch by Roman Iten and Pirmin Duss.

Issue #3466
2019-12-19 17:01:42 +01:00
Norman Feske 0c8ec41c21 vfs/pipe: let num_dirent return 0
This prevents the original value ~0UL from messing up the output
of 'ls -l /dev'.

Issue #3578
2019-12-19 17:01:42 +01:00
Norman Feske 9f7b8c1a17 vfs/log: allow output redirection via '> /dev/log'
Issue #3578
2019-12-19 17:01:42 +01:00
Norman Feske cd92b32622 libc: close all open FDs on exit
This is important to issue sync requests for written-to files.

As the closing must be performed by an atexit handler, it happens at a
time _after_ libc plugins are destructed. Consequently an FD allocated
by such a plugin results in a close error, which in turn, does not
destruct the FD. We ultimatedly end up in an infinte loop of
re-attempting the close. For this reason, the patch changes 'close' to
be robust against this special case.

This is generally not a problem because libc plugins are phased out.
However, at present, the libc_noux plugin is still important. With the
changed 'close' in place, there occurred an error message "Error: close:
close not implemented" at the exit of each noux program. This patch
removes the error printing from the libc plugin mechansim to avoid this
noise. The error messages are not important anyway because the
deprecation of the libc plugin interface.

Issue #3578
2019-12-19 17:00:48 +01:00
Norman Feske 5853a68904 libc: silence calls of getpeername w/o socket fs
The getpeername function is provided only by the socket fs.
In the case where the socket fs is not configured, return an appropriate
errno instead probing for a libc plugin (there is none).

Issue #3578
2019-12-19 17:00:48 +01:00
Norman Feske ae64830bd5 libc: silence get(e)gid, get(e)uid, getppid
These dummies spam the log when running bash + make, like in the
genodians.org scenario.

Issue #3578
2019-12-19 17:00:48 +01:00
Norman Feske e8878eee8a ldso: increase initial heap block
This is needed to enable the fork of 'make' in the genodians.org
scenario on NOVA.

Issue #3578
2019-12-19 17:00:48 +01:00
Norman Feske 3897ddea03 cxx: don't rely on global ctors
This patch removes the global variable 'blocker', which was expected to
be constructed via the global ctors. This mechanism, however, is not
used for the base library, which resulted in the use of an unconstructed
object. Specifically, the spinlock of the 'Lock' of the 'Registry'
defaulted to the LOCKED state (value 0), which eventually would lead to
a deadlock in the contention case of the cxa guard.

I could observe this deadlock once on during the component startup on
base-linux during the construction of the 'startup_lock'.

This patch fixes the problem by explicitly initializing the registry
of blockers via an init function.

Issue #2299
Issue #3578
2019-12-19 17:00:48 +01:00
Norman Feske 6858270517 base: disarm atexit handling for signal thread
The signal thread is not supposed to be destructed in any scenario other
than the noux fork mechanism (where no signals occur).

Issue #3578
2019-12-19 17:00:48 +01:00
Norman Feske 4e57b6eceb core: fix destruction of dependent CPU sessions
Issue #3578
2019-12-19 17:00:48 +01:00
Norman Feske 298f317f44 core: remove quota-related diagnostic messages
Issue #3578
2019-12-19 17:00:48 +01:00
Norman Feske 5820ad8309 fiasco: silence ipc_send error messages
These diagnostic messages spam the log but can occur during the regular
component-destruction procedure.

Issue #3578
2019-12-19 17:00:48 +01:00
Norman Feske b7fbe65ff2 libc: fork/execve improvements
- Close FDs marked with the close-on-execve flag
  (needed for 'make', which sets the flag for the pipe-in
  FD of forked children)
- Update binary name on execve to use as ROM for subsequent fork
- Enable vfork as an alias for fork (needed by make)
- Purge line buffers for output streams during execve because they
  may be allocated at the allocation heap, which does not survive
  the execve call.
- Consider short-lived processes that may exit while the parent still
  blocks in the fork call.

With these changes, the website generator of genodians.org works without
the need for the Noux runtime.

Issue #3578
2019-12-19 17:00:47 +01:00
Norman Feske d1cf216384 libc: propagate pipe config to child processes
Issue #3578
2019-12-19 17:00:47 +01:00
Alexander Boettcher 3011dc5876 sculpt: add vbox5 generic package as option
Fixes #3574
2019-12-19 17:00:47 +01:00
Alexander Boettcher 6e99f00f5c usb_hid_raw: enable imx8q_evk for nightly testing
Issue #3571
2019-12-19 17:00:47 +01:00
Alexander Boettcher beb1e084a6 base: add imx8 evk usb driver to platform config
Issue #3571
2019-12-19 17:00:47 +01:00
Alexander Boettcher e34b443c29 usb: add imx8q_evk support to usb_host
Issue #3571
2019-12-19 17:00:47 +01:00
Alexander Boettcher 6b17bb647e dde_linux: add barriers to readl/writel
Issue #3571
2019-12-19 17:00:47 +01:00
Christian Helmuth 4299b85cdb base-linux: support invalid dataspace for RM client
This restores behavior introduced in

  commit cb232891bf
  Author: Norman Feske <norman.feske@genode-labs.com>
  Date:   Tue May 10 11:55:25 2016 +0200

    Fix noux.run on base-linux

but removed by issue #2829.

Related to issue #1938
2019-12-19 17:00:47 +01:00
Sebastian Sumpf 6dae147785 libc: limit fd id allocations to FD_SETSIZE
fd > FD_SETSIZE cannot use 'select' or 'poll' within our libc.
Therefore, we added a bit allocator in order to allocate fd < FD_SETSIZE
(1024).

fixes #3568
2019-12-19 17:00:47 +01:00
Sebastian Sumpf e4255e4c8b vfs/lxip: wait for i/o progress on connect
Since connect is asynchronous, add a waiter during connect

issue #3568
2019-12-19 17:00:47 +01:00
Christian Helmuth 161274f785 pistachio: check for 'ed' tool on port prepare
Some debian systems seems to come without 'ed' in the base installation.
The tool is needed when building the pistachio kernel.
2019-12-19 17:00:47 +01:00
Roman Iten 6145cdcf37 run: close connection to spawned processes on kill
From the man page of expect:

> Both expect and interact will detect when the current process exits
> and implicitly do a close.  But if you kill the process by, say, "exec
> kill  $pid",  you  will need to explicitly call close.

Fixes #3569
2019-12-19 17:00:47 +01:00
Tomasz Gajewski b57a4c98cf tool/run: run external command plugin for power_on subsystem
Fixes #3385
2019-12-19 16:59:03 +01:00
Ehmry - a3e43aca87 Clang: undeclared identifier __UINT64_C
Issue #3564
2019-12-19 16:59:03 +01:00
Norman Feske 6b6915e304 ttf_font: fix artifacts with large font sizes
This patch is a follow-up fix for "ttf_font: prevent out-of-bounds
access", which produced sporadic single-pixel artifacts with large font
sizes, e.g., with the monospaced font set to 24px in Sculpt.

The artifacts occurred only for some horizontal sub-pixel positions, in
combination with the font cache, and after the rendering of '>'
characters. They were ultimately caused by the missed clearning of the
first pixel of a glyph where x0 is 1 (e.g., the character 'd'). In this
case, a pixel from the previously evicted cache entry (the '>') shined
through. The patch fixes the problem by clearing the glyph starting from
the first, not the x0's, pixel.

Fixes #3567
2019-12-19 16:59:03 +01:00
Alexander Boettcher 3f83ac5580 tool: add imx8_evk board variable hint 2019-12-19 16:59:03 +01:00
Ehmry - 7f57de1b74 VFS/terminal: fix clang warning
Variable-sized object may not be initialized.

Issue #3564
2019-12-19 16:59:03 +01:00
Ehmry - 648382db74 Align after template expansion
Clang Cannot align template structs. Also, cannot cast void* to addr_t
in constexpr function.

Issue #3564
2019-12-19 16:59:03 +01:00
Ehmry - 2c510bb7f9 Remove unused lamba capture to fix clang warning
Issue #3564
2019-12-19 16:59:03 +01:00
Ehmry - 23710dff5e Remove dead code
Issue #3564
2019-12-19 16:59:03 +01:00
Ehmry - ff0436357b nic_stress: keep signal-context cap by value
Fixes clang warning about binding reference to stack allocated
parameter.

Issue #3564
2019-12-19 16:59:03 +01:00
Ehmry - 091e5157aa vfs server: fix File_system namespace warnings
Issue #3564
2019-12-19 16:59:03 +01:00
Alexander Boettcher c1e181a407 vbox: handle invalid dataspace exception
Fixes #3566
2019-12-19 16:59:03 +01:00
Stefan Kalkowski 8f71c90ca8 dde_rump: backport aarch64 (Fix #3565) 2019-12-19 16:59:03 +01:00
Norman Feske f85ec313de os/vfs.h: handle zero-sized files
The 'File_content' class failed to consider zero-sized files.

Fixes #3557
2019-12-19 16:59:03 +01:00
Norman Feske 2aa6471608 test/depot_query: add test for zero-sized archives
This test covers the situation where depot_query evaluates depot content
that is incompletely extracted. In particular, if the 'archives' file
already exists but has a size of zero, depot_query would produce a
page fault. This situation can be manually provoked by deliberately
creating a zero-sized archives file for any otherwise correct pkg.

This patch also fixes the success indicator of the test. It wrongly
matched an early line of the log output.

Issue #3557
2019-12-19 16:59:02 +01:00
Stefan Kalkowski 9814fc5447 libports: enable arm_64 libssl, libcrypto variant
Fix #3563
2019-12-19 16:59:02 +01:00
Martin Stein 3655ea77a3 depot_autopilot: rework log matching
* The log history of a test is stored as a whole for the lifetime of the test.
* Matching of the log history against log patterns is done correctly now
  (previously, a pattern like "AAB" on an input like "AAAB" wouldn't have
  triggered).
* Use memcmp, memcpy, memmove instead of the former character-wise operations.
* Sanitizing of log input and log patterns now works more generic through the
  new Filter class for all replacements/removals.
* Sanitizing is done as soon as a string is available and remains for the
  lifetime of the test.
* Sanitizing doesn't interfer with the matching algorithm.
* Decomposing into small clearly named functions.

Ref #3555
2019-12-19 16:59:02 +01:00
Johannes Kliemann 89d35bc41e tool: boot Genode on bare metal Linux
Fixes #2829
2019-12-19 16:59:02 +01:00
Johannes Kliemann 93639532f0 base-linux: core session support (IO_PORT, IO_MEM, IRQ) 2019-12-19 16:59:02 +01:00
1103 changed files with 29124 additions and 11632 deletions

View File

@ -1 +1 @@
19.11
20.02

View File

@ -12,19 +12,19 @@ sCaRvwPZdRCDDdhObkgkMlYROVNdC7ju8jZmB4n5O/5N7Ll7/RVhUWD7KeJu1UTM
oNEmhxEMrEcYcHFt8N8YVtJleRMVnsrZBNxOkFnpsPZr02XIQKfYi5tqSaBQZ47h
TTtXP3+FEaU+EoJprWqH55Sh97Fg6vuBJEmcGJeMGudFrypTzwqnM22DHwARAQAB
tCdKb3NlZiBTw7ZudGdlbiA8Y251a2VAZGVwb3QuZ2Vub2RlLm9yZz6JAlQEEwEI
AD4WIQSFq6G0496kOfRE2qnpSz5BlOa1+AUCWpAOsgIbAwUJA8JnAAULCQgHAgYV
CAkKCwIEFgIDAQIeAQIXgAAKCRDpSz5BlOa1+NGTEACg69FezAbc9Rzeb7j66NwW
3x/Zpi/jbmezMEtCZqAOcR8HJ7C0DN8gmCWPPB6oxAEeyL/i2cUb+9F0fTD6N7OL
TSOH75mNlyB9b8D2HdDILnLy4ClEitEOHFLMnlP58PGVtUNgbmsiM6cLLQtlJKvg
1xHlBTG9Ic8qgBcd808lLSC1XWN+nufVYBTE2RHNZqGeIWqPG5z1eW/JJO4M3V3j
MAw1p5Rpf9G6iWNxURutQOl/ii+97IKmHXX7N6ZRzawMGkOCAGNk1xeI71wCrALv
i3m7NmXb6XIJjD88hO5xfjjRO/0Gcw3vdmTXcVNzM1TvWj8ZsU6XjnMvNxa4LHqh
MxWuHlX0cAeCOzo1LJZ54f13hJ3YlTCrv68UIoNGRVi1LEbpE0sU0Ycdbw7ur2Gt
8Brx5WXv3hXTL8s3fmJzYU3/cFDfXjnaRiMWcNYdvckdHy6R7zPTk1NOvmfkolnO
W73ivdbonXpn0YqRGo2L76GdahLaVYn2gEeisqHnyeBCvI2snI+dMlEK0YNFrEkP
wgtWnF131Oorn0HMS6mpjcq4su4s5d84KCMGevFnW69oBRG27Bk/fJQiv2dSqkZg
+3TnyNApg1G7Bp5uD83mOvJWKdTWAntCJSQGbg1dmEsOBG+Bu7EE5LVBoMH3h/LQ
GB7c5NpgNIFQ2DZy2vkOI7kCDQRakA6yARAAws48PKN3BQPEM0M4kTO57/OqwGrA
AD4CGwMFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AWIQSFq6G0496kOfRE2qnpSz5B
lOa1+AUCXk6dFAUJB4D1YgAKCRDpSz5BlOa1+JHXEACyB6vfzfuyo8fu1IaGrloC
qUUuSfhdleF1tPhZQn9W92bEEoXPfqFUuiNaxeFIXonyiD7wJYdcowdIb6CiNWrx
B8yjDQ7yb08sDLlL821I93kByy24Er5hY3QEMuEL3qv8YD/6Bh36Q0aoTXqQXMuQ
3AcHp0JI932Oez3q+gEdW7CUe40N9LaTx0A7ZTHe0i8IELkUPFtDg8xibOjZhBMR
vlxNUtzQVvC5kT5Wt0w6ZFKPGJguFylaE+TcsTNtiLNS4Z8PmRPgygrWotmprELo
2/py/VMxgQb7p4LFj+sNmU9x3ulFO3Efb9cVZVjBMYx5xh83ZiLZ3PvK43Eo+7nm
kYQhPinAjNmqng4/ZdQFrayFMkZc4oKCqV6BaYnybbsSn2ZEwVQqpDMeswWXTf9k
qC6DONz3ETtyzBEF8cHDpy+BwHRXx+pysGLhIvHS9C3M91j8oXvogZRbw/dEKGX2
eWes7nsdHeTbyRJunCCnsXDm0Js8cZcqj3Eu3Kpeu2CbgJGD+ajOel2RSMo2mFtg
OoRWjCibWHDSeUS+LGtspDpry+4VYwm4KBdcyEgiXnE8WDb/xk/hZgJCr2814AJC
RPpXoIZdFiwSP46vgoAnHynPbGTmE/Wt+F9Y2cn/dz6rmg5ynS8AKuTOUSoAKEUV
J20mBJpkSx7Cc95AGE8K/LkCDQRakA6yARAAws48PKN3BQPEM0M4kTO57/OqwGrA
AMlxnB3n+AP7rtZEC2L548+3pfg7Ub45Oq1X0ySxgPhV15CDUEK69pgs0JhphMbM
DyaUp04DyQWFhdueAqQVFnKvg6nZm/WIJF1VYEc0/q6Ramsdv2cWdxFBkFHYsH3P
G2bXCZZAEO6eJI8cdmBH6+bVptky/AybzBLztp1ruWlj+rm79qULmW7zJfxYwL1U
@ -35,18 +35,18 @@ kAVN0Y0H9EGSEoVyKwS1DErzcBgajPKWedKlmjU1uIzupRWn5oqetVbNfZ3Z/EJ/
HdMCX0PN1kxg4WoI9mkP/moly1yopVOTTLJwvC2C85NQUmxyZeb4h9O7toFczBxn
7pV9Eprm/xRcO3ZEEpmdM7gR3+R3PpxkjgPIZAn9il32VYzdT3eQmDZ8sKC0qASG
ik2if34YnAggGmsrVB0nzT9fZR7CQq2IR7eohczLJRl+n7USQMgRweF+sl9PcbDT
aC0b0i+VveSEBOEAEQEAAYkCPAQYAQgAJhYhBIWrobTj3qQ59ETaqelLPkGU5rX4
BQJakA6yAhsMBQkDwmcAAAoJEOlLPkGU5rX4QjEQAIJF78XjvGomhafMsWlcd7fP
/j45B+KIpyruc7wHtLqWibi+YoDuvtG4m1/4Ckcz5qNrV0f5nQojEAeCSCh7Sl+s
yAJ9tmP1XET29DJq1t0iMsu+RDCLhdOfL/Wi/YJARtDloYbDlD8Rc/JnL2aOx2W/
Ybajj2lloxSDxKCnzCh1aZixie1YaQSm8ErshT2k4qTx48D3mRoBLAYyzdEbLkl3
ZBGDQy3Xk/miJ/hsj6L3w3G2YjMywZZZEjgDSUgSJ6MazBTgMmbCy1/0YGh7rNF7
iUoWyDZq4qiDGNAI695I6tas7s4X2dhZn10xgbJoa5Dq2rqQLek+ErEsr3DFYN53
7e9H0vJ9ydXB7piRJ9bxVFBng5CX9677IN5k9T/0lvcZWAFnDcHiMkIjIrTQ1Y04
WkG6DMVvzLD+PKA07cZLf692rsrbfpP4sGj8X6baWh58mGAMMwZ2Dy07grsi73qI
p/H4r4c/xRsH6nTbvb40zLfqcCz1xOTEcDtflYGMoeshu/H2EoruNMFi3c/9WO2G
3zrSOUenWFSiacbsh8HVE9HUFGddBTB3SrLddO5vvvi15OvGI4aWpnkW+9s4107h
jE0d0+c/Xm4AS0T59OGj/cd45k/vRe5vaPhQobZ6hXBzkKWPVt5uH8xbROiGiqdR
jMuaeWIldeJ60aeu39Dh
=JE0L
aC0b0i+VveSEBOEAEQEAAYkCPAQYAQgAJgIbDBYhBIWrobTj3qQ59ETaqelLPkGU
5rX4BQJeTp05BQkHgPWHAAoJEOlLPkGU5rX4RRAQAKSsr//mEXy6iQyoqaxJ796s
ljaoqsmT4ly/+0k9diX1+/wkulSkj4/fL2fDvRQK2cU1i6mYJVugN5swqXvp8WF8
scnDS/H75v/3Z+clTlsMjZ4qI0PmXYDpcvp5+zU85USEjOxpHmIKvQGflZ0NMvkI
uo2ZC6F4xnB5iizx9Ebm0gGAiKKEJ8ID/LLhJmOtidnGc3322SUVXIl4+ue9KgpO
hTBjx5UdIQ+21uSRf+zv3ZQH/KA/08iNyD20fIiUZKfEoeovlW8SipoO/pf/+1DE
WSiJqL3K7T3ixkC4oWSp7tbo2MWU247PItxTnnGF+KjwbkzpPwyPYPHT5Ed3XEZV
e39r9xUzdvYKKDCNDToDFsh4bm4hq7xXgnTwAbF6hw0iyBK02ZB6FKJsF/ZJi8gC
Ni4d3Lb54CV/Z7nAqMFbTa6KT8o9fc0Bw6tgX2ch7SRWU70yVGYmQzrdRsOtDkIV
iYA05JozwwsIcJQS7hBVnsqgD/huYLd+y7iCUgw35NdQ5764jzVlUpYtFO0NFrM6
QSKnnFFRiwr3+ZqIja2SGW455uP1hsl2ccA4Rdp/JRuEI6ojIo0R+JBpcMeqdv9d
HcNsAoZkrm/cQfIwlyKsU4/dEFL09kEtv7x/aO2ImqjAZ5xT3ml+4kFGEn7M7rsc
M6R6fgkYrVo1GhjXTlCL
=4bj4
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -6,26 +6,26 @@ spm0DdNCEVfUbIQUstbSNt1kDGIlqPvZmoRj5YwDECW6ULG8jTWhaAz9SybJCE86
jLPzZHjKtVhCVO1X0ogSxvvYGemUpqVCLfKcIb1TucieKKCrnjiHwp0XZ41DWqSb
kBwWW2YQMEsw8JNGNTfCCUFf6+1l4mMixtv2sEqFiH1wQJ0c4gSa4iSYZ+eNmzJ0
B13K8kONOctSg3NYZz/dC1aUzLOTkgJHqEPHABEBAAG0KVN0ZWZhbiBLYWxrb3dz
a2kgPHNrYWxrQGRlcG90Lmdlbm9kZS5vcmc+iQFUBBMBCAA+FiEEI2X1/oP+p+Ls
2L28qrC4CLnp/P8FAlrQZGACGwMFCQPCZwAFCwkIBwIGFQgJCgsCBBYCAwECHgEC
F4AACgkQqrC4CLnp/P9kKQgAxc11eDhYkMVg9cuipFoqtV5lY9aT2qkocZ28IhbF
LXhy9lcn5FlxZSVdkzJQ5tUf4nSuhhMb6z3r8edaOebcYAyFk0DTymNpcEyT2XHd
lsOcInhfU423m1tCNHdmxtv9HERtj2zS1KNkjWxY6xsqfEw1eDfUvdS3K9KpUqc6
vWZwsPd9EHxW3mzWJS3lrSAnNsCwtdmiqB9045Yss4KednMcN6qxE+uHppQ+25Ib
5ZICpiVqOJ+eQXeY3kRx84lfZJr3uFdn00RSU5fn0uol8ZZYX9tQd9SC1GIlkyYj
HxNLKNVaYzF1nnmR1s7cpY6PUAYbt0im6kd4VJ1wQcWTnrkBDQRaU+QuAQgAuame
a2kgPHNrYWxrQGRlcG90Lmdlbm9kZS5vcmc+iQFUBBMBCAA+AhsDBQsJCAcCBhUI
CQoLAgQWAgMBAh4BAheAFiEEI2X1/oP+p+Ls2L28qrC4CLnp/P8FAl4XHPUFCQ0p
OkcACgkQqrC4CLnp/P8bAgf/ToUKzXMGdRXpB+xIBbOxuu8xVdLRj+5cm7cjZRiy
N0ulrzAlaZqrfqb5rTujPDjakmVSBVRIi8zWlzU7y67fevTFdi/Q9xeLgbqP3cWU
UgUJs03cdacFIamSIO//I9gaImZ2kpUcA6Nj+N+jPepRgUBzljsJG8678ndicA0e
Yio4uAvZY9JmsWGn48rmkqshPf9lag4GUnXn+R/AFKCts55kOiPekux3pJBhmrLJ
TdLgdAzlzGQfHxQbz3oVK4yE19ReAd6rnpW06oK4KfiWrgCmaEk1quirDNfIMDfr
nwe6571TY5is0f9zJjJgP8ogLUMI3n54OvwMezUMz+bLbbkBDQRaU+QuAQgAuame
2VDCgNmiwu+QmWyNN4jzbE7+VNmDr37HO9lZRIROC4eACPOGfUL03jLGvUn7rrxQ
JK+Pit6gXXCoIWDhCMNRSZKho416KJZWxF2jxKBKGQ7DtWaTR3YOzSf0ka9DZSrp
wG22xS0Uf1U/0ZBIf24LbyUDFLc8zt4eey2D9AHm+9vCf7wnf8TV6SNIXRz3wj7d
VqoZLXRTT7twBSaNahLhNtg7fhS8Nu6/THuwXpNKPAvAsgJRTGk7kmrKj5P7rOZA
rNHC1pvK1EWJJi2onHOmCzBccKRp9SeQlj+ddqG6seZhEnRYG6l7uhkyNZoyvKxO
Fguc5g8Xf37VyuRMfwARAQABiQE8BBgBCAAmFiEEI2X1/oP+p+Ls2L28qrC4CLnp
/P8FAlpT5C4CGwwFCQPCZwAACgkQqrC4CLnp/P/IOAf+LnQVtU7aHh4AZDsi1wXq
KBo5l6r3G8tC/S0HEf8nnWMUio2/mwVrkbuTvBeKrcQ/mXFHHAG8YCAIHPgR7T0y
2L6l2PL4HoXiLD8EwJ0sWZu2waxuxcTX+bb1i3Xm3squnqDtCX3pyoXWx0GVgrz9
7I/zitxeER+35ScaZ+JAAcNW59LpiV1SdIXqbtrw5QBJBuZUp0bvnzCNvdZLhnhb
gWfwPEfcXFt5K87iTmfMFJOJpbUrEz/NWE9gOBCBjqxW0wVb+IWr0oFWvfxjuBq7
IW9DezwkN1wAavP6g7+B4esCD6SRq+3CCzbT1By3X2h3SevU8tHkCSA3cIKgWdyD
2A==
=IsaH
Fguc5g8Xf37VyuRMfwARAQABiQE8BBgBCAAmAhsMFiEEI2X1/oP+p+Ls2L28qrC4
CLnp/P8FAl4XHW4FCQ0pOsAACgkQqrC4CLnp/P/xGggAhMz6NH1dYiFtc9+3vkAW
bZ10MDvxdgyU+G1a0BVYVo2ZXkhJlb2yg5MEeL1MZ6cUtM7MR1OL0U1jayfdcTfr
kkUi2a35BdvKRpxc3hcc4i2CdDxdx+IGrBa75P+vIKFj8WIvwABgRJNVzY1Oq6Lq
zKPUpVPug80Hch++Kv6l1DEpcoXlGaI8Z1dWfAjYQ7HJF/YJNHloKwxa1mXo/l/S
qQSFHB23IN682ANm8iEUphuvJVbOw4mubpCEpmJvIhEBeesgXfB503nniOsshq+9
1bNZ3CFv/ylnj5sy5VzU0lfW/TrHiW4OOOSbX8mCSvcqN2mhjcu6r4olV0fWPrrV
Lg==
=H+8g
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -3,6 +3,66 @@
Genode News
===========
Genode OS Framework release 20.02 | 2020-02-28
##############################################
| With version 20.02, Genode makes Sculpt OS fit for running on i.MX 64-bit
| ARM hardware, optimizes the performance throughout the entire software stack,
| and takes the next evolutionary step of the user-facing side of Sculpt OS.
Without any doubt, Sculpt OS has been the driving motivation behind most
working topics featured by the new release. One particularly exciting line
of work is the enabling of Sculpt on i.MX-based 64-bit ARM hardware, which
touched the framework on all levels, from the boot loader, over the kernel,
device drivers, libraries, system management, up to the application level.
The work goes as far as supporting Sculpt OS as a hypervisor platform for
hosting Linux in a virtual machine.
As a second Sculpt-related development, we strive to make the user-visible
side of the operating system better approachable and more logical. With this
background, the current release comes with a profound redesign of the
administrative user interface of Sculpt OS. An updated downloadable system
image will follow soon.
Also related to Sculpt are an updated audio driver based on OpenBSD 6.6,
the support of virtual desktops, and performance optimization of the
Seoul virtual machine monitor on x86 hardware.
Regarding the framework API, the release introduces a new library for
building multi-component applications. It aims to bring the benefits of
Genode's unique security architecture from the operating-system level to the
application level.
These topics are only the tip of the iceberg. For the complete picture,
please consult the
[https:/documentation/release-notes/20.02 - release documentation of version 20.02...]
Road Map for 2020 | 2020-01-20
##############################
| In 2019, we will be concerned about dwarfing the barrier of entry into
| the Genode world.
Following the last year's leitmotif of "bridging worlds", we turn our
attention to the removal of the hurdles faced by aspiring developers and
users. During the annual road-map
[https://lists.genode.org/pipermail/users/2019-December/006987.html - discussion]
on our mailing list, we identified four tangible approaches towards that
goal. First, making Sculpt OS more user friendly. Second, reinforcing trust in
Genode by fostering the framework's high quality. Third, making the tooling
around Genode a joy to use. And finally, the illustration of Genode's
versatility in the form practical use cases.
Besides this overall theme, we plan to continue our commitment to the
NXP i.MX SoC family, revisit Genode's low-latency audio support, and
extend the cultivation of Ada/SPARK within (and on top of) Genode.
More background information about the new road map and a rough schedule are
presented at our official [https:/about/road-map - road-map page].
Genode OS Framework release 19.11 | 2019-11-28
##############################################

814
doc/release_notes-20-02.txt Normal file
View File

@ -0,0 +1,814 @@
===============================================
Release notes for the Genode OS Framework 20.02
===============================================
Genode Labs
This year's [https://genode.org/about/road-map - road map] is all about making
Genode and Sculpt OS more approachable. It turns out that the first release of
the year already pays tribute to that goal. First, it equips Sculpt OS with a
much more logical and welcoming graphical user interface
(Section [Redesign of the administrative user interface of Sculpt OS]).
Second, it greatly reduces the friction when hosting existing applications on
Genode by smoothening several rough edges with respect to POSIX compatibility,
and by generally improving performance.
Most topics of the release are closely related to Sculpt. The biggest
break-though is certainly the ability of running Sculpt OS on 64-bit ARM
hardware (Section [Sculpt OS on 64-bit ARM i.MX8 hardware]) along with our
custom virtual machine monitor (VMM). On PC hardware, Sculpt users can enjoy
an updated audio driver and optimizations of the Seoul VMM. Furthermore,
Sculpt's window manager received the much anticipated ability to use virtual
desktops.
At the framework-API level, the most significant changes are the introduction
of dedicated types for inter-thread synchronization patterns
(Section [Base-framework refinements]) and a new library for
bringing the benefits of the Genode architecture to the application level
(Section [New sandbox library based on the init component]).
Redesign of the administrative user interface of Sculpt OS
##########################################################
On our [https://genode.org/about/road-map - road map] for 2020, we stated
the dwarfing of the barrier of entry as our main concern of the year.
We highlighted the ease of use of Sculpt OS as one particular work area.
Removing Unix from the picture
------------------------------
Until now, Sculpt's administrative user interface - lyrically called
Leitzentrale - employed a small Unix runtime and the Vim editor as utility for
basic file operations and for the tweaking of configurations. Even though this
was a practical intermediate solution, we have to face the fact that not
everyone loves the Unix command-line interface as much as we do. Quite the
opposite, actually. When presenting Sculpt, we can clearly sense that people
with a non-Unix background are put off by it. The audience generally loves the
runtime graph, visual cues, and discoverability. Furthermore, command-line
interfaces are (albeit wrongly) perceived as archaic and impenetrable relics
by many computer users who are otherwise perfectly happy with the notion of
files and directories. We identified that file-manipulation tasks performed in
the Leitzentrale are rare and simple. Relying on Unix for those basic tasks is
like taking a sledgehammer to crack a nut. On average, the Leitzentrale is
used in just a few moments a day for basic things like browsing a file-system
hierarchy, glimpsing at the reports stored on the report file system, deleting
or copying a file or two, or tweaking a configuration file. With a Unix shell
presenting one barrier, Vim is certainly an even higher one. Familiarity with
Vim should definitely not be a prerequisite for using an operating system.
Following this reasoning, we decided to swap out the command-line interface
and Vim by a simple GUI-based file browser and a notepad-like editor, which do
not require any learning curve.
Note that even once the Unix command-line interface is removed from Sculpt's
Leitzentrale, advanced users will still be able to manipulate Sculpt's config
file system via a Unix runtime deployed as a regular component, similar to the
use of the noux-system package we have today.
New user-interface layout
-------------------------
The move away from the command-line interface goes hand in hand with the
redesign of the overall user-interface layout. A new panel at the top of the
screen contains two centered tabs for switching between the runtime graph and
the file-system browser.
[image sculpt_20.02_panel]
The storage-management functionality has been moved from the former storage
dialog into the respective nodes of the runtime graph. E.g., to format a block
device, the user can now select a USB or storage node of the graph to get a
menu of block-device-level operations.
[image sculpt_20.02_storage]
The network-management is now located at a drop-down menu that can be toggled
via a button at the right side of the panel.
[image sculpt_20.02_network]
A new button on the left side of the panel allows the user to toggle a
drop-down menu for GUI settings. At the current time, there is only the option
to adjust the font size. In the future, the dialog will give easy access to
the screen-resolution options and the keyboard layout.
The log-message view is now hidden in another drop-down menu that can be
toggled via a panel button. So when starting the system, the user is greeted
with only the runtime graph, which is a much nicer and cleaner looking
experience.
Informative or diagnostic messages are displayed in the left-bottom corner of
the screen.
[image sculpt_20.02_message]
The "Files" tab of the panel switches the main screen area to a simple file
browser that lists all file systems available. By toggling one of the
file-system buttons, the directory hierarchy can be browsed. When hovering
a file, an "Edit" or "View" button appears, which can be used to open
the file in a text area that appears on the right side of the file browser.
The editor supports the usual notepad-like motions, operations, and
shortcuts (control-c for copy, control-v for paste, control-s for save).
[image sculpt_20.02_editor]
Half-way there
--------------
With the current release, one can already accomplish a lot without having to
resort to a command-line interface: connecting to the network, managing
storage devices, installing and deploying software, inspecting the system
state, and tweaking configurations.
There are still a few gaps though. In particular the file browser does
not yet support file operations like the copying, renaming, or removal of
files. For these tasks, the current version of Sculpt still features the
Unix-based inspect window, which can be accessed by toggling the "Inspect"
button inside the USB or storage dialog. Once selected, the panel presents an
"Inspect" tab that features the familiar Unix shell and Vim. Note, however,
that we keep the inspect window only as an interim solution. It will
eventually be removed. As with every new feature, there are still rough edges
to be expected in the editor and file browser, e.g., the editing of files with
long lines or the browsing of directories with many entries is not
appropriately covered yet.
To see the current new version of Sculpt OS in action, you may find the
following presentation entertaining.
:Live demonstration of Sculpt OS at FOSDEM 2020:
[https://fosdem.org/2020/schedule/event/uk_sculpt/]
The new version 20.02 of Sculpt OS is part of this release and can be built
from source and used right now. Several Genode developers already provide
ready-to-use packages for the new version. The software depots by alex-ab,
cnuke, skalk are worth exploring. A downloadable system image along with an
updated manual will be released shortly.
Sculpt OS on 64-bit ARM i.MX8 hardware
######################################
Within the past two releases, big steps were taken to support ARMv8 hardware in
the Genode OS framework. After implementing basic support for Raspberry Pi 3,
and the i.MX 8M Evaluation Kit, the network card was enabled for the latter.
Moreover, we updated the Linux TCP/IP, and C library ports, as well as
the Noux environment to support the architecture. Finally, with the latest
releases, a new ARMv8-compliant virtual-machine monitor for the base-hw kernel
entered the framework.
The rapid achievements motivated us to strive for a more ambitious scenario to
run on top of the currently focused ARMv8 hardware platform. So why not using
Sculpt OS on the i.MX 8M System-on-Chip?
Persistent storage
==================
There were several challenges to cope with initially. First, persistent
storage was needed. Luckily, the Genode OS framework contained already an
SD-card driver implementation for the i.MX series. The driver was written for
Genode from scratch and initially supported the i.MX53 SoC only. From then, it
got extended repeatedly to drive the SD-card controller of several i.MX6 and
i.MX7 platforms. Therefore, it was not a big issue to support the new hardware
too. However, when we later used it in Sculpt, it turned out that the driver
has some low-latency requirements. If those were not met, it got stuck. This
was the time where the CPU-quota mechanism came in handy in a real-world
scenario. It helped to let the interrupt handler of the driver be scheduled in
time, and thereby let the driver run stable.
Having a working block device is one part, but it is of little use without a
file system. In Sculpt OS, the NetBSD rump kernel's ext2 file-system is
typically used to host the depot package system and for keeping configuration
files persistent. Unfortunately, the version of NetBSD as used in Genode's
rump kernel port does not contain the ARMv8 architecture. Of course, we could
have upgraded the rump kernel as a whole. But this software stack is quite
complex with a lot of threads reproducing a sophisticated state machine. It
took some time in the past to meet its required semantics. Therefore,
backporting some header definitions and a few architecture-dependent functions
seemed more attractive. Luckily, it turned out to be the right decision, and
after a day of backporting work, the file system could run on ARMv8.
Display engine
==============
One of the more challenging tasks was certainly the enabling of the Display
Controller Subsystem (DCSS) of the i.MX 8M SoC. Originally, we hoped to profit
from our experiences with the Image Processing Unit (IPU), the display engine
of former i.MX SoCs. But as it turned out, the DCSS is a completely new
design, and has not much in common with the IPU. When first writing a driver
for the IPU of the i.MX53, we were surprised by the complexity and flexibility
of this piece of hardware. Back then, it took months to get something
meaningful working. To not lose too much time by re-implementing a driver from
scratch, we decided to take the DDE Linux approach, which worked out pretty
fast. The resulting driver should provide the same flexibility like the Linux
original one. However, as the i.MX 8M EVK board provides a HDMI connector
only, we did not test more than that. The configuration of the driver is
analogous to the Intel framebuffer driver, and looks like the following:
! <config>
! <connector name="HDMI-A-1" width="1920" height="1080" hz="60" enabled="true"/>
! </config>
Later, when using the driver in practice within the Sculpt OS, we could
experience a slightly sluggish behaviour, which was due to a missing
architectural back end of the blitting library of Genode. After tweaking this
too, the graphical user interface experience was good.
USB and Input
=============
The last missing I/O device to run Sculpt OS on the ARMv8 was something for
user generated input. Therefore, the existent USB host controller driver for
the i.MX series got updated. The only roadblock here was the powering of the
device. As there is no platform driver for the target hardware yet, which
would manage power and clocks, the hardware either has to be pre-configured
correctly, or the driver has to enable it on its own. Ethernet card, SD-card,
and the display engine were all already powered by the bootloader, but not
USB. In contrast to the first devices, the u-boot bootloader turns off USB
explicitly as soon as it starts the OS. As an interim solution, we patched
u-boot to not turn off the USB host controller, and enforced u-boot to
initialize the powering in our boot scripts. Therefore, if one wants to use
USB on the i.MX 8M EVK, make sure to take our modified version. As a
convenient solution, you can use the 'uboot' port within the base repository.
Just issue the following command in the Genode directory:
! tool/ports/prepare_port uboot
Finally, you have to copy u-boot to the SD-card as root user:
! dd if=`tool/ports/current uboot`/imx8q_evk/imx-mkimage/iMX8M/flash.bin \
! of=/dev/sd<?> bs=1k seek=33 conv=fsync
Of course, you have replace 'sd<?>' with the correct device node of your
attached SD-card.
After enabling the USB host controller driver, we could successfully re-use the
USB HID client driver to drive keyboard and mouse connected to the board. As a
nice side-effect, the list of possible storage devices got extended with USB
mass storage too by adding the USB block client driver.
Missing libraries
=================
Finally, when building the necessary and optional packages for Sculpt OS, we
stumbled across several libraries that needed to be adapted to compile and
link for ARMv8 too. Mostly, the inclusion of some other compilation units and
headers was sufficient. The related libraries are: libssl, libcrypto, libpng,
and Mesa. With the latter two, it is now even possible to execute Qt5
components on the target hardware.
Apart from all the new driver components and extended libraries, the Sculpt
manager had to be slightly modified to execute on the i.MX 8M hardware. In its
original form it is inherently dependent on x86 drivers, as it for example
generates configurations for some of those drivers. For the time being, the
changes to the Sculpt manager are not yet part of the official release.
Nevertheless, you can produce a Sculpt OS image to be run on an i.MX 8M EVK
board by using the following
[https://github.com/skalk/sculpt_20.02_imx8q_evk/ - topic branch].
Alternatively, you can also have a look at Sculpt OS on ARMv8 hardware by
following the video recordings of the following talk at FOSDEM 2020.
:Live demonstration of Sculpt OS on i.MX 8M EVK at FOSDEM 2020:
[https://fosdem.org/2020/schedule/event/uk_genode_armv8/]
Base framework and OS-level infrastructure
##########################################
New sandbox library based on the init component
===============================================
The init component is Genode's canonical mechanism for the composition of
components. This role was further amplified when init became
[https://genode.org/documentation/release-notes/17.02#Dynamically_reconfigurable_init_component - dynamically reconfigurable].
The latter change cleared the ground for system scenarios like Sculpt OS, the
on-target deployment of packages, and dynamic device discovery. One typical
pattern found in such scenarios is one dynamically configured instance of init
accompanied by a controlling component that is usually called "manager". The
manager would consume reports of the subsystem hosted within the dynamic init,
and adjust the init configuration according to a domain-specific policy. Such
a configuration change, in turn, may trigger new reports, which effectively
turns this setting into a feedback control loop.
Whereas this established pattern is suitable for many scenarios, it is not
always natural. In particular if the manager does not only need to
manage a subsystem but also wants to intercept a service used by the
subsystem, the roles are no longer clear-cut. A practical example is a
GUI application that employs the menu-view component for the GUI rendering
while processing keyboard events locally. This application would need to
intercept the menu-view's GUI session to obtain the stream of user input
events. For such an application, the most natural approach would be the
co-location of the init functionality with the application logic into a
single all-encompassing component.
To accommodate such scenarios where a domain-specific management component is
tightly coupled with a dynamic subsystem, we extracted the child-management
functionality from the init component into a new library called "sandbox". The
library API is located at
[https://github.com/genodelabs/genode/blob/master/repos/os/include/os/sandbox.h - os/include/os/sandbox.h].
In addition to the hosting of components, the sandbox API also allows for the
interaction with the sandboxed children by providing locally implemented
services. The latter mechanism is illustrated by a new test available at
_os/src/test/sandbox_.
POSIX compatibility improvements
================================
During the release cycle of Genode 20.02, we continued our mission to host
POSIX software effortlessly as Genode components. In particular, we followed
up the line of work pursued with the two previous releases
[https://genode.org/documentation/release-notes/19.08#Consolidation_of_the_C_runtime_and_Noux - 19.08] and
[https://genode.org/documentation/release-notes/19.11#C_runtime_with_improved_POSIX_compatibility - 19.11]
with respect to the traditional Unix mechanisms fork, execve, and pipes.
After covering several edge cases - cloexec, file-descriptor lifetimes,
line-buffer handling, vfork, just to name a few - as needed by programs like
make, bash, and tclsh, we eventually reached a state where the website
generator of [https://genodians.org] works without the need for the now
deprecated Noux runtime.
For years we have been running complex software stacks like the Qt-based web
browser on top of our C runtime but not without carefully placed tweaks and
occasional patches. With the current release, we address the area of
concurrency and introduce a thorough reimplementation of the synchronization
primitives namely POSIX mutexes and condition variables as well as semaphores.
We also reaped the fruit of our labor by replacing our custom Qt thread back
end by the standard POSIX-thread based implementation. Further, we reduced the
number of threads in Qt applications by moving the QPA event handling to the
component entrypoint and removing the timed-semaphore utility from LibC.
Beyond Qt, we also address synchronization issues revealed by running a
third-party port of [https://grpc.io/ - gRPC] in our network back ends and
amended thread-local errno in the C runtime. Finally, our POSIX thread
implementation supports cleanup handlers now.
Base-framework refinements
==========================
Replacing the 'Lock' type by new 'Mutex' and 'Blockade' types
-------------------------------------------------------------
Up to now, Genode's lock implementation supports mainly two flavour of usage.
On the one hand, it is used to protect critical sections where the lock is
initialized as unlocked. In the contention case, the lock holder is supposed
to release the critical section. On the other hand, the lock is used as
blockade to synchronize startup between various executions of threads. Here
the lock is initialized as locked during instantiation whereby the thread that
releases the lock is not necessarily the same thread as the creator of the
lock.
We decided to make the two usage pattern more obvious by introducing two
separate classes, called 'Mutex' and 'Blockade'. The reasons are two fold.
First, during code review, the usage pattern at hand becomes more obvious.
Second, by codifying the programmer's intent behind the use of a
synchronization primitive, Genode becomes able to perform additional checks,
and diagnose certain dead-lock situations and other usage errors on the spot.
The separation got introduced shortly before this release. Up to now, it is
only used in 'Genode::Thread', 'Genode::Heap', and 'Genode::Registry'. The
plan is to cultivate the usage across all Genode sources over the next
releases and to ultimately remove the 'Genode::Lock' from the public API.
The 'Mutex' class is more restrictive compared to the 'Lock' class.
* At initialisation time, it is always unlocked.
* To enter and leave a critical section the methods 'acquire()' and
'release()' are used.
* A 'Mutex::Guard' is provided, which will 'acquire()' a mutex at
construction time and release it automatically at destruction time of
the guard.
* No thread is permitted to lock twice. The code will generate a warning if
a dead-lock is detected.
* Only the lock holder is permitted to release the mutex. The code will
generate a warning and will not release the mutex if this rule is violated.
! Genode::Mutex mutex;
! mutex.acquire();
! mutex.release();
!
! {
! Genode::Mutex::Guard guard(mutex) /* acquire() during construction */
! } /* release() on guard object destruction */
!
! Genode::Mutex::Guard guard(mutex);
! mutex.acquire(); /* <-- Will cause a warning about the dead-lock */
The 'Blockade' class is always initialized as locked and provides the methods
'block()' and 'wakeup()'. Beside the initialization aspect, the 'Blockade'
behaves up to now like the 'Genode::Lock' implementation.
! Genode::Blockade blockade;
!
! /* step */ /* thread A */ /* thread B */
! 0: -start thread B-
! 1: ... -startup-
! 2: blockade.block(); ...
! 3: -sleep- ...
! 4: -sleep- blockade.wakeup();
! 5: ... ...
Performance optimization of the XML parser
------------------------------------------
Genode's XML parser used to rely on C++ exceptions while parsing, which is an
almost historic artifact inherited from the initial implementation. The
performance penalties of exceptions in the rare use of XML was acceptable
back when we started. But modern Genode systems like Sculpt OS rely on the
dynamic processing of XML like a back bone. The overhead became particularly
apparent when executing [Sculpt OS on 64-bit ARM i.MX8 hardware]. Prompted by
this observation, we reworked the code such that exceptions are no longer
thrown in any hot code path. The public interface of 'Xml_node' remains
unchanged.
New polling variant for register framework
------------------------------------------
Genode's register framework has offered a 'wait_for' method for a long time.
This function sleeps for a certain amount of microseconds and checks if one or
more given conditions become true. The number of attempts to sleep and check
the conditions must also be specified. In case the conditions are not met
after these attempts, a polling timeout exception is thrown. The function
simply returns in case of success. With the current Genode release, we have
added a 'wait_for_any' method with almost the same semantics but instead of
waiting for all conditions to become true, it returns if any condition is
meet, and thus, implements a logical OR.
Migration to modern block-device API
====================================
With release 19.02, Genode introduced two new APIs for block-session handling.
The client side of a block session now uses the job API in order to send block
requests to the server, which in turn receives those jobs as requests through
the Request API. These two APIs replace Genode's 'Block::Driver' and
'Block::Session_component' implementations that used the packet stream API
directly, which turned out to be error prone for block session implementations.
Instead, these new APIs wrap the packet stream handling in a controlled
manner while handling all corner cases and even the overcommit of packets.
With the current release, we have adapted Genode's AHCI driver and partition
manager to these new interfaces, with the plan to adjust all block session
clients/servers to the new APIs with Genode release 20.05.
During this line of work, the AHCI driver received a major cleanup. For
example, dynamic memory allocations were removed, the whole initialization
state machine has been removed, ATAPI support for Qemu has been re-enabled,
and Exynos5 AHCI support is gone - since the platform is outdated and not
supported by Genode any more.
Updated audio driver based on OpenBSD 6.6
=========================================
In this release, we updated the 3rd-party sources of the audio driver component
to OpenBSD 6.6 and adapted the emulation glue code. While doing so, we fixed
a bug regarding the 'delay()' implementation where the function expects
microseconds but was given milliseconds. This led to a increased start-up
time of the component. We also fixed the logging back end that accidentally
was rendered silent and brought in the 'printf' back end from DDE Linux to
be able to produce better formatted LOG messages in the future.
Until now the component only supported HDA and EAP (ES1370 PCI) devices. The
first is primarily intended to be used with real hardware wheres the latter
was used during the initial porting effort in Qemu. That being said, the EAP
driver apparently also works on hardware according to community feedback.
Since the HDA driver does not work when used in VirtualBox and users expressed
the desire to also use audio when running in a VM, we enabled another driver,
for which a device-model in VirtualBox exists: the AC97 ICH. As it turned out,
using this driver, we can produce audio, albeit the quality is far from
usable. Nevertheless, with the driver enabled, interested parties are free to
investigate the cause for the current issues.
All in all, this update is solely a catch up effort to stay more
update-to-date with the upstream changes and to pull in HDA quirks for more
recent systems. More interesting changes to the driver component, like
reworking the OpenBSD kernel emulation layer and bringing support for USB
audio devices, are scheduled for future releases.
Support for unlabeled LOG output
================================
In situations where a Genode system is remotely controlled and monitored,
it is useful to allow a special component to produce log output with no
Genode label applied. This way, such a component can produce log data in
a format that is immediately suitable for a controller. This feature can be
enabled for a component by rewriting the label of the component's LOG session
to "unlabeled".
! <route>
! <service name="LOG"> <parent label="unlabeled"/> </service>
! ...
! </route>
Libraries and applications
##########################
Custom virtual machine monitor on ARM
=====================================
The ARMv8-compliant virtual-machine monitor introduced in the previous release
19.11 now contains new device models to enable the interaction with a
virtual-machine via network and terminal services. The new virtual ethernet
card and console implementations are compliant to the virtualization standard
VIRTIO 1.1.
Currently, the VMM cannot be configured to contain specific devices. It is
hard-wired to provide exactly:
* One virtual ethernet card that connects to Genode's "Nic" service,
* A VIRTIO console that opens up a session to the "Terminal" service using the
label "console", and
* The traditional PL011 serial device model, which connects to a
"Terminal" service too but uses the label "earlycon"
Seoul VMM
=========
During the usage of Seoul on Sculpt, it became apparent that the Seoul VMM
caused a constant CPU load even when the guest VM was idling. After some
investigation it became clear that having a fixed rate to synchronize the
guest graphic memory with the Genode GUI service was the main reason for the
constant load. With this release, we added the feature to dynamically adjust
the GUI refresh rate depending on the rate of user interactivity.
Additionally, if all virtual CPUs go to idle state, the GUI refresh is stopped
completely. With these measures, the overall CPU load could be reduced
noticeable.
TCP terminal
============
The TCP terminal is a long-living component in the Genode OS framework since
release 11.11. It can be used, e.g., to connect to a headless Genode system
via telnet. Until now, it always listened to incoming network connections at
configured ports. The port had to be configured for each terminal session
client.
The TCP terminal got extended to either listen to incoming network
connections, or to directly connect to another network server, dependent on
the policy defined for the corresponding terminal client. The following
example configuration illustrates the differences:
! <config>
! <policy label="client" ip="10.0.0.5" port="1234"/>
! <policy label="another_client" port="4567"/>
! </config>
If only a port is described in the policy, the TCP terminal will listen on
that port for incoming connections. If an IP address is provided additionally,
it connects to the IP address using the given port.
Virtual desktops
================
Genode's GUI stack enables a high degree of flexibility. Beside the fundamental
nitpicker component, responsible for basically multiplexing input events and
framebuffer content, there is the window-manager component, and example
implementations of a window-layouter, and decorator. The interplay of the
latter three allows a window management that scales from simple to rich and
sophisticated without lowering its security properties. For a brief description
of its architecture, please refer to the release notes of
[http://genode.org/documentation/release-notes/14.08 - 14.08].
In this architecture, the window layouter is responsible for the arrangement
of the different windows. It exports a data model of the window layout.
Although, the example implementation of the window layouter introduced in
14.08 was simple, it already contained a notion of having different virtual
screens and screen sections, beside the actual window placements. However,
until now there was no use-case of switching dynamically in between different
virtual screens respectively window sets related to them.
While using more and more different graphical components within Sculpt, the
window layouter in its initial form hit a limit. Although it already allowed to
switch in-between different windows via configured key-combinations, it became
inconvenient when having more than a handful windows hiding each other.
Therefore, the window layouter now got extended to allow switching dynamically
in between several pre-defined virtual screens. For the time being, one has to
assign a new window to a screen in the rule-set of the window layouter
initially by hand. Defining the currently visible screen can either be done by
editing the rule-set, or by using pre-configured key-combinations.
The new default configuration of the window layouter as exported by its
corresponding depot package looks like the following:
! <config rules="rom">
! <rules>
! <screen name="screen_1"/>
! <screen name="screen_2"/>
! <screen name="screen_3"/>
! <screen name="screen_4"/>
! <screen name="screen_5"/>
! <screen name="screen_6"/>
! <screen name="screen_7"/>
! <screen name="screen_8"/>
! <screen name="screen_9"/>
! <screen name="screen_0"/>
! <assign label_prefix="" target="screen_1" xpos="any" ypos="any"/>
! </rules>
!
! <press key="KEY_SCREEN">
! <press key="KEY_ENTER" action="toggle_fullscreen"/>
! <press key="KEY_1" action="screen" target="screen_1"/>
! <press key="KEY_2" action="screen" target="screen_2"/>
! <press key="KEY_3" action="screen" target="screen_3"/>
! <press key="KEY_4" action="screen" target="screen_4"/>
! <press key="KEY_5" action="screen" target="screen_5"/>
! <press key="KEY_6" action="screen" target="screen_6"/>
! <press key="KEY_7" action="screen" target="screen_7"/>
! <press key="KEY_8" action="screen" target="screen_8"/>
! <press key="KEY_9" action="screen" target="screen_9"/>
! <press key="KEY_0" action="screen" target="screen_0"/>
! ...
As can be seen, individual keys are assigned to switch to a specific virtual
screen. By default ten screens are defined that are accessible via the number
keys. The first screen definition in the rules configuration marks the
currently visible screen.
Menu-view widget renderer
=========================
The line of work described in Section
[Redesign of the administrative user interface of Sculpt OS] called for
the enhancement of Genode's GUI-rendering component. This component - named
menu view - was
[https://genode.org/documentation/release-notes/14.11#New_menu_view_application - originally introduced in Genode 14.11]
for the rendering of the relatively simple menus of an application launcher.
Its software design largely deviates from the beaten track of established
widget toolkits, which come in the form of client-side libraries. The
menu view is not a complete toolkit but solely a dialog renderer sandboxed
in a dedicated component. This design reinforces the strict separation of the
view from the application logic, fosters screen-resolution independence, and -
most importantly - keeps the complexity of pixel processing out of the
application program. Because of the latter, it lends itself to the
implementation of security-sensitive interactive applications.
It would certainly be misguiding to tout our menu-view as feature competitive
with existing toolkits. We certainly won't recommend using it over Qt in
general. But Sculpt's custom administrative user interface "Leitzentrale"
presented us with the perfect playground to explore and grow the potential of
our novel approach.
In contrast to the previous iteration of the Leitzentrale GUI, which relied on
a small Unix runtime and Vim for editing text files, the new version ought to
feature a simple text editor integrated in the GUI. A text editor requires
a much tighter interplay between the view and the actual program logic
compared to an application with just a bunch of buttons. Think about cursor
handling, scrolling text, displaying textual selections, or placing a text
cursor with the mouse. On the course of the work towards the text-area
component featured in the new Leitzentrale, the menu view received the
following improvements:
:Text-cursor support:
The label widget gained the ability to display one or multiple text cursors,
as illustrated by the following example:
! <label text="...">
! <cursor at="10"/>
! </label>
For the display of multiple cursors, each cursor must feature a distinctive
'name' attribute.
:Character position featured in the hover report:
The hovering information provided by the menu view used to be at the
granularity of widgets, which is insufficient for placing a text cursor with
the mouse. Hence, the information of a hovered label additionally provides
the character position within the label now.
:Unquoting label text attribute values:
The text displayed in label widgets is provided by a 'text' attribute value,
which raises the question of how to present '"' characters on the GUI. With
the new version, the attribute value can contain XML-quoted characters,
specifically "&quot;".
:Support for displaying text selections:
Similarly to the way of how a <cursor> can be defined for a <label>
widget, a selection can now be expressed as follows:
! <label ...>
! <selection at="2" length="12"/>
! </label>
:Support of multiple '<float>' widgets within a '<frame>':
We refined the hover reporting of <float> widgets such that a float widget
never responds to hovering unless a child is hovered. This way, it becomes
possible to stack multiple float widgets within one frame and still reach
all child widgets. This is useful for aligning multiple widgets within one
screen area independently from each other. For example, for left-aligning,
centering, and right-aligning the elements of a panel.
:Enforcing the minimum size of a label:
The new '<label min_ex="..">' attribute can be used to enforce a minimum
width in the unit of the size of the character 'x'. In the absence of a
'text' attribute, the minimum height of a label is implicitly set to 0. The
combination of both changes makes the label usable as a horizontal spacer.
:Basic support for styling labels:
The new version allows for the customization of the text color and alpha
value of the label widget by the means of a style-definition file. The
mechanism is exemplified with the new "invisible" label style that sets the
alpha value to zero.
With these few incremental changes in place, the menu-view widget renderer
becomes usable as the basis of the simple text editor used in Sculpt's new user
interface.
Self-hosting the tool chain on 64-bit ARM
=========================================
With our ongoing ARM 64-bit effort, we have successfully updated Genode's tool
chain with release
[https://genode.org/documentation/release-notes/19.05#Broadened_CPU_architecture_support_and_updated_tool_chain - 19.05].
With the current release, we have additionally managed to make Genode's tool
chain self hosting on ARM 64-bit, which means the tool chain can compile
source code on ARM 64-bit directly.
Platforms
#########
Execution on bare hardware (base-hw)
====================================
The generic code base of the base-hw kernel underwent several cosmetic changes
to reduce or eliminate the application of certain problematic constructs like
too much inheritance, pointers, and dynamic casts. Those changes were
motivated to ease the translation of several kernel parts to the Ada/SPARK
language in the context of the Spunky project. For more information regarding
this experiment to write a Genode kernel in Ada/SPARK, please have a look at
the recent [https://genodians.org/m-stein/index - genodians.org article series]
of Martin Stein or listen to his recent
[https://video.fosdem.org/2020/AW1.125/ada_spunky.mp4 - FOSDEM talk].
Moreover, the IPC path implementation got simplified to lower the overhead
costs introduced by the transfer of capabilities. Together with the mentioned
Spunky cleanup efforts, this change measurably improved IPC performance.
The base-hw kernel now exports time consumption of individual threads via
the trace service analogously to the implementation for NOVA. Thereby, it
becomes possible to use for instance the top component within the Sculpt OS
also on this kernel.
Until now, support for the Raspberry Pi 3 was limited to Qemu emulation only.
Thanks to a contribution of Tomasz Gajewski, it is now possible to execute
Genode on all four CPUs of the actual hardware concurrently.
Execution on Linux
==================
Traditionally, the Linux version of Genode serves us as very handy development
vehicle but it was never intended as an actual target platform. On Linux,
Genode is usually executed as a multi-process application on top of a regular
GNU/Linux desktop distribution by specifying 'KERNEL=linux' and 'BOARD=linux'
to the run tool.
However, thanks to the work of Johannes Kliemann, Genode has become able to
run on a bare-bone Linux kernel without any other user land.
We blatantly used to refer to this idea as the
[https://genode.org/about/challenges#Platforms - microkernelization of Linux].
Johannes picked up the idea, supplemented Genode's core with the services
needed for user-level device drivers (IRQ, IOMEM, IOPORT) and supplemented
the tooling for the integration of Genode scenarios into a bootable initrd
image. This target of execution can be addressed by specifying 'KERNEL=linux'
and 'BOARD=pc' to the run tool now. If specified, the run tool will produce a
bootable Linux system image for the given run script and run it in Qemu.
That said, as this line of work is still considered as an experimental
playground - not for productive use - the work flow is not entirely automated.
In particular, one needs to prepare a suitable
[https://github.com/jklmnn/linux/commits/genode - Linux kernel] manually.
If you are interested in the topic, please refer to the background information
given in the [https://github.com/genodelabs/genode/pull/2829 - issue tracker].

View File

@ -14,122 +14,121 @@ The road map is not fixed. If there is commercial interest of pushing the
Genode technology to a certain direction, we are willing to revisit our plans.
Review of 2018
Review of 2019
##############
Sculpt is our take on creating a Genode-based general-purpose operating
system. When we declared 2018 as Genode's Year of Sculpt one year ago, our
vision of how Sculpt OS would shape up was still vague. We were convinced that
we had - functionality-wise - all building blocks of a general-purpose OS in
place. But it was rather unclear how to best put them together to attain a
practical system. The unconquered design space seemed vast, which was both
exciting but also - at times - a bit paralyzing.
For the road map 2019, we picked "bridging worlds" as our guiding theme:
(1) Lowering the friction when combining existing software with Genode,
(2) Fostering interoperability with widely used protocols and APIs, and
(3) Making Genode easier to approach and generally more practical.
The Year of Sculpt was more than anything a design-space exploration, not
an up-front planned activity. The process was driven by intensive
brainstorming, experimentation, and the continuous practical evaluation
through the day-to-day use of the system by its developers. For us, this ride
was certainly the most rewarding period in Genode's history so far. Now, when
looking at the result, we are proud about what we have achieved together.
Whenever having the chance to showing off Sculpt running on our laptops,
the system doesn't fail to impress.
With respect to (1), we identified Genode's custom tooling (build
system, run scripts, ports mechanism, depot tools) as a point of
friction. They are arguably powerful and flexible but require a lot of
up-front learning. This is certainly a burden unacceptable for a casual
developer without a black belt in Make and Expect/Tcl. The new
[https://genode.org/documentation/release-notes/19.11#New_tooling_for_bridging_existing_build_systems_with_Genode - Goa]
tool rearranges the existing tools in a way that puts the concerns of casual
developers into focus, allowing for the use of commodity build systems,
eliminating Tcl syntax from the equation, running sub-second test cycles, and
streamlining the packaging of software.
Unsurprisingly, many topics of the past year had a direct connection to
Sculpt, e.g., the NIC router, the huge device-driver efforts, the GUI-stack
improvements, our custom microcode update mechanism, the software packaging
and deployment, and the work on the file-system and networking stacks.
On account of (2), we
[https://genode.org/documentation/release-notes/19.05#Broadened_CPU_architecture_support_and_updated_tool_chain - switched to C++17]
by default, fostered the use of
[https://genodians.org/ssumpf/2019-02-27-java-19-02 - Java],
updated Qt5, and put
[https://genode.org/documentation/release-notes/19.11#C_runtime_with_improved_POSIX_compatibility - POSIX]
compatibility into the spotlight. We were eventually able to dissolve the need
for our custom Unix runtime (Noux) because all features of Noux are covered by
our regular libc now.
The bottom line of the Year of Sculpt is that Sculpt OS has become a
surprisingly versatile and robust system. It can be deployed in a few seconds
by booting from USB, runs as day-to-day OS on almost all of our laptops, its
mechanisms for installing and updating software from packages have become a
second nature, and it continues to inspire us to explore new application
areas. Even outside of Genode Labs, there is a small and enthusiastic user
base.
Our biggest step towards (3) is the [https://genodians.org] website we
started in winter 2019, which gives individual members of our community
an easy way to present thoughts, projects, and experiences.
Complementing Genode's formal documentation, it also conserves practical
tips and tricks that were previously not covered in written form.
Besides Sculpt, we set forth a number of other goals one year ago.
When speaking of "bridging worlds", we should not forget to mention the
tremendous effort to bring Sculpt-OS-like workloads to the 64-bit ARM world.
Thanks to the added support for
[https://genode.org/documentation/release-notes/19.08#64-bit_ARM_and_NXP_i.MX8 - multi-core AARCH64],
hardware-based
[https://genode.org/documentation/release-notes/19.11#Virtualization_of_64-bit_ARM_platforms - virtualization],
and network/USB/graphics drivers for the i.MX8 SoC, the flexibility of Sculpt
OS will eventually become available on PC hardware and ARM-based devices
alike.
:The transition from NOVA to our custom kernel and seL4: is ongoing but
the topic received less attention than originally planned. This has
two reasons. First, Alexander Boettcher's excellent maintenance and gradual
improvement of NOVA keeps us hooked. Over the past year, there has been not
much incentive of actual Sculpt users to move away from NOVA. Second, there
is renewed interest in NOVA beyond our use of the kernel. Most specifically,
we started joining forces with
[https://cyberus-technology.de - Cyberus Technology] to improve NOVA
together. That's fantastic!
This development notwithstanding, we still follow our ambition to bring the
support for the other kernels like seL4 on par with NOVA to give Genode
users the ultimate choice.
Speaking of seL4, throughout the year, we have continuously adapted Genode
to the kernel's upstream development and enjoy the informal collaboration
with seL4 developer community. That said, the seL4 version of Genode still
remains a side activity with no commercial backing.
:NXP i.MX: support has become much better, particularly with respect to
network support and performance. Our ongoing commitment to the i.MX
platform is also fueled by privacy-advocating projects like the Librem
phone that are based on the same SoC.
:Software quality and resilience: ultimately became the title story of the
[https://genode.org/documentation/release-notes/18.11#Raising_the_bar_of_quality_assurance - release 18.11].
We greatly intensified the amount and quality of testing, explored static
code analysis, and vastly scaled up the complexity of workloads carried
by Genode.
:System monitoring, tracing, profiling: remains a somewhat underdeveloped area
of Genode. As a step in the right direction, we introduced a simple
trace-logging tool. Also, Sculpt's introspection features like the ability
to inspect the runtime's state live on the machine make Genode's behavior
easier to capture and to understand. But that said, the use of these
features remains a black art mastered only by a few.
:Java: has found its way into Genode via our port of OpenJDK. Details such as
the enabling of the JIT engine on ARM took much more effort than anticipated.
We are happy to report that Tomcat works fine. But at the current state, it
is still too early to advertise Java as a stable feature.
Over the course of 2019, we admittedly skipped a few topics originally
mentioned on our road map. In particular, the user-visible side of
Sculpt OS received less attention than originally envisioned. We also
deferred several ideas we had in mind about reworking our GUI stack.
Instead, we expanded our work in the areas of storage (block-level APIs,
test infrastructure,
[https://genode.org/documentation/release-notes/19.11#Preliminary_block-device_encrypter - block encryption])
and
[https://genode.org/documentation/release-notes/19.08#Flexible_keyboard_layouts - input processing].
This shift of focus is mostly attributed to the priorities of Genode Labs'
customers who fund our work.
2019 - Bridging Worlds
######################
2020 - Dwarfing the barrier of entry
####################################
We dedicated the year 2018 to prove that Genode scales to general-purpose
computing. [https://genode.org/download/sculpt - Sculpt OS] leaves no doubt
about that. The logical next step is to make Sculpt OS relevant and appealing
for a broader community.
During our public road-map
[https://lists.genode.org/pipermail/users/2018-December/006517.html - discussion]
on our mailing list, we identified three ways towards that goal:
Genode as a technology is there. For more than one decade, we walked unfathomed
territory, fought with countless deep rabbit holes, took risky decisions,
tracked back, explored design spaces, developed taste and distaste, pruned
technical debt, and eventually found formulas of success. Today, there are no
(fundamental) unsolved questions. All the puzzle pieces are in place. There
could be no better proof than our daily use of Sculpt OS. The time is right
to make Genode palatable for a wider circle. We identified four actionable
topics to achieve that.
# In order to capture the interest of new Genode users, we have to
put *emphasis on the practical use* of Genode, not on its technical prowess.
With practical use, we refer to both desktop computing and headless
scenarios like network appliances and servers. Over the course of 2019,
we plan to establish (variations of) Sculpt as an attractive foundation for
those application areas, and advance Genode's protocol stacks (storage and
encryption come in mind) and hardware support (e.g., ARM 64-bit) accordingly.
:User friendliness of Sculpt OS:
This will go hand in hand with making Genode easier to discover and to use,
describing use cases at a digestible level of detail, and fostering the
sense of one community that includes both users and developers.
Until now, Sculpt OS is not exactly friendly towards users who are
unfamiliar with the Unix command-line tools. Since Sculpt is not Unix
based, this is a bit paradoxical. 2020 will give Sculpt OS a friendlier
and discoverable user experience. In this context, we will inevitably
put our attention to Genode's GUI stack.
# Since an operating system is only valuable with applications, we have
to make the *porting of existing software* and the use of popular
*programming languages* a frictionless experience. Besides supporting the
reuse of existing software, we should also cultivate the "Genode way" as
an option for designing native applications. Such applications can
leverage the unique capabilities of the framework, in particular the
sandboxing of code at a very fine granularity and the low footprint of raw
Genode components.
:Perception of high quality:
# Because an operating system does not exist in isolation, we must foster
Genode's *interoperability* with other systems and applications by speaking
widely used protocols and supporting universally expected
software-integration features.
Compared to commodity operating systems who stood the test of time,
Genode is a young and largely unproven technology. It understandably calls
for skepticism. All the more we must leave no doubts about our high
quality standards. There must be no room for uncertainty. Hence, during
2020, we will intensify the consolidation and optimization of the framework
and its API, and talk about it.
:Enjoyable tooling:
Genode's success at large will depend on developers. As of today, software
development for Genode requires a huge up-front learning curve. This is
fine for people who are already convinced of Genode. But it unacceptable
for casual developers who want to get their toes wet. We should aim for
tooling that allows new developers to keep up their flow and beloved
tools. The recently introduced [https://genodians.org/nfeske/2019-11-25-goa - Goa]
tooling is our first take in this respect. It is certainly too early to call
Goa a success. In order to find out if we are on the right track, we want to
expose Goa to as many problems as possible, primarily by the means of
porting software. Also, things like IDE usage or adapters for a variety of
build systems will certainly move into focus in 2020.
:Convincing use cases:
Use cases can give exemplary proof of the fitness of Genode. We already
took a few baby steps to extend the range of documented use cases beyond
Sculpt OS last year. The boot2java scenenario comes in mind. 2020 will
hopefully see several more illustrations of Genode's versatility.
Milestones for 2019
Apart from this overall theme, we plan to continue our commitment to the
NXP i.MX SoC family, revisit Genode's low-latency audio support, and
extend the cultivation of Ada/SPARK within (and on top of) Genode.
Milestones for 2020
###################
In the following, we present a rough schedule of the planned work. As usual,
@ -137,57 +136,64 @@ it is not set in stone. If you are interested in a particular line of work,
please get in touch.
February - Release 19.02
February - Release 20.02
========================
* OpenJDK with JIT on ARM and x86
* Sculpt with support for online package discovery
* Showcase of a Genode-based web appliance
* Showcase of a multi-port network appliance
* Consolidation: removal of the Noux runtime
* Library version of the init component
* Updated audio drivers
* Sculpt
* 64-bit ARM (i.MX8)
* Revised administrative user interface
* System image without Unix tools
May - Release 19.05
May - Release 20.05
===================
* Updated "Genode Foundations" book
* Tool-chain update and SDK (C++-17, enabling O3 by default, considering GDC)
* Headless Sculpt
* Pluggable network drivers
* Native support for Let's Encrypt certificates
* Revisited GUI-related framework interfaces
* Consolidation
* Block-level components (update to Genode's modern block APIs)
* ARM device drivers (introducing the notion of a platform driver)
* Improved STL support (e.g., threading and mutexes)
* Continuous POSIX-compliance testing
* Systematic network-stack stress and performance tests
* Desktop: panel and virtual desktops
* Use case: Genode-based network router
* Goa: broadened support for 3rd-party build systems
* Native tool chain, including Git
* Sculpt
* Improved interactive system composition
* Passphrase handling
* Clipboard support
* Kernel-agnostic virtual-machine monitors
* ARM 64-bit
* Interactive device management
* Keyboard-controlled administration
* Support for BSPs maintained outside of Genode's mainline repository
August - Release 19.08
August - Release 20.08
======================
* Interactive tracing tool
* Virtualization support for the base-hw kernel on x86
* Library version of the init component
* Revisited GUI-related framework interfaces
* Extended tooling for performance monitoring
* Goa: Qt development workflow
* Desktop
* Native mail client
* Native web browser
* Sculpt
* Fine-grained USB-device policies
* Interactive depot manager (ability to add/remove software providers)
* Configuration of CPU affinities and scheduling priorities
* Audio
* Showcase of a Sculpt-based network router
* VM-based desktop applications (enhanced VM integration features)
* Updated Qt5
* Consolidation of the Noux runtime (performance)
* Configurable CPU resources
* On-screen documentation
* Block encryption via our
[https://genode.org/documentation/release-notes/19.11#Preliminary_block-device_encrypter - consistent block encrypter]
implemented in Ada/SPARK
* USB audio
* Initial version of a kernel implemented in Ada/SPARK
November - Release 19.11
November - Release 20.11
========================
* Building Genode packages directly on Sculpt
* VNC server support
* Sculpt
* On-target debugging of components
* Shutdown protocol
* Block-level encrypted storage
* Drag-and-drop protocol
* Consolidation of capability-space management across kernels
* CPU-load balancing
* Hardware-accelerated graphics on i.MX8 (experimental)
* Reworked audio stack (interfaces, mixing)
* Sculpt: component lifetime management, shutdown protocol
* VFS plugins for lwext4 and FUSE-based file systems

View File

@ -10,5 +10,7 @@ LIBS += startup-fiasco syscall-fiasco
SRC_CC += capability.cc capability_raw.cc
SRC_CC += rpc_dispatch_loop.cc
SRC_CC += rpc_entrypoint_manage.cc
SRC_CC += thread.cc thread_bootstrap.cc thread_myself.cc
SRC_CC += stack_area_addr.cc
SRC_CC += rpc_entry.cc

View File

@ -6,3 +6,4 @@ SRC_CC += thread_start.cc
SRC_CC += cache.cc
SRC_CC += capability_space.cc
SRC_CC += signal_transmitter.cc signal.cc
SRC_CC += platform.cc

View File

@ -1 +1 @@
2019-11-25 c7e2a3eca5820b2304b4520d0fc831ede73691f2
2020-02-27 6311f83c887384fa01828af695bae799b148e0ad

View File

@ -29,7 +29,7 @@ void Thread::_thread_start()
{
Thread::myself()->_thread_bootstrap();
Thread::myself()->entry();
Thread::myself()->_join_lock.unlock();
Thread::myself()->_join.wakeup();
sleep_forever();
}

View File

@ -201,16 +201,14 @@ void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
snd_header.protocol_word,
snd_header.num_caps,
L4_IPC_SEND_TIMEOUT_0, &result);
if (L4_IPC_IS_ERROR(result))
error("ipc_send error ", Hex(L4_IPC_ERROR(result)), ", ignored");
}
Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
Rpc_exception_code exc,
Msgbuf_base &reply_msg,
Msgbuf_base &request_msg)
Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
Rpc_exception_code exc,
Msgbuf_base &reply_msg,
Msgbuf_base &request_msg,
Rpc_entrypoint::Native_context &)
{
using namespace Fiasco;
@ -277,9 +275,10 @@ Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
}
Ipc_server::Ipc_server()
Ipc_server::Ipc_server(Rpc_entrypoint::Native_context& native_context)
:
Native_capability(Capability_space::import(Fiasco::l4_myself(), Rpc_obj_key()))
Native_capability(Capability_space::import(Fiasco::l4_myself(), Rpc_obj_key())),
_native_context(native_context)
{ }

View File

@ -13,6 +13,7 @@
/* Genode includes */
#include <base/cancelable_lock.h>
#include <base/thread.h>
#include <cpu/atomic.h>
#include <cpu/memory_barrier.h>
@ -33,6 +34,13 @@ Cancelable_lock::Cancelable_lock(Cancelable_lock::State initial)
void Cancelable_lock::lock()
{
Applicant myself(Thread::myself());
lock(myself);
}
void Cancelable_lock::lock(Applicant &myself)
{
/*
* XXX: How to notice cancel-blocking signals issued when being outside the
@ -41,11 +49,14 @@ void Cancelable_lock::lock()
while (!Genode::cmpxchg(&_state, UNLOCKED, LOCKED))
if (Fiasco::l4_ipc_sleep(Fiasco::l4_ipc_timeout(0, 0, 500, 0)) != L4_IPC_RETIMEOUT)
throw Genode::Blocking_canceled();
_owner = myself;
}
void Cancelable_lock::unlock()
{
_owner = Applicant(nullptr);
Genode::memory_barrier();
_state = UNLOCKED;
}

View File

@ -10,6 +10,9 @@ LIBS += syscall-foc startup-foc
SRC_CC += spin_lock.cc cap_map.cc
SRC_CC += rpc_dispatch_loop.cc
SRC_CC += rpc_entrypoint_manage.cc
SRC_CC += thread.cc thread_bootstrap.cc thread_myself.cc utcb.cc
SRC_CC += capability.cc
SRC_CC += signal_source_client.cc
SRC_CC += platform.cc
SRC_CC += rpc_entry.cc

View File

@ -1 +1 @@
2019-11-25 9a459c4fd8a907810d91041751affcf3e119fcb1
2020-02-27 82bbd7275951340ff82061af8bc2cce41f1519e3

View File

@ -1 +1 @@
2019-11-25 d8ff4913b8aa117aef77a7918bc82808e38a4ee7
2020-02-27 c5602daf28cdc5d005a26f408527e64ab905197e

View File

@ -1 +1 @@
2019-11-25 a750c8988106d5c26e46dcceb1f76bfd7bfa1457
2020-02-27 a3912478467dcf01ab6379502bb15719b748c388

View File

@ -1 +1 @@
2019-11-25 0c0a26b6ddb0ee5261f0be30f229e9ce04b61eda
2020-02-27 e7f8bca57dbed6597e46aafd0256dfd5a6ac42c3

View File

@ -1 +1 @@
2019-11-25 bce6f0a8f1f46f8edf62ef2180dbfc949123432d
2020-02-27 b03dfe2bde7fe637c0a7eff9e709845e64b4d09c

View File

@ -1 +1 @@
2019-11-25 307d01e531dbbcd672463a4ea090f40bb399cae8
2020-02-27 a1eb6dfc01d82b598f0778c0b74f2a49387cc42d

View File

@ -36,7 +36,7 @@ void Ipc_pager::_parse(unsigned long label) {
if (_type == PAGEFAULT || _type == EXCEPTION)
_parse_pagefault();
if (_type == PAUSE || _type == EXCEPTION)
memcpy(&_regs, l4_utcb_exc(), sizeof(l4_exc_regs_t));
_regs = *l4_utcb_exc();
}
@ -134,7 +134,7 @@ void Ipc_pager::acknowledge_wakeup()
void Ipc_pager::acknowledge_exception()
{
memcpy(l4_utcb_exc(), &_regs, sizeof(l4_exc_regs_t));
_regs = *l4_utcb_exc();
l4_cap_idx_t dst = Fiasco::Capability::valid(_last.kcap)
? _last.kcap : (l4_cap_idx_t)L4_SYSF_REPLY;
Fiasco::l4_msgtag_t const msg_tag =

View File

@ -495,6 +495,10 @@ Platform::Platform() :
xml.node("hardware", [&] () {
_setup_platform_info(xml, sigma0_map_kip());
});
xml.node("affinity-space", [&] () {
xml.attribute("width", affinity_space().width());
xml.attribute("height", affinity_space().height());
});
});
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, size,

View File

@ -78,7 +78,7 @@ static inline void thread_switch_to(Genode::Thread *thread_base)
__attribute__((optimize("-fno-omit-frame-pointer")))
__attribute__((noinline))
__attribute__((used))
static void thread_stop_myself()
static void thread_stop_myself(Genode::Thread *)
{
using namespace Fiasco;

View File

@ -238,6 +238,11 @@ static l4_msgtag_t copy_msgbuf_to_utcb(Msgbuf_base &snd_msg,
/* setup flexpage for valid capability to delegate */
if (caps[i].valid) {
unsigned const idx = num_msg_words + 2*num_cap_sel;
/* check bounds of 'l4_msg_regs_t::mr' */
if (idx + 1 >= L4_UTCB_GENERIC_DATA_SIZE)
break;
l4_utcb_mr()->mr[idx] = L4_ITEM_MAP/* | L4_ITEM_CONT*/;
l4_utcb_mr()->mr[idx + 1] = l4_obj_fpage(caps[i].sel,
0, L4_FPAGE_RWX).raw;
@ -311,10 +316,11 @@ void Genode::ipc_reply(Native_capability, Rpc_exception_code exc,
}
Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
Rpc_exception_code exc,
Msgbuf_base &reply_msg,
Msgbuf_base &request_msg)
Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
Rpc_exception_code exc,
Msgbuf_base &reply_msg,
Msgbuf_base &request_msg,
Rpc_entrypoint::Native_context &)
{
Receive_window &rcv_window = Thread::myself()->native_thread().rcv_window;
@ -365,9 +371,10 @@ Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
}
Ipc_server::Ipc_server()
Ipc_server::Ipc_server(Rpc_entrypoint::Native_context& native_context)
:
Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE])
Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]),
_native_context(native_context)
{
Thread::myself()->native_thread().rcv_window.init();
}

View File

@ -59,6 +59,6 @@ void Genode::Thread::_thread_start()
Thread::myself()->_thread_bootstrap();
Thread::myself()->entry();
Thread::myself()->_join_lock.unlock();
Thread::myself()->_join.wakeup();
sleep_forever();
}

View File

@ -10,5 +10,7 @@ include $(BASE_DIR)/lib/mk/base-common.inc
LIBS += syscall-hw
SRC_CC += rpc_dispatch_loop.cc
SRC_CC += rpc_entrypoint_manage.cc
SRC_CC += thread.cc thread_myself.cc thread_bootstrap.cc
SRC_CC += signal_transmitter.cc
SRC_CC += rpc_entry.cc

View File

@ -7,5 +7,6 @@ SRC_CC += raw_write_string.cc
SRC_CC += signal_receiver.cc
SRC_CC += stack_area_addr.cc
SRC_CC += native_utcb.cc
SRC_CC += platform.cc
LIBS += startup-hw base-hw-common cxx timeout-hw

View File

@ -52,7 +52,6 @@ SRC_CC += pager.cc
SRC_CC += _main.cc
SRC_CC += kernel/cpu.cc
SRC_CC += kernel/cpu_scheduler.cc
SRC_CC += kernel/double_list.cc
SRC_CC += kernel/init.cc
SRC_CC += kernel/ipc_node.cc
SRC_CC += kernel/irq.cc

View File

@ -17,7 +17,7 @@ SRC_CC += spec/arm/platform_support.cc
# add assembly sources
SRC_S += spec/arm/crt0.s
SRC_S += spec/arm/exception_vector.s
SRC_S += spec/arm/exception_vector.S
vpath spec/32bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw

View File

@ -1 +1 @@
2019-11-25 c60d834ce54a46a946c36249784e734e06274d97
2020-02-27 e1a80cef41a848e8f63df9a249a4e57148e66331

View File

@ -1 +1 @@
2019-11-25 e9232754efd81c14aa65d4852d276852f591f3e5
2020-02-27 bd79fb9d11cef09e99ba545408128a605b47814a

View File

@ -1 +1 @@
2019-11-25 2ab0250606cee0da4f08ac08f7f33c743f32c88c
2020-02-27 879f89b08454a6aab78bab0c018d1902af792a47

View File

@ -1 +1 @@
2019-11-25 7780e0570ac0277d678dee76a579a9d9f9a1a776
2020-02-27 447889337c681d7b9f68c637f9a3eac3abfd2f30

View File

@ -1 +1 @@
2019-11-25 2dee497b7892f706236fdbfabae53bbd4e62463b
2020-02-27 42c284564d38f3bdbd6b30e58280a2f699b657f9

View File

@ -1 +1 @@
2019-11-25 efd164d66086a998484d7413c5416e3aa128e560
2020-02-27 9d9e438a93c416499bb7b414bbcf2de7f2d3650f

View File

@ -1 +1 @@
2019-11-25 25f54b8744778f0860ac2a93c11ee6b1cd16d0c9
2020-02-27 ff3428ffdd5d60514fa5028b003b54327da895ad

View File

@ -1 +1 @@
2019-11-25 ceeaef3ad58fc5b88cf4686aa42f50fd254063e3
2020-02-27 84aec73deeae79a6b34374fe859ea5333d05da69

View File

@ -1 +1 @@
2019-11-25 aee36abdef456d2d1c6bba023f16cbca08eceabe
2020-02-27 e87fc4e86962227db5c41bf048eeacf1c27d04c1

View File

@ -1 +1 @@
2019-11-25 ede7ce464c3f4b8486fd93413088a1b83fbf796a
2020-02-27 ebd97e5400e2b99fd810cd233c0f881ede48f376

View File

@ -1 +1 @@
2019-11-25 2bea4132b9ab877e802cfb81ad3c62bda0c2bc50
2020-02-27 5d0722736647b538eb52b35286b7734581402426

View File

@ -1 +1 @@
2019-11-25 807893480c51457cad7e00e1275eff9749c91c68
2020-02-27 1caed3e6b2d8bc98948b9fd43f3bb26abd52f780

View File

@ -1 +1 @@
2019-11-25 6a3f12cd6429f5d5bcf617cdd3ea9d345e8614ad
2020-02-27 6d72eb037774a58fc079c5df7bd5b7348c8799b4

View File

@ -1 +1 @@
2019-11-25 a318db7d985930e3f58ce3bccce290bc13aaedab
2020-02-27 41e345219f64781ef6cb472d4f9d374b0295328b

View File

@ -1 +1 @@
2019-11-25 75f1b89ea50fdfd0a69c33dee4ba1e120d49fad5
2020-02-27 c2481cbfd690b653b38c6bfe09c296094240e90d

View File

@ -23,7 +23,7 @@ install_config {
<default-route>
<any-service> <parent/> </any-service>
</default-route>
<start name="test-cpu_scheduler">
<start name="test-cpu_scheduler" caps="100">
<resource name="RAM" quantum="10M"/>
</start>
</config>}

View File

@ -16,11 +16,14 @@ install_config {
<parent-provides>
<service name="LOG"/>
<service name="RM"/>
<service name="PD"/>
<service name="CPU"/>
<service name="ROM"/>
</parent-provides>
<default-route>
<any-service> <parent/> </any-service>
</default-route>
<start name="test-double_list">
<start name="test-double_list" caps="100">
<resource name="RAM" quantum="10M"/>
</start>
</config>

View File

@ -12,6 +12,7 @@
*/
#include <base/lock.h>
#include <base/mutex.h>
#include <hw/assert.h>
Genode::Cancelable_lock::Cancelable_lock(Genode::Cancelable_lock::State state)
@ -30,3 +31,13 @@ void Genode::Cancelable_lock::lock()
assert(_state == UNLOCKED);
_state = LOCKED;
}
void Genode::Mutex::acquire()
{
_lock.lock();
}
void Genode::Mutex::release()
{
_lock.unlock();
}

View File

@ -19,6 +19,7 @@
using namespace Bootstrap;
extern unsigned _bss_end;
/*****************************
** Platform::Ram_allocator **
@ -179,7 +180,7 @@ Platform::Platform()
/* temporarily map all bootstrap memory 1:1 for transition to core */
// FIXME do not insert as mapping for core
core_pd->map_insert(Mapping(bootstrap_region.base, bootstrap_region.base,
bootstrap_region.size, Hw::PAGE_FLAGS_KERN_TEXT));
(addr_t)&_bss_end - (addr_t)&_prog_img_beg, Hw::PAGE_FLAGS_KERN_TEXT));
/* map memory-mapped I/O for core */
board.core_mmio.for_each_mapping([&] (Mapping const & m) {

View File

@ -109,13 +109,18 @@ unsigned Bootstrap::Platform::enable_mmu()
static Cpu_counter data_cache_invalidated;
static Cpu_counter data_cache_enabled;
static Cpu_counter smp_coherency_enabled;
static unsigned long diag_reg = 0;
bool primary = primary_cpu;
if (primary) primary_cpu = false;
if (primary) {
primary_cpu = false;
diag_reg = Cpu::Diag::read();
}
Cpu::Sctlr::init();
Cpu::Cpsr::init();
Actlr::disable_smp();
Cpu::Diag::write(diag_reg);
/* locally initialize interrupt controller */
::Board::Pic pic { };
@ -170,6 +175,7 @@ unsigned Bootstrap::Platform::enable_mmu()
/* wait for other cores' coherency activation */
smp_coherency_enabled.wait_for(NR_OF_CPUS);
Cpu::synchronization_barrier();
asm volatile("dsb sy\n"
"isb sy\n" ::: "memory");
return Cpu::Mpidr::Aff_0::get(Cpu::Mpidr::read());
}

View File

@ -16,7 +16,7 @@
using Board::Cpu;
extern "C" void * _crt0_enable_fpu;
extern "C" void * _crt0_start_secondary;
static inline void prepare_non_secure_world()
{
@ -144,6 +144,9 @@ unsigned Bootstrap::Platform::enable_mmu()
Cpu::Ttbr::access_t ttbr =
Cpu::Ttbr::Baddr::masked((Genode::addr_t)core_pd->table_base);
/* primary cpu wakes up all others */
if (primary && NR_OF_CPUS > 1) Cpu::wake_up_all_cpus(&_crt0_start_secondary);
while (Cpu::current_privilege_level() > Cpu::Current_el::EL1) {
if (Cpu::current_privilege_level() == Cpu::Current_el::EL3) {
prepare_non_secure_world();
@ -153,11 +156,11 @@ unsigned Bootstrap::Platform::enable_mmu()
}
}
/* primary cpu wakes up all others */
if (primary && NR_OF_CPUS > 1) Cpu::wake_up_all_cpus(&_crt0_enable_fpu);
/* enable performance counter for user-land */
Cpu::Pmuserenr_el0::write(0b1111);
Cpu::Pmcr_el0::access_t pmcr = Cpu::Pmcr_el0::read();
Cpu::Pmcr_el0::write(pmcr | 1);
Cpu::Pmcntenset_el0::write(1 << 31);
/* enable user-level access of physical/virtual counter */
Cpu::Cntkctl_el1::write(0b11);
@ -198,5 +201,5 @@ unsigned Bootstrap::Platform::enable_mmu()
Cpu::Sctlr::Uct::set(sctlr, 1);
Cpu::Sctlr_el1::write(sctlr);
return 0;
return (Cpu::Mpidr::read() & 0xff);
}

View File

@ -11,22 +11,25 @@
* under the terms of the GNU Affero General Public License version 3.
*/
/**
* Store CPU number in register x0
*/
.macro _cpu_number
mrs x0, mpidr_el1
and x0, x0, #0b11111111
.endm
.section ".text.crt0"
.global _start
_start:
/***********************
** Detect CPU number **
***********************/
mrs x0, mpidr_el1
and x0, x0, #0b11111111
cbz x0, _crt0_fill_bss_zero
/**
* Hack for Qemu, which starts all cpus at once
* only first CPU runs through, all others wait for wakeup
*/
_cpu_number
cbz x0, _crt0_fill_bss_zero
1:
ldr x1, =_crt0_qemu_start_secondary_cpus
ldr w1, [x1]
@ -52,11 +55,18 @@
b 1b
/************************************
** Common Entrypoint for all CPUs **
************************************/
.global _crt0_start_secondary
_crt0_start_secondary:
/****************
** Enable FPU **
****************/
.global _crt0_enable_fpu
_crt0_enable_fpu:
mov x1, #0b11
lsl x1, x1, #20
@ -69,6 +79,7 @@
.set STACK_SIZE, 0x2000
_cpu_number
ldr x1, =_crt0_start_stack
ldr x2, [x1]
mul x0, x0, x2
@ -82,4 +93,3 @@
.endr
_crt0_start_stack:
.long STACK_SIZE

View File

@ -30,8 +30,16 @@ Bootstrap::Platform::Board::Board()
extern unsigned int _crt0_qemu_start_secondary_cpus;
void Board::Cpu::wake_up_all_cpus(void *)
void Board::Cpu::wake_up_all_cpus(void * ip)
{
/* start when in qemu */
_crt0_qemu_start_secondary_cpus = 1;
asm volatile("dsb #0; sev");
/* start on real hardware */
*((void * volatile *) 0xe0) = ip; /* cpu 1 */
*((void * volatile *) 0xe8) = ip; /* cpu 2 */
*((void * volatile *) 0xf0) = ip; /* cpu 3 */
/* send event for both variants */
asm volatile("dsb #15; sev");
}

View File

@ -18,6 +18,9 @@
#include <cpu_session_component.h>
#include <kernel/configuration.h>
/* base-internal includes */
#include <base/internal/native_utcb.h>
using namespace Genode;
@ -33,3 +36,7 @@ Cpu_session::Quota Cpu_session_component::quota()
size_t const u = quota_lim_downscale<sizet_arithm_t>(_quota, spu);
return { spu, u };
}
size_t Cpu_session_component::_utcb_quota_size() {
return sizeof(Native_utcb); }

View File

@ -40,7 +40,7 @@ void Cpu_job::_activate_own_share() { _cpu->schedule(this); }
void Cpu_job::_deactivate_own_share()
{
assert(_cpu->id() == Cpu::executing_id());
_cpu->scheduler().unready(this);
_cpu->scheduler().unready(*this);
}
@ -74,13 +74,13 @@ void Cpu_job::_interrupt(unsigned const /* cpu_id */)
void Cpu_job::affinity(Cpu &cpu)
{
_cpu = &cpu;
_cpu->scheduler().insert(this);
_cpu->scheduler().insert(*this);
}
void Cpu_job::quota(unsigned const q)
{
if (_cpu) { _cpu->scheduler().quota(this, q); }
if (_cpu) { _cpu->scheduler().quota(*this, q); }
else { Cpu_share::quota(q); }
}
@ -93,7 +93,7 @@ Cpu_job::Cpu_job(Cpu_priority const p, unsigned const q)
Cpu_job::~Cpu_job()
{
if (!_cpu) { return; }
_cpu->scheduler().remove(this);
_cpu->scheduler().remove(*this);
}
@ -115,8 +115,13 @@ Cpu::Idle_thread::Idle_thread(Cpu &cpu)
void Cpu::schedule(Job * const job)
{
if (_id == executing_id()) { _scheduler.ready(&job->share()); }
else if (_scheduler.ready_check(&job->share())) { trigger_ip_interrupt(); }
if (_id == executing_id()) { _scheduler.ready(job->share()); }
else {
_scheduler.ready_check(job->share());
if (_scheduler.need_to_schedule()) {
trigger_ip_interrupt();
}
}
}
@ -140,7 +145,8 @@ Cpu_job & Cpu::schedule()
_scheduler.update(_timer.time());
time_t t = _scheduler.head_quota();
_timer.set_timeout(this, t);
_timer.schedule_timeout();
time_t duration = _timer.schedule_timeout();
old_job.update_execution_time(duration);
}
/* return new job */
@ -161,7 +167,7 @@ Cpu::Cpu(unsigned const id,
Inter_processor_work_list & global_work_list)
:
_id(id), _timer(*this),
_scheduler(&_idle, _quota(), _fill()), _idle(*this),
_scheduler(_idle, _quota(), _fill()), _idle(*this),
_ipi_irq(*this),
_global_work_list(global_work_list)
{ _arch_init(); }

View File

@ -169,7 +169,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
* Returns the currently active job
*/
Job & scheduled_job() const {
return *static_cast<Job *>(_scheduler.head())->helping_sink(); }
return *static_cast<Job *>(&_scheduler.head())->helping_sink(); }
unsigned id() const { return _id; }
Cpu_scheduler &scheduler() { return _scheduler; }
@ -178,6 +178,11 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
Inter_processor_work_list & work_list() {
return _local_work_list; }
/**
* Return CPU's idle thread object
*/
Kernel::Thread &idle_thread() { return _idle; }
};

View File

@ -35,6 +35,8 @@ class Kernel::Cpu_job : private Cpu_share
friend class Cpu; /* static_cast from 'Cpu_share' to 'Cpu_job' */
time_t _execution_time { 0 };
/*
* Noncopyable
*/
@ -112,6 +114,16 @@ class Kernel::Cpu_job : private Cpu_share
*/
bool own_share_active() { return Cpu_share::ready(); }
/**
* Update total execution time
*/
void update_execution_time(time_t duration) { _execution_time += duration; }
/**
* Return total execution time
*/
time_t execution_time() const { return _execution_time; }
/***************
** Accessors **

View File

@ -18,14 +18,16 @@
using namespace Kernel;
void Cpu_scheduler::_reset(Claim * const c) {
_share(c)->_claim = _share(c)->_quota; }
void Cpu_scheduler::_reset(Cpu_share &share)
{
share._claim = share._quota;
}
void Cpu_scheduler::_reset_claims(unsigned const p)
{
_rcl[p].for_each([&] (Claim * const c) { _reset(c); });
_ucl[p].for_each([&] (Claim * const c) { _reset(c); });
_rcl[p].for_each([&] (Cpu_share &share) { _reset(share); });
_ucl[p].for_each([&] (Cpu_share &share) { _reset(share); });
}
@ -43,11 +45,11 @@ void Cpu_scheduler::_consumed(unsigned const q)
}
void Cpu_scheduler::_set_head(Share * const s, unsigned const q, bool const c)
void Cpu_scheduler::_set_head(Share &s, unsigned const q, bool const c)
{
_head_quota = q;
_head_claims = c;
_head = s;
_head = &s;
}
@ -63,13 +65,13 @@ void Cpu_scheduler::_head_claimed(unsigned const r)
if (!_head->_quota) { return; }
_head->_claim = r > _head->_quota ? _head->_quota : r;
if (_head->_claim || !_head->_ready) { return; }
_rcl[_head->_prio].to_tail(_head);
_rcl[_head->_prio].to_tail(&_head->_claim_item);
}
void Cpu_scheduler::_head_filled(unsigned const r)
{
if (_fills.head() != _head) { return; }
if (_fills.head() != &_head->_fill_item) { return; }
if (r) { _head->_fill = r; }
else { _next_fill(); }
}
@ -78,10 +80,11 @@ void Cpu_scheduler::_head_filled(unsigned const r)
bool Cpu_scheduler::_claim_for_head()
{
for (signed p = Prio::MAX; p > Prio::MIN - 1; p--) {
Share * const s = _share(_rcl[p].head());
if (!s) { continue; }
if (!s->_claim) { continue; }
_set_head(s, s->_claim, 1);
Double_list_item<Cpu_share> *const item { _rcl[p].head() };
if (!item) { continue; }
Cpu_share &share { item->payload() };
if (!share._claim) { continue; }
_set_head(share, share._claim, 1);
return 1;
}
return 0;
@ -90,14 +93,17 @@ bool Cpu_scheduler::_claim_for_head()
bool Cpu_scheduler::_fill_for_head()
{
Share * const s = _share(_fills.head());
if (!s) { return 0; }
_set_head(s, s->_fill, 0);
Double_list_item<Cpu_share> *const item { _fills.head() };
if (!item) {
return 0;
}
Share &share = item->payload();
_set_head(share, share._fill, 0);
return 1;
}
unsigned Cpu_scheduler::_trim_consumption(unsigned & q)
unsigned Cpu_scheduler::_trim_consumption(unsigned &q)
{
q = Genode::min(Genode::min(q, _head_quota), _residual);
if (!_head_yields) { return _head_quota - q; }
@ -106,23 +112,23 @@ unsigned Cpu_scheduler::_trim_consumption(unsigned & q)
}
void Cpu_scheduler::_quota_introduction(Share * const s)
void Cpu_scheduler::_quota_introduction(Share &s)
{
if (s->_ready) { _rcl[s->_prio].insert_tail(s); }
else { _ucl[s->_prio].insert_tail(s); }
if (s._ready) { _rcl[s._prio].insert_tail(&s._claim_item); }
else { _ucl[s._prio].insert_tail(&s._claim_item); }
}
void Cpu_scheduler::_quota_revokation(Share * const s)
void Cpu_scheduler::_quota_revokation(Share &s)
{
if (s->_ready) { _rcl[s->_prio].remove(s); }
else { _ucl[s->_prio].remove(s); }
if (s._ready) { _rcl[s._prio].remove(&s._claim_item); }
else { _ucl[s._prio].remove(&s._claim_item); }
}
void Cpu_scheduler::_quota_adaption(Share * const s, unsigned const q)
void Cpu_scheduler::_quota_adaption(Share &s, unsigned const q)
{
if (q) { if (s->_claim > q) { s->_claim = q; } }
if (q) { if (s._claim > q) { s._claim = q; } }
else { _quota_revokation(s); }
}
@ -147,56 +153,62 @@ void Cpu_scheduler::update(time_t time)
}
bool Cpu_scheduler::ready_check(Share * const s1)
void Cpu_scheduler::ready_check(Share &s1)
{
assert(_head);
ready(s1);
if (_need_to_schedule) return _need_to_schedule;
if (_need_to_schedule) {
return;
}
Share * s2 = _head;
if (!s1->_claim) {
_need_to_schedule = s2 == _idle;
if (!s1._claim) {
_need_to_schedule = s2 == &_idle;
} else if (!_head_claims) {
_need_to_schedule = true;
} else if (s1->_prio != s2->_prio) {
_need_to_schedule = s1->_prio > s2->_prio;
} else if (s1._prio != s2->_prio) {
_need_to_schedule = s1._prio > s2->_prio;
} else {
for (; s2 && s2 != s1; s2 = _share(Claim_list::next(s2))) ;
for (
; s2 && s2 != &s1;
s2 =
Double_list<Cpu_share>::next(&s2->_claim_item) != nullptr ?
&Double_list<Cpu_share>::next(&s2->_claim_item)->payload() :
nullptr) ;
_need_to_schedule = !s2;
}
return _need_to_schedule;
}
void Cpu_scheduler::ready(Share * const s)
void Cpu_scheduler::ready(Share &s)
{
assert(!s->_ready && s != _idle);
assert(!s._ready && &s != &_idle);
_need_to_schedule = true;
s->_ready = 1;
s->_fill = _fill;
_fills.insert_tail(s);
if (!s->_quota) { return; }
_ucl[s->_prio].remove(s);
if (s->_claim) { _rcl[s->_prio].insert_head(s); }
else { _rcl[s->_prio].insert_tail(s); }
s._ready = 1;
s._fill = _fill;
_fills.insert_tail(&s._fill_item);
if (!s._quota) { return; }
_ucl[s._prio].remove(&s._claim_item);
if (s._claim) { _rcl[s._prio].insert_head(&s._claim_item); }
else { _rcl[s._prio].insert_tail(&s._claim_item); }
}
void Cpu_scheduler::unready(Share * const s)
void Cpu_scheduler::unready(Share &s)
{
assert(s->_ready && s != _idle);
assert(s._ready && &s != &_idle);
_need_to_schedule = true;
s->_ready = 0;
_fills.remove(s);
if (!s->_quota) { return; }
_rcl[s->_prio].remove(s);
_ucl[s->_prio].insert_tail(s);
s._ready = 0;
_fills.remove(&s._fill_item);
if (!s._quota) { return; }
_rcl[s._prio].remove(&s._claim_item);
_ucl[s._prio].insert_tail(&s._claim_item);
}
@ -207,39 +219,46 @@ void Cpu_scheduler::yield()
}
void Cpu_scheduler::remove(Share * const s)
void Cpu_scheduler::remove(Share &s)
{
assert(s != _idle);
assert(&s != &_idle);
_need_to_schedule = true;
if (s == _head) _head = nullptr;
if (s->_ready) { _fills.remove(s); }
if (!s->_quota) { return; }
if (s->_ready) { _rcl[s->_prio].remove(s); }
else { _ucl[s->_prio].remove(s); }
if (&s == _head) _head = nullptr;
if (s._ready) { _fills.remove(&s._fill_item); }
if (!s._quota) { return; }
if (s._ready) { _rcl[s._prio].remove(&s._claim_item); }
else { _ucl[s._prio].remove(&s._claim_item); }
}
void Cpu_scheduler::insert(Share * const s)
void Cpu_scheduler::insert(Share &s)
{
assert(!s->_ready);
assert(!s._ready);
_need_to_schedule = true;
if (!s->_quota) { return; }
s->_claim = s->_quota;
_ucl[s->_prio].insert_head(s);
if (!s._quota) { return; }
s._claim = s._quota;
_ucl[s._prio].insert_head(&s._claim_item);
}
void Cpu_scheduler::quota(Share * const s, unsigned const q)
void Cpu_scheduler::quota(Share &s, unsigned const q)
{
assert(s != _idle);
if (s->_quota) { _quota_adaption(s, q); }
assert(&s != &_idle);
if (s._quota) { _quota_adaption(s, q); }
else if (q) { _quota_introduction(s); }
s->_quota = q;
s._quota = q;
}
Cpu_scheduler::Cpu_scheduler(Share * const i, unsigned const q,
Cpu_share &Cpu_scheduler::head() const
{
assert(_head);
return *_head;
}
Cpu_scheduler::Cpu_scheduler(Share &i, unsigned const q,
unsigned const f)
: _idle(i), _quota(q), _residual(q), _fill(f)
{ _set_head(i, f, 0); }

View File

@ -27,16 +27,6 @@ namespace Kernel
*/
class Cpu_priority;
/**
* Scheduling context that has quota and priority (low-latency)
*/
class Cpu_claim : public Double_list_item { };
/**
* Scheduling context that has no quota or priority (best effort)
*/
class Cpu_fill : public Double_list_item { };
/**
* Scheduling context that is both claim and fill
*/
@ -70,7 +60,7 @@ class Kernel::Cpu_priority
* Standard operators
*/
Cpu_priority & operator =(signed const v)
Cpu_priority &operator =(signed const v)
{
_value = Genode::min(v, MAX);
return *this;
@ -79,17 +69,19 @@ class Kernel::Cpu_priority
operator signed() const { return _value; }
};
class Kernel::Cpu_share : public Cpu_claim, public Cpu_fill
class Kernel::Cpu_share
{
friend class Cpu_scheduler;
private:
signed const _prio;
unsigned _quota;
unsigned _claim;
unsigned _fill = 0;
bool _ready = false;
Double_list_item<Cpu_share> _fill_item { *this };
Double_list_item<Cpu_share> _claim_item { *this };
signed const _prio;
unsigned _quota;
unsigned _claim;
unsigned _fill { 0 };
bool _ready { false };
public:
@ -114,60 +106,53 @@ class Kernel::Cpu_scheduler
{
private:
typedef Cpu_share Share;
typedef Cpu_fill Fill;
typedef Cpu_claim Claim;
typedef Double_list_typed<Claim> Claim_list;
typedef Double_list_typed<Fill> Fill_list;
typedef Cpu_priority Prio;
typedef Cpu_share Share;
typedef Cpu_priority Prio;
Claim_list _rcl[Prio::MAX + 1]; /* ready claims */
Claim_list _ucl[Prio::MAX + 1]; /* unready claims */
Fill_list _fills { }; /* ready fills */
Share * const _idle;
Share * _head = nullptr;
unsigned _head_quota = 0;
bool _head_claims = false;
bool _head_yields = false;
unsigned const _quota;
unsigned _residual;
unsigned const _fill;
bool _need_to_schedule { true };
time_t _last_time { 0 };
Double_list<Cpu_share> _rcl[Prio::MAX + 1]; /* ready claims */
Double_list<Cpu_share> _ucl[Prio::MAX + 1]; /* unready claims */
Double_list<Cpu_share> _fills { }; /* ready fills */
Share &_idle;
Share *_head = nullptr;
unsigned _head_quota = 0;
bool _head_claims = false;
bool _head_yields = false;
unsigned const _quota;
unsigned _residual;
unsigned const _fill;
bool _need_to_schedule { true };
time_t _last_time { 0 };
template <typename F> void _for_each_prio(F f) {
for (signed p = Prio::MAX; p > Prio::MIN - 1; p--) { f(p); } }
template <typename T>
static Share * _share(T * const t) { return static_cast<Share *>(t); }
static void _reset(Claim * const c);
static void _reset(Cpu_share &share);
void _reset_claims(unsigned const p);
void _next_round();
void _consumed(unsigned const q);
void _set_head(Share * const s, unsigned const q, bool const c);
void _set_head(Share &s, unsigned const q, bool const c);
void _next_fill();
void _head_claimed(unsigned const r);
void _head_filled(unsigned const r);
bool _claim_for_head();
bool _fill_for_head();
unsigned _trim_consumption(unsigned & q);
unsigned _trim_consumption(unsigned &q);
/**
* Fill 's' becomes a claim due to a quota donation
*/
void _quota_introduction(Share * const s);
void _quota_introduction(Share &s);
/**
* Claim 's' looses its state as claim due to quota revokation
*/
void _quota_revokation(Share * const s);
void _quota_revokation(Share &s);
/**
* The quota of claim 's' changes to 'q'
*/
void _quota_adaption(Share * const s, unsigned const q);
void _quota_adaption(Share &s, unsigned const q);
public:
@ -179,7 +164,7 @@ class Kernel::Cpu_scheduler
* \param q total amount of time quota that can be claimed by shares
* \param f time-slice length of the fill round-robin
*/
Cpu_scheduler(Share * const i, unsigned const q, unsigned const f);
Cpu_scheduler(Share &i, unsigned const q, unsigned const f);
bool need_to_schedule() { return _need_to_schedule; }
void timeout() { _need_to_schedule = true; }
@ -192,17 +177,17 @@ class Kernel::Cpu_scheduler
/**
* Set 's1' ready and return wether this outdates current head
*/
bool ready_check(Share * const s1);
void ready_check(Share &s1);
/**
* Set share 's' ready
*/
void ready(Share * const s);
void ready(Share &s);
/**
* Set share 's' unready
*/
void unready(Share * const s);
void unready(Share &s);
/**
* Current head looses its current claim/fill for this round
@ -212,23 +197,23 @@ class Kernel::Cpu_scheduler
/**
* Remove share 's' from scheduler
*/
void remove(Share * const s);
void remove(Share &s);
/**
* Insert share 's' into scheduler
*/
void insert(Share * const s);
void insert(Share &s);
/**
* Set quota of share 's' to 'q'
*/
void quota(Share * const s, unsigned const q);
void quota(Share &s, unsigned const q);
/*
* Accessors
*/
Share * head() const { return _head; }
Share &head() const;
unsigned head_quota() const {
return Genode::min(_head_quota, _residual); }
unsigned quota() const { return _quota; }

View File

@ -1,86 +0,0 @@
/*
* \brief List of double connected items
* \author Martin Stein
* \date 2012-11-30
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* core includes */
#include <kernel/double_list.h>
using namespace Kernel;
void Double_list::_connect_neighbors(Item * const i)
{
i->_prev->_next = i->_next;
i->_next->_prev = i->_prev;
}
void Double_list::_to_tail(Item * const i)
{
if (i == _tail) { return; }
_connect_neighbors(i);
i->_prev = _tail;
i->_next = 0;
_tail->_next = i;
_tail = i;
}
Double_list::Double_list(): _head(0), _tail(0) { }
void Double_list::to_tail(Item * const i)
{
if (i == _head) { head_to_tail(); }
else { _to_tail(i); }
}
void Double_list::insert_tail(Item * const i)
{
if (_tail) { _tail->_next = i; }
else { _head = i; }
i->_prev = _tail;
i->_next = 0;
_tail = i;
}
void Double_list::insert_head(Item * const i)
{
if (_head) { _head->_prev = i; }
else { _tail = i; }
i->_next = _head;
i->_prev = 0;
_head = i;
}
void Double_list::remove(Item * const i)
{
if (i == _tail) { _tail = i->_prev; }
else { i->_next->_prev = i->_prev; }
if (i == _head) { _head = i->_next; }
else { i->_prev->_next = i->_next; }
}
void Double_list::head_to_tail()
{
if (!_head || _head == _tail) { return; }
_head->_prev = _tail;
_tail->_next = _head;
_head = _head->_next;
_head->_prev = 0;
_tail = _tail->_next;
_tail->_next = 0;
}

View File

@ -19,78 +19,130 @@ namespace Kernel
/**
* Ability to be an item in a double connected list
*/
template <typename T>
class Double_list_item;
/**
* List of double connected items
*/
template <typename T>
class Double_list;
/**
* Double list over objects of type 'T' that inherits from double-list item
*/
template <typename T> class Double_list_typed;
}
template <typename T>
class Kernel::Double_list_item
{
friend class Double_list;
friend class Double_list<T>;
private:
Double_list_item * _next = nullptr;
Double_list_item * _prev = nullptr;
T & _payload;
public:
Double_list_item(T &payload) : _payload(payload) { }
T &payload() { return _payload; }
};
template <typename T>
class Kernel::Double_list
{
private:
typedef Double_list_item Item;
typedef Double_list_item<T> Item;
Item * _head;
Item * _tail;
void _connect_neighbors(Item * const i);
void _to_tail(Item * const i);
void _connect_neighbors(Item * const i)
{
i->_prev->_next = i->_next;
i->_next->_prev = i->_prev;
}
void _to_tail(Item * const i)
{
if (i == _tail) { return; }
_connect_neighbors(i);
i->_prev = _tail;
i->_next = 0;
_tail->_next = i;
_tail = i;
}
public:
/**
* Construct empty list
*/
Double_list();
Double_list() : _head(0), _tail(0) { }
/**
* Move item 'i' from its current list position to the tail
*/
void to_tail(Item * const i);
void to_tail(Item * const i)
{
if (i == _head) { head_to_tail(); }
else { _to_tail(i); }
}
/**
* Insert item 'i' as new tail into list
*/
void insert_tail(Item * const i);
void insert_tail(Item * const i)
{
if (_tail) { _tail->_next = i; }
else { _head = i; }
i->_prev = _tail;
i->_next = 0;
_tail = i;
}
/**
* Insert item 'i' as new head into list
*/
void insert_head(Item * const i);
void insert_head(Item * const i)
{
if (_head) { _head->_prev = i; }
else { _tail = i; }
i->_next = _head;
i->_prev = 0;
_head = i;
}
/**
* Remove item 'i' from list
*/
void remove(Item * const i);
void remove(Item * const i)
{
if (i == _tail) { _tail = i->_prev; }
else { i->_next->_prev = i->_prev; }
if (i == _head) { _head = i->_next; }
else { i->_prev->_next = i->_next; }
}
/**
* Move head item of list to tail position
*/
void head_to_tail();
void head_to_tail()
{
if (!_head || _head == _tail) { return; }
_head->_prev = _tail;
_tail->_next = _head;
_head = _head->_next;
_head->_prev = 0;
_tail = _tail->_next;
_tail->_next = 0;
}
/**
* Call function 'f' of type 'void (Item *)' for each item in the list
*/
template <typename F> void for_each(F f) {
for (Item * i = _head; i; i = i->_next) { f(i); } }
for (Item * i = _head; i; i = i->_next) { f(i->payload()); } }
/*
* Accessors
@ -100,30 +152,4 @@ class Kernel::Double_list
static Item * next(Item * const i) { return i->_next; }
};
template <typename T> class Kernel::Double_list_typed : public Double_list
{
private:
typedef Double_list_item Item;
static T * _typed(Item * const i) {
return i ? static_cast<T *>(i) : 0; }
public:
/*
* 'Double_list' interface
*/
template <typename F> void for_each(F f) {
Double_list::for_each([&] (Item * const i) { f(_typed(i)); }); }
void to_tail(T * const t) { Double_list::to_tail(t); }
void insert_tail(T * const t) { Double_list::insert_tail(t); }
void insert_head(T * const t) { Double_list::insert_head(t); }
void remove(T * const t) { Double_list::remove(t); }
static T * next(T * const t) { return _typed(Double_list::next(t)); }
T * head() const { return _typed(Double_list::head()); }
};
#endif /* _CORE__KERNEL__DOUBLE_LIST_H_ */

View File

@ -19,74 +19,16 @@
#include <base/internal/native_utcb.h>
/* core includes */
#include <platform_pd.h>
#include <kernel/ipc_node.h>
#include <kernel/pd.h>
#include <kernel/kernel.h>
#include <kernel/thread.h>
using namespace Kernel;
static inline void free_obj_id_ref(Pd &pd, void *ptr)
{
pd.platform_pd().capability_slab().free(ptr, sizeof(Object_identity_reference));
}
void Ipc_node::copy_msg(Ipc_node &sender)
{
using namespace Genode;
using Reference = Object_identity_reference;
/* copy payload and set destination capability id */
*_utcb = *sender._utcb;
_utcb->destination(sender._capid);
/* translate capabilities */
for (unsigned i = 0; i < _rcv_caps; i++) {
capid_t id = sender._utcb->cap_get(i);
/* if there is no capability to send, just free the pre-allocation */
if (i >= sender._utcb->cap_cnt()) {
free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
continue;
}
/* lookup the capability id within the caller's cap space */
Reference *oir = (id == cap_id_invalid())
? nullptr : sender.pd().cap_tree().find(id);
/* if the caller's capability is invalid, free the pre-allocation */
if (!oir) {
_utcb->cap_add(cap_id_invalid());
free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
continue;
}
/* lookup the capability id within the callee's cap space */
Reference *dst_oir = oir->find(pd());
/* if it is not found, and the target is not core, create a reference */
if (!dst_oir && (&pd() != &core_pd())) {
dst_oir = oir->factory(_obj_id_ref_ptr[i], pd());
if (!dst_oir)
free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
} else /* otherwise free the pre-allocation */
free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
if (dst_oir) dst_oir->add_to_utcb();
/* add the translated capability id to the target buffer */
_utcb->cap_add(dst_oir ? dst_oir->capid() : cap_id_invalid());
}
}
void Ipc_node::_receive_request(Ipc_node &caller)
{
copy_msg(caller);
_thread.ipc_copy_msg(caller._thread);
_caller = &caller;
_state = INACTIVE;
}
@ -94,9 +36,9 @@ void Ipc_node::_receive_request(Ipc_node &caller)
void Ipc_node::_receive_reply(Ipc_node &callee)
{
copy_msg(callee);
_thread.ipc_copy_msg(callee._thread);
_state = INACTIVE;
_send_request_succeeded();
_thread.ipc_send_request_succeeded();
}
@ -105,19 +47,21 @@ void Ipc_node::_announce_request(Ipc_node &node)
/* directly receive request if we've awaited it */
if (_state == AWAIT_REQUEST) {
_receive_request(node);
_await_request_succeeded();
_thread.ipc_await_request_succeeded();
return;
}
/* cannot receive yet, so queue request */
_request_queue.enqueue(node);
_request_queue.enqueue(node._request_queue_item);
}
void Ipc_node::_cancel_request_queue()
{
_request_queue.dequeue_all([] (Ipc_node &node) {
node._outbuf_request_cancelled(); });
_request_queue.dequeue_all([] (Queue_item &item) {
Ipc_node &node { item.object() };
node._outbuf_request_cancelled();
});
}
@ -142,7 +86,7 @@ void Ipc_node::_cancel_inbuf_request()
void Ipc_node::_announced_request_cancelled(Ipc_node &node)
{
if (_caller == &node) _caller = nullptr;
else _request_queue.remove(node);
else _request_queue.remove(node._request_queue_item);
}
@ -152,40 +96,24 @@ void Ipc_node::_outbuf_request_cancelled()
_callee = nullptr;
_state = INACTIVE;
_send_request_failed();
_thread.ipc_send_request_failed();
}
bool Ipc_node::_helps_outbuf_dst() { return (_state == AWAIT_REPLY) && _help; }
void Ipc_node::_init(Genode::Native_utcb &utcb, Ipc_node &starter)
bool Ipc_node::can_send_request()
{
_utcb = &utcb;
_rcv_caps = starter._utcb->cap_cnt();
Genode::Allocator &slab = pd().platform_pd().capability_slab();
for (unsigned i = 0; i < _rcv_caps; i++)
_obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
copy_msg(starter);
return _state == INACTIVE;
}
void Ipc_node::send_request(Ipc_node &callee, capid_t capid, bool help,
unsigned rcv_caps)
void Ipc_node::send_request(Ipc_node &callee, bool help)
{
if (_state != INACTIVE) {
Genode::raw("IPC send request: bad state");
return;
}
Genode::Allocator &slab = pd().platform_pd().capability_slab();
for (unsigned i = 0; i < rcv_caps; i++)
_obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
_state = AWAIT_REPLY;
_callee = &callee;
_capid = capid;
_help = false;
_rcv_caps = rcv_caps;
/* announce request */
_callee->_announce_request(*this);
@ -194,32 +122,22 @@ void Ipc_node::send_request(Ipc_node &callee, capid_t capid, bool help,
}
Ipc_node * Ipc_node::helping_sink() {
return _helps_outbuf_dst() ? _callee->helping_sink() : this; }
Thread &Ipc_node::helping_sink() {
return _helps_outbuf_dst() ? _callee->helping_sink() : _thread; }
bool Ipc_node::await_request(unsigned rcv_caps)
bool Ipc_node::can_await_request()
{
if (_state != INACTIVE) {
Genode::raw("IPC await request: bad state");
return true;
}
Genode::Allocator &slab = pd().platform_pd().capability_slab();
for (unsigned i = 0; i < rcv_caps; i++)
_obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
return _state == INACTIVE;
}
_rcv_caps = rcv_caps;
/* if no request announced then wait */
bool announced = false;
void Ipc_node::await_request()
{
_state = AWAIT_REQUEST;
/* if anybody already announced a request receive it */
_request_queue.dequeue([&] (Ipc_node &ipc) {
_receive_request(ipc);
announced = true;
_request_queue.dequeue([&] (Queue_item &item) {
_receive_request(item.object());
});
return announced;
}
@ -239,11 +157,11 @@ void Ipc_node::cancel_waiting()
case AWAIT_REPLY:
_cancel_outbuf_request();
_state = INACTIVE;
_send_request_failed();
_thread.ipc_send_request_failed();
break;
case AWAIT_REQUEST:
_state = INACTIVE;
_await_request_failed();
_thread.ipc_await_request_failed();
break;
return;
default: return;
@ -251,6 +169,12 @@ void Ipc_node::cancel_waiting()
}
Ipc_node::Ipc_node(Thread &thread)
:
_thread(thread)
{ }
Ipc_node::~Ipc_node()
{
_cancel_request_queue();

View File

@ -15,30 +15,25 @@
#ifndef _CORE__KERNEL__IPC_NODE_H_
#define _CORE__KERNEL__IPC_NODE_H_
/* base-local includes */
#include <base/internal/native_utcb.h>
/* core includes */
#include <kernel/interface.h>
#include <assertion.h>
namespace Genode { class Msgbuf_base; };
/* Genode includes */
#include <util/fifo.h>
namespace Kernel
{
class Pd;
class Thread;
/**
* Backend for end points of synchronous interprocess communication
*/
class Ipc_node;
using Ipc_node_queue = Genode::Fifo<Ipc_node>;
}
class Kernel::Ipc_node : private Ipc_node_queue::Element
class Kernel::Ipc_node
{
protected:
private:
using Queue_item = Genode::Fifo_element<Ipc_node>;
using Queue = Genode::Fifo<Queue_item>;
enum State
{
@ -47,26 +42,13 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
AWAIT_REQUEST = 3,
};
void _init(Genode::Native_utcb &utcb, Ipc_node &callee);
private:
friend class Core_thread;
friend class Genode::Fifo<Ipc_node>;
State _state = INACTIVE;
capid_t _capid = cap_id_invalid();
Ipc_node * _caller = nullptr;
Ipc_node * _callee = nullptr;
bool _help = false;
size_t _rcv_caps = 0; /* max capability num to receive */
Genode::Native_utcb * _utcb = nullptr;
Ipc_node_queue _request_queue { };
/* pre-allocation array for obkject identity references */
void * _obj_id_ref_ptr[Genode::Msgbuf_base::MAX_CAPS_PER_MSG];
inline void copy_msg(Ipc_node &sender);
Thread &_thread;
Queue_item _request_queue_item { *this };
State _state { INACTIVE };
Ipc_node *_caller { nullptr };
Ipc_node *_callee { nullptr };
bool _help { false };
Queue _request_queue { };
/**
* Buffer next request from request queue in 'r' to handle it
@ -114,40 +96,26 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
bool _helps_outbuf_dst();
/**
* IPC node returned from waiting due to reply receipt
* Make the class noncopyable because it has pointer members
*/
virtual void _send_request_succeeded() = 0;
Ipc_node(const Ipc_node&) = delete;
/**
* IPC node returned from waiting due to reply cancellation
* Make the class noncopyable because it has pointer members
*/
virtual void _send_request_failed() = 0;
/**
* IPC node returned from waiting due to request receipt
*/
virtual void _await_request_succeeded() = 0;
/**
* IPC node returned from waiting due to request cancellation
*/
virtual void _await_request_failed() = 0;
protected:
Pd * _pd = nullptr; /* pointer to PD this IPC node is part of */
/***************
** Accessors **
***************/
Ipc_node * callee() { return _callee; }
State state() { return _state; }
const Ipc_node& operator=(const Ipc_node&) = delete;
public:
virtual ~Ipc_node();
/**
* Destructor
*/
~Ipc_node();
/**
* Constructor
*/
Ipc_node(Thread &thread);
/**
* Send a request and wait for the according reply
@ -155,13 +123,14 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
* \param callee targeted IPC node
* \param help wether the request implies a helping relationship
*/
void send_request(Ipc_node &callee, capid_t capid, bool help,
unsigned rcv_caps);
bool can_send_request();
void send_request(Ipc_node &callee,
bool help);
/**
* Return root destination of the helping-relation tree we are in
*/
Ipc_node * helping_sink();
Thread &helping_sink();
/**
* Call function 'f' of type 'void (Ipc_node *)' for each helper
@ -169,11 +138,13 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
template <typename F> void for_each_helper(F f)
{
/* if we have a helper in the receive buffer, call 'f' for it */
if (_caller && _caller->_help) f(*_caller);
if (_caller && _caller->_help) f(_caller->_thread);
/* call 'f' for each helper in our request queue */
_request_queue.for_each([f] (Ipc_node &node) {
if (node._help) f(node); });
_request_queue.for_each([f] (Queue_item &item) {
Ipc_node &node { item.object() };
if (node._help) f(node._thread);
});
}
/**
@ -181,7 +152,8 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
*
* \return wether a request could be received already
*/
bool await_request(unsigned rcv_caps);
bool can_await_request();
void await_request();
/**
* Reply to last request if there's any
@ -193,20 +165,7 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
*/
void cancel_waiting();
/***************
** Accessors **
***************/
Pd &pd() const
{
if (_pd)
return *_pd;
ASSERT_NEVER_CALLED;
}
Genode::Native_utcb *utcb() { return _utcb; }
bool awaits_request() const { return _state == AWAIT_REQUEST; }
};
#endif /* _CORE__KERNEL__IPC_NODE_H_ */

View File

@ -119,10 +119,11 @@ class Kernel::Irq : Genode::Avl_node<Irq>
};
class Kernel::User_irq : public Kernel::Irq, public Kernel::Object
class Kernel::User_irq : public Kernel::Irq
{
private:
Kernel::Object _kernel_object { *this };
Signal_context &_context;
/**
@ -150,7 +151,9 @@ class Kernel::User_irq : public Kernel::Irq, public Kernel::Object
*/
void occurred() override
{
_context.submit(1);
if (_context.can_submit(1)) {
_context.submit(1);
}
disable();
}
@ -186,6 +189,8 @@ class Kernel::User_irq : public Kernel::Irq, public Kernel::Object
*/
static void syscall_destroy(Genode::Kernel_object<User_irq> &irq) {
call(call_id_delete_irq(), (Call_arg) &irq); }
Object &kernel_object() { return _kernel_object; }
};
#endif /* _CORE__KERNEL__IRQ_H_ */

View File

@ -11,12 +11,99 @@ using namespace Kernel;
** Object **
************/
Object::Object(Thread &obj)
:
_type { THREAD },
_obj { (void *)&obj }
{ }
Object::Object(Irq &obj)
:
_type { IRQ },
_obj { (void *)&obj }
{ }
Object::Object(Signal_receiver &obj)
:
_type { SIGNAL_RECEIVER },
_obj { (void *)&obj }
{ }
Object::Object(Signal_context &obj)
:
_type { SIGNAL_CONTEXT },
_obj { (void *)&obj }
{ }
Object::Object(Pd &obj)
:
_type { PD },
_obj { (void *)&obj }
{ }
Object::Object(Vm &obj)
:
_type { VM },
_obj { (void *)&obj }
{ }
Object::~Object()
{
for (Object_identity * oi = first(); oi; oi = first())
oi->invalidate();
}
namespace Kernel {
template <> Pd *Object::obj<Pd>() const
{
if (_type != PD) {
return nullptr; }
return reinterpret_cast<Pd *>(_obj);
}
template <> Irq *Object::obj<Irq>() const
{
if (_type != IRQ) {
return nullptr; }
return reinterpret_cast<Irq *>(_obj);
}
template <> Signal_receiver *Object::obj<Signal_receiver>() const
{
if (_type != SIGNAL_RECEIVER) {
return nullptr; }
return reinterpret_cast<Signal_receiver *>(_obj);
}
template <> Signal_context *Object::obj<Signal_context>() const
{
if (_type != SIGNAL_CONTEXT) {
return nullptr; }
return reinterpret_cast<Signal_context *>(_obj);
}
template <> Thread *Object::obj<Thread>() const
{
if (_type != THREAD) {
return nullptr; }
return reinterpret_cast<Thread *>(_obj);
}
template <> Vm *Object::obj<Vm>() const
{
if (_type != VM) {
return nullptr; }
return reinterpret_cast<Vm *>(_obj);
}
}
/*********************
** Object_identity **

View File

@ -27,7 +27,16 @@
namespace Kernel
{
class Pd; /* forward declaration */
/*
* Forward declarations
*/
class Pd;
class Irq;
class Thread;
class Signal_context;
class Signal_receiver;
class Vm;
/**
* Base class of all Kernel objects
@ -73,12 +82,39 @@ namespace Kernel
}
struct Kernel::Object : private Object_identity_list
class Kernel::Object : private Object_identity_list
{
using Object_identity_list::remove;
using Object_identity_list::insert;
private:
virtual ~Object();
enum Type { THREAD, PD, SIGNAL_RECEIVER, SIGNAL_CONTEXT, IRQ, VM };
/*
* Noncopyable
*/
Object(Object const &) = delete;
Object &operator = (Object const &) = delete;
Type const _type;
void *const _obj;
public:
struct Cannot_cast_to_type : Genode::Exception { };
using Object_identity_list::remove;
using Object_identity_list::insert;
Object(Thread &obj);
Object(Irq &obj);
Object(Signal_receiver &obj);
Object(Signal_context &obj);
Object(Pd &obj);
Object(Vm &obj);
~Object();
template <typename T>
T *obj() const;
};
@ -102,7 +138,7 @@ class Kernel::Object_identity
~Object_identity();
template <typename KOBJECT>
KOBJECT * object() { return dynamic_cast<KOBJECT*>(_object); }
KOBJECT * object() { return _object->obj<KOBJECT>(); }
void invalidate();
};
@ -190,7 +226,7 @@ class Kernel::Core_object_identity : public Object_identity,
public:
Core_object_identity(T & object)
: Object_identity(object),
: Object_identity(object.kernel_object()),
Object_identity_reference(this, core_pd()) { }
capid_t core_capid() { return capid(); }

View File

@ -39,7 +39,7 @@ namespace Kernel
}
class Kernel::Pd : public Kernel::Object
class Kernel::Pd
{
public:
@ -49,6 +49,7 @@ class Kernel::Pd : public Kernel::Object
private:
Kernel::Object _kernel_object { *this };
Hw::Page_table &_table;
Genode::Platform_pd &_platform_pd;
Capid_allocator _capid_alloc { };
@ -108,6 +109,7 @@ class Kernel::Pd : public Kernel::Object
** Accessors **
***************/
Object &kernel_object() { return _kernel_object; }
Genode::Platform_pd &platform_pd() { return _platform_pd; }
Hw::Page_table &translation_table() { return _table; }
Capid_allocator &capid_alloc() { return _capid_alloc; }
@ -118,7 +120,7 @@ class Kernel::Pd : public Kernel::Object
template<>
inline Kernel::Core_object_identity<Kernel::Pd>::Core_object_identity(Kernel::Pd & pd)
: Object_identity(pd),
: Object_identity(pd.kernel_object()),
Object_identity_reference(this, pd.core_pd() ? pd : core_pd()) { }
#endif /* _CORE__KERNEL__PD_H_ */

View File

@ -13,6 +13,7 @@
/* core includes */
#include <kernel/signal_receiver.h>
#include <kernel/thread.h>
using namespace Kernel;
@ -24,12 +25,14 @@ using namespace Kernel;
void Signal_handler::cancel_waiting()
{
if (_receiver) {
_receiver->_handler_cancelled(this);
_receiver->_handler_cancelled(*this);
_receiver = 0;
}
}
Signal_handler::Signal_handler(Thread &thread) : _thread { thread } { }
Signal_handler::~Signal_handler() { cancel_waiting(); }
@ -43,7 +46,10 @@ void Signal_context_killer::cancel_waiting()
}
Signal_context_killer::Signal_context_killer() : _context(nullptr) { }
Signal_context_killer::Signal_context_killer(Thread &thread)
:
_thread { thread }
{ }
Signal_context_killer::~Signal_context_killer() { cancel_waiting(); }
@ -55,7 +61,7 @@ Signal_context_killer::~Signal_context_killer() { cancel_waiting(); }
void Signal_context::_deliverable()
{
if (_submits) { _receiver._add_deliverable(this); }
if (_submits) { _receiver._add_deliverable(*this); }
}
@ -69,12 +75,18 @@ void Signal_context::_delivered()
void Signal_context::_killer_cancelled() { _killer = 0; }
int Signal_context::submit(unsigned const n)
bool Signal_context::can_submit(unsigned const n) const
{
if (_killed || _submits >= (unsigned)~0 - n) { return -1; }
if (_killed || _submits >= (unsigned)~0 - n) { return false; }
return true;
}
void Signal_context::submit(unsigned const n)
{
if (_killed || _submits >= (unsigned)~0 - n) { return; }
_submits += n;
if (_ack) { _deliverable(); }
return 0;
}
@ -88,37 +100,46 @@ void Signal_context::ack()
}
if (_killer) {
_killer->_context = 0;
_killer->_signal_context_kill_done();
_killer->_thread.signal_context_kill_done();
_killer = 0;
}
}
int Signal_context::kill(Signal_context_killer * const k)
bool Signal_context::can_kill() const
{
/* check if in a kill operation or already killed */
if (_killed) {
if (_ack) { return 0; }
return -1;
if (_ack) { return true; }
return false;
}
return true;
}
void Signal_context::kill(Signal_context_killer &k)
{
/* check if in a kill operation or already killed */
if (_killed) {
return;
}
/* kill directly if there is no unacknowledged delivery */
if (_ack) {
_killed = 1;
return 0;
return;
}
/* wait for delivery acknowledgement */
_killer = k;
_killer = &k;
_killed = 1;
_killer->_context = this;
_killer->_signal_context_kill_pending();
return 0;
_killer->_thread.signal_context_kill_pending();
}
Signal_context::~Signal_context()
{
if (_killer) { _killer->_signal_context_kill_failed(); }
_receiver._context_destructed(this);
if (_killer) { _killer->_thread.signal_context_kill_failed(); }
_receiver._context_destructed(*this);
}
@ -126,7 +147,7 @@ Signal_context::Signal_context(Signal_receiver & r, addr_t const imprint)
: _receiver(r),
_imprint(imprint)
{
r._add_context(this);
r._add_context(*this);
}
@ -134,10 +155,10 @@ Signal_context::Signal_context(Signal_receiver & r, addr_t const imprint)
** Signal_receiver **
*********************/
void Signal_receiver::_add_deliverable(Signal_context * const c)
void Signal_receiver::_add_deliverable(Signal_context &c)
{
if (!c->_deliver_fe.enqueued()) {
_deliver.enqueue(c->_deliver_fe);
if (!c._deliver_fe.enqueued()) {
_deliver.enqueue(c._deliver_fe);
}
_listen();
}
@ -164,7 +185,7 @@ void Signal_receiver::_listen()
_handlers.dequeue([&] (Signal_handler::Fifo_element &elem) {
auto const handler = &elem.object();
handler->_receiver = nullptr;
handler->_receive_signal(&data, sizeof(data));
handler->_thread.signal_receive_signal(&data, sizeof(data));
});
context->_delivered();
});
@ -172,30 +193,36 @@ void Signal_receiver::_listen()
}
void Signal_receiver::_context_destructed(Signal_context * const c)
void Signal_receiver::_context_destructed(Signal_context &c)
{
_contexts.remove(c->_contexts_fe);
if (!c->_deliver_fe.enqueued()) { return; }
_deliver.remove(c->_deliver_fe);
_contexts.remove(c._contexts_fe);
if (!c._deliver_fe.enqueued()) { return; }
_deliver.remove(c._deliver_fe);
}
void Signal_receiver::_handler_cancelled(Signal_handler * const h) {
_handlers.remove(h->_handlers_fe); }
void Signal_receiver::_handler_cancelled(Signal_handler &h) {
_handlers.remove(h._handlers_fe); }
void Signal_receiver::_add_context(Signal_context * const c) {
_contexts.enqueue(c->_contexts_fe); }
void Signal_receiver::_add_context(Signal_context &c) {
_contexts.enqueue(c._contexts_fe); }
int Signal_receiver::add_handler(Signal_handler * const h)
bool Signal_receiver::can_add_handler(Signal_handler const &h) const
{
if (h->_receiver) { return -1; }
_handlers.enqueue(h->_handlers_fe);
h->_receiver = this;
h->_await_signal(this);
if (h._receiver) { return false; }
return true;
}
void Signal_receiver::add_handler(Signal_handler &h)
{
if (h._receiver) { return; }
_handlers.enqueue(h._handlers_fe);
h._receiver = this;
h._thread.signal_wait_for_signal();
_listen();
return 0;
}

View File

@ -23,6 +23,8 @@
namespace Kernel
{
class Thread;
/**
* Ability to receive signals from signal receivers
*/
@ -59,36 +61,15 @@ class Kernel::Signal_handler
typedef Genode::Fifo_element<Signal_handler> Fifo_element;
Fifo_element _handlers_fe { *this };
Signal_receiver * _receiver { nullptr };
/**
* Let the handler block for signal receipt
*
* \param receiver the signal pool that the thread blocks for
*/
virtual void _await_signal(Signal_receiver * const receiver) = 0;
/**
* Signal delivery backend
*
* \param base signal-data base
* \param size signal-data size
*/
virtual void _receive_signal(void * const base, size_t const size) = 0;
protected:
/***************
** Accessors **
***************/
Signal_receiver * receiver() const { return _receiver; }
Thread &_thread;
Fifo_element _handlers_fe { *this };
Signal_receiver *_receiver { nullptr };
public:
Signal_handler() { }
virtual ~Signal_handler();
Signal_handler(Thread &thread);
~Signal_handler();
/**
* Stop waiting for a signal receiver
@ -108,35 +89,14 @@ class Kernel::Signal_context_killer
Signal_context_killer(Signal_context_killer const &);
Signal_context_killer &operator = (Signal_context_killer const &);
Signal_context * _context;
/**
* Notice that the kill operation is pending
*/
virtual void _signal_context_kill_pending() = 0;
/**
* Notice that pending kill operation is done
*/
virtual void _signal_context_kill_done() = 0;
/**
* Notice that pending kill operation failed
*/
virtual void _signal_context_kill_failed() = 0;
protected:
/***************
** Accessors **
***************/
Signal_context * context() const { return _context; }
Thread &_thread;
Signal_context *_context { nullptr };
public:
Signal_context_killer();
virtual ~Signal_context_killer();
Signal_context_killer(Thread &thread);
~Signal_context_killer();
/**
* Stop waiting for a signal context
@ -144,7 +104,7 @@ class Kernel::Signal_context_killer
void cancel_waiting();
};
class Kernel::Signal_context : public Kernel::Object
class Kernel::Signal_context
{
friend class Signal_receiver;
friend class Signal_context_killer;
@ -159,14 +119,15 @@ class Kernel::Signal_context : public Kernel::Object
typedef Genode::Fifo_element<Signal_context> Fifo_element;
Fifo_element _deliver_fe { *this };
Fifo_element _contexts_fe { *this };
Kernel::Object _kernel_object { *this };
Fifo_element _deliver_fe { *this };
Fifo_element _contexts_fe { *this };
Signal_receiver & _receiver;
addr_t const _imprint;
Signal_context_killer * _killer { nullptr };
unsigned _submits { 0 };
bool _ack { true };
bool _killed { false };
Signal_context_killer * _killer { nullptr };
unsigned _submits { 0 };
bool _ack { true };
bool _killed { false };
/**
* Tell receiver about the submits of the context if any
@ -208,7 +169,8 @@ class Kernel::Signal_context : public Kernel::Object
* \retval 0 succeeded
* \retval -1 failed
*/
int submit(unsigned const n);
bool can_submit(unsigned const n) const;
void submit(unsigned const n);
/**
* Acknowledge delivery of signal
@ -223,7 +185,8 @@ class Kernel::Signal_context : public Kernel::Object
* \retval 0 succeeded
* \retval -1 failed
*/
int kill(Signal_context_killer * const k);
bool can_kill() const;
void kill(Signal_context_killer &k);
/**
* Create a signal context and assign it to a signal receiver
@ -249,9 +212,11 @@ class Kernel::Signal_context : public Kernel::Object
*/
static void syscall_destroy(Genode::Kernel_object<Signal_context> &c) {
call(call_id_delete_signal_context(), (Call_arg)&c); }
Object &kernel_object() { return _kernel_object; }
};
class Kernel::Signal_receiver : public Kernel::Object
class Kernel::Signal_receiver
{
friend class Signal_context;
friend class Signal_handler;
@ -262,14 +227,15 @@ class Kernel::Signal_receiver : public Kernel::Object
template <typename T> class Fifo : public Genode::Fifo<T> { };
Fifo<Signal_handler::Fifo_element> _handlers { };
Fifo<Signal_context::Fifo_element> _deliver { };
Fifo<Signal_context::Fifo_element> _contexts { };
Kernel::Object _kernel_object { *this };
Fifo<Signal_handler::Fifo_element> _handlers { };
Fifo<Signal_context::Fifo_element> _deliver { };
Fifo<Signal_context::Fifo_element> _contexts { };
/**
* Recognize that context 'c' has submits to deliver
*/
void _add_deliverable(Signal_context * const c);
void _add_deliverable(Signal_context &c);
/**
* Deliver as much submits as possible
@ -281,17 +247,17 @@ class Kernel::Signal_receiver : public Kernel::Object
*
* \param c destructed context
*/
void _context_destructed(Signal_context * const c);
void _context_destructed(Signal_context &c);
/**
* Notice that handler 'h' has cancelled waiting
*/
void _handler_cancelled(Signal_handler * const h);
void _handler_cancelled(Signal_handler &h);
/**
* Assign context 'c' to the receiver
*/
void _add_context(Signal_context * const c);
void _add_context(Signal_context &c);
public:
@ -303,7 +269,8 @@ class Kernel::Signal_receiver : public Kernel::Object
* \retval 0 succeeded
* \retval -1 failed
*/
int add_handler(Signal_handler * const h);
bool can_add_handler(Signal_handler const &h) const;
void add_handler(Signal_handler &h);
/**
* Syscall to create a signal receiver
@ -322,6 +289,8 @@ class Kernel::Signal_receiver : public Kernel::Object
*/
static void syscall_destroy(Genode::Kernel_object<Signal_receiver> &r) {
call(call_id_delete_signal_receiver(), (Call_arg)&r); }
Object &kernel_object() { return _kernel_object; }
};
#endif /* _CORE__KERNEL__SIGNAL_RECEIVER_H_ */

View File

@ -36,6 +36,81 @@ extern "C" void _core_start(void);
using namespace Kernel;
void Thread::_ipc_alloc_recv_caps(unsigned cap_count)
{
Genode::Allocator &slab = pd().platform_pd().capability_slab();
for (unsigned i = 0; i < cap_count; i++) {
if (_obj_id_ref_ptr[i] == nullptr)
_obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
}
_ipc_rcv_caps = cap_count;
}
void Thread::_ipc_free_recv_caps()
{
for (unsigned i = 0; i < _ipc_rcv_caps; i++) {
if (_obj_id_ref_ptr[i]) {
Genode::Allocator &slab = pd().platform_pd().capability_slab();
slab.free(_obj_id_ref_ptr[i], sizeof(Object_identity_reference));
}
}
_ipc_rcv_caps = 0;
}
void Thread::_ipc_init(Genode::Native_utcb &utcb, Thread &starter)
{
_utcb = &utcb;
_ipc_alloc_recv_caps(starter._utcb->cap_cnt());
ipc_copy_msg(starter);
}
void Thread::ipc_copy_msg(Thread &sender)
{
using namespace Genode;
using Reference = Object_identity_reference;
/* copy payload and set destination capability id */
*_utcb = *sender._utcb;
_utcb->destination(sender._ipc_capid);
/* translate capabilities */
for (unsigned i = 0; i < _ipc_rcv_caps; i++) {
capid_t id = sender._utcb->cap_get(i);
/* if there is no capability to send, nothing to do */
if (i >= sender._utcb->cap_cnt()) { continue; }
/* lookup the capability id within the caller's cap space */
Reference *oir = (id == cap_id_invalid())
? nullptr : sender.pd().cap_tree().find(id);
/* if the caller's capability is invalid, continue */
if (!oir) {
_utcb->cap_add(cap_id_invalid());
continue;
}
/* lookup the capability id within the callee's cap space */
Reference *dst_oir = oir->find(pd());
/* if it is not found, and the target is not core, create a reference */
if (!dst_oir && (&pd() != &core_pd())) {
dst_oir = oir->factory(_obj_id_ref_ptr[i], pd());
if (dst_oir) _obj_id_ref_ptr[i] = nullptr;
}
if (dst_oir) dst_oir->add_to_utcb();
/* add the translated capability id to the target buffer */
_utcb->cap_add(dst_oir ? dst_oir->capid() : cap_id_invalid());
}
}
Thread::Tlb_invalidation::Tlb_invalidation(Thread & caller, Pd & pd,
addr_t addr, size_t size,
unsigned cnt)
@ -76,14 +151,14 @@ void Thread_fault::print(Genode::Output &out) const
}
void Thread::_signal_context_kill_pending()
void Thread::signal_context_kill_pending()
{
assert(_state == ACTIVE);
_become_inactive(AWAITS_SIGNAL_CONTEXT_KILL);
}
void Thread::_signal_context_kill_done()
void Thread::signal_context_kill_done()
{
assert(_state == AWAITS_SIGNAL_CONTEXT_KILL);
user_arg_0(0);
@ -91,7 +166,7 @@ void Thread::_signal_context_kill_done()
}
void Thread::_signal_context_kill_failed()
void Thread::signal_context_kill_failed()
{
assert(_state == AWAITS_SIGNAL_CONTEXT_KILL);
user_arg_0(-1);
@ -99,14 +174,13 @@ void Thread::_signal_context_kill_failed()
}
void Thread::_await_signal(Signal_receiver * const receiver)
void Thread::signal_wait_for_signal()
{
_become_inactive(AWAITS_SIGNAL);
_signal_receiver = receiver;
}
void Thread::_receive_signal(void * const base, size_t const size)
void Thread::signal_receive_signal(void * const base, size_t const size)
{
assert(_state == AWAITS_SIGNAL);
Genode::memcpy(utcb()->data(), base, size);
@ -114,7 +188,7 @@ void Thread::_receive_signal(void * const base, size_t const size)
}
void Thread::_send_request_succeeded()
void Thread::ipc_send_request_succeeded()
{
assert(_state == AWAITS_IPC);
user_arg_0(0);
@ -123,7 +197,7 @@ void Thread::_send_request_succeeded()
}
void Thread::_send_request_failed()
void Thread::ipc_send_request_failed()
{
assert(_state == AWAITS_IPC);
user_arg_0(-1);
@ -132,7 +206,7 @@ void Thread::_send_request_failed()
}
void Thread::_await_request_succeeded()
void Thread::ipc_await_request_succeeded()
{
assert(_state == AWAITS_IPC);
user_arg_0(0);
@ -140,7 +214,7 @@ void Thread::_await_request_succeeded()
}
void Thread::_await_request_failed()
void Thread::ipc_await_request_failed()
{
assert(_state == AWAITS_IPC);
user_arg_0(-1);
@ -151,15 +225,15 @@ void Thread::_await_request_failed()
void Thread::_deactivate_used_shares()
{
Cpu_job::_deactivate_own_share();
Ipc_node::for_each_helper([&] (Ipc_node &h) {
static_cast<Thread &>(h)._deactivate_used_shares(); });
_ipc_node.for_each_helper([&] (Thread &thread) {
thread._deactivate_used_shares(); });
}
void Thread::_activate_used_shares()
{
Cpu_job::_activate_own_share();
Ipc_node::for_each_helper([&] (Ipc_node &h) {
static_cast<Thread &>(h)._activate_used_shares(); });
_ipc_node.for_each_helper([&] (Thread &thread) {
thread._activate_used_shares(); });
}
void Thread::_become_active()
@ -180,7 +254,7 @@ void Thread::_die() { _become_inactive(DEAD); }
Cpu_job * Thread::helping_sink() {
return static_cast<Thread *>(Ipc_node::helping_sink()); }
return &_ipc_node.helping_sink(); }
size_t Thread::_core_to_kernel_quota(size_t const quota) const
@ -212,7 +286,7 @@ void Thread::_call_start_thread()
/* join protection domain */
thread._pd = (Pd *) user_arg_3();
thread.Ipc_node::_init(*(Native_utcb *)user_arg_4(), *this);
thread._ipc_init(*(Native_utcb *)user_arg_4(), *this);
thread._become_active();
}
@ -285,15 +359,15 @@ void Thread::_cancel_blocking()
_become_active();
return;
case AWAITS_IPC:
Ipc_node::cancel_waiting();
_ipc_node.cancel_waiting();
return;
case AWAITS_SIGNAL:
Signal_handler::cancel_waiting();
_signal_handler.cancel_waiting();
user_arg_0(-1);
_become_active();
return;
case AWAITS_SIGNAL_CONTEXT_KILL:
Signal_context_killer::cancel_waiting();
_signal_context_killer.cancel_waiting();
return;
case ACTIVE:
return;
@ -339,11 +413,18 @@ void Thread::_call_delete_thread()
void Thread::_call_await_request_msg()
{
if (Ipc_node::await_request(user_arg_1())) {
if (_ipc_node.can_await_request()) {
_ipc_alloc_recv_caps(user_arg_1());
_ipc_node.await_request();
if (_ipc_node.awaits_request()) {
_become_inactive(AWAITS_IPC);
} else {
user_arg_0(0);
}
} else {
Genode::raw("IPC await request: bad state");
user_arg_0(0);
return;
}
_become_inactive(AWAITS_IPC);
}
@ -372,8 +453,11 @@ void Thread::timeout_triggered()
{
Signal_context * const c =
pd().cap_tree().find<Signal_context>(_timeout_sigid);
if (!c || c->submit(1))
if (!c || !c->can_submit(1)) {
Genode::raw(*this, ": failed to submit timeout signal");
return;
}
c->submit(1);
}
@ -390,8 +474,14 @@ void Thread::_call_send_request_msg()
bool const help = Cpu_job::_helping_possible(*dst);
oir = oir->find(dst->pd());
Ipc_node::send_request(*dst, oir ? oir->capid() : cap_id_invalid(),
help, user_arg_2());
if (!_ipc_node.can_send_request()) {
Genode::raw("IPC send request: bad state");
} else {
_ipc_alloc_recv_caps(user_arg_2());
_ipc_capid = oir ? oir->capid() : cap_id_invalid();
_ipc_node.send_request(dst->_ipc_node, help);
}
_state = AWAITS_IPC;
if (!help || !dst->own_share_active()) { _deactivate_used_shares(); }
}
@ -399,7 +489,7 @@ void Thread::_call_send_request_msg()
void Thread::_call_send_reply_msg()
{
Ipc_node::send_reply();
_ipc_node.send_reply();
bool const await_request_msg = user_arg_2();
if (await_request_msg) { _call_await_request_msg(); }
else { user_arg_0(0); }
@ -434,11 +524,12 @@ void Thread::_call_await_signal()
return;
}
/* register handler at the receiver */
if (r->add_handler(this)) {
if (!r->can_add_handler(_signal_handler)) {
Genode::raw("failed to register handler at signal receiver");
user_arg_0(-1);
return;
}
r->add_handler(_signal_handler);
user_arg_0(0);
}
@ -455,10 +546,11 @@ void Thread::_call_pending_signal()
}
/* register handler at the receiver */
if (r->add_handler(this)) {
if (!r->can_add_handler(_signal_handler)) {
user_arg_0(-1);
return;
}
r->add_handler(_signal_handler);
if (_state == AWAITS_SIGNAL) {
_cancel_blocking();
@ -500,11 +592,12 @@ void Thread::_call_submit_signal()
}
/* trigger signal context */
if (c->submit(user_arg_2())) {
if (!c->can_submit(user_arg_2())) {
Genode::raw("failed to submit signal context");
user_arg_0(-1);
return;
}
c->submit(user_arg_2());
user_arg_0(0);
}
@ -534,11 +627,12 @@ void Thread::_call_kill_signal_context()
}
/* kill signal context */
if (c->kill(this)) {
if (!c->can_kill()) {
Genode::raw("failed to kill signal context");
user_arg_0(-1);
return;
}
c->kill(_signal_context_killer);
}
@ -721,17 +815,23 @@ void Thread::_mmu_exception()
if (_core)
Genode::raw(*this, " raised a fault, which should never happen ",
_fault);
_fault);
if (_pager) _pager->submit(1);
if (_pager && _pager->can_submit(1)) {
_pager->submit(1);
}
}
Thread::Thread(unsigned const priority, unsigned const quota,
char const * const label, bool core)
:
Cpu_job(priority, quota), _state(AWAITS_START),
_signal_receiver(0), _label(label), _core(core), regs(core) { }
Kernel::Object { *this },
Cpu_job(priority, quota), _ipc_node(*this), _state(AWAITS_START),
_label(label), _core(core), regs(core) { }
Thread::~Thread() { _ipc_free_recv_caps(); }
void Thread::print(Genode::Output &out) const

View File

@ -14,6 +14,8 @@
#ifndef _CORE__KERNEL__THREAD_H_
#define _CORE__KERNEL__THREAD_H_
/* Genode includes */
#include <base/signal.h>
#include <util/reconstructible.h>
@ -24,6 +26,12 @@
#include <kernel/signal_receiver.h>
#include <kernel/ipc_node.h>
#include <object.h>
#include <kernel/interface.h>
#include <assertion.h>
/* base-local includes */
#include <base/internal/native_utcb.h>
namespace Kernel
{
@ -48,11 +56,7 @@ struct Kernel::Thread_fault
/**
* Kernel back-end for userland execution-contexts
*/
class Kernel::Thread
:
public Kernel::Object, public Cpu_job,
public Ipc_node, public Signal_context_killer, public Signal_handler,
private Timeout
class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
{
private:
@ -121,15 +125,24 @@ class Kernel::Thread
DEAD = 7,
};
Signal_context * _pager = nullptr;
Thread_fault _fault { };
State _state;
Signal_receiver * _signal_receiver;
char const * const _label;
capid_t _timeout_sigid = 0;
bool _paused = false;
bool _cancel_next_await_signal = false;
bool const _core = false;
enum { MAX_RCV_CAPS = Genode::Msgbuf_base::MAX_CAPS_PER_MSG };
void *_obj_id_ref_ptr[MAX_RCV_CAPS] { nullptr };
Ipc_node _ipc_node;
capid_t _ipc_capid { cap_id_invalid() };
size_t _ipc_rcv_caps { 0 };
Genode::Native_utcb *_utcb { nullptr };
Pd *_pd { nullptr };
Signal_context *_pager { nullptr };
Thread_fault _fault { };
State _state;
Signal_handler _signal_handler { *this };
Signal_context_killer _signal_context_killer { *this };
char const *const _label;
capid_t _timeout_sigid { 0 };
bool _paused { false };
bool _cancel_next_await_signal { false };
bool const _core { false };
Genode::Constructible<Tlb_invalidation> _tlb_invalidation {};
Genode::Constructible<Destroy> _destroy {};
@ -258,32 +271,9 @@ class Kernel::Thread
kobj.destruct();
}
/***************************
** Signal_context_killer **
***************************/
void _signal_context_kill_pending() override;
void _signal_context_kill_failed() override;
void _signal_context_kill_done() override;
/********************
** Signal_handler **
********************/
void _await_signal(Signal_receiver * const receiver) override;
void _receive_signal(void * const base, size_t const size) override;
/**************
** Ipc_node **
**************/
void _send_request_succeeded() override;
void _send_request_failed() override;
void _await_request_succeeded() override;
void _await_request_failed() override;
void _ipc_alloc_recv_caps(unsigned rcv_cap_count);
void _ipc_free_recv_caps();
void _ipc_init(Genode::Native_utcb &utcb, Thread &callee);
public:
@ -308,6 +298,8 @@ class Kernel::Thread
Thread(char const * const label)
: Thread(Cpu_priority::MIN, 0, label, true) { }
~Thread();
/**************************
** Support for syscalls **
@ -373,6 +365,27 @@ class Kernel::Thread
void print(Genode::Output &out) const;
/**************
** Ipc_node **
**************/
void ipc_send_request_succeeded() ;
void ipc_send_request_failed() ;
void ipc_await_request_succeeded();
void ipc_await_request_failed() ;
void ipc_copy_msg(Thread &sender) ;
/*************
** Signals **
*************/
void signal_context_kill_pending();
void signal_context_kill_failed();
void signal_context_kill_done();
void signal_wait_for_signal();
void signal_receive_signal(void * const base, size_t const size);
/*************
** Cpu_job **
@ -394,8 +407,18 @@ class Kernel::Thread
** Accessors **
***************/
Object &kernel_object() { return *this; }
char const * label() const { return _label; }
Thread_fault fault() const { return _fault; }
Genode::Native_utcb *utcb() { return _utcb; }
Pd &pd() const
{
if (_pd)
return *_pd;
ASSERT_NEVER_CALLED;
}
};

View File

@ -60,16 +60,19 @@ void Timer::set_timeout(Timeout * const timeout, time_t const duration)
}
void Timer::schedule_timeout()
time_t Timer::schedule_timeout()
{
/* get the timeout with the nearest end time */
Timeout * timeout = _timeout_list.first();
assert(timeout);
/* install timeout at timer hardware */
_time += _duration();
time_t duration = _duration();
_time += duration;
_last_timeout_duration = (timeout->_end > _time) ? timeout->_end - _time : 1;
_start_one_shot(_last_timeout_duration);
return duration;
}

View File

@ -91,7 +91,10 @@ class Kernel::Timer
Timer(Cpu & cpu);
void schedule_timeout();
/**
* Return duration from last call of this function
*/
time_t schedule_timeout();
void process_timeouts();

View File

@ -33,8 +33,7 @@ namespace Kernel
}
class Kernel::Vm : public Cpu_job,
public Kernel::Object
class Kernel::Vm : public Cpu_job
{
private:
@ -48,6 +47,7 @@ class Kernel::Vm : public Cpu_job,
enum Scheduler_state { ACTIVE, INACTIVE };
Object _kernel_object { *this };
unsigned _id = 0;
State & _state;
Signal_context & _context;
@ -110,6 +110,7 @@ class Kernel::Vm : public Cpu_job,
static void syscall_destroy(Genode::Kernel_object<Vm> & vm) {
call(call_id_delete_vm(), (Call_arg) &vm); }
Object &kernel_object() { return _kernel_object; }
/****************
** Vm_session **

View File

@ -12,8 +12,6 @@
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <base/log.h>
/* core includes */
#include <boot_modules.h>
@ -32,6 +30,10 @@
#include <base/internal/crt0.h>
#include <base/internal/stack_area.h>
/* Genode includes */
#include <base/log.h>
#include <trace/source_registry.h>
using namespace Genode;
@ -128,6 +130,10 @@ void Platform::_init_platform_info()
{
xml.node("kernel", [&] () { xml.attribute("name", "hw"); });
_init_additional_platform_info(xml);
xml.node("affinity-space", [&] () {
xml.attribute("width", affinity_space().width());
xml.attribute("height", affinity_space().height());
});
});
if (!unmap_local(virt_addr, pages)) {
@ -205,6 +211,40 @@ Platform::Platform()
init_core_log(Core_log_range { core_local_addr, log_size } );
}
struct Trace_source : public Trace::Source::Info_accessor,
private Trace::Control,
private Trace::Source
{
Kernel::Thread &thread;
Affinity::Location const affinity;
/**
* Trace::Source::Info_accessor interface
*/
Info trace_source_info() const override
{
Trace::Execution_time execution_time { thread.execution_time(), 0 };
return { Session_label("kernel"), thread.label(), execution_time,
affinity };
}
Trace_source(Trace::Source_registry &registry,
Kernel::Thread &thread, Affinity::Location affinity)
:
Trace::Control(),
Trace::Source(*this, *this),
thread(thread), affinity(affinity)
{
registry.insert(this);
}
};
/* create trace sources for idle threads */
Kernel::cpu_pool().for_each_cpu([&] (Kernel::Cpu & cpu) {
new (core_mem_alloc()) Trace_source(Trace::sources(), cpu.idle_thread(),
Affinity::Location(cpu.id(), 0));
});
log(_rom_fs);
}

View File

@ -88,7 +88,7 @@ Hw::Address_space::Address_space(Page_table & tt,
Hw::Address_space::Address_space(Platform_pd & pd)
: _tt(*construct_at<Page_table>(_table_alloc(), *((Page_table*)Hw::Mm::core_page_tables().base))),
_tt_phys((addr_t)_cma().phys_addr(&_tt)),
_tt_array(new (_cma()) Array([this] (void * virt) {
_tt_array(new (_cma()) Array([] (void * virt) {
return (addr_t)_cma().phys_addr(virt);})),
_tt_alloc(_tt_array->alloc()),
_kobj(true, *(Page_table*)translation_table_phys(), pd) { }
@ -132,10 +132,6 @@ bool Platform_pd::bind_thread(Platform_thread &t)
}
void Platform_pd::unbind_thread(Platform_thread &t) {
t.join_pd(nullptr, false, Address_space::weak_ptr()); }
void Platform_pd::assign_parent(Native_capability parent)
{
if (!_parent.valid() && parent.valid())

View File

@ -209,11 +209,6 @@ class Genode::Platform_pd : public Hw::Address_space,
*/
bool bind_thread(Platform_thread &);
/**
* Unbind thread from protection domain
*/
void unbind_thread(Platform_thread &);
/**
* Assign parent interface to protection domain
*/

View File

@ -208,8 +208,11 @@ namespace Genode {
/**
* Return execution time consumed by the thread
*/
Trace::Execution_time execution_time() const {
return { 0, 0, _quota, _priority }; }
Trace::Execution_time execution_time() const
{
Genode::uint64_t execution_time =
const_cast<Platform_thread *>(this)->_kobj->execution_time();
return { execution_time, 0, _quota, _priority }; }
/***************

View File

@ -83,3 +83,24 @@ void Arm_cpu::mmu_fault_status(Fsr::access_t fsr, Thread_fault & fault)
default: fault.type = Thread_fault::UNKNOWN;
};
}
void Arm_cpu::switch_to(Arm_cpu::Context&, Arm_cpu::Mmu_context & o)
{
if (o.cidr == 0) return;
Cidr::access_t cidr = Cidr::read();
if (cidr != o.cidr) {
/**
* First switch to global mappings only to prevent
* that wrong branch predicts result due to ASID
* and Page-Table not being in sync (see ARM RM B 3.10.4)
*/
Cidr::write(0);
Cpu::synchronization_barrier();
Ttbr0::write(o.ttbr0);
Cpu::synchronization_barrier();
Cidr::write(o.cidr);
Cpu::synchronization_barrier();
}
}

View File

@ -110,16 +110,7 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
else Tlbiall::write(0);
}
void switch_to(Context&, Mmu_context & o)
{
if (o.cidr == 0) return;
Cidr::access_t cidr = Cidr::read();
if (cidr != o.cidr) {
Cidr::write(o.cidr);
Ttbr0::write(o.ttbr0);
}
}
void switch_to(Context&, Mmu_context & o);
static void mmu_fault(Context & c, Kernel::Thread_fault & fault);
static void mmu_fault_status(Fsr::access_t fsr,

View File

@ -12,6 +12,7 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#include <synchronize.s>
/*********************
** Constant values **
@ -123,6 +124,8 @@
ldr r1, [r1]
blx r1
SYSTEM_REGISTER_SYNC_BARRIER /* synchronize after the context switch */
/*
* Go to kernel entry code
*/
@ -164,4 +167,5 @@
ldr r1, [sp, #16*4]
msr spsr_cxsf, r1
ldm sp, {r0-r14}^
SYSTEM_REGISTER_SYNC_BARRIER /* synchronize after the context switch */
subs pc, lr, #0

View File

@ -18,6 +18,11 @@
/* core includes */
#include <spec/arm/cpu_support.h>
namespace Genode { using Cpu = Arm_cpu; }
namespace Genode { struct Cpu; }
struct Genode::Cpu : Arm_cpu
{
static inline void synchronization_barrier() {}
};
#endif /* _CORE__SPEC__ARM_V6__CPU_H_ */

View File

@ -0,0 +1,15 @@
/*
* \brief Assembler macros for ARMv6
* \author Stefan Kalkowski
* \date 2020-02-16
*/
/*
* Copyright (C) 2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
.macro SYSTEM_REGISTER_SYNC_BARRIER
.endm

View File

@ -41,6 +41,12 @@ struct Genode::Arm_v7_cpu : Arm_cpu
else Tlbiallis::write(0);
} else Arm_cpu::invalidate_tlb(asid);
}
static inline void synchronization_barrier()
{
asm volatile("dsb sy\n"
"isb sy\n" ::: "memory");
}
};
#endif /* _CORE__SPEC__ARM_V7__CPU_SUPPORT_H_ */

View File

@ -0,0 +1,17 @@
/*
* \brief Assembler macros for ARMv7
* \author Stefan Kalkowski
* \date 2020-02-16
*/
/*
* Copyright (C) 2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
.macro SYSTEM_REGISTER_SYNC_BARRIER
dsb sy
isb sy
.endm

View File

@ -40,12 +40,13 @@ class Board::Pic
void irq_occurred(unsigned irq)
{
isr[irq] = true;
if (irq < NR_OF_IRQ)
isr[irq] = true;
}
bool take_request(unsigned &irq)
{
for (int i = 0; i < 256; i++) {
for (int i = 0; i < NR_OF_IRQ; i++) {
if (isr[i] == true) {
irq = i;
isr[i] = false;

View File

@ -209,9 +209,12 @@ class Board::Pic : public Genode::Mmio
void irq_mode(unsigned irq, unsigned trigger, unsigned polarity);
void store_apic_id(unsigned const cpu_id) {
Id::access_t const lapic_id = read<Id>();
lapic_ids[cpu_id] = (lapic_id >> 24) & 0xff;
void store_apic_id(unsigned const cpu_id)
{
if (cpu_id < NR_OF_CPUS) {
Id::access_t const lapic_id = read<Id>();
lapic_ids[cpu_id] = (lapic_id >> 24) & 0xff;
}
}
void send_ipi(unsigned const);

View File

@ -26,6 +26,7 @@
#include <kernel/kernel.h>
#include <platform.h>
#include <platform_thread.h>
#include <trace/source_registry.h>
using namespace Genode;
@ -35,8 +36,44 @@ namespace Hw { extern Untyped_capability _main_thread_cap; }
void Thread::start()
{
/* start thread with stack pointer at the top of stack */
if (native_thread().platform_thread->start((void *)&_thread_start, stack_top()))
if (native_thread().platform_thread->start((void *)&_thread_start, stack_top())) {
error("failed to start thread");
return;
}
struct Trace_source : public Trace::Source::Info_accessor,
private Trace::Control,
private Trace::Source
{
Genode::Thread &thread;
/**
* Trace::Source::Info_accessor interface
*/
Info trace_source_info() const override
{
Platform_thread * t = thread.native_thread().platform_thread;
Trace::Execution_time execution_time { 0, 0 };
if (t)
execution_time = t->execution_time();
return { Session_label("core"), thread.name(),
execution_time, thread.affinity() };
}
Trace_source(Trace::Source_registry &registry, Genode::Thread &thread)
:
Trace::Control(),
Trace::Source(*this, *this),
thread(thread)
{
registry.insert(this);
}
};
/* create trace sources for core threads */
new (platform().core_mem_alloc()) Trace_source(Trace::sources(), *this);
}

View File

@ -62,7 +62,7 @@ thread_check_stopped_and_restart(Genode::Thread * const t)
/**
* Pause execution of current thread
*/
static inline void thread_stop_myself() { Kernel::stop_thread(); }
static inline void thread_stop_myself(Genode::Thread *) { Kernel::stop_thread(); }
#endif /* _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ */

View File

@ -249,6 +249,9 @@ struct Hw::Arm_cpu
/* Physical Count register */
ARM_CP15_REGISTER_64BIT(Cntpct, c14, 0);
/* Diagnostic register */
ARM_CP15_REGISTER_32BIT(Diag, c15, c0, 0, 1);
/******************************
** Program status registers **
******************************/
@ -283,12 +286,6 @@ struct Hw::Arm_cpu
** Cache maintainance functions **
**********************************/
static inline void synchronization_barrier()
{
asm volatile("dsb\n"
"isb\n");
}
static inline void wait_for_xchg(volatile void * addr,
unsigned long new_value,
unsigned long expected_value)

View File

@ -422,6 +422,9 @@ class Hw::Page_table
size_t const size, Page_flags const & flags,
Allocator & alloc)
{
if (i > MAX_INDEX)
return;
using Pt = Page_table_level_2;
using Ptd = Page_table_descriptor;

View File

@ -137,6 +137,8 @@ struct Hw::Arm_64_cpu
SYSTEM_REGISTER(64, Mpidr, mpidr_el1);
SYSTEM_REGISTER(32, Pmcr_el0, pmcr_el0);
SYSTEM_REGISTER(32, Pmcntenset_el0, pmcntenset_el0);
SYSTEM_REGISTER(32, Pmuserenr_el0, pmuserenr_el0);
SYSTEM_REGISTER(64, Scr, scr_el3,

View File

@ -57,13 +57,6 @@ namespace Hw
template <typename ENTRY, unsigned PAGE_SIZE_LOG2, unsigned SIZE_LOG2>
class Page_directory;
using Level_3_translation_table =
Page_directory<Level_4_translation_table,
SIZE_LOG2_2MB, SIZE_LOG2_1GB>;
using Level_2_translation_table =
Page_directory<Level_3_translation_table,
SIZE_LOG2_1GB, SIZE_LOG2_512GB>;
/**
* IA-32e common descriptor.
*
@ -489,7 +482,24 @@ class Hw::Page_directory
*/
void remove_translation(addr_t vo, size_t size, Allocator & alloc) {
_range_op(vo, 0, size, Remove_func(alloc)); }
} __attribute__((aligned(1 << ALIGNM_LOG2)));
};
namespace Hw {
struct Level_3_translation_table :
Page_directory<
Level_4_translation_table,
SIZE_LOG2_2MB, SIZE_LOG2_1GB>
{ } __attribute__((aligned(1 << ALIGNM_LOG2)));
struct Level_2_translation_table :
Page_directory<
Level_3_translation_table,
SIZE_LOG2_1GB, SIZE_LOG2_512GB>
{ } __attribute__((aligned(1 << ALIGNM_LOG2)));
}
class Hw::Pml4_table

View File

@ -56,7 +56,7 @@ namespace Hw
* \param p pointer
* \param alignm_log2 log2 of the required alignment
*/
constexpr bool aligned(void * const p, addr_t alignm_log2) {
inline bool aligned(void * const p, addr_t alignm_log2) {
return (addr_t)p == trunc((addr_t)p, alignm_log2); }
/**

View File

@ -130,10 +130,11 @@ void Genode::ipc_reply(Native_capability, Rpc_exception_code exc,
}
Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
Rpc_exception_code exc,
Msgbuf_base &reply_msg,
Msgbuf_base &request_msg)
Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
Rpc_exception_code exc,
Msgbuf_base &reply_msg,
Msgbuf_base &request_msg,
Rpc_entrypoint::Native_context &)
{
Native_utcb &utcb = *Thread::myself()->utcb();
@ -162,10 +163,11 @@ Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
}
Ipc_server::Ipc_server()
Ipc_server::Ipc_server(Rpc_entrypoint::Native_context& _native_context)
:
Native_capability(Thread::myself() ? Thread::myself()->native_thread().cap
: Hw::_main_thread_cap)
: Hw::_main_thread_cap),
_native_context(_native_context)
{ }

View File

@ -75,7 +75,7 @@ void Thread::_thread_start()
{
Thread::myself()->_thread_bootstrap();
Thread::myself()->entry();
Thread::myself()->_join_lock.unlock();
Thread::myself()->_join.wakeup();
Genode::sleep_forever();
}

View File

@ -5,7 +5,7 @@
#
TARGET = test-cpu_scheduler
SRC_CC = test.cc cpu_scheduler.cc double_list.cc
SRC_CC = test.cc cpu_scheduler.cc
INC_DIR += $(REP_DIR)/src/core $(REP_DIR)/src/include $(BASE_DIR)/src/include
LIBS = base

View File

@ -33,7 +33,7 @@ struct Data
Cpu_scheduler scheduler;
char shares[9][sizeof(Cpu_share)];
Data() : idle(0, 0), scheduler(&idle, 1000, 100) { }
Data() : idle(0, 0), scheduler(idle, 1000, 100) { }
};
Data * data()
@ -79,13 +79,13 @@ void create(unsigned const id)
case 9: new (p) Cpu_share(2, 0); break;
default: return;
}
data()->scheduler.insert(s);
data()->scheduler.insert(*s);
}
void destroy(unsigned const id)
{
Cpu_share * const s = share(id);
data()->scheduler.remove(s);
data()->scheduler.remove(*s);
s->~Cpu_share();
}
@ -104,10 +104,10 @@ void update_check(unsigned const l, unsigned const c, unsigned const t,
Genode::log("wrong time ", st, " in line ", l);
done();
}
Cpu_share * const hs = data()->scheduler.head();
Cpu_share &hs = data()->scheduler.head();
unsigned const hq = data()->scheduler.head_quota();
if (hs != share(s)) {
unsigned const hi = share_id(hs);
if (&hs != share(s)) {
unsigned const hi = share_id(&hs);
Genode::log("wrong share ", hi, " in line ", l);
done();
}
@ -119,9 +119,9 @@ void update_check(unsigned const l, unsigned const c, unsigned const t,
void ready_check(unsigned const l, unsigned const s, bool const x)
{
bool const y = data()->scheduler.ready_check(share(s));
if (y != x) {
Genode::log("wrong check result ", y, " in line ", l);
data()->scheduler.ready_check(*share(s));
if (data()->scheduler.need_to_schedule() != x) {
Genode::log("wrong check result ", data()->scheduler.need_to_schedule(), " in line ", l);
done();
}
}
@ -133,10 +133,10 @@ void ready_check(unsigned const l, unsigned const s, bool const x)
#define C(s) create(s);
#define D(s) destroy(s);
#define A(s) data()->scheduler.ready(share(s));
#define I(s) data()->scheduler.unready(share(s));
#define A(s) data()->scheduler.ready(*share(s));
#define I(s) data()->scheduler.unready(*share(s));
#define Y data()->scheduler.yield();
#define Q(s, q) data()->scheduler.quota(share(s), q);
#define Q(s, q) data()->scheduler.quota(*share(s), q);
#define U(c, t, s, q) update_check(__LINE__, c, t, s, q);
#define O(s) ready_check(__LINE__, s, true);
#define N(s) ready_check(__LINE__, s, false);

View File

@ -6,7 +6,7 @@
TARGET = test-double_list
INC_DIR = $(REP_DIR)/src/core
SRC_CC = test.cc double_list.cc
SRC_CC = test.cc
LIBS = base
vpath double_list.cc $(REP_DIR)/src/core/kernel

View File

@ -24,18 +24,18 @@
*/
using Genode::size_t;
using Kernel::Double_list_typed;
using Kernel::Double_list;
using Kernel::Double_list_item;
void * operator new(__SIZE_TYPE__, void * p) { return p; }
struct Item_load { char volatile x = 0, y = 0, z = 0; };
struct Item : Item_load, Double_list_item
struct Item : Item_load, Double_list_item<Item>
{
unsigned _id;
Item(unsigned const id) : _id(id) { x = 1; y = 2; z = 3; }
Item(unsigned const id) : Double_list_item<Item>(*this), _id(id) { x = 1; y = 2; z = 3; }
void iteration() { Genode::log(_id); }
};
@ -44,7 +44,7 @@ struct Data
{
static constexpr unsigned nr_of_items = 9;
Double_list_typed<Item> list { };
Double_list<Item> list { };
char items[nr_of_items][sizeof(Item)];
Data()
@ -68,24 +68,27 @@ void done()
void check(unsigned i1, unsigned l)
{
Item * const i2 = data()->list.head();
if (i1 && i2) {
if(i1 == i2->_id) { return; }
Genode::log("head ", i2->_id, " in line ", l);
done();
} else if (i1 && !i2) {
Double_list_item<Item> * const li2 = data()->list.head();
if (li2) {
Item * const i2 = &li2->payload();
if (i1) {
if(i1 == i2->_id) { return; }
Genode::log("head ", i2->_id, " in line ", l);
done();
} else {
Genode::log("non-empty ", i2->_id, " in line ", l);
done();
}
} else if (i1) {
Genode::log("empty in line ", l);
done();
} else if (!i1 && i2){
Genode::log("non-empty ", i2->_id, " in line ", l);
done();
}
}
void print_each()
{
Genode::log("print each");
data()->list.for_each([] (Item * const i) { i->iteration(); });
data()->list.for_each([] (Item &i) { i.iteration(); });
}
Item * item(unsigned const i) {

View File

@ -7,7 +7,7 @@ include $(call select_from_repositories,lib/import/import-syscall-linux.mk)
# Manually supply all library search paths of the host compiler to our tool
# chain.
#
HOST_LIB_SEARCH_DIRS = $(shell cc $(CC_MARCH) -print-search-dirs | grep libraries |\
HOST_LIB_SEARCH_DIRS = $(shell $(CUSTOM_HOST_CC) $(CC_MARCH) -print-search-dirs | grep libraries |\
sed "s/.*=//" | sed "s/:/ /g" |\
sed "s/\/ / /g" | sed "s/\/\$$//")
#
@ -68,11 +68,11 @@ endif
LD_TEXT_ADDR ?=
LD_SCRIPT_STATIC ?=
EXT_OBJECTS += $(shell cc $(CC_MARCH) -print-file-name=crt1.o)
EXT_OBJECTS += $(shell cc $(CC_MARCH) -print-file-name=crti.o)
EXT_OBJECTS += $(shell $(CUSTOM_HOST_CC) $(CC_MARCH) -print-file-name=crt1.o)
EXT_OBJECTS += $(shell $(CUSTOM_HOST_CC) $(CC_MARCH) -print-file-name=crti.o)
EXT_OBJECTS += $(shell $(CUSTOM_CC) $(CC_MARCH) -print-file-name=crtbegin.o)
EXT_OBJECTS += $(shell $(CUSTOM_CC) $(CC_MARCH) -print-file-name=crtend.o)
EXT_OBJECTS += $(shell cc $(CC_MARCH) -print-file-name=crtn.o)
EXT_OBJECTS += $(shell $(CUSTOM_HOST_CC) $(CC_MARCH) -print-file-name=crtn.o)
LX_LIBS_OPT += -lgcc -lgcc_s -lsupc++ -lc -lpthread
@ -105,7 +105,7 @@ endif
LD_LIBGCC = $(LX_LIBS_OPT)
# use the host c++ for linking to find shared libraries in DT_RPATH library paths
LD_CMD = c++
LD_CMD = $(CUSTOM_HOST_CXX)
# disable format-string security checks, which prevent non-literal format strings
CC_OPT += -Wno-format-security
@ -114,8 +114,8 @@ CC_OPT += -Wno-format-security
# Disable position-independent executables (which are enabled by default on
# Ubuntu 16.10 or newer)
#
CXX_LINK_OPT_NO_PIE := $(shell \
(echo "int main(){}" | $(LD_CMD) -no-pie -x c++ - -o /dev/null >& /dev/null \
CXX_LINK_OPT_NO_PIE = $(shell \
(echo "int main(){}" | $(CUSTOM_HOST_CXX) -no-pie -x c++ - -o /dev/null >& /dev/null \
&& echo "-no-pie") || true)
CXX_LINK_OPT += $(CXX_LINK_OPT_NO_PIE)

View File

@ -1,8 +1,9 @@
HOST_INC_DIR += $(dir $(call select_from_repositories,src/lib/syscall/linux_syscalls.h))
HOST_INC_DIR += $(dir $(CUSTOM_HOST_CC))/../$(shell $(CUSTOM_HOST_CC) -dumpmachine)/libc/usr/include
HOST_INC_DIR += /usr/include
# needed for Ubuntu >= 11.04
HOST_INC_DIR += /usr/include/$(shell gcc -dumpmachine)
HOST_INC_DIR += /usr/include/$(shell $(CUSTOM_HOST_CC) -dumpmachine)
#
# Explicitly add some well-known paths as the dumpmachine magic above does not

Some files were not shown because too many files have changed in this diff Show More