Compare commits
247 Commits
Author | SHA1 | Date |
---|---|---|
Ehmry - | ecc9c8b28b | |
Christian Helmuth | cfb49c7316 | |
Norman Feske | a3fad2e171 | |
Norman Feske | dd5db8484a | |
Christian Helmuth | 5affd51250 | |
Alexander Boettcher | ce27b5ebce | |
Norman Feske | fce9cd8c22 | |
Christian Prochaska | 8faa916d93 | |
Christian Helmuth | e52802162c | |
Josef Söntgen | f3ec246b67 | |
Christian Prochaska | 434c9ceb5d | |
Norman Feske | c3fb81d1a1 | |
Norman Feske | c340f57207 | |
Norman Feske | bbe1bf9c3a | |
Alexander Boettcher | accda1211b | |
Norman Feske | daee1f4cb8 | |
Stefan Kalkowski | 87cb10c558 | |
Norman Feske | 904651ada9 | |
Norman Feske | 1d3ce93107 | |
Sebastian Sumpf | 103dcdeea8 | |
Sebastian Sumpf | f77531138a | |
Sebastian Sumpf | c8b3b060aa | |
Stefan Kalkowski | 7780ee6a34 | |
Stefan Kalkowski | 2e2625e952 | |
Stefan Kalkowski | 55c3eb7c14 | |
Stefan Thöni | a7a9855493 | |
Norman Feske | 5eaaee0dbe | |
Norman Feske | b2bc718c1f | |
Norman Feske | 7118ad494c | |
Norman Feske | 582e0e718c | |
Norman Feske | 1713583a19 | |
Norman Feske | 38aef49428 | |
Alexander Boettcher | a9caf3fbe4 | |
Josef Söntgen | 80ff844dc2 | |
Josef Söntgen | c53be5a3fb | |
Josef Söntgen | 6addd6cf1e | |
Sebastian Sumpf | 3995d2f4a2 | |
Sebastian Sumpf | b95dc611d6 | |
Christian Helmuth | 4cccf74664 | |
Stefan Kalkowski | 8cc48d5688 | |
Stefan Kalkowski | b76bd57ed1 | |
Alexander Boettcher | 2afc218767 | |
Alexander Boettcher | 5bbaa30655 | |
Alexander Boettcher | 5440cd4b50 | |
Alexander Boettcher | e686ff78e9 | |
Alexander Boettcher | 2bd77722c7 | |
Alexander Boettcher | 00f69bc70d | |
Stefan Kalkowski | d1609e771a | |
Norman Feske | 89f813f113 | |
Norman Feske | 9b0fbf000e | |
Stefan Kalkowski | 725d16e18e | |
Martin Stein | e42a205a51 | |
Martin Stein | 0d5f185267 | |
Martin Stein | c146a215fb | |
Martin Stein | eef7b5e168 | |
Martin Stein | a753b6ce46 | |
Martin Stein | 793e12f8f3 | |
Martin Stein | 751e6430fa | |
Martin Stein | 9eb20c2be7 | |
Martin Stein | 5e460394d2 | |
Martin Stein | 88043e144a | |
Martin Stein | 3cc7774fe4 | |
Martin Stein | a04243aaf4 | |
Martin Stein | 5a95183c3e | |
Martin Stein | 6a5aa18a7b | |
Christian Prochaska | 4b3c40f35b | |
Stefan Kalkowski | 79fba6c2ac | |
Tomasz Gajewski | 4f217b19a9 | |
Stefan Kalkowski | 202333c881 | |
Christian Prochaska | 2ce0395fd8 | |
Ehmry - | bbdf181828 | |
Norman Feske | 0181c6025a | |
Norman Feske | 6eff83c1eb | |
Norman Feske | 5aae0f2379 | |
Norman Feske | 49ae4a834f | |
Norman Feske | 5b650434b0 | |
Norman Feske | e612f7cd7d | |
Norman Feske | 7cc4aa2a28 | |
Norman Feske | 60f5d0e34a | |
Norman Feske | 46c5a90ba1 | |
Stefan Kalkowski | 1273c573b6 | |
Norman Feske | 3a2895af19 | |
Norman Feske | 0bffac6c98 | |
Norman Feske | c25de5dba3 | |
Norman Feske | 60edfa4d77 | |
Norman Feske | 52e582132f | |
Norman Feske | a888041ba4 | |
Norman Feske | 844af06782 | |
Norman Feske | 7da3404bd0 | |
Sid Hussmann | 7676f47540 | |
Josef Söntgen | 9d7a58f6a7 | |
Christian Prochaska | 9bd3d2aa5c | |
Christian Prochaska | 28e782dda5 | |
Christian Prochaska | 597098845c | |
Sebastian Sumpf | 8a7deae238 | |
Sebastian Sumpf | 73f2c7043c | |
Sebastian Sumpf | de24035066 | |
Norman Feske | 57ea1dbdd3 | |
Christian Prochaska | 9f73f09cec | |
Martin Stein | d56b21d329 | |
Christian Helmuth | 8d60bc11b5 | |
Christian Helmuth | 604f4c666b | |
Christian Helmuth | ff5175ec76 | |
Christian Helmuth | 6aebd5dd95 | |
Christian Helmuth | 3d4bed3374 | |
Alexander Boettcher | ee7a77643e | |
Alexander Boettcher | 646d6c368c | |
Alexander Boettcher | d96e14fe16 | |
Alexander Boettcher | 3a9d450106 | |
Martin Stein | a73ef9fc06 | |
Stefan Kalkowski | 3016b64fac | |
Stefan Kalkowski | 22498e0b09 | |
Stefan Kalkowski | 79dff674fd | |
Stefan Kalkowski | 56ef7ca9e7 | |
Stefan Kalkowski | 9db50753f1 | |
Stefan Kalkowski | e84e1bbf36 | |
Stefan Kalkowski | fda337a1c0 | |
Stefan Kalkowski | f49f91da08 | |
Christian Helmuth | 90535a1401 | |
Christian Helmuth | 43719b5fd1 | |
Stefan Kalkowski | 2a94f8cdb4 | |
Christian Helmuth | 1e578f1a50 | |
Alexander Boettcher | a036d2373a | |
Norman Feske | a2b303e95a | |
Alexander Boettcher | 7b964fa700 | |
Alexander Boettcher | 72f5f9d133 | |
Christian Prochaska | 186a6bc080 | |
Norman Feske | 567d9f7910 | |
Norman Feske | d70cf314d8 | |
Norman Feske | c6445da654 | |
Norman Feske | 96cde52838 | |
Norman Feske | c67a0d3dd8 | |
Norman Feske | 78c0e5f6b6 | |
Norman Feske | f82e7df0ba | |
Norman Feske | 640a001ab6 | |
Alexander Boettcher | c5c5f8754c | |
Alexander Boettcher | 5be3bf4f26 | |
Alexander Boettcher | d132fc0a73 | |
Christian Helmuth | 285a33c97d | |
Alexander Boettcher | f09ac23144 | |
Alexander Boettcher | 734752d6b5 | |
Christian Prochaska | 4fc6c4ff5c | |
Christian Prochaska | 746d373362 | |
Alexander Boettcher | 2256f5fb4b | |
Christian Prochaska | d8e2c95597 | |
Alexander Boettcher | 6506240642 | |
Sebastian Sumpf | bd284347da | |
Sebastian Sumpf | 3813f9772a | |
Sebastian Sumpf | 1902d1a06b | |
Josef Söntgen | 7ecabb25eb | |
Alexander Boettcher | 5b633a83df | |
Norman Feske | beb8bf498c | |
Norman Feske | de764d8490 | |
Norman Feske | 5635c1318c | |
Norman Feske | 01713c74f9 | |
Norman Feske | 9ec66f0594 | |
Norman Feske | 6947bddd3f | |
Norman Feske | 37ec636018 | |
Norman Feske | 9bba6613e7 | |
Christian Prochaska | d4f246517c | |
Stefan Kalkowski | 5bfebe7a3f | |
Stefan Kalkowski | 3df67362b4 | |
Christian Prochaska | f1042e7fb1 | |
Christian Prochaska | b29112efdf | |
Stefan Kalkowski | fe899eecc7 | |
Norman Feske | c2a2ec121f | |
Norman Feske | e1e1fa23b7 | |
Norman Feske | aee8d35dc4 | |
Christian Helmuth | 4bbbf5d2e3 | |
Norman Feske | ba7e832c5d | |
Norman Feske | bbfc092a31 | |
Norman Feske | de52cf1cdd | |
Norman Feske | 783c05fd6c | |
Norman Feske | 6ae98e2e6d | |
Norman Feske | ffc099eb54 | |
Christian Helmuth | 9321067b68 | |
Christian Prochaska | 0eaa1f7a08 | |
Christian Helmuth | 18f90ca1e3 | |
Christian Helmuth | 9a35743df6 | |
Christian Helmuth | 8d63a3c1f3 | |
Alexander Boettcher | 1ac33caa90 | |
Alexander Boettcher | 1c361bf545 | |
Alexander Boettcher | a41dd48986 | |
Christian Helmuth | b931b67cba | |
Christian Helmuth | 24435e9ca1 | |
Alexander Boettcher | e54ff599ca | |
Sebastian Sumpf | 04969b6be0 | |
Christian Helmuth | 1ddf1dbc25 | |
Christian Helmuth | 8699f5592f | |
Norman Feske | 73d089da36 | |
Christian Prochaska | c8cd09e72c | |
Christian Prochaska | be1ef01f10 | |
Alexander Boettcher | 0a1bc1f4b7 | |
Alexander Boettcher | bcb7f45201 | |
Alexander Boettcher | 33db0e0d4d | |
Christian Helmuth | 504539ad1e | |
Christian Prochaska | a62fce8dc5 | |
Christian Prochaska | 81a78cf1d0 | |
Christian Helmuth | 283135c9cd | |
Sebastian Sumpf | 22d4d5c1c1 | |
Sebastian Sumpf | 9c372c36c1 | |
Sebastian Sumpf | 9767c4db0e | |
Alexander Boettcher | 9812799b24 | |
Alexander Boettcher | d385749ead | |
Christian Helmuth | 23ed5d3936 | |
Christian Helmuth | cebc963396 | |
Norman Feske | 0c8ec41c21 | |
Norman Feske | 9f7b8c1a17 | |
Norman Feske | cd92b32622 | |
Norman Feske | 5853a68904 | |
Norman Feske | ae64830bd5 | |
Norman Feske | e8878eee8a | |
Norman Feske | 3897ddea03 | |
Norman Feske | 6858270517 | |
Norman Feske | 4e57b6eceb | |
Norman Feske | 298f317f44 | |
Norman Feske | 5820ad8309 | |
Norman Feske | b7fbe65ff2 | |
Norman Feske | d1cf216384 | |
Alexander Boettcher | 3011dc5876 | |
Alexander Boettcher | 6e99f00f5c | |
Alexander Boettcher | beb1e084a6 | |
Alexander Boettcher | e34b443c29 | |
Alexander Boettcher | 6b17bb647e | |
Christian Helmuth | 4299b85cdb | |
Sebastian Sumpf | 6dae147785 | |
Sebastian Sumpf | e4255e4c8b | |
Christian Helmuth | 161274f785 | |
Roman Iten | 6145cdcf37 | |
Tomasz Gajewski | b57a4c98cf | |
Ehmry - | a3e43aca87 | |
Norman Feske | 6b6915e304 | |
Alexander Boettcher | 3f83ac5580 | |
Ehmry - | 7f57de1b74 | |
Ehmry - | 648382db74 | |
Ehmry - | 2c510bb7f9 | |
Ehmry - | 23710dff5e | |
Ehmry - | ff0436357b | |
Ehmry - | 091e5157aa | |
Alexander Boettcher | c1e181a407 | |
Stefan Kalkowski | 8f71c90ca8 | |
Norman Feske | f85ec313de | |
Norman Feske | 2aa6471608 | |
Stefan Kalkowski | 9814fc5447 | |
Martin Stein | 3655ea77a3 | |
Johannes Kliemann | 89d35bc41e | |
Johannes Kliemann | 93639532f0 |
|
@ -2,21 +2,10 @@
|
|||
*.orig
|
||||
*.swp
|
||||
*.rej
|
||||
result
|
||||
result-*
|
||||
|
||||
/build
|
||||
/contrib
|
||||
/depot
|
||||
/public
|
||||
/repos/world
|
||||
/.tup
|
||||
/build-*
|
||||
/configs
|
||||
##### TUP GITIGNORE #####
|
||||
##### Lines below automatically generated by Tup.
|
||||
##### Do not edit.
|
||||
.tup
|
||||
/.gitignore
|
||||
/dev
|
||||
/out
|
||||
|
||||
|
|
|
@ -1,29 +1,16 @@
|
|||
**FORK AHEAD**
|
||||
|
||||
This a fork of the Genode OS reference implementation with a replacement
|
||||
build system that is humane and interoperable.
|
||||
=================================
|
||||
Genode Operating System Framework
|
||||
=================================
|
||||
|
||||
Changes against [Genode Labs](https://genode-labs.com/) master may be
|
||||
reviewed with the following commands:
|
||||
|
||||
```sh
|
||||
git remote add genodelabs https://github.com/genodelabs/genode.git
|
||||
git fetch genodelabs
|
||||
git diff genodelabs/master
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Genode Operating System Framework
|
||||
|
||||
This is the source tree of the reference implementation of the Genode OS
|
||||
architecture. For a general overview about the architecture, please refer to
|
||||
the project's official website:
|
||||
|
||||
### Official project website for the Genode OS Framework
|
||||
|
||||
https://genode.org/documentation/general-overview
|
||||
:Official project website for the Genode OS Framework:
|
||||
|
||||
[https://genode.org/documentation/general-overview]
|
||||
|
||||
The current implementation can be compiled for 8 different kernels: Linux,
|
||||
L4ka::Pistachio, L4/Fiasco, OKL4, NOVA, Fiasco.OC, seL4, and a custom
|
||||
|
@ -46,14 +33,15 @@ the kernel that fits best with the requirements at hand for the particular
|
|||
usage scenario.
|
||||
|
||||
|
||||
## Documentation
|
||||
Documentation
|
||||
#############
|
||||
|
||||
The primary documentation is the book "Genode Foundations", which is available
|
||||
on the front page of Genode website:
|
||||
|
||||
### Download the book "Genode Foundations"
|
||||
:Download the book "Genode Foundations":
|
||||
|
||||
https://genode.org
|
||||
[https://genode.org]
|
||||
|
||||
The book describes Genode in a holistic and comprehensive way. It equips you
|
||||
with a thorough understanding of the architecture, assists developers with the
|
||||
|
@ -65,75 +53,79 @@ The project has a quarterly release cycle. Each version is accompanied with
|
|||
detailed release documentation, which is available at the documentation
|
||||
section of the project website:
|
||||
|
||||
### Release documentation
|
||||
:Release documentation:
|
||||
|
||||
https://genode.org/documentation/release-notes/
|
||||
[https://genode.org/documentation/release-notes/]
|
||||
|
||||
|
||||
## Directory overview
|
||||
Directory overview
|
||||
##################
|
||||
|
||||
The source tree is composed of the following subdirectories:
|
||||
|
||||
### 'doc'
|
||||
:'doc':
|
||||
|
||||
This directory contains general documentation. Please consider the following
|
||||
document for a quick guide to get started with the framework:
|
||||
|
||||
[doc/getting_started.txt](doc/getting_started.txt)
|
||||
! doc/getting_started.txt
|
||||
|
||||
If you are curious about the ready-to-use components that come with the
|
||||
framework, please review the components overview:
|
||||
|
||||
[doc/components.txt](doc/components.txt)
|
||||
! doc/components.txt
|
||||
|
||||
### 'repos':
|
||||
:'repos':
|
||||
|
||||
This directory contains the so-called source-code repositories of Genode.
|
||||
Please refer to the README file in the 'repos' directory to learn more
|
||||
about the roles of the individual repositories.
|
||||
|
||||
### 'tool'
|
||||
:'tool':
|
||||
|
||||
Source-code management tools and scripts. Please refer to the README file
|
||||
contained in the directory.
|
||||
|
||||
### 'depot' and 'public'
|
||||
:'depot' and 'public':
|
||||
|
||||
Local depot and public archive of Genode packages. Please refer to
|
||||
|
||||
[doc/depot.txt](doc/depot.txt)
|
||||
! doc/depot.txt
|
||||
|
||||
for more details.
|
||||
|
||||
|
||||
## Additional community-maintained components
|
||||
Additional community-maintained components
|
||||
##########################################
|
||||
|
||||
The components found within the main source tree are complemented by a growing
|
||||
library of additional software, which can be seamlessly integrated into Genode
|
||||
system scenarios.
|
||||
|
||||
### Genode-world repository
|
||||
:Genode-world repository:
|
||||
|
||||
https://github.com/genodelabs/genode-world
|
||||
[https://github.com/genodelabs/genode-world]
|
||||
|
||||
|
||||
## Contact
|
||||
Contact
|
||||
#######
|
||||
|
||||
The best way to get in touch with Genode developers and users is the project's
|
||||
mailing list. Please feel welcome to join in!
|
||||
|
||||
### Genode Mailing Lists
|
||||
:Genode Mailing Lists:
|
||||
|
||||
https://genode.org/community/mailing-lists
|
||||
[https://genode.org/community/mailing-lists]
|
||||
|
||||
|
||||
## Commercial support
|
||||
Commercial support
|
||||
##################
|
||||
|
||||
The driving force behind the Genode OS Framework is the German company Genode
|
||||
Labs. The company offers commercial licensing, trainings, support, and
|
||||
contracted development work:
|
||||
|
||||
### Genode Labs website
|
||||
:Genode Labs website:
|
||||
|
||||
https://www.genode-labs.com
|
||||
[https://www.genode-labs.com]
|
||||
|
46
Tuprules.gcc
46
Tuprules.gcc
|
@ -1,46 +0,0 @@
|
|||
TOOLCHAIN_CONFIGURED=$(TOOLCHAIN_CONFIGURED)X
|
||||
|
||||
ifeq (@(TUP_ARCH),i386)
|
||||
CC_MARCH = -march=i686 -m32
|
||||
LD_MARCH = -melf_i386
|
||||
AS_MARCH = -march=i686 --32
|
||||
endif
|
||||
|
||||
ifeq (@(TUP_ARCH),x86_64)
|
||||
CC_MARCH = -m64 -mcmodel=large
|
||||
LD_MARCH = -melf_x86_64
|
||||
endif
|
||||
|
||||
ifeq (@(TUP_ARCH),arm_v8)
|
||||
CC_MARCH = -march=armv8-a
|
||||
endif
|
||||
|
||||
ifdef CXXFLAGS
|
||||
CXXFLAGS = @(CXXFLAGS)
|
||||
endif
|
||||
|
||||
CXXFLAGS += -Wno-error=implicit-fallthrough
|
||||
CXXFLAGS += -Wno-error=unknown-pragmas
|
||||
CXXFLAGS += -Wextra
|
||||
CXXFLAGS += -Weffc++
|
||||
CXXFLAGS += -Werror
|
||||
CXXFLAGS += -Wsuggest-override
|
||||
CXXFLAGS += -Wno-unknown-pragmas
|
||||
|
||||
LIBGCC = `$(CXX) $(CC_MARCH) -print-libgcc-file-name`
|
||||
|
||||
!ir = | $(DEV_DIR)/<pkg-config> |> clang $(OLEVEL) $(CXXFLAGS) $(CXXFLAGS_%e) $(CXXFLAGS_%f) `$(PKG_CONFIG) --cflags $(LIBS)` $(CPPFLAGS) -S -emit-llvm %f |> %B.ll
|
||||
|
||||
!asm = |> ^ CC %b^ @(CC_WRAPPER) $(CC) $(OLEVEL) $(CFLAGS) $(CFLAGS_%e) $(CFLAGS_%f) -D__ASSEMBLY__ $(CPPFLAGS) -c %f -o %o |> %B.o
|
||||
|
||||
!cc = | $(DEV_DIR)/<pkg-config> |> ^o CC %f^ @(CC_WRAPPER) $(CC) $(OLEVEL) $(CFLAGS) $(CFLAGS_%e) $(CFLAGS_%f) $(CPPFLAGS) `$(PKG_CONFIG) --cflags $(LIBS) $(LIBS_CFLAGS)` -c -fPIC %f -o %o |> %B.o
|
||||
|
||||
!cxx = | $(DEV_DIR)/<pkg-config> |> ^o CXX %b^ @(CC_WRAPPER) $(CXX) $(OLEVEL) $(CXXFLAGS) $(CXXFLAGS_%e) $(CXXFLAGS_%f) $(CPPFLAGS) `$(PKG_CONFIG) --cflags $(LIBS)` -c -fPIC %f -o %o |> %B.o
|
||||
|
||||
!ld = | $(DEV_DIR)/<lib> $(DEV_DIR)/<pkg-config> |> ^o LD %o^ $(LD) -o %o $(LDFLAGS) `$(PKG_CONFIG) --libs $(LIBS)` %f |>
|
||||
|
||||
!incbin = |> ^ incbin %f^ \
|
||||
export SYM=_binary_`echo %b | sed 's/\./_/g'`; \
|
||||
echo ".global ${SYM}_start, ${SYM}_end; .data; .align 4; ${SYM}_start:; .incbin \"%f\"; ${SYM}_end:" \
|
||||
| x86_64-unknown-genode-as $(AS_MARCH) -o %o - \
|
||||
|> binary_%b.o
|
|
@ -1,40 +0,0 @@
|
|||
TOOLCHAIN_CONFIGURED=$(TOOLCHAIN_CONFIGURED)X
|
||||
|
||||
ifeq (@(TUP_ARCH),i386)
|
||||
CC_MARCH = -march=i686 -m32
|
||||
LD_MARCH = -melf_i386
|
||||
AS_MARCH = -march=i686 --32
|
||||
endif
|
||||
|
||||
ifeq (@(TUP_ARCH),x86_64)
|
||||
CC_MARCH = -m64 -mcmodel=large
|
||||
LD_MARCH = -melf_x86_64
|
||||
endif
|
||||
|
||||
ifeq (@(TUP_ARCH),arm_v8)
|
||||
CC_MARCH = -march=armv8-a
|
||||
endif
|
||||
|
||||
ifdef CXXFLAGS
|
||||
CXXFLAGS = @(CXXFLAGS)
|
||||
endif
|
||||
|
||||
CXXFLAGS += -Wno-undefined-bool-conversion -Wno-unknown-attributes -Wsystem-headers -Werror -Wno-uninitialized -Wno-mismatched-tags
|
||||
|
||||
LIBGCC = `$(CC) $(CC_MARCH) -print-libgcc-file-name`
|
||||
|
||||
!ir = | $(DEV_DIR)/<pkg-config> |> clang $(OLEVEL) $(CXXFLAGS) $(CXXFLAGS_%e) $(CXXFLAGS_%f) `$(PKG_CONFIG) --cflags $(LIBS)` $(CPPFLAGS) -S -emit-llvm %f |> %B.ll
|
||||
|
||||
!asm = |> ^ CC %b^ @(CC_WRAPPER) $(CC) $(OLEVEL) $(CFLAGS) $(CFLAGS_%e) $(CFLAGS_%f) -D__ASSEMBLY__ $(CPPFLAGS) -c %f -o %o |> %B.o
|
||||
|
||||
!cc = | $(DEV_DIR)/<pkg-config> |> ^o CC %f^ @(CC_WRAPPER) $(CC) $(OLEVEL) $(CFLAGS) $(CFLAGS_%e) $(CFLAGS_%f) $(CPPFLAGS) `$(PKG_CONFIG) --cflags $(LIBS) $(LIBS_CFLAGS)` -c -fPIC %f -o %o |> %B.o
|
||||
|
||||
!cxx = | $(DEV_DIR)/<pkg-config> |> ^o CXX %b^ @(CC_WRAPPER) $(CXX) $(OLEVEL) $(CXXFLAGS) $(CXXFLAGS_%e) $(CXXFLAGS_%f) $(CPPFLAGS) `$(PKG_CONFIG) --cflags $(LIBS)` -c -fPIC %f -o %o |> %B.o
|
||||
|
||||
!ld = | $(DEV_DIR)/<lib> $(DEV_DIR)/<pkg-config> |> ^o LD %o^ $(LD) $(LDFLAGS) `$(PKG_CONFIG) --libs $(LIBS)` --whole-archive --start-group %f --no-whole-archive --end-group -o %o |>
|
||||
|
||||
!incbin = |> ^ incbin %f^ \
|
||||
export SYM=_binary_`echo %b | sed 's/\./_/g'`; \
|
||||
echo ".global ${SYM}_start, ${SYM}_end; .data; .align 4; ${SYM}_start:; .incbin \"%f\"; ${SYM}_end:" \
|
||||
| llvm-mc -filetype=obj - > %o \
|
||||
|> binary_%b.o
|
103
Tuprules.tup
103
Tuprules.tup
|
@ -1,103 +0,0 @@
|
|||
.gitignore
|
||||
|
||||
AR = @(AR)
|
||||
AS = @(AS)
|
||||
CC = @(CC)
|
||||
CXX = @(CXX)
|
||||
LD= @(LD)
|
||||
OBJCOPY = @(OBJCOPY)
|
||||
STRIP = @(STRIP)
|
||||
|
||||
OUT_DIR=$(TUP_CWD)/out
|
||||
DEV_DIR = $(TUP_CWD)/dev
|
||||
DEV_LIB_DIR = $(DEV_DIR)/lib
|
||||
|
||||
ifdef IS_GCC
|
||||
include Tuprules.gcc
|
||||
endif
|
||||
|
||||
ifdef IS_LLVM
|
||||
include Tuprules.llvm
|
||||
endif
|
||||
|
||||
ifeq ($(TOOLCHAIN_CONFIGURED),)
|
||||
error no toolchain configuration is active
|
||||
endif
|
||||
|
||||
ifneq ($(TOOLCHAIN_CONFIGURED),X)
|
||||
error "multiple toolchain configurations are active "
|
||||
endif
|
||||
|
||||
ifeq (@(TUP_ARCH),i386)
|
||||
X86 = y
|
||||
endif
|
||||
|
||||
ifeq (@(TUP_ARCH),x86_64)
|
||||
X86 = y
|
||||
endif
|
||||
|
||||
GENODE_DIR = $(TUP_CWD)
|
||||
|
||||
!prg = | $(DEV_DIR)/<lib> $(DEV_DIR)/<pkg-config> \
|
||||
|> ^o LD %o^ $(LD) -o %o $(LD_MARCH) $(LDFLAGS) -L$(DEV_LIB_DIR) %f `$(PKG_CONFIG) --libs $(LIBS) genode-prg` $(LIBGCC) |> %d
|
||||
|
||||
!lib = | $(DEV_DIR)/<lib> $(DEV_DIR)/<pkg-config> |> ^o LD %o^ $(LD) $(LD_MARCH) %f $(LDFLAGS) `$(PKG_CONFIG) --libs genode-lib $(LIBS)` -L$(DEV_LIB_DIR) -o %o |> %d.lib.so
|
||||
|
||||
!collect_bin = |> ^ COLLECT %b^ \
|
||||
$(STRIP) -o %o %f \
|
||||
|> $(OUT_DIR)/bin/%b $(OUT_DIR)/<bin>
|
||||
|
||||
!collect_shared = |> ^ COLLECT %b^ \
|
||||
cp %f %o \
|
||||
|> $(OUT_DIR)/lib/%b $(OUT_DIR)/<lib>
|
||||
|
||||
!collect_static = |> ^ COLLECT %b^ \
|
||||
cp %f %o \
|
||||
|> $(DEV_LIB_DIR)/%b \
|
||||
$(DEV_DIR)/<lib> \
|
||||
|
||||
PKG_CONFIG_DIR = $(DEV_DIR)/lib/pkgconfig
|
||||
|
||||
ifdef NIX_OUTPUTS_DEV
|
||||
export PKG_CONFIG_PATH
|
||||
PKG_CONFIG = PKG_CONFIG_PATH=$(PKG_CONFIG_DIR):$PKG_CONFIG_PATH @(PKGCONFIG)
|
||||
else
|
||||
PKG_CONFIG = PKG_CONFIG_PATH=$(PKG_CONFIG_DIR) @(PKGCONFIG)
|
||||
endif
|
||||
|
||||
CFLAGS += -g
|
||||
CXXFLAGS += -g
|
||||
|
||||
ifdef OLEVEL
|
||||
OLEVEL = @(OLEVEL)
|
||||
else
|
||||
OLEVEL = -O2
|
||||
endif
|
||||
|
||||
!strip = |> $(STRIP) -o %o %f |>
|
||||
|
||||
!ln = |> ln -s %f %o |>
|
||||
|
||||
!ar = |> $(AR) -rcs %o %f |> %d.a
|
||||
|
||||
GIT_VERSION = `git describe || echo @(VERSION)`
|
||||
|
||||
SED_PKGCONFIG_FLAGS += -e "s|@VERSION@|$(GIT_VERSION)|"
|
||||
|
||||
!sed_pkgconfig_file = |> ^o SED %B^ \
|
||||
sed $(SED_PKGCONFIG_FLAGS) $(SED_FLAGS) < %f > %o; \
|
||||
$(PKG_CONFIG) --validate %o; \
|
||||
|> $(PKG_CONFIG_DIR)/%B $(DEV_DIR)/<pkg-config>
|
||||
|
||||
!sed_pkgconfig_flags = |> ^o SED %d.pc^ \
|
||||
sed $(SED_PKGCONFIG_FLAGS) $(SED_FLAGS) > %o; \
|
||||
$(PKG_CONFIG) --validate %o; \
|
||||
|> $(PKG_CONFIG_DIR)/%d.pc $(DEV_DIR)/<pkg-config>
|
||||
|
||||
!emit_lib_pkg_config = |> ^ emit %d.a pkg-config^ \
|
||||
echo Name: %d >> %o; \
|
||||
echo Description: Genode %d library >> %o; \
|
||||
echo Version: $(GIT_VERSION) >> %o; \
|
||||
echo Libs: -l:%d.a >> %o; \
|
||||
$(PKG_CONFIG) --validate %o; \
|
||||
|> $(PKG_CONFIG_DIR)/%d.pc $(DEV_DIR)/<pkg-config>
|
|
@ -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-----
|
||||
|
|
|
@ -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-----
|
||||
|
|
60
doc/news.txt
60
doc/news.txt
|
@ -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
|
||||
##############################################
|
||||
|
||||
|
|
|
@ -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 """.
|
||||
|
||||
: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].
|
||||
|
278
doc/road_map.txt
278
doc/road_map.txt
|
@ -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
|
||||
|
||||
|
|
56
flake.lock
56
flake.lock
|
@ -1,56 +0,0 @@
|
|||
{
|
||||
"inputs": {
|
||||
"genodepkgs": {
|
||||
"inputs": {
|
||||
"dhall-haskell": {
|
||||
"inputs": {
|
||||
"nixpkgs": {
|
||||
"inputs": {},
|
||||
"narHash": "sha256-wJg4DA700SoQbEz61448sR6BgxRa1R92K3vvCV1g+HY=",
|
||||
"originalUrl": "git+https://github.com/nixos/nixpkgs.git?ref=18.09-beta&rev=1d4de0d552ae9aa66a5b8dee5fb0650a4372d148",
|
||||
"url": "git+https://github.com/nixos/nixpkgs.git?ref=18.09-beta&rev=1d4de0d552ae9aa66a5b8dee5fb0650a4372d148"
|
||||
},
|
||||
"nixpkgsStaticLinux": {
|
||||
"inputs": {},
|
||||
"narHash": "sha256-famU3pJZ4vkElV9qc71HmyRVSvcrAhfMZ0UJKpmmKP8=",
|
||||
"originalUrl": "git+https://github.com/nh2/nixpkgs.git?ref=static-haskell-nix-stack-dhall-working",
|
||||
"url": "git+https://github.com/nh2/nixpkgs.git?ref=static-haskell-nix-stack-dhall-working&rev=925aac04f4ca58aceb83beef18cb7dae0715421b"
|
||||
}
|
||||
},
|
||||
"narHash": "sha256-KJl9ZLcMcEsLSPcwcWoc0Ac74/6HKC9LkVMeLwhyhlg=",
|
||||
"originalUrl": "git+https://github.com/dhall-lang/dhall-haskell?ref=flake",
|
||||
"url": "git+https://github.com/dhall-lang/dhall-haskell?ref=flake&rev=aea28adf3d10ff1982aa4ddd176d1476251b932f"
|
||||
},
|
||||
"genode-depot": {
|
||||
"inputs": {
|
||||
"nixpkgs": {
|
||||
"inputs": {},
|
||||
"narHash": "sha256-NB+H7zK3BB//zM127FqgbG4iAfY+nS/IOyO+uGWA5Ho=",
|
||||
"originalUrl": "nixpkgs",
|
||||
"url": "github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9"
|
||||
}
|
||||
},
|
||||
"narHash": "sha256-7eL2MfGgeEaIwJXPc4LQ7pBa4JeGicm9th7onjKgzsE=",
|
||||
"originalUrl": "git+https://gitea.c3d2.de/ehmry/genode-depot.git",
|
||||
"url": "git+https://gitea.c3d2.de/ehmry/genode-depot.git?ref=master&rev=8c2aafed45b4075e37f1cd93de0ebf93f38c83c3"
|
||||
},
|
||||
"nixpkgs": {
|
||||
"inputs": {},
|
||||
"narHash": "sha256-EqxCk6ORqq4fkewWttpvks0VycBec9X9spAZ+Pq/CEI=",
|
||||
"originalUrl": "github:ehmry/nixpkgs",
|
||||
"url": "github:ehmry/nixpkgs/cf50f3b8bdc28832249afab6bca68acad832e011"
|
||||
}
|
||||
},
|
||||
"narHash": "sha256-78eloDNkEjWAckNLbfNait0zb6QBG4QxltX6FyV1vAk=",
|
||||
"originalUrl": "git+https://git.sr.ht/~ehmry/genodepkgs",
|
||||
"url": "git+https://git.sr.ht/~ehmry/genodepkgs?ref=master&rev=dad28cc17b17542ada59ba2005fbf1af5d5f8209"
|
||||
},
|
||||
"nixpkgs": {
|
||||
"inputs": {},
|
||||
"narHash": "sha256-NB+H7zK3BB//zM127FqgbG4iAfY+nS/IOyO+uGWA5Ho=",
|
||||
"originalUrl": "nixpkgs",
|
||||
"url": "github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9"
|
||||
}
|
||||
},
|
||||
"version": 3
|
||||
}
|
14
flake.nix
14
flake.nix
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
description = "Genode development flake";
|
||||
|
||||
edition = 201909;
|
||||
|
||||
inputs.genodepkgs.uri = "git+https://git.sr.ht/~ehmry/genodepkgs";
|
||||
|
||||
outputs = { self, nixpkgs, genodepkgs }: {
|
||||
|
||||
devShell.x86_64-linux =
|
||||
genodepkgs.packages.x86_64-linux-x86_64-genode.genode.base;
|
||||
|
||||
};
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
# Tup rules that are local to this Git repo and
|
||||
# should not be shared with other projects.
|
||||
|
||||
&LD_SCRIPT_SO = base/src/ld/genode_rel.ld
|
||||
|
||||
ifeq (@(TUP_ARCH),x86_64)
|
||||
ASM_SYM_DEPENDENCY = movq \1@GOTPCREL(%rip), %rax
|
||||
else
|
||||
ASM_SYM_DEPENDENCY = .long \1
|
||||
endif
|
||||
|
||||
!abi_stub = |> ^ STUB %o^\
|
||||
sed \
|
||||
-e "s/^\(\w\+\) D \(\w\+\)\$/.data; .global \1; .type \1,%%object; .size \1,\2; \1:/" \
|
||||
-e "s/^\(\w\+\) V/.data; .weak \1; .type \1,%%object; \1:/" \
|
||||
-e "s/^\(\w\+\) T/.text; .global \1; .type \1,%%function; \1:/" \
|
||||
-e "s/^\(\w\+\) R \(\w\+\)\$/.section .rodata; .global \1; .type \1,%%object; .size \1,\2; \1:/" \
|
||||
-e "s/^\(\w\+\) W/.text; .weak \1; .type \1,%%function; \1:/" \
|
||||
-e "s/^\(\w\+\) B \(\w\+\)\$/.bss; .global \1; .type \1,%%object; .size \1,\2; \1:/" \
|
||||
-e "s/^\(\w\+\) U/.text; .global \1; $(ASM_SYM_DEPENDENCY)/" \
|
||||
%f > stub.s; \
|
||||
$(CC) $(CC_MARCH) -x assembler -c stub.s; \
|
||||
$(LD) -o %o \
|
||||
-shared \
|
||||
-T &(LD_SCRIPT_SO) \
|
||||
stub.o; \
|
||||
rm -v stub.o stub.s; \
|
||||
|> $(DEV_LIB_DIR)/%B.lib.so $(DEV_DIR)/<lib>
|
||||
|
||||
BASE_DIR = $(GENODE_DIR)/repos/base
|
||||
&BASE_DIR = base
|
||||
|
||||
ifeq (@(TUP_ARCH),i386)
|
||||
CPPFLAGS += -I$(BASE_DIR)/include/spec/x86_32
|
||||
CPPFLAGS += -I$(BASE_DIR)/include/spec/x86
|
||||
CPPFLAGS += -I$(BASE_DIR)/include/spec/32bit
|
||||
endif
|
||||
|
||||
ifeq (@(TUP_ARCH),x86_64)
|
||||
CPPFLAGS += -I$(BASE_DIR)/include/spec/x86_64
|
||||
CPPFLAGS += -I$(BASE_DIR)/include/spec/x86
|
||||
CPPFLAGS += -I$(BASE_DIR)/include/spec/64bit
|
||||
endif
|
||||
|
||||
ifeq (@(TUP_ARCH),arm64)
|
||||
CPPFLAGS += -I$(BASE_DIR)/include/spec/arm_64
|
||||
CPPFLAGS += -I$(BASE_DIR)/include/spec/64bit
|
||||
endif
|
||||
|
||||
CPPFLAGS += -I$(BASE_DIR)/include
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 c7e2a3eca5820b2304b4520d0fc831ede73691f2
|
||||
2020-02-27 6311f83c887384fa01828af695bae799b148e0ad
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{ }
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 9a459c4fd8a907810d91041751affcf3e119fcb1
|
||||
2020-02-27 82bbd7275951340ff82061af8bc2cce41f1519e3
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 d8ff4913b8aa117aef77a7918bc82808e38a4ee7
|
||||
2020-02-27 c5602daf28cdc5d005a26f408527e64ab905197e
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 a750c8988106d5c26e46dcceb1f76bfd7bfa1457
|
||||
2020-02-27 a3912478467dcf01ab6379502bb15719b748c388
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 0c0a26b6ddb0ee5261f0be30f229e9ce04b61eda
|
||||
2020-02-27 e7f8bca57dbed6597e46aafd0256dfd5a6ac42c3
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 bce6f0a8f1f46f8edf62ef2180dbfc949123432d
|
||||
2020-02-27 b03dfe2bde7fe637c0a7eff9e709845e64b4d09c
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 307d01e531dbbcd672463a4ea090f40bb399cae8
|
||||
2020-02-27 a1eb6dfc01d82b598f0778c0b74f2a49387cc42d
|
||||
|
|
|
@ -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 =
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
ifeq (@(TUP_ARCH),x86_64)
|
||||
CPPFLAGS += -I$(TUP_CWD)/include/spec/x86_64
|
||||
endif
|
||||
|
||||
CPPFLAGS += -I$(TUP_CWD)/include
|
||||
|
||||
include &(BASE_DIR)/Tuprules.tup
|
||||
REP_DIR = $(TUP_CWD)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 c60d834ce54a46a946c36249784e734e06274d97
|
||||
2020-02-27 e1a80cef41a848e8f63df9a249a4e57148e66331
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 e9232754efd81c14aa65d4852d276852f591f3e5
|
||||
2020-02-27 bd79fb9d11cef09e99ba545408128a605b47814a
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 2ab0250606cee0da4f08ac08f7f33c743f32c88c
|
||||
2020-02-27 879f89b08454a6aab78bab0c018d1902af792a47
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 7780e0570ac0277d678dee76a579a9d9f9a1a776
|
||||
2020-02-27 447889337c681d7b9f68c637f9a3eac3abfd2f30
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 2dee497b7892f706236fdbfabae53bbd4e62463b
|
||||
2020-02-27 42c284564d38f3bdbd6b30e58280a2f699b657f9
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 efd164d66086a998484d7413c5416e3aa128e560
|
||||
2020-02-27 9d9e438a93c416499bb7b414bbcf2de7f2d3650f
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 25f54b8744778f0860ac2a93c11ee6b1cd16d0c9
|
||||
2020-02-27 ff3428ffdd5d60514fa5028b003b54327da895ad
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 ceeaef3ad58fc5b88cf4686aa42f50fd254063e3
|
||||
2020-02-27 84aec73deeae79a6b34374fe859ea5333d05da69
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 aee36abdef456d2d1c6bba023f16cbca08eceabe
|
||||
2020-02-27 e87fc4e86962227db5c41bf048eeacf1c27d04c1
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 ede7ce464c3f4b8486fd93413088a1b83fbf796a
|
||||
2020-02-27 ebd97e5400e2b99fd810cd233c0f881ede48f376
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 2bea4132b9ab877e802cfb81ad3c62bda0c2bc50
|
||||
2020-02-27 5d0722736647b538eb52b35286b7734581402426
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 807893480c51457cad7e00e1275eff9749c91c68
|
||||
2020-02-27 1caed3e6b2d8bc98948b9fd43f3bb26abd52f780
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 6a3f12cd6429f5d5bcf617cdd3ea9d345e8614ad
|
||||
2020-02-27 6d72eb037774a58fc079c5df7bd5b7348c8799b4
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 a318db7d985930e3f58ce3bccce290bc13aaedab
|
||||
2020-02-27 41e345219f64781ef6cb472d4f9d374b0295328b
|
||||
|
|
|
@ -1 +1 @@
|
|||
2019-11-25 75f1b89ea50fdfd0a69c33dee4ba1e120d49fad5
|
||||
2020-02-27 c2481cbfd690b653b38c6bfe09c296094240e90d
|
||||
|
|
|
@ -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>}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
CPPFLAGS += -I$(TUP_CWD)/include
|
||||
CPPFLAGS += -I$(BASE_DIR)/src/include
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
ifeq (@(TUP_ARCH),x86_64)
|
||||
CPPFLAGS += -I$(TUP_CWD)/spec/x86_64
|
||||
NR_OF_CPUS = 32
|
||||
CPPFLAGS += -DNR_OF_CPUS=$(NR_OF_CPUS)
|
||||
LDFLAGS += --defsym NR_OF_CPUS=$(NR_OF_CPUS)
|
||||
endif
|
||||
|
||||
GEN_CORE_DIR = $(BASE_DIR)/src/core
|
||||
|
||||
# add include paths
|
||||
CPPFLAGS += -I$(BASE_DIR)/../base-hw/src/core
|
||||
CPPFLAGS += -I$(GEN_CORE_DIR)/include
|
||||
CPPFLAGS += -I$(BASE_DIR)/../base-hw/src/include
|
||||
CPPFLAGS += -I$(BASE_DIR)/src/include
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += $(GEN_CORE_DIR)/core_log.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/core_mem_alloc.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/core_rpc_cap_alloc.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/cpu_session_component.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/cpu_thread_component.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/dataspace_component.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/default_log.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/dump_alloc.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/heartbeat.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/io_mem_session_component.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/main.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/pd_session_component.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/pd_session_support.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/platform_rom_modules.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/ram_dataspace_factory.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/region_map_component.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/rom_session_component.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/signal_receiver.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/signal_transmitter_noinit.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/stack_area.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/trace_session_component.cc
|
||||
SRC_CC += $(GEN_CORE_DIR)/version.cc
|
||||
|
||||
CXXFLAGS_$(GEN_CORE_DIR)/version.cc += -DGENODE_VERSION=\"`git describe`\"
|
||||
|
||||
SRC_CC += $(TUP_CWD)/capability.cc
|
||||
SRC_CC += $(TUP_CWD)/core_log_out.cc
|
||||
SRC_CC += $(TUP_CWD)/core_region_map.cc
|
||||
SRC_CC += $(TUP_CWD)/cpu_session_support.cc
|
||||
SRC_CC += $(TUP_CWD)/env.cc
|
||||
SRC_CC += $(TUP_CWD)/io_mem_session_support.cc
|
||||
SRC_CC += $(TUP_CWD)/irq_session_component.cc
|
||||
SRC_CC += $(TUP_CWD)/kernel_log.cc
|
||||
SRC_CC += $(TUP_CWD)/native_pd_component.cc
|
||||
SRC_CC += $(TUP_CWD)/native_utcb.cc
|
||||
SRC_CC += $(TUP_CWD)/pager.cc
|
||||
SRC_CC += $(TUP_CWD)/platform.cc
|
||||
SRC_CC += $(TUP_CWD)/platform_pd.cc
|
||||
SRC_CC += $(TUP_CWD)/platform_thread.cc
|
||||
SRC_CC += $(TUP_CWD)/ram_dataspace_support.cc
|
||||
SRC_CC += $(TUP_CWD)/region_map_support.cc
|
||||
SRC_CC += $(TUP_CWD)/stack_area_addr.cc
|
||||
SRC_CC += $(TUP_CWD)/thread_start.cc
|
||||
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/cpu.cc
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/cpu_scheduler.cc
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/double_list.cc
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/init.cc
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/ipc_node.cc
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/irq.cc
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/kernel.cc
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/object.cc
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/signal_receiver.cc
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/thread.cc
|
||||
SRC_CC_KERNEL += $(TUP_CWD)/kernel/timer.cc
|
|
@ -17,7 +17,7 @@
|
|||
#include <base/internal/raw_write_string.h>
|
||||
|
||||
#include <core_log.h>
|
||||
#include "kernel/log.h"
|
||||
#include <kernel/log.h>
|
||||
|
||||
|
||||
void Genode::Core_log::out(char const c) { Kernel::log(c); }
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <core_region_map.h>
|
||||
#include "map_local.h"
|
||||
#include <map_local.h>
|
||||
#include <util.h>
|
||||
#include <base/heap.h>
|
||||
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
|
||||
/* core includes */
|
||||
#include <cpu_session_component.h>
|
||||
#include "kernel/configuration.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); }
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
*/
|
||||
|
||||
/* base-hw includes */
|
||||
#include "kernel/core_interface.h"
|
||||
#include <kernel/core_interface.h>
|
||||
|
||||
/* core includes */
|
||||
#include "kernel/irq.h"
|
||||
#include <kernel/irq.h>
|
||||
#include <irq_root.h>
|
||||
#include <core_env.h>
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
*/
|
||||
|
||||
/* core includes */
|
||||
#include "cpu.h"
|
||||
#include "kernel.h"
|
||||
#include "thread.h"
|
||||
#include "irq.h"
|
||||
#include "pd.h"
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/irq.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <board.h>
|
||||
#include <hw/assert.h>
|
||||
#include <hw/boot_info.h>
|
||||
|
@ -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(); }
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
|
||||
/* core includes */
|
||||
#include <board.h>
|
||||
#include "cpu_context.h"
|
||||
#include "irq.h"
|
||||
#include "inter_processor_work.h"
|
||||
#include "thread.h"
|
||||
#include <kernel/cpu_context.h>
|
||||
#include <kernel/irq.h>
|
||||
#include <kernel/inter_processor_work.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
@ -69,7 +69,6 @@ namespace Kernel
|
|||
* publicly provide via a 'typedef Genode::Cpu::Arch_regs Arch_regs'.
|
||||
* Then, the 'Genode::Cpu' could be inherited privately.
|
||||
*/
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
|
||||
class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
|
||||
|
@ -170,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; }
|
||||
|
@ -179,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; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
#define _CORE__KERNEL__CPU_CONTEXT_H_
|
||||
|
||||
/* core includes */
|
||||
#include "cpu_scheduler.h"
|
||||
#include "timer.h"
|
||||
#include <kernel/cpu_scheduler.h>
|
||||
#include <kernel/timer.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
@ -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 **
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include <kernel/cpu.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
|
|
|
@ -13,19 +13,21 @@
|
|||
|
||||
#include <base/log.h>
|
||||
#include <hw/assert.h>
|
||||
#include "cpu_scheduler.h"
|
||||
#include <kernel/cpu_scheduler.h>
|
||||
|
||||
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); }
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
/* core includes */
|
||||
#include <util.h>
|
||||
#include <util/misc_math.h>
|
||||
#include "configuration.h"
|
||||
#include "double_list.h"
|
||||
#include <kernel/configuration.h>
|
||||
#include <kernel/double_list.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
@ -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; }
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include <kernel/cpu.h>
|
||||
|
||||
void Kernel::Cpu::Ipi::occurred() { }
|
||||
|
||||
|
|
|
@ -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 "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;
|
||||
}
|
|
@ -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_ */
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
*/
|
||||
|
||||
/* core includes */
|
||||
#include "pd.h"
|
||||
#include "cpu.h"
|
||||
#include "kernel.h"
|
||||
#include "lock.h"
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/lock.h>
|
||||
#include <platform_pd.h>
|
||||
#include <board.h>
|
||||
#include <platform_thread.h>
|
||||
|
|
|
@ -19,74 +19,16 @@
|
|||
#include <base/internal/native_utcb.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform_pd.h>
|
||||
#include "ipc_node.h"
|
||||
#include "pd.h"
|
||||
#include "kernel.h"
|
||||
#include "thread.h"
|
||||
#include <kernel/ipc_node.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();
|
||||
|
|
|
@ -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 struct 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_ */
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
*/
|
||||
|
||||
/* core includes */
|
||||
#include "kernel.h"
|
||||
#include "cpu.h"
|
||||
#include "irq.h"
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
|
||||
void Kernel::Irq::disable() const {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <base/internal/unmanaged_singleton.h>
|
||||
|
||||
/* core includes */
|
||||
#include "signal_receiver.h"
|
||||
#include <kernel/signal_receiver.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ namespace Genode
|
|||
class Kernel::Irq : Genode::Avl_node<Irq>
|
||||
{
|
||||
friend class Genode::Avl_tree<Irq>;
|
||||
friend struct Genode::Avl_node<Irq>;
|
||||
friend class Genode::Avl_node<Irq>;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -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_ */
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
*/
|
||||
|
||||
/* core includes */
|
||||
#include "cpu.h"
|
||||
#include "lock.h"
|
||||
#include "kernel.h"
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/kernel.h>
|
||||
|
||||
|
||||
extern "C" void kernel()
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
#include <cpu/atomic.h>
|
||||
#include <cpu/memory_barrier.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "lock.h"
|
||||
#include "kernel.h"
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/kernel.h>
|
||||
|
||||
Kernel::Lock & Kernel::data_lock()
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "object.h"
|
||||
#include "pd.h"
|
||||
#include "kernel.h"
|
||||
#include <kernel/object.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/kernel.h>
|
||||
|
||||
#include <util/construct_at.h>
|
||||
|
||||
|
@ -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 = list.first(); oi; oi = list.first())
|
||||
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 **
|
||||
|
@ -24,18 +111,18 @@ Object::~Object()
|
|||
|
||||
void Object_identity::invalidate()
|
||||
{
|
||||
for (Object_identity_reference * oir = list.first(); oir; oir = list.first())
|
||||
for (Object_identity_reference * oir = first(); oir; oir = first())
|
||||
oir->invalidate();
|
||||
|
||||
if (_object) {
|
||||
_object->list.remove(this);
|
||||
_object->remove(this);
|
||||
_object = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Object_identity::Object_identity(Object & object)
|
||||
: _object(&object) { _object->list.insert(this); }
|
||||
: _object(&object) { _object->insert(this); }
|
||||
|
||||
|
||||
Object_identity::~Object_identity() { invalidate(); }
|
||||
|
@ -50,7 +137,7 @@ Object_identity_reference::find(Pd &pd)
|
|||
{
|
||||
if (!_identity) return nullptr;
|
||||
|
||||
for (Object_identity_reference * oir = _identity->list.first();
|
||||
for (Object_identity_reference * oir = _identity->first();
|
||||
oir; oir = oir->next())
|
||||
if (&pd == &(oir->_pd)) return oir;
|
||||
return nullptr;
|
||||
|
@ -79,7 +166,7 @@ Object_identity_reference * Object_identity_reference::factory(void * dst,
|
|||
|
||||
|
||||
void Object_identity_reference::invalidate() {
|
||||
if (_identity) _identity->list.remove(this);
|
||||
if (_identity) _identity->remove(this);
|
||||
_identity = nullptr;
|
||||
}
|
||||
|
||||
|
@ -88,7 +175,7 @@ Object_identity_reference::Object_identity_reference(Object_identity *oi,
|
|||
Pd &pd)
|
||||
: _capid(pd.capid_alloc().alloc()), _identity(oi), _pd(pd), _in_utcbs(0)
|
||||
{
|
||||
if (_identity) _identity->list.insert(this);
|
||||
if (_identity) _identity->insert(this);
|
||||
_pd.cap_tree().insert(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,16 +23,25 @@
|
|||
/* core includes */
|
||||
#include <kernel/core_interface.h>
|
||||
#include <kernel/interface.h>
|
||||
#include "kernel.h"
|
||||
#include <kernel/kernel.h>
|
||||
|
||||
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
|
||||
*/
|
||||
struct Object;
|
||||
class Object;
|
||||
|
||||
/**
|
||||
* An object identity helps to distinguish different capability owners
|
||||
|
@ -73,16 +82,45 @@ namespace Kernel
|
|||
}
|
||||
|
||||
|
||||
struct Kernel::Object
|
||||
class Kernel::Object : private Object_identity_list
|
||||
{
|
||||
Object_identity_list list { };
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
class Kernel::Object_identity
|
||||
: public Object_identity_list::Element
|
||||
: public Object_identity_list::Element,
|
||||
public Kernel::Object_identity_reference_list
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -96,13 +134,11 @@ class Kernel::Object_identity
|
|||
|
||||
public:
|
||||
|
||||
Kernel::Object_identity_reference_list list { };
|
||||
|
||||
Object_identity(Object & object);
|
||||
~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(); }
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
*/
|
||||
|
||||
/* core includes */
|
||||
#include "signal_receiver.h"
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
|
||||
/* core includes */
|
||||
#include <hw/assert.h>
|
||||
#include "cpu.h"
|
||||
#include "kernel.h"
|
||||
#include "thread.h"
|
||||
#include "irq.h"
|
||||
#include "log.h"
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/irq.h>
|
||||
#include <kernel/log.h>
|
||||
#include <map_local.h>
|
||||
#include <platform_pd.h>
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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,12 +26,18 @@
|
|||
#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
|
||||
{
|
||||
struct Thread_fault;
|
||||
class Thread;
|
||||
struct Core_thread;
|
||||
class Core_thread;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
*/
|
||||
|
||||
/* Core includes */
|
||||
#include "cpu.h"
|
||||
#include "timer.h"
|
||||
#include "configuration.h"
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/timer.h>
|
||||
#include <kernel/configuration.h>
|
||||
#include <hw/assert.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
/* base-hw includes */
|
||||
#include <kernel/types.h>
|
||||
#include "irq.h"
|
||||
#include <kernel/irq.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list.h>
|
||||
|
@ -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();
|
||||
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
namespace Genode { class Vm_state; }
|
||||
|
||||
/* core includes */
|
||||
#include "cpu_context.h"
|
||||
#include "kernel.h"
|
||||
#include "pd.h"
|
||||
#include "signal_receiver.h"
|
||||
#include <kernel/cpu_context.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/signal_receiver.h>
|
||||
|
||||
#include <board.h>
|
||||
|
||||
|
@ -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 **
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
|
||||
/* core includes */
|
||||
#include "thread.h"
|
||||
#include <kernel/thread.h>
|
||||
|
||||
void Kernel::Thread::_call_new_vm() { user_arg_0(-1); }
|
||||
void Kernel::Thread::_call_delete_vm() { user_arg_0(-1); }
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
*/
|
||||
|
||||
/* core includes */
|
||||
#include "thread.h"
|
||||
#include "vm.h"
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/vm.h>
|
||||
|
||||
void Kernel::Thread::_call_new_vm()
|
||||
{
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include <board.h>
|
||||
#include <platform.h>
|
||||
#include "kernel/log.h"
|
||||
#include <kernel/log.h>
|
||||
|
||||
|
||||
void Kernel::log(char const c)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue