mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-11 13:22:33 +00:00
parent
c20bfd4414
commit
76cb06794a
repos/libports
60
repos/libports/run/libc_with_libc.run
Normal file
60
repos/libports/run/libc_with_libc.run
Normal file
@ -0,0 +1,60 @@
|
||||
set build_components {
|
||||
core init drivers/timer test/libc_with_libc
|
||||
}
|
||||
|
||||
source ${genode_dir}/repos/base/run/platform_drv.inc
|
||||
append_platform_drv_build_components
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
set config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Timer"/> </provides>
|
||||
</start>}
|
||||
|
||||
append_platform_drv_config
|
||||
|
||||
append config {
|
||||
<start name="test-libc_with_libc">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config>
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
<libc stdout="/dev/log"/>
|
||||
</config>
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
install_config $config
|
||||
|
||||
set boot_modules {
|
||||
core init timer
|
||||
ld.lib.so libc.lib.so
|
||||
test-libc_with_libc
|
||||
}
|
||||
|
||||
append_platform_drv_boot_modules
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
append qemu_args " -nographic -m 64 "
|
||||
|
||||
run_genode_until ".*finished with_libc tests.*\n" 10
|
@ -370,6 +370,8 @@ struct Libc::Kernel
|
||||
|
||||
State _state = KERNEL;
|
||||
|
||||
Application_code *_nested_app_code = nullptr;
|
||||
|
||||
Application_code *_app_code = nullptr;
|
||||
bool _app_returned = false;
|
||||
|
||||
@ -507,6 +509,25 @@ struct Libc::Kernel
|
||||
_valid_user_context = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* During the supension of the application code a nested
|
||||
* Libc::with_libc() call took place, which will be executed
|
||||
* before returning to the first Libc::with_libc() call.
|
||||
*/
|
||||
if (_nested_app_code) {
|
||||
|
||||
/*
|
||||
* We have to explicitly set the user context back to true
|
||||
* because we are borrowing it to execute our nested application
|
||||
* code.
|
||||
*/
|
||||
_valid_user_context = true;
|
||||
|
||||
_nested_app_code->execute();
|
||||
_nested_app_code = nullptr;
|
||||
_longjmp(_kernel_context, 1);
|
||||
}
|
||||
|
||||
return timeout_ms > 0 ? _main_timeout.duration_left() : 0;
|
||||
}
|
||||
|
||||
@ -547,6 +568,7 @@ struct Libc::Kernel
|
||||
|
||||
while (!_app_returned) {
|
||||
_env.ep().wait_and_dispatch_one_signal();
|
||||
|
||||
if (_resume_main_once && !_setjmp(_kernel_context))
|
||||
_switch_to_user();
|
||||
}
|
||||
@ -643,6 +665,23 @@ struct Libc::Kernel
|
||||
|
||||
_resume_main();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if main is currently suspended
|
||||
*/
|
||||
bool main_suspended() { return _state == KERNEL; }
|
||||
|
||||
/**
|
||||
* Execute application code while already executing in run()
|
||||
*/
|
||||
void nested_execution(Libc::Application_code &app_code)
|
||||
{
|
||||
_nested_app_code = &app_code;
|
||||
|
||||
if (!_setjmp(_kernel_context)) {
|
||||
_switch_to_user();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -722,7 +761,12 @@ void Libc::execute_in_application_context(Libc::Application_code &app_code)
|
||||
static bool nested = false;
|
||||
|
||||
if (nested) {
|
||||
error("nested call of with_libc() detected");
|
||||
|
||||
if (kernel->main_suspended()) {
|
||||
kernel->nested_execution(app_code);
|
||||
} else {
|
||||
app_code.execute();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
143
repos/libports/src/test/libc_with_libc/main.cc
Normal file
143
repos/libports/src/test/libc_with_libc/main.cc
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* \brief Test Libc::with_libc nesting
|
||||
* \author Josef Soentgen
|
||||
* \date 2017-02-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <libc/component.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <sys/select.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
struct Test
|
||||
{
|
||||
int _id;
|
||||
|
||||
Test(Env &env, int id) : _id(id) { log("Start test ", _id); }
|
||||
|
||||
virtual ~Test() { log("Finished test ", _id); }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Explicitly_nested test
|
||||
*
|
||||
* Call with_libc from within with_libc.
|
||||
*/
|
||||
struct Explicitly_nested : Test
|
||||
{
|
||||
Explicitly_nested(Env &env, int id) : Test(env, id)
|
||||
{
|
||||
log("calling with_libc");
|
||||
Libc::with_libc([&] () {
|
||||
|
||||
log("calling with_libc nested");
|
||||
Libc::with_libc([&] () {
|
||||
printf("Hello from with_libc nested\n");
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Implicitly_nested test
|
||||
*
|
||||
* Call with_libc from within a signal handler while being
|
||||
* suspended in a select() call.
|
||||
*/
|
||||
struct Implicitly_nested : Test
|
||||
{
|
||||
Env &_env;
|
||||
|
||||
void _handle()
|
||||
{
|
||||
log("calling with_libc from signal handler");
|
||||
Libc::with_libc([&] () {
|
||||
|
||||
printf("Hello from with_libc in signal handler\n");
|
||||
});
|
||||
}
|
||||
|
||||
Signal_handler<Implicitly_nested> _dispatcher {
|
||||
_env.ep(), *this, &Implicitly_nested::_handle };
|
||||
|
||||
Implicitly_nested(Env &env, int id)
|
||||
: Test(env, id), _env(env)
|
||||
{
|
||||
log("calling with_libc");
|
||||
|
||||
Libc::with_libc([&] () {
|
||||
Signal_transmitter(_dispatcher).submit();
|
||||
|
||||
unsigned const secs = 3;
|
||||
|
||||
log("calling select with ", secs, " secs timeout from with_libc");
|
||||
|
||||
timeval to { secs, 0 };
|
||||
select(0, nullptr, nullptr, nullptr, &to);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Explicitly_triple_nested test
|
||||
*
|
||||
* Call with_libc from within with_libc from within with_libc.
|
||||
*/
|
||||
struct Explicitly_triple_nested : Test
|
||||
{
|
||||
Explicitly_triple_nested(Env &env, int id) : Test(env, id)
|
||||
{
|
||||
log("calling with_libc");
|
||||
Libc::with_libc([&] () {
|
||||
|
||||
log("calling with_libc nested");
|
||||
Libc::with_libc([&] () {
|
||||
|
||||
log("calling with_libc nested again");
|
||||
Libc::with_libc([&] () {
|
||||
|
||||
printf("Hello from with_libc nested again\n");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Main
|
||||
{
|
||||
Constructible<Explicitly_nested> test_1;
|
||||
Constructible<Implicitly_nested> test_2;
|
||||
Constructible<Explicitly_triple_nested> test_3;
|
||||
|
||||
Main(Env &env)
|
||||
{
|
||||
log("--- start with_libc tests ---");
|
||||
|
||||
test_1.construct(env, 1); test_1.destruct();
|
||||
test_2.construct(env, 2); test_2.destruct();
|
||||
test_3.construct(env, 3); test_3.destruct();
|
||||
|
||||
log("--- finished with_libc tests ---");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Libc::Component::construct(Libc::Env &env) { static Main main(env); }
|
3
repos/libports/src/test/libc_with_libc/target.mk
Normal file
3
repos/libports/src/test/libc_with_libc/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
TARGET = test-libc_with_libc
|
||||
SRC_CC = main.cc
|
||||
LIBS = libc
|
Loading…
x
Reference in New Issue
Block a user