mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 11:55:24 +00:00
parent
0a1664b892
commit
146b34bf40
@ -3,8 +3,7 @@ SHARED_LIB = yes
|
||||
LIB_DIR = $(REP_DIR)/src/lib/lxip
|
||||
LIB_INC_DIR = $(LIB_DIR)/include
|
||||
|
||||
# FIXME should we *really* effecticely add dde_kit to this shared library?
|
||||
LIBS += dde_kit
|
||||
LIBS += lx
|
||||
|
||||
LX_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/lib/lxip
|
||||
NET_DIR := $(LX_CONTRIB_DIR)/net
|
||||
|
@ -323,7 +323,6 @@ DUMMY(-1, mod_delayed_work)
|
||||
DUMMY(-1, module_put)
|
||||
DUMMY(-1, move_addr_to_kernel)
|
||||
DUMMY(-1, mq_qdisc_ops)
|
||||
DUMMY(-1, msecs_to_jiffies)
|
||||
DUMMY(-1, msleep)
|
||||
DUMMY(-1, mutex_is_locked)
|
||||
DUMMY(-1, need_resched)
|
||||
|
@ -17,14 +17,7 @@
|
||||
#ifndef _LX_EMUL_H_
|
||||
#define _LX_EMUL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#include <dde_kit/panic.h>
|
||||
#include <dde_kit/printf.h>
|
||||
#include <dde_kit/types.h>
|
||||
#include <lx/lx.h>
|
||||
|
||||
#define DEBUG_PRINTK 1
|
||||
#define DEBUG_SLAB 0
|
||||
@ -39,31 +32,6 @@ extern "C" {
|
||||
#define KBUILD_MODNAME "mod-noname"
|
||||
|
||||
|
||||
/***************
|
||||
** asm/bug.h **
|
||||
***************/
|
||||
|
||||
#define WARN_ON(condition) ({ \
|
||||
int ret = !!(condition); \
|
||||
if (ret) dde_kit_printf("[%s] WARN_ON(" #condition ")\n", __func__); \
|
||||
ret; })
|
||||
|
||||
#define WARN(condition, format, ...) ({ \
|
||||
int ret = !!(condition); \
|
||||
if (ret) dde_kit_printf("[%s] WARN(" #condition ") " format "\n" , __func__, __VA_ARGS__); \
|
||||
ret; })
|
||||
|
||||
#define WARN_ON_ONCE WARN_ON
|
||||
#define WARN_ONCE WARN
|
||||
|
||||
#define BUG() do { \
|
||||
dde_kit_debug("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
|
||||
while (1); \
|
||||
} while (0)
|
||||
|
||||
#define BUG_ON(condition) do { if (condition) BUG(); } while(0)
|
||||
|
||||
|
||||
/*******************************
|
||||
** linux/errno.h and friends **
|
||||
*******************************/
|
||||
@ -239,31 +207,10 @@ int try_module_get(struct module *);
|
||||
#define CONFIG_DEFAULT_TCP_CONG "cubic"
|
||||
|
||||
|
||||
/***************
|
||||
** asm/bug.h **
|
||||
***************/
|
||||
|
||||
#define BUG() do { \
|
||||
dde_kit_debug("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
|
||||
while (1); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*******************
|
||||
** linux/types.h **
|
||||
*******************/
|
||||
|
||||
typedef dde_kit_int8_t int8_t;
|
||||
typedef dde_kit_int16_t int16_t;
|
||||
typedef dde_kit_int32_t int32_t;
|
||||
typedef dde_kit_int64_t int64_t;
|
||||
|
||||
typedef dde_kit_uint8_t uint8_t;
|
||||
typedef dde_kit_uint16_t uint16_t;
|
||||
typedef dde_kit_uint32_t uint32_t;
|
||||
typedef dde_kit_uint64_t uint64_t;
|
||||
typedef dde_kit_size_t size_t;
|
||||
|
||||
typedef uint32_t uint;
|
||||
|
||||
typedef int8_t s8;
|
||||
@ -353,10 +300,7 @@ enum { true = 1, false = 0 };
|
||||
** linux/jiffies.h **
|
||||
*********************/
|
||||
|
||||
/* we directly map 'jiffies' to 'dde_kit_timer_ticks' */
|
||||
#define jiffies dde_kit_timer_ticks
|
||||
|
||||
extern volatile unsigned long jiffies;
|
||||
extern unsigned long jiffies;
|
||||
|
||||
enum { INITIAL_JIFFIES = 0 };
|
||||
|
||||
@ -371,6 +315,7 @@ static inline long time_before(long a, long b) { return time_after(b, a); }
|
||||
static inline long time_before_eq(long a, long b) { return time_after_eq(b ,a); }
|
||||
|
||||
clock_t jiffies_to_clock_t(unsigned long);
|
||||
void update_jiffies(void);
|
||||
|
||||
|
||||
/******************
|
||||
@ -441,11 +386,11 @@ void sg_set_page(struct scatterlist *, struct page *, unsigned int,
|
||||
|
||||
#define KERN_WARNING KERN_WARN
|
||||
|
||||
#define pr_crit(fmt, ...) dde_kit_printf(KERN_CRIT fmt, ##__VA_ARGS__)
|
||||
#define pr_emerg(fmt, ...) dde_kit_printf(KERN_EMERG fmt, ##__VA_ARGS__)
|
||||
#define pr_err(fmt, ...) dde_kit_printf(KERN_ERR fmt, ##__VA_ARGS__)
|
||||
#define pr_warn(fmt, ...) dde_kit_printf(KERN_WARN fmt, ##__VA_ARGS__)
|
||||
#define pr_info(fmt, ...) dde_kit_printf(KERN_INFO fmt, ##__VA_ARGS__)
|
||||
#define pr_crit(fmt, ...) lx_printf(KERN_CRIT fmt, ##__VA_ARGS__)
|
||||
#define pr_emerg(fmt, ...) lx_printf(KERN_EMERG fmt, ##__VA_ARGS__)
|
||||
#define pr_err(fmt, ...) lx_printf(KERN_ERR fmt, ##__VA_ARGS__)
|
||||
#define pr_warn(fmt, ...) lx_printf(KERN_WARN fmt, ##__VA_ARGS__)
|
||||
#define pr_info(fmt, ...) lx_printf(KERN_INFO fmt, ##__VA_ARGS__)
|
||||
#define pr_notice(fmt, ...) printk(KERN_NOTICE fmt, ##__VA_ARGS__)
|
||||
#define pr_cont(fmt, ...) printk(KERN_CONT fmt, ##__VA_ARGS__)
|
||||
|
||||
@ -468,15 +413,14 @@ static inline int _printk(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
dde_kit_vprintf(fmt, args);
|
||||
lx_vprintf(fmt, args);
|
||||
va_end(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if DEBUG_PRINTK
|
||||
#define printk _printk
|
||||
#define vprintk dde_kit_vprintf
|
||||
#define panic dde_kit_panic
|
||||
#define vprintk lx_vprintf
|
||||
#else
|
||||
|
||||
static inline int printk(const char *fmt, ...)
|
||||
@ -485,7 +429,6 @@ static inline int printk(const char *fmt, ...)
|
||||
}
|
||||
|
||||
#define vprintk(...)
|
||||
#define panic(...)
|
||||
#endif
|
||||
|
||||
|
||||
@ -974,9 +917,6 @@ enum {
|
||||
PAGE_SHIFT = 12,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define private priv
|
||||
#endif
|
||||
struct page
|
||||
{
|
||||
int pfmemalloc;
|
||||
@ -984,9 +924,6 @@ struct page
|
||||
atomic_t _count;
|
||||
void *addr;
|
||||
unsigned long private;
|
||||
#ifdef __cplusplus
|
||||
#undef priv
|
||||
#endif
|
||||
} __attribute((packed));
|
||||
|
||||
|
||||
@ -2241,17 +2178,12 @@ ssize_t splice_to_pipe(struct pipe_inode_info *, struct splice_pipe_desc *);
|
||||
/*****************
|
||||
** linux/aio.h **
|
||||
*****************/
|
||||
#ifdef __cplusplus
|
||||
#define private priv
|
||||
#endif
|
||||
|
||||
struct kiocb
|
||||
{
|
||||
void *private;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
#undef private
|
||||
#endif
|
||||
|
||||
/*****************
|
||||
** linux/uio.h **
|
||||
@ -2499,9 +2431,7 @@ struct u64_stats_sync { };
|
||||
** net/net_namespace.h **
|
||||
*************************/
|
||||
|
||||
#define new _new
|
||||
#include <linux/list.h>
|
||||
#undef new
|
||||
#include <uapi/linux/snmp.h>
|
||||
#include <net/netns/mib.h>
|
||||
#include <net/netns/ipv4.h>
|
||||
@ -2795,13 +2725,7 @@ void csum_replace2(__sum16 *, __be16, __be16);
|
||||
** uapi/linux/net_tstamp.h **
|
||||
*****************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define class device_class
|
||||
#endif
|
||||
#include <uapi/linux/if_link.h>
|
||||
#ifdef __cplusplus
|
||||
#undef class
|
||||
#endif
|
||||
#include <net/netlink.h>
|
||||
|
||||
enum {
|
||||
@ -3327,9 +3251,5 @@ void log_sock(struct socket *sock);
|
||||
|
||||
void lx_trace_event(char const *, ...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _LX_EMUL_H_ */
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
#include <dde_kit/timer.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <net/tcp.h>
|
||||
#include <init.h>
|
||||
@ -58,9 +57,6 @@ int lxip_init(char *address_config)
|
||||
/* init data */
|
||||
INIT_LIST_HEAD(&init_net.dev_base_head);
|
||||
|
||||
/*start jiffies */
|
||||
dde_kit_timer_init(0, 0);
|
||||
|
||||
/* call __setup stuff */
|
||||
__ip_auto_config_setup(address_config);
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/ip_fib.h>
|
||||
#include <uapi/linux/rtnetlink.h>
|
||||
#include <dde_kit/memory.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/route.h>
|
||||
#include <net/tcp.h>
|
||||
@ -33,7 +32,7 @@ struct kmem_cache
|
||||
struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align,
|
||||
unsigned long falgs, void (*ctor)(void *))
|
||||
{
|
||||
dde_kit_log(DEBUG_SLAB, "\"%s\" obj_size=%zd", name, size);
|
||||
lx_log(DEBUG_SLAB, "\"%s\" obj_size=%zd", name, size);
|
||||
|
||||
struct kmem_cache *cache;
|
||||
|
||||
@ -57,49 +56,25 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
|
||||
|
||||
void *kmem_cache_alloc_node(struct kmem_cache *cache, gfp_t flags, int node)
|
||||
{
|
||||
dde_kit_log(DEBUG_SLAB, "\"%s\" alloc obj_size=%u", cache->name,cache->size);
|
||||
lx_log(DEBUG_SLAB, "\"%s\" alloc obj_size=%u", cache->name,cache->size);
|
||||
return kmalloc(cache->size, 0);
|
||||
}
|
||||
|
||||
|
||||
void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags)
|
||||
{
|
||||
dde_kit_log(DEBUG_SLAB, "\"%s\" alloc obj_size=%u", cache->name,cache->size);
|
||||
lx_log(DEBUG_SLAB, "\"%s\" alloc obj_size=%u", cache->name,cache->size);
|
||||
return kmalloc(cache->size, 0);
|
||||
}
|
||||
|
||||
|
||||
void kmem_cache_free(struct kmem_cache *cache, void *objp)
|
||||
{
|
||||
dde_kit_log(DEBUG_SLAB, "\"%s\" (%p)", cache->name, objp);
|
||||
lx_log(DEBUG_SLAB, "\"%s\" (%p)", cache->name, objp);
|
||||
kfree(objp);
|
||||
}
|
||||
|
||||
|
||||
void *alloc_large_system_hash(const char *tablename,
|
||||
unsigned long bucketsize,
|
||||
unsigned long numentries,
|
||||
int scale,
|
||||
int flags,
|
||||
unsigned int *_hash_shift,
|
||||
unsigned int *_hash_mask,
|
||||
unsigned long low_limit,
|
||||
unsigned long high_limit)
|
||||
{
|
||||
unsigned long elements = numentries ? numentries : high_limit;
|
||||
unsigned long nlog2 = ilog2(elements);
|
||||
nlog2 <<= (1 << nlog2) < elements ? 1 : 0;
|
||||
|
||||
void *table = dde_kit_simple_malloc(elements * bucketsize);
|
||||
|
||||
if (_hash_mask)
|
||||
*_hash_mask = (1 << nlog2) - 1;
|
||||
if (_hash_shift)
|
||||
*_hash_shift = nlog2;
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
/********************
|
||||
** linux/bitmap.h **
|
||||
********************/
|
||||
|
@ -17,12 +17,12 @@
|
||||
#include <timer_session/connection.h>
|
||||
#include <trace/timestamp.h>
|
||||
|
||||
#include <lx/extern_c_begin.h>
|
||||
#include <lx_emul.h>
|
||||
#include <lx/extern_c_end.h>
|
||||
|
||||
#include <env.h>
|
||||
|
||||
extern "C" {
|
||||
#include <dde_kit/memory.h>
|
||||
}
|
||||
|
||||
/*
|
||||
* VM-area to reserve for back-end allocator
|
||||
@ -379,6 +379,7 @@ void *kzalloc_node(size_t size, gfp_t flags, int node)
|
||||
return kzalloc(size, 0);
|
||||
}
|
||||
|
||||
|
||||
size_t ksize(const void *p)
|
||||
{
|
||||
if (!(Malloc::mem()->inside((Genode::addr_t)p))) {
|
||||
@ -391,6 +392,32 @@ size_t ksize(const void *p)
|
||||
}
|
||||
|
||||
|
||||
void *alloc_large_system_hash(const char *tablename,
|
||||
unsigned long bucketsize,
|
||||
unsigned long numentries,
|
||||
int scale,
|
||||
int flags,
|
||||
unsigned int *_hash_shift,
|
||||
unsigned int *_hash_mask,
|
||||
unsigned long low_limit,
|
||||
unsigned long high_limit)
|
||||
{
|
||||
unsigned long elements = numentries ? numentries : high_limit;
|
||||
unsigned long nlog2 = ilog2(elements);
|
||||
nlog2 <<= (1 << nlog2) < elements ? 1 : 0;
|
||||
|
||||
void *table = Genode::env()->heap()->alloc(elements * bucketsize);
|
||||
|
||||
if (_hash_mask)
|
||||
*_hash_mask = (1 << nlog2) - 1;
|
||||
if (_hash_shift)
|
||||
*_hash_shift = nlog2;
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************
|
||||
** linux/string.h **
|
||||
********************/
|
||||
@ -515,7 +542,8 @@ static void __wait_event(signed long timeout)
|
||||
while (timeout > jiffies && !Net::Env::receiver()->pending())
|
||||
{
|
||||
timer.msleep(1);
|
||||
//dde_kit_thread_msleep(1);
|
||||
update_jiffies();
|
||||
|
||||
if (timeout <= jiffies)
|
||||
return;
|
||||
}
|
||||
@ -584,7 +612,7 @@ class Avl_page : public Genode::Avl_node<Avl_page>
|
||||
_page->addr = (void *)_addr;
|
||||
atomic_set(&_page->_count, 1);
|
||||
|
||||
dde_kit_log(DEBUG_SLAB, "alloc page: %p addr: %lx-%lx", _page, _addr, _addr + size);
|
||||
lx_log(DEBUG_SLAB, "alloc page: %p addr: %lx-%lx", _page, _addr, _addr + size);
|
||||
}
|
||||
|
||||
virtual ~Avl_page()
|
||||
@ -632,7 +660,7 @@ struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
|
||||
struct page *virt_to_head_page(const void *x)
|
||||
{
|
||||
Avl_page *p = tree.first()->find_by_address((Genode::addr_t)x);
|
||||
dde_kit_log(DEBUG_SLAB, "virt_to_head_page: %p page %p\n", x,p ? p->page() : 0);
|
||||
lx_log(DEBUG_SLAB, "virt_to_head_page: %p page %p\n", x,p ? p->page() : 0);
|
||||
|
||||
return p ? p->page() : 0;
|
||||
}
|
||||
@ -643,7 +671,7 @@ void put_page(struct page *page)
|
||||
if (!atomic_dec_and_test(&page->_count))
|
||||
return;
|
||||
|
||||
dde_kit_log(DEBUG_SLAB, "put_page: %p", page);
|
||||
lx_log(DEBUG_SLAB, "put_page: %p", page);
|
||||
Avl_page *p = tree.first()->find_by_address((Genode::addr_t)page->addr);
|
||||
|
||||
tree.remove(p);
|
||||
|
@ -26,18 +26,17 @@ static const bool verbose = false;
|
||||
|
||||
|
||||
namespace Linux {
|
||||
extern "C" {
|
||||
#include <lx/extern_c_begin.h>
|
||||
#include <lx_emul.h>
|
||||
#include <linux/socket.h>
|
||||
#include <uapi/linux/in.h>
|
||||
|
||||
extern int sock_setsockopt(struct socket *sock, int level,
|
||||
int op, char __user *optval,
|
||||
unsigned int optlen);
|
||||
extern int sock_getsockopt(struct socket *sock, int level,
|
||||
int op, char __user *optval,
|
||||
int __user *optlen);
|
||||
}
|
||||
#include <lx/extern_c_end.h>
|
||||
}
|
||||
|
||||
namespace Net
|
||||
|
@ -13,85 +13,289 @@
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/tslab.h>
|
||||
#include <os/server.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <util/volatile_object.h>
|
||||
|
||||
#include <lx/extern_c_begin.h>
|
||||
#include <lx_emul.h>
|
||||
#include <lx/extern_c_end.h>
|
||||
|
||||
#include <env.h>
|
||||
|
||||
extern "C" {
|
||||
#include <dde_kit/timer.h>
|
||||
}
|
||||
#include <lx/list.h>
|
||||
|
||||
static void handler(void *timer);
|
||||
|
||||
/*********************
|
||||
** linux/jiffies.h **
|
||||
*********************/
|
||||
|
||||
unsigned long jiffies;
|
||||
|
||||
unsigned long msecs_to_jiffies(const unsigned int m) { return m / (1000 / HZ); }
|
||||
|
||||
/**
|
||||
* Signal context for time-outs
|
||||
* Lx::Timer
|
||||
*/
|
||||
class Timer_context
|
||||
namespace Lx {
|
||||
class Timer;
|
||||
}
|
||||
|
||||
class Lx::Timer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Context encapsulates a regular linux timer_list
|
||||
*/
|
||||
struct Context : public Lx::List<Context>::Element
|
||||
{
|
||||
enum { INVALID_TIMEOUT = ~0UL };
|
||||
enum Type { LIST };
|
||||
|
||||
Type type;
|
||||
void *timer;
|
||||
bool pending { false };
|
||||
unsigned long timeout { INVALID_TIMEOUT }; /* absolute in jiffies */
|
||||
bool programmed { false };
|
||||
|
||||
Context(struct timer_list *timer) : type(LIST), timer(timer) { }
|
||||
|
||||
void expires(unsigned long e)
|
||||
{
|
||||
if (type == LIST)
|
||||
static_cast<timer_list *>(timer)->expires = e;
|
||||
}
|
||||
|
||||
void function()
|
||||
{
|
||||
switch (type) {
|
||||
case LIST:
|
||||
{
|
||||
timer_list *t = static_cast<timer_list *>(timer);
|
||||
if (t->function)
|
||||
t->function(t->data);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
timer_list *_timer; /* Linux timer */
|
||||
dde_kit_timer *_dde_timer; /* DDE kit timer */
|
||||
Genode::Signal_dispatcher<Timer_context> _dispatcher;
|
||||
|
||||
/* call timer function */
|
||||
void _handle(unsigned) { _timer->function(_timer->data); }
|
||||
::Timer::Connection _timer_conn;
|
||||
Lx::List<Context> _list;
|
||||
Genode::Signal_dispatcher<Lx::Timer> _dispatcher;
|
||||
Genode::Tslab<Context, 32 * sizeof(Context)> _timer_alloc;
|
||||
|
||||
public:
|
||||
|
||||
Timer_context(timer_list *timer)
|
||||
: _timer(timer), _dde_timer(0),
|
||||
_dispatcher(*Net::Env::receiver(), *this, &Timer_context::_handle) {}
|
||||
bool ready { true };
|
||||
|
||||
/* schedule next timeout */
|
||||
void schedule(unsigned long expires)
|
||||
private:
|
||||
|
||||
/**
|
||||
* Lookup local timer
|
||||
*/
|
||||
Context *_find_context(void const *timer)
|
||||
{
|
||||
if (!_dde_timer)
|
||||
_dde_timer = dde_kit_timer_add(handler, this, expires);
|
||||
else
|
||||
dde_kit_timer_schedule_absolute(_dde_timer, expires);
|
||||
for (Context *c = _list.first(); c; c = c->next())
|
||||
if (c->timer == timer)
|
||||
return c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if timer is pending
|
||||
* Program the first timer in the list
|
||||
*
|
||||
* The first timer is programmed if the 'programmed' flag was not set
|
||||
* before. The second timer is flagged as not programmed as
|
||||
* 'Timer::trigger_once' invalidates former registered one-shot
|
||||
* timeouts.
|
||||
*/
|
||||
bool pending() const
|
||||
void _program_first_timer()
|
||||
{
|
||||
return _dde_timer ? dde_kit_timer_pending(_dde_timer) : false;
|
||||
Context *ctx = _list.first();
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
if (ctx->programmed)
|
||||
return;
|
||||
|
||||
/* calculate relative microseconds for trigger */
|
||||
unsigned long us = ctx->timeout > jiffies ?
|
||||
jiffies_to_msecs(ctx->timeout - jiffies) * 1000 : 0;
|
||||
_timer_conn.trigger_once(us);
|
||||
|
||||
ctx->programmed = true;
|
||||
|
||||
/* possibly programmed successor must be reprogrammed later */
|
||||
if (Context *next = ctx->next())
|
||||
next->programmed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return internal signal cap
|
||||
* Schedule timer
|
||||
*
|
||||
* Add the context to the scheduling list depending on its timeout
|
||||
* and reprogram the first timer.
|
||||
*/
|
||||
Genode::Signal_context_capability cap() const { return _dispatcher; }
|
||||
void submit() { _dispatcher.submit(1); }
|
||||
void _schedule_timer(Context *ctx, unsigned long expires)
|
||||
{
|
||||
_list.remove(ctx);
|
||||
|
||||
ctx->timeout = expires;
|
||||
ctx->pending = true;
|
||||
ctx->programmed = false;
|
||||
/*
|
||||
* Also write the timeout value to the expires field in
|
||||
* struct timer_list because the checks
|
||||
* it directly.
|
||||
*/
|
||||
ctx->expires(expires);
|
||||
|
||||
Context *c;
|
||||
for (c = _list.first(); c; c = c->next())
|
||||
if (ctx->timeout <= c->timeout)
|
||||
break;
|
||||
_list.insert_before(ctx, c);
|
||||
|
||||
_program_first_timer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert 'timer_list' to 'Timer_conext'
|
||||
* Handle trigger_once signal
|
||||
*/
|
||||
static Timer_context *to_ctx(timer_list const *timer) {
|
||||
return static_cast<Timer_context *>(timer->timer); }
|
||||
|
||||
void remove()
|
||||
void _handle(unsigned)
|
||||
{
|
||||
if (_dde_timer)
|
||||
dde_kit_timer_del(_dde_timer);
|
||||
update_jiffies();
|
||||
|
||||
_dde_timer = 0;
|
||||
while (Lx::Timer::Context *ctx = _list.first()) {
|
||||
if (ctx->timeout > jiffies)
|
||||
break;
|
||||
|
||||
ctx->function();
|
||||
del(ctx->timer);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Timer()
|
||||
:
|
||||
_dispatcher(*Net::Env::receiver(), *this, &Lx::Timer::_handle),
|
||||
_timer_alloc(Genode::env()->heap())
|
||||
{
|
||||
_timer_conn.sigh(_dispatcher);
|
||||
jiffies = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new linux timer
|
||||
*/
|
||||
template <typename TIMER>
|
||||
void add(TIMER *timer)
|
||||
{
|
||||
Context *t = new (&_timer_alloc) Context(timer);
|
||||
_list.append(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete linux timer
|
||||
*/
|
||||
int del(void *timer)
|
||||
{
|
||||
Context *ctx = _find_context(timer);
|
||||
|
||||
/**
|
||||
* If the timer expired it was already cleaned up after its
|
||||
* execution.
|
||||
*/
|
||||
if (!ctx)
|
||||
return 0;
|
||||
|
||||
int rv = ctx->timeout != Context::INVALID_TIMEOUT ? 1 : 0;
|
||||
|
||||
_list.remove(ctx);
|
||||
destroy(&_timer_alloc, ctx);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial scheduling of linux timer
|
||||
*/
|
||||
int schedule(void *timer, unsigned long expires)
|
||||
{
|
||||
Context *ctx = _find_context(timer);
|
||||
if (!ctx) {
|
||||
PERR("schedule unknown timer %p", timer);
|
||||
return -1; /* XXX better use 0 as rv? */
|
||||
}
|
||||
|
||||
/*
|
||||
* If timer was already active return 1, otherwise 0. The return
|
||||
* value is needed by mod_timer().
|
||||
*/
|
||||
int rv = ctx->timeout != Context::INVALID_TIMEOUT ? 1 : 0;
|
||||
|
||||
_schedule_timer(ctx, expires);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule next linux timer
|
||||
*/
|
||||
void schedule_next() { _program_first_timer(); }
|
||||
|
||||
/**
|
||||
* Check if the timer is currently pending
|
||||
*/
|
||||
bool pending(void const *timer)
|
||||
{
|
||||
Context *ctx = _find_context(timer);
|
||||
if (!ctx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ctx->pending;
|
||||
}
|
||||
|
||||
Context *find(struct timer_list const *timer) {
|
||||
return _find_context(timer); }
|
||||
|
||||
/**
|
||||
* Update jiffie counter
|
||||
*/
|
||||
void update_jiffies()
|
||||
{
|
||||
jiffies = msecs_to_jiffies(_timer_conn.elapsed_ms());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first timer context
|
||||
*/
|
||||
Context* first() { return _list.first(); }
|
||||
|
||||
static Timer &t()
|
||||
{
|
||||
static Lx::Timer _t;
|
||||
return _t;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* C handler for DDE timer interface
|
||||
*/
|
||||
static void handler(void *timer)
|
||||
void update_jiffies()
|
||||
{
|
||||
Timer_context *t = static_cast<Timer_context *>(timer);
|
||||
t->submit();
|
||||
/* set context and submit
|
||||
Genode::Signal_transmitter transmitter(t->cap());
|
||||
transmitter.submit(); */
|
||||
Lx::Timer::t().update_jiffies();
|
||||
}
|
||||
|
||||
|
||||
@ -99,9 +303,7 @@ static void handler(void *timer)
|
||||
** linux/timer.h **
|
||||
*******************/
|
||||
|
||||
void init_timer(struct timer_list *timer) {
|
||||
timer->timer = (void *) new (Genode::env()->heap()) Timer_context(timer); }
|
||||
|
||||
void init_timer(struct timer_list *timer) { }
|
||||
|
||||
void add_timer(struct timer_list *timer)
|
||||
{
|
||||
@ -110,12 +312,15 @@ void add_timer(struct timer_list *timer)
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mod_timer(struct timer_list *timer, unsigned long expires)
|
||||
{
|
||||
dde_kit_log(DEBUG_TIMER, "Timer: %p j: %lu ex: %lu func %p",
|
||||
timer, jiffies, expires, timer->function);
|
||||
Timer_context::to_ctx(timer)->schedule(expires);
|
||||
return 0;
|
||||
update_jiffies();
|
||||
|
||||
if (!Lx::Timer::t().find(timer))
|
||||
Lx::Timer::t().add(timer);
|
||||
|
||||
return Lx::Timer::t().schedule(timer, expires);
|
||||
}
|
||||
|
||||
|
||||
@ -124,22 +329,25 @@ void setup_timer(struct timer_list *timer,void (*function)(unsigned long),
|
||||
{
|
||||
timer->function = function;
|
||||
timer->data = data;
|
||||
init_timer(timer);
|
||||
}
|
||||
|
||||
|
||||
int timer_pending(const struct timer_list * timer)
|
||||
{
|
||||
bool pending = Timer_context::to_ctx(timer)->pending();
|
||||
dde_kit_log(DEBUG_TIMER, "Pending %p %u", timer, pending);
|
||||
bool pending = Lx::Timer::t().pending(timer);
|
||||
lx_log(DEBUG_TIMER, "Pending %p %u", timer, pending);
|
||||
return pending;
|
||||
}
|
||||
|
||||
|
||||
int del_timer(struct timer_list *timer)
|
||||
{
|
||||
dde_kit_log(DEBUG_TIMER, "Delete timer %p", timer);
|
||||
Timer_context::to_ctx(timer)->remove();
|
||||
return 0;
|
||||
update_jiffies();
|
||||
lx_log(DEBUG_TIMER, "Delete timer %p", timer);
|
||||
int rv = Lx::Timer::t().del(timer);
|
||||
Lx::Timer::t().schedule_next();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
@ -306,7 +306,6 @@ typedef unsigned short ushort;
|
||||
** linux/jiffies.h **
|
||||
*********************/
|
||||
|
||||
/* we directly map 'jiffies' to 'dde_kit_timer_ticks' */
|
||||
extern unsigned long jiffies;
|
||||
unsigned long msecs_to_jiffies(const unsigned int m);
|
||||
unsigned int jiffies_to_msecs(const unsigned long j);
|
||||
|
Loading…
x
Reference in New Issue
Block a user