mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-15 15:07:16 +00:00
parent
f97e0f3fa0
commit
791138ee63
62
repos/os/include/os/time_source.h
Normal file
62
repos/os/include/os/time_source.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* \brief Interface of a time source that can handle one timeout at a time
|
||||
* \author Martin Stein
|
||||
* \date 2016-11-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef _OS__TIME_SOURCE_H_
|
||||
#define _OS__TIME_SOURCE_H_
|
||||
|
||||
namespace Genode { class Time_source; }
|
||||
|
||||
/**
|
||||
* Interface of a time source that can handle one timeout at a time
|
||||
*/
|
||||
struct Genode::Time_source
|
||||
{
|
||||
/**
|
||||
* Makes it clear which time unit an interfaces takes
|
||||
*/
|
||||
struct Microseconds
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
explicit Microseconds(unsigned long const value) : value(value) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface of a timeout callback
|
||||
*/
|
||||
struct Timeout_handler
|
||||
{
|
||||
virtual void handle_timeout(Microseconds curr_time) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the current time of the source
|
||||
*/
|
||||
virtual Microseconds curr_time() const = 0;
|
||||
|
||||
/**
|
||||
* Return the maximum timeout duration that the source can handle
|
||||
*/
|
||||
virtual Microseconds max_timeout() const = 0;
|
||||
|
||||
/**
|
||||
* Install a timeout, overrides the last timeout if any
|
||||
*
|
||||
* \param duration timeout duration
|
||||
* \param handler timeout callback
|
||||
*/
|
||||
virtual void schedule_timeout(Microseconds duration,
|
||||
Timeout_handler &handler) = 0;
|
||||
};
|
||||
|
||||
#endif /* _OS__TIME_SOURCE_H_ */
|
259
repos/os/include/os/timeout.h
Normal file
259
repos/os/include/os/timeout.h
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* \brief Multiplexing one time source amongst different timeouts
|
||||
* \author Martin Stein
|
||||
* \date 2016-11-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef _OS__TIMEOUT_H_
|
||||
#define _OS__TIMEOUT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/noncopyable.h>
|
||||
#include <os/time_source.h>
|
||||
#include <os/alarm.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Timeout_scheduler;
|
||||
class Timeout;
|
||||
class Alarm_timeout_scheduler;
|
||||
template <typename> class Periodic_timeout;
|
||||
template <typename> class One_shot_timeout;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Interface of a time-source multiplexer
|
||||
*/
|
||||
struct Genode::Timeout_scheduler
|
||||
{
|
||||
using Microseconds = Time_source::Microseconds;
|
||||
|
||||
/**
|
||||
* Read out the now time of the scheduler
|
||||
*/
|
||||
virtual Microseconds curr_time() const = 0;
|
||||
|
||||
/**
|
||||
* Add a one-shot timeout to the schedule
|
||||
*
|
||||
* \param timeout timeout callback object
|
||||
* \param duration timeout trigger delay
|
||||
*/
|
||||
virtual void schedule_one_shot(Timeout &timeout, Microseconds duration) = 0;
|
||||
|
||||
/**
|
||||
* Add a periodic timeout to the schedule
|
||||
*
|
||||
* \param timeout timeout callback object
|
||||
* \param duration timeout trigger period
|
||||
*/
|
||||
virtual void schedule_periodic(Timeout &timeout, Microseconds duration) = 0;
|
||||
|
||||
/**
|
||||
* Remove timeout from the scheduler
|
||||
*
|
||||
* \param timeout corresponding timeout callback object
|
||||
*/
|
||||
virtual void discard(Timeout &timeout) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Timeout callback that can be used for both one-shot and periodic timeouts
|
||||
*
|
||||
* This class should be used only if it is necessary to use one timeout
|
||||
* callback for both periodic and one-shot timeouts. This is the case, for
|
||||
* example, in a Timer-session server. If this is not the case, the classes
|
||||
* Periodic_timeout and One_shot_timeout are the better choice.
|
||||
*/
|
||||
class Genode::Timeout : private Noncopyable
|
||||
{
|
||||
friend class Alarm_timeout_scheduler;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Interface of a timeout handler
|
||||
*/
|
||||
struct Handler
|
||||
{
|
||||
using Microseconds = Time_source::Microseconds;
|
||||
|
||||
virtual void handle_timeout(Microseconds curr_time) = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
using Microseconds = Time_source::Microseconds;
|
||||
|
||||
|
||||
struct Alarm : Genode::Alarm
|
||||
{
|
||||
Timeout_scheduler &timeout_scheduler;
|
||||
Handler *handler = nullptr;
|
||||
bool periodic;
|
||||
|
||||
Alarm(Timeout_scheduler &timeout_scheduler)
|
||||
: timeout_scheduler(timeout_scheduler) { }
|
||||
|
||||
|
||||
/*******************
|
||||
** Genode::Alarm **
|
||||
*******************/
|
||||
|
||||
bool on_alarm(unsigned) override;
|
||||
|
||||
} _alarm;
|
||||
|
||||
public:
|
||||
|
||||
Timeout(Timeout_scheduler &timeout_scheduler)
|
||||
: _alarm(timeout_scheduler) { }
|
||||
|
||||
~Timeout() { _alarm.timeout_scheduler.discard(*this); }
|
||||
|
||||
void schedule_periodic(Microseconds duration, Handler &handler);
|
||||
|
||||
void schedule_one_shot(Microseconds duration, Handler &handler);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Periodic timeout that is linked to a custom handler, starts when constructed
|
||||
*/
|
||||
template <typename HANDLER>
|
||||
struct Genode::Periodic_timeout : private Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Microseconds = Timeout_scheduler::Microseconds;
|
||||
|
||||
private:
|
||||
|
||||
typedef void (HANDLER::*Handler_method)(Microseconds);
|
||||
|
||||
Timeout _timeout;
|
||||
|
||||
struct Handler : Timeout::Handler
|
||||
{
|
||||
HANDLER &object;
|
||||
Handler_method const method;
|
||||
|
||||
Handler(HANDLER &object, Handler_method method)
|
||||
: object(object), method(method) { }
|
||||
|
||||
|
||||
/**********************
|
||||
** Timeout::Handler **
|
||||
**********************/
|
||||
|
||||
void handle_timeout(Microseconds curr_time) override {
|
||||
(object.*method)(curr_time); }
|
||||
|
||||
} _handler;
|
||||
|
||||
public:
|
||||
|
||||
Periodic_timeout(Timeout_scheduler &timeout_scheduler,
|
||||
HANDLER &object,
|
||||
Handler_method method,
|
||||
Microseconds duration)
|
||||
:
|
||||
_timeout(timeout_scheduler), _handler(object, method)
|
||||
{
|
||||
_timeout.schedule_periodic(duration, _handler);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* One-shot timeout that is linked to a custom handler, started manually
|
||||
*/
|
||||
template <typename HANDLER>
|
||||
class Genode::One_shot_timeout : private Noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
using Microseconds = Timeout_scheduler::Microseconds;
|
||||
|
||||
typedef void (HANDLER::*Handler_method)(Microseconds);
|
||||
|
||||
Timeout _timeout;
|
||||
|
||||
struct Handler : Timeout::Handler
|
||||
{
|
||||
HANDLER &object;
|
||||
Handler_method const method;
|
||||
|
||||
Handler(HANDLER &object, Handler_method method)
|
||||
: object(object), method(method) { }
|
||||
|
||||
|
||||
/**********************
|
||||
** Timeout::Handler **
|
||||
**********************/
|
||||
|
||||
void handle_timeout(Microseconds curr_time) override {
|
||||
(object.*method)(curr_time); }
|
||||
|
||||
} _handler;
|
||||
|
||||
public:
|
||||
|
||||
One_shot_timeout(Timeout_scheduler &timeout_scheduler,
|
||||
HANDLER &object,
|
||||
Handler_method method)
|
||||
: _timeout(timeout_scheduler), _handler(object, method) { }
|
||||
|
||||
void start(Microseconds duration) {
|
||||
_timeout.schedule_one_shot(duration, _handler); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Timeout-scheduler implementation using the Alarm framework
|
||||
*/
|
||||
class Genode::Alarm_timeout_scheduler : private Noncopyable,
|
||||
public Timeout_scheduler,
|
||||
public Time_source::Timeout_handler
|
||||
{
|
||||
private:
|
||||
|
||||
Time_source &_time_source;
|
||||
Alarm_scheduler _alarm_scheduler;
|
||||
|
||||
|
||||
/**********************************
|
||||
** Time_source::Timeout_handler **
|
||||
**********************************/
|
||||
|
||||
void handle_timeout(Microseconds curr_time) override;
|
||||
|
||||
public:
|
||||
|
||||
Alarm_timeout_scheduler(Time_source &time_source);
|
||||
|
||||
|
||||
/***********************
|
||||
** Timeout_scheduler **
|
||||
***********************/
|
||||
|
||||
void schedule_one_shot(Timeout &timeout, Microseconds duration) override;
|
||||
void schedule_periodic(Timeout &timeout, Microseconds duration) override;
|
||||
|
||||
Microseconds curr_time() const override {
|
||||
return _time_source.curr_time(); }
|
||||
|
||||
void discard(Timeout &timeout) override {
|
||||
_alarm_scheduler.discard(&timeout._alarm); }
|
||||
};
|
||||
|
||||
#endif /* _OS__TIMEOUT_H_ */
|
107
repos/os/include/os/timer.h
Normal file
107
repos/os/include/os/timer.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* \brief Multiplexes a timer session amongst different timeouts
|
||||
* \author Martin Stein
|
||||
* \date 2016-11-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef _TIMER_H_
|
||||
#define _TIMER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <timer_session/timer_session.h>
|
||||
#include <os/time_source.h>
|
||||
#include <os/timeout.h>
|
||||
|
||||
namespace Genode { class Timer; }
|
||||
|
||||
|
||||
/**
|
||||
* Multiplexes a timer session amongst different timeouts
|
||||
*/
|
||||
class Genode::Timer : public Timeout_scheduler
|
||||
{
|
||||
private:
|
||||
|
||||
class Time_source : public Genode::Time_source
|
||||
{
|
||||
private:
|
||||
|
||||
enum { MIN_TIMEOUT_US = 100000 };
|
||||
|
||||
using Signal_handler =
|
||||
Genode::Signal_handler<Time_source>;
|
||||
|
||||
::Timer::Session &_session;
|
||||
Signal_handler _signal_handler;
|
||||
Timeout_handler *_handler = nullptr;
|
||||
|
||||
void _handle_timeout()
|
||||
{
|
||||
if (_handler) {
|
||||
_handler->handle_timeout(curr_time()); }
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Time_source(::Timer::Session &session, Entrypoint &ep)
|
||||
:
|
||||
_session(session),
|
||||
_signal_handler(ep, *this, &Time_source::_handle_timeout)
|
||||
{
|
||||
_session.sigh(_signal_handler);
|
||||
}
|
||||
|
||||
Microseconds curr_time() const {
|
||||
return Microseconds(1000ULL * _session.elapsed_ms()); }
|
||||
|
||||
void schedule_timeout(Microseconds duration,
|
||||
Timeout_handler &handler)
|
||||
{
|
||||
if (duration.value < MIN_TIMEOUT_US) {
|
||||
duration.value = MIN_TIMEOUT_US; }
|
||||
|
||||
if (duration.value > max_timeout().value) {
|
||||
duration.value = max_timeout().value; }
|
||||
|
||||
_handler = &handler;
|
||||
_session.trigger_once(duration.value);
|
||||
}
|
||||
|
||||
Microseconds max_timeout() const {
|
||||
return Microseconds(~0UL); }
|
||||
|
||||
} _time_source;
|
||||
|
||||
Alarm_timeout_scheduler _timeout_scheduler { _time_source };
|
||||
|
||||
public:
|
||||
|
||||
Timer(::Timer::Session &session, Entrypoint &ep)
|
||||
: _time_source(session, ep) { }
|
||||
|
||||
|
||||
/***********************
|
||||
** Timeout_scheduler **
|
||||
***********************/
|
||||
|
||||
void schedule_periodic(Timeout &timeout, Microseconds duration) override {
|
||||
_timeout_scheduler.schedule_periodic(timeout, duration); }
|
||||
|
||||
void schedule_one_shot(Timeout &timeout, Microseconds duration) override {
|
||||
_timeout_scheduler.schedule_one_shot(timeout, duration); }
|
||||
|
||||
Microseconds curr_time() const override {
|
||||
return _timeout_scheduler.curr_time(); }
|
||||
|
||||
void discard(Timeout &timeout) override {
|
||||
_timeout_scheduler.discard(timeout); }
|
||||
};
|
||||
|
||||
#endif /* _TIMER_H_ */
|
5
repos/os/lib/mk/timeout.mk
Normal file
5
repos/os/lib/mk/timeout.mk
Normal file
@ -0,0 +1,5 @@
|
||||
SRC_CC += timeout.cc
|
||||
|
||||
LIBS += alarm
|
||||
|
||||
vpath % $(REP_DIR)/src/lib/timeout
|
72
repos/os/run/timeout.run
Normal file
72
repos/os/run/timeout.run
Normal file
@ -0,0 +1,72 @@
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
build "core init drivers/timer test/timeout"
|
||||
|
||||
#
|
||||
# Boot image
|
||||
#
|
||||
|
||||
create_boot_directory
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<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="10M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="test">
|
||||
<binary name="test-timeout"/>
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
build_boot_image "core init timer test-timeout"
|
||||
|
||||
#
|
||||
# Execution
|
||||
#
|
||||
|
||||
append qemu_args "-nographic -m 64"
|
||||
|
||||
#
|
||||
# We check for each timeout that has a distance of at least 200ms to each
|
||||
# other timeout:
|
||||
#
|
||||
# 0 ms
|
||||
# 0 ms
|
||||
# 700 ms -> check for 700 ms
|
||||
# 1000 ms -> check for 1000 ms
|
||||
# 1400 ms -> check for 700 ms
|
||||
# 2000 ms
|
||||
# 2100 ms
|
||||
# 2800 ms -> check for 700 ms
|
||||
# 3000 ms -> check for 1000 ms
|
||||
# 3250 ms -> check for 3250 ms
|
||||
# 3500 ms -> check for 700 ms
|
||||
# 4000 ms -> check for 1000 ms
|
||||
# 4200 ms -> check for 700 ms
|
||||
# 4900 ms
|
||||
# 5000 ms
|
||||
# 5200 ms -> check for 5200 ms
|
||||
# 5600 ms -> check for 700 ms
|
||||
# 6000 ms -> check for 1000 ms
|
||||
#
|
||||
|
||||
run_genode_until ".*700ms timeout.*\n.*1000ms timeout.*\n.*700ms timeout.*\n.*700ms timeout.*\n.*1000ms timeout.*\n.*3250ms timeout.*\n.*700ms timeout.*\n.*1000ms timeout.*\n.*700ms timeout.*\n.*5200ms timeout.*\n.*700ms timeout.*\n.*1000ms timeout.*\n" 20
|
101
repos/os/src/lib/timeout/timeout.cc
Normal file
101
repos/os/src/lib/timeout/timeout.cc
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* \brief Multiplexing one time source amongst different timeout subjects
|
||||
* \author Martin Stein
|
||||
* \date 2016-11-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 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 <os/timeout.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/*************
|
||||
** Timeout **
|
||||
*************/
|
||||
|
||||
void Timeout::schedule_periodic(Microseconds duration, Handler &handler)
|
||||
{
|
||||
_alarm.handler = &handler;
|
||||
_alarm.periodic = true;
|
||||
_alarm.timeout_scheduler.schedule_periodic(*this, duration);
|
||||
}
|
||||
|
||||
void Timeout::schedule_one_shot(Microseconds duration, Handler &handler)
|
||||
{
|
||||
_alarm.handler = &handler;
|
||||
_alarm.periodic = false;
|
||||
_alarm.timeout_scheduler.schedule_one_shot(*this, duration);
|
||||
}
|
||||
|
||||
|
||||
/********************
|
||||
** Timeout::Alarm **
|
||||
********************/
|
||||
|
||||
bool Timeout::Alarm::on_alarm(unsigned)
|
||||
{
|
||||
if (handler) {
|
||||
handler->handle_timeout(timeout_scheduler.curr_time()); }
|
||||
return periodic;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************
|
||||
** Alarm_timeout_scheduler **
|
||||
*****************************/
|
||||
|
||||
void Alarm_timeout_scheduler::handle_timeout(Microseconds curr_time)
|
||||
{
|
||||
_alarm_scheduler.handle(curr_time.value);
|
||||
|
||||
unsigned long sleep_time_us;
|
||||
Alarm::Time deadline_us;
|
||||
if (_alarm_scheduler.next_deadline(&deadline_us)) {
|
||||
sleep_time_us = deadline_us - curr_time.value;
|
||||
} else {
|
||||
sleep_time_us = _time_source.max_timeout().value; }
|
||||
|
||||
if (sleep_time_us == 0) {
|
||||
sleep_time_us = 1; }
|
||||
|
||||
_time_source.schedule_timeout(Microseconds(sleep_time_us), *this);
|
||||
}
|
||||
|
||||
|
||||
Alarm_timeout_scheduler::Alarm_timeout_scheduler(Time_source &time_source)
|
||||
:
|
||||
_time_source(time_source)
|
||||
{
|
||||
time_source.schedule_timeout(Microseconds(0), *this);
|
||||
}
|
||||
|
||||
|
||||
void Alarm_timeout_scheduler::schedule_one_shot(Timeout &timeout,
|
||||
Microseconds duration)
|
||||
{
|
||||
_alarm_scheduler.schedule_absolute(&timeout._alarm,
|
||||
_time_source.curr_time().value +
|
||||
duration.value);
|
||||
|
||||
if (_alarm_scheduler.head_timeout(&timeout._alarm)) {
|
||||
_time_source.schedule_timeout(Microseconds(0), *this); }
|
||||
}
|
||||
|
||||
|
||||
void Alarm_timeout_scheduler::schedule_periodic(Timeout &timeout,
|
||||
Microseconds duration)
|
||||
{
|
||||
_alarm_scheduler.handle(_time_source.curr_time().value);
|
||||
_alarm_scheduler.schedule(&timeout._alarm, duration.value);
|
||||
if (_alarm_scheduler.head_timeout(&timeout._alarm)) {
|
||||
_time_source.schedule_timeout(Microseconds(0), *this); }
|
||||
}
|
60
repos/os/src/test/timeout/main.cc
Normal file
60
repos/os/src/test/timeout/main.cc
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* \brief Test for timeout library
|
||||
* \author Martin Stein
|
||||
* \date 2016-11-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 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/component.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <os/timer.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
class Main
|
||||
{
|
||||
private:
|
||||
|
||||
using Microseconds = Genode::Timer::Microseconds;
|
||||
|
||||
void _handle(Microseconds now, Cstring name) {
|
||||
log(now.value / 1000, " ms: ", name, " timeout triggered"); }
|
||||
|
||||
void _handle_pt1(Microseconds now) { _handle(now, "Periodic 700ms"); }
|
||||
void _handle_pt2(Microseconds now) { _handle(now, "Periodic 1000ms"); }
|
||||
void _handle_ot1(Microseconds now) { _handle(now, "One-shot 3250ms"); }
|
||||
void _handle_ot2(Microseconds now) { _handle(now, "One-shot 5200ms"); }
|
||||
|
||||
Timer::Connection _timer_connection;
|
||||
Genode::Timer _timer;
|
||||
Periodic_timeout<Main> _pt1 { _timer, *this, &Main::_handle_pt1, Microseconds(700000) };
|
||||
Periodic_timeout<Main> _pt2 { _timer, *this, &Main::_handle_pt2, Microseconds(1000000) };
|
||||
One_shot_timeout<Main> _ot1 { _timer, *this, &Main::_handle_ot1 };
|
||||
One_shot_timeout<Main> _ot2 { _timer, *this, &Main::_handle_ot2 };
|
||||
|
||||
public:
|
||||
|
||||
Main(Env &env) : _timer_connection(env),
|
||||
_timer(_timer_connection, env.ep())
|
||||
{
|
||||
_ot1.start(Microseconds(3250000));
|
||||
_ot2.start(Microseconds(5300000));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/***************
|
||||
** Component **
|
||||
***************/
|
||||
|
||||
size_t Component::stack_size() { return 4 * 1024 * sizeof(addr_t); }
|
||||
void Component::construct(Env &env) { static Main main(env); }
|
4
repos/os/src/test/timeout/target.mk
Normal file
4
repos/os/src/test/timeout/target.mk
Normal file
@ -0,0 +1,4 @@
|
||||
TARGET = test-timeout
|
||||
SRC_CC += main.cc
|
||||
LIBS += base timeout
|
||||
INC_DIR += $(PRG_DIR)
|
@ -75,3 +75,4 @@ cpu_sampler_noux
|
||||
usb_hid
|
||||
smartcard
|
||||
new_delete
|
||||
timeout
|
||||
|
Loading…
x
Reference in New Issue
Block a user