mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-23 09:15:36 +00:00
lx_kit: adjust to 4.16.3
This commit is contained in:
committed by
Josef Söntgen
parent
bb8e532361
commit
2efc64ace7
@ -42,8 +42,8 @@
|
|||||||
|
|
||||||
#define ATOMIC_INIT(i) { (i) }
|
#define ATOMIC_INIT(i) { (i) }
|
||||||
|
|
||||||
typedef struct atomic { long counter; } atomic_t;
|
typedef struct atomic { int counter; } atomic_t;
|
||||||
typedef atomic_t atomic_long_t;
|
typedef struct { long counter; } atomic_long_t;
|
||||||
|
|
||||||
static inline int atomic_read(const atomic_t *p) { return p->counter; }
|
static inline int atomic_read(const atomic_t *p) { return p->counter; }
|
||||||
static inline void atomic_set(atomic_t *p, int i) { p->counter = i; }
|
static inline void atomic_set(atomic_t *p, int i) { p->counter = i; }
|
||||||
@ -60,10 +60,10 @@ static inline int atomic_inc_return(atomic_t *p) { return atomic_add_return(1
|
|||||||
static inline int atomic_dec_and_test(atomic_t *p) { return atomic_sub_and_test(1, p); }
|
static inline int atomic_dec_and_test(atomic_t *p) { return atomic_sub_and_test(1, p); }
|
||||||
static inline int atomic_inc_not_zero(atomic_t *p) { return p->counter ? atomic_inc_return(p) : 0; }
|
static inline int atomic_inc_not_zero(atomic_t *p) { return p->counter ? atomic_inc_return(p) : 0; }
|
||||||
|
|
||||||
static inline void atomic_long_inc(atomic_long_t *p) { atomic_add(1, p); }
|
static inline void atomic_long_inc(atomic_long_t *p) { p->counter += 1; }
|
||||||
static inline void atomic_long_sub(int i, atomic_long_t *p) { atomic_sub(i, p); }
|
static inline void atomic_long_sub(long i, atomic_long_t *p) { p->counter -= i; }
|
||||||
static inline long atomic_long_add_return(long i, atomic_long_t *p) { return atomic_add_return(i, p); }
|
static inline long atomic_long_add_return(long i, atomic_long_t *p) { p->counter += i; return p->counter; }
|
||||||
static inline long atomic_long_read(atomic_long_t *p) { return atomic_read(p); }
|
static inline long atomic_long_read(atomic_long_t *p) { return p->counter; }
|
||||||
|
|
||||||
static inline int atomic_cmpxchg(atomic_t *v, int old, int n)
|
static inline int atomic_cmpxchg(atomic_t *v, int old, int n)
|
||||||
{
|
{
|
||||||
@ -101,6 +101,16 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
|
|||||||
return ret != u;
|
return ret != u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int atomic_dec_if_positive(atomic_t *v)
|
||||||
|
{
|
||||||
|
int c = atomic_read(v);
|
||||||
|
|
||||||
|
if (c >= 0)
|
||||||
|
atomic_dec(v);
|
||||||
|
|
||||||
|
return c - 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define smp_mb__before_atomic_dec()
|
#define smp_mb__before_atomic_dec()
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#define BIT(nr) (1UL << (nr))
|
#define BIT(nr) (1UL << (nr))
|
||||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
||||||
|
|
||||||
|
#define BIT_ULL(nr) (1ULL << (nr))
|
||||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||||
|
|
||||||
@ -85,6 +86,11 @@ static inline unsigned long __ffs64(u64 word)
|
|||||||
(bit) < (size); \
|
(bit) < (size); \
|
||||||
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||||
|
|
||||||
|
#define for_each_clear_bit(bit, addr, size) \
|
||||||
|
for ((bit) = find_first_zero_bit((addr), (size)); \
|
||||||
|
(bit) < (size); \
|
||||||
|
(bit) = find_next_zero_bit((addr), (size), (bit) + 1))
|
||||||
|
|
||||||
static inline int get_bitmask_order(unsigned int count) {
|
static inline int get_bitmask_order(unsigned int count) {
|
||||||
return __builtin_clz(count) ^ 0x1f; }
|
return __builtin_clz(count) ^ 0x1f; }
|
||||||
|
|
||||||
@ -109,3 +115,7 @@ static inline __u16 ror16(__u16 word, unsigned int shift)
|
|||||||
return (word >> shift) | (word << (16 - shift));
|
return (word >> shift) | (word << (16 - shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BITS_PER_LONG_LONG (sizeof(long long) * 8)
|
||||||
|
#define GENMASK_ULL(h, l) \
|
||||||
|
(((~0ULL) - (1ULL << (l)) + 1) & \
|
||||||
|
(~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
|
||||||
|
@ -39,8 +39,14 @@
|
|||||||
|
|
||||||
#define BUG_ON(condition) do { if (condition) BUG(); } while(0)
|
#define BUG_ON(condition) do { if (condition) BUG(); } while(0)
|
||||||
|
|
||||||
|
#define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e))))
|
||||||
|
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
|
||||||
|
|
||||||
#define BUILD_BUG_ON_MSG(cond,msg) ({ \
|
#define BUILD_BUG_ON_MSG(cond,msg) ({ \
|
||||||
extern int __attribute__((error(msg))) build_bug(); \
|
extern int __attribute__((error(msg))) build_bug(); \
|
||||||
if (cond) { build_bug(); } })
|
if (cond) { build_bug(); } })
|
||||||
|
|
||||||
#define BUILD_BUG() BUILD_BUG_ON_MSG(1,"BUILD_BUG failed")
|
#define BUILD_BUG() BUILD_BUG_ON_MSG(1,"BUILD_BUG failed")
|
||||||
|
|
||||||
|
#define BUILD_BUG_ON_NOT_POWER_OF_2(n) \
|
||||||
|
BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
|
||||||
|
@ -60,10 +60,15 @@
|
|||||||
#define WRITE_ONCE(x, val) \
|
#define WRITE_ONCE(x, val) \
|
||||||
({ \
|
({ \
|
||||||
barrier(); \
|
barrier(); \
|
||||||
__builtin_memcpy((void *)&(x), (const void *)&(val), sizeof(x)); \
|
union { typeof(x) v; char c[1]; } u = \
|
||||||
|
{ .v = (typeof(x)) (val) }; \
|
||||||
|
__builtin_memcpy((void *)&(x), (const void *)u.c, sizeof(x)); \
|
||||||
barrier(); \
|
barrier(); \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/* XXX alpha, powerpc, blackfin needs proper implementation */
|
||||||
|
#define smp_read_barrier_depends() do { } while (0)
|
||||||
|
#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); barrier(); } while (0)
|
||||||
|
|
||||||
/**************************
|
/**************************
|
||||||
** linux/compiler-gcc.h **
|
** linux/compiler-gcc.h **
|
||||||
@ -73,5 +78,9 @@
|
|||||||
#define __packed __attribute__((packed))
|
#define __packed __attribute__((packed))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define __aligned(x) __attribute__((aligned(x)))
|
||||||
|
|
||||||
#define uninitialized_var(x) x = x
|
#define uninitialized_var(x) x = x
|
||||||
|
|
||||||
|
#define unreachable() \
|
||||||
|
do { __builtin_unreachable(); } while (0)
|
||||||
|
@ -21,7 +21,9 @@
|
|||||||
struct completion;
|
struct completion;
|
||||||
|
|
||||||
void complete(struct completion *);
|
void complete(struct completion *);
|
||||||
|
void complete_all(struct completion *);
|
||||||
void init_completion(struct completion *c);
|
void init_completion(struct completion *c);
|
||||||
|
bool try_wait_for_completion(struct completion *);
|
||||||
|
|
||||||
void wait_for_completion(struct completion *c);
|
void wait_for_completion(struct completion *c);
|
||||||
unsigned long wait_for_completion_timeout(struct completion *c,
|
unsigned long wait_for_completion_timeout(struct completion *c,
|
||||||
|
@ -35,6 +35,8 @@ enum {
|
|||||||
EIO = 5,
|
EIO = 5,
|
||||||
ENXIO = 6,
|
ENXIO = 6,
|
||||||
E2BIG = 7,
|
E2BIG = 7,
|
||||||
|
ENOEXEC = 8,
|
||||||
|
EBADF = 9,
|
||||||
EDEADLK = 11,
|
EDEADLK = 11,
|
||||||
ENOMEM = 12,
|
ENOMEM = 12,
|
||||||
EACCES = 13,
|
EACCES = 13,
|
||||||
@ -103,6 +105,8 @@ enum {
|
|||||||
EPROBE_DEFER = 210,
|
EPROBE_DEFER = 210,
|
||||||
|
|
||||||
EL3RST = 211,
|
EL3RST = 211,
|
||||||
|
ENOKEY = 212,
|
||||||
|
ECHRNG = 213,
|
||||||
|
|
||||||
MAX_ERRNO = 4095,
|
MAX_ERRNO = 4095,
|
||||||
};
|
};
|
||||||
@ -112,10 +116,10 @@ enum {
|
|||||||
** linux/err.h **
|
** linux/err.h **
|
||||||
*****************/
|
*****************/
|
||||||
|
|
||||||
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
|
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)(0UL-MAX_ERRNO))
|
||||||
|
|
||||||
static inline bool IS_ERR(void const *ptr) {
|
static inline bool IS_ERR(void const *ptr) {
|
||||||
return (unsigned long)(ptr) > (unsigned long)(-1000); }
|
return (unsigned long)(ptr) >= (unsigned long)(0UL-MAX_ERRNO); }
|
||||||
|
|
||||||
static inline void * ERR_PTR(long error) {
|
static inline void * ERR_PTR(long error) {
|
||||||
return (void *) error; }
|
return (void *) error; }
|
||||||
|
@ -24,13 +24,12 @@ enum {
|
|||||||
__GFP_HIGHMEM = 0x00000002u,
|
__GFP_HIGHMEM = 0x00000002u,
|
||||||
__GFP_DMA32 = 0x00000004u,
|
__GFP_DMA32 = 0x00000004u,
|
||||||
__GFP_MOVABLE = 0x00000008u,
|
__GFP_MOVABLE = 0x00000008u,
|
||||||
__GFP_WAIT = 0x00000010u,
|
__GFP_RECLAIMABLE = 0x00000010u,
|
||||||
__GFP_HIGH = 0x00000020u,
|
__GFP_HIGH = 0x00000020u,
|
||||||
__GFP_IO = 0x00000040u,
|
__GFP_IO = 0x00000040u,
|
||||||
__GFP_FS = 0x00000080u,
|
__GFP_FS = 0x00000080u,
|
||||||
__GFP_COLD = 0x00000100u,
|
|
||||||
__GFP_NOWARN = 0x00000200u,
|
__GFP_NOWARN = 0x00000200u,
|
||||||
__GFP_REPEAT = 0x00000400u,
|
__GFP_RETRY_MAYFAIL = 0x00000400u,
|
||||||
__GFP_NOFAIL = 0x00000800u,
|
__GFP_NOFAIL = 0x00000800u,
|
||||||
__GFP_NORETRY = 0x00001000u,
|
__GFP_NORETRY = 0x00001000u,
|
||||||
__GFP_MEMALLOC = 0x00002000u,
|
__GFP_MEMALLOC = 0x00002000u,
|
||||||
@ -39,24 +38,24 @@ enum {
|
|||||||
__GFP_NOMEMALLOC = 0x00010000u,
|
__GFP_NOMEMALLOC = 0x00010000u,
|
||||||
__GFP_HARDWALL = 0x00020000u,
|
__GFP_HARDWALL = 0x00020000u,
|
||||||
__GFP_THISNODE = 0x00040000u,
|
__GFP_THISNODE = 0x00040000u,
|
||||||
__GFP_RECLAIMABLE = 0x00080000u,
|
__GFP_ATOMIC = 0x00080000u,
|
||||||
__GFP_KMEMCG = 0x00100000u,
|
__GFP_ACCOUNT = 0x00100000u,
|
||||||
__GFP_NOTRACK = 0x00200000u,
|
__GFP_DIRECT_RECLAIM = 0x00200000u,
|
||||||
__GFP_NO_KSWAPD = 0x00400000u,
|
__GFP_WRITE = 0x00800000u,
|
||||||
__GFP_OTHER_NODE = 0x00800000u,
|
__GFP_KSWAPD_RECLAIM = 0x01000000u,
|
||||||
__GFP_WRITE = 0x01000000u,
|
|
||||||
__GFP_DIRECT_RECLAIM = 0x400000u,
|
|
||||||
__GFP_KSWAPD_RECLAIM = 0x2000000u,
|
|
||||||
|
|
||||||
GFP_LX_DMA = 0x80000000u,
|
GFP_LX_DMA = 0x80000000u,
|
||||||
__GFP_RECLAIM = __GFP_DIRECT_RECLAIM | __GFP_KSWAPD_RECLAIM,
|
__GFP_RECLAIM = __GFP_DIRECT_RECLAIM | __GFP_KSWAPD_RECLAIM,
|
||||||
|
|
||||||
GFP_ATOMIC = __GFP_HIGH,
|
GFP_ATOMIC = (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM),
|
||||||
GFP_DMA = __GFP_DMA,
|
GFP_DMA = __GFP_DMA,
|
||||||
GFP_DMA32 = __GFP_DMA32,
|
GFP_DMA32 = __GFP_DMA32,
|
||||||
GFP_KERNEL = __GFP_WAIT | __GFP_IO | __GFP_FS,
|
GFP_KERNEL = __GFP_RECLAIM | __GFP_IO | __GFP_FS,
|
||||||
|
/*
|
||||||
GFP_TEMPORARY = __GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_RECLAIMABLE,
|
GFP_TEMPORARY = __GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_RECLAIMABLE,
|
||||||
GFP_USER = __GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL,
|
*/
|
||||||
GFP_HIGHUSER = __GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL |
|
GFP_USER = __GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL,
|
||||||
__GFP_HIGHMEM,
|
GFP_HIGHUSER = GFP_USER | __GFP_HIGHMEM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM)
|
||||||
|
@ -24,13 +24,14 @@ void init_waitqueue_head(wait_queue_head_t *wq)
|
|||||||
wq->list = new (&Lx_kit::env().heap()) Wait_list;
|
wq->list = new (&Lx_kit::env().heap()) Wait_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_wait_queue(wait_queue_head_t *q, wait_queue_entry_t *wait)
|
||||||
void remove_wait_queue(wait_queue_head_t *wq, wait_queue_t *wait)
|
|
||||||
{
|
{
|
||||||
Wait_list *list = static_cast<Wait_list*>(wq->list);
|
printk("%s called\n", __func__);
|
||||||
if (!list) { return; }
|
}
|
||||||
|
|
||||||
destroy(&Lx_kit::env().heap(), list);
|
void remove_wait_queue(wait_queue_head_t *wq, wait_queue_entry_t *wait)
|
||||||
|
{
|
||||||
|
printk("%s called\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -87,12 +88,32 @@ void init_completion(struct completion *work)
|
|||||||
|
|
||||||
void complete(struct completion *work)
|
void complete(struct completion *work)
|
||||||
{
|
{
|
||||||
work->done = 1;
|
if (work->done != UINT_MAX)
|
||||||
|
work->done++;
|
||||||
|
|
||||||
Lx::Task *task = static_cast<Lx::Task*>(work->task);
|
Lx::Task *task = static_cast<Lx::Task*>(work->task);
|
||||||
if (task) { task->unblock(); }
|
if (task) { task->unblock(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void complete_all(struct completion *work)
|
||||||
|
{
|
||||||
|
work->done = UINT_MAX;
|
||||||
|
|
||||||
|
Lx::Task *task = static_cast<Lx::Task*>(work->task);
|
||||||
|
if (task) { task->unblock(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_wait_for_completion(struct completion *work)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
if (!work->done)
|
||||||
|
ret = 0;
|
||||||
|
else if (work->done != UINT_MAX)
|
||||||
|
work->done--;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long wait_for_completion_timeout(struct completion *work,
|
unsigned long wait_for_completion_timeout(struct completion *work,
|
||||||
unsigned long timeout)
|
unsigned long timeout)
|
||||||
|
@ -34,7 +34,11 @@ static inline void __delay_timer(unsigned long usecs)
|
|||||||
_delay_timer->usleep(usecs);
|
_delay_timer->usleep(usecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void udelay(unsigned long usecs) { __delay_timer(usecs); }
|
void udelay(unsigned long usecs)
|
||||||
|
{
|
||||||
|
__delay_timer(usecs);
|
||||||
|
Lx::timer_update_jiffies();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void msleep(unsigned int msecs)
|
void msleep(unsigned int msecs)
|
||||||
|
@ -18,13 +18,18 @@
|
|||||||
#include <lx_kit/env.h>
|
#include <lx_kit/env.h>
|
||||||
|
|
||||||
|
|
||||||
struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
|
struct page *alloc_pages(gfp_t const gfp_mask, unsigned int order)
|
||||||
{
|
{
|
||||||
|
using Genode::Cache_attribute;
|
||||||
|
|
||||||
struct page *page = (struct page *)kzalloc(sizeof(struct page), 0);
|
struct page *page = (struct page *)kzalloc(sizeof(struct page), 0);
|
||||||
|
|
||||||
size_t size = PAGE_SIZE << order;
|
size_t size = PAGE_SIZE << order;
|
||||||
|
|
||||||
Genode::Ram_dataspace_capability ds_cap = Lx::backend_alloc(size, Genode::UNCACHED);
|
gfp_t const dma_mask = (GFP_DMA | GFP_LX_DMA | GFP_DMA32);
|
||||||
|
Cache_attribute const cached = (gfp_mask & dma_mask) ? Genode::UNCACHED
|
||||||
|
: Genode::CACHED;
|
||||||
|
Genode::Ram_dataspace_capability ds_cap = Lx::backend_alloc(size, cached);
|
||||||
page->addr = Lx_kit::env().rm().attach(ds_cap);
|
page->addr = Lx_kit::env().rm().attach(ds_cap);
|
||||||
page->paddr = Genode::Dataspace_client(ds_cap).phys_addr();
|
page->paddr = Genode::Dataspace_client(ds_cap).phys_addr();
|
||||||
|
|
||||||
@ -57,3 +62,9 @@ void get_page(struct page *page)
|
|||||||
{
|
{
|
||||||
atomic_inc(&page->_count);
|
atomic_inc(&page->_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void put_page(struct page *page)
|
||||||
|
{
|
||||||
|
TRACE;
|
||||||
|
}
|
||||||
|
@ -34,7 +34,7 @@ void mutex_destroy(struct mutex *m)
|
|||||||
Lx::Task::List *waiters = static_cast<Lx::Task::List *>(m->waiters);
|
Lx::Task::List *waiters = static_cast<Lx::Task::List *>(m->waiters);
|
||||||
|
|
||||||
/* FIXME potentially blocked tasks are not unblocked */
|
/* FIXME potentially blocked tasks are not unblocked */
|
||||||
if (waiters->first()) {
|
if (waiters && waiters->first()) {
|
||||||
Genode::error(__func__, "destroying non-empty waiters list");
|
Genode::error(__func__, "destroying non-empty waiters list");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Implementation of linux/sched.h
|
* \brief Implementation of linux/sched.h
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2015-09-09
|
* \date 2015-09-09
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -14,26 +15,33 @@
|
|||||||
/* Linux kit includes */
|
/* Linux kit includes */
|
||||||
#include <lx_kit/scheduler.h>
|
#include <lx_kit/scheduler.h>
|
||||||
|
|
||||||
|
struct process_timer {
|
||||||
|
struct timer_list timer;
|
||||||
|
Lx::Task &task;
|
||||||
|
|
||||||
static void unblock_task(unsigned long task)
|
process_timer(Lx::Task &task) : task(task) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void process_timeout(struct timer_list *list)
|
||||||
{
|
{
|
||||||
Lx::Task *t = (Lx::Task *)task;
|
struct process_timer *timeout = from_timer(timeout, list, timer);
|
||||||
|
timeout->task.unblock();
|
||||||
t->unblock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
signed long schedule_timeout(signed long timeout)
|
signed long schedule_timeout(signed long timeout)
|
||||||
{
|
{
|
||||||
struct timer_list timer;
|
Lx::Task & cur_task = *Lx::scheduler().current();
|
||||||
|
struct process_timer timer { cur_task };
|
||||||
|
timer_setup(&timer.timer, process_timeout, 0);
|
||||||
|
|
||||||
unsigned long expire = timeout + jiffies;
|
unsigned long expire = timeout + jiffies;
|
||||||
setup_timer(&timer, unblock_task, (unsigned long)Lx::scheduler().current());
|
mod_timer(&timer.timer, expire);
|
||||||
mod_timer(&timer, expire);
|
|
||||||
|
|
||||||
Lx::scheduler().current()->block_and_schedule();
|
cur_task.block_and_schedule();
|
||||||
|
|
||||||
del_timer(&timer);
|
del_timer(&timer.timer);
|
||||||
|
|
||||||
timeout = (expire - jiffies);
|
timeout = (expire - jiffies);
|
||||||
|
|
||||||
|
@ -46,6 +46,12 @@ void *kzalloc(size_t size, gfp_t flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *kvzalloc(size_t size, gfp_t flags)
|
||||||
|
{
|
||||||
|
return kmalloc(size, flags | __GFP_ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void *kzalloc_node(size_t size, gfp_t flags, int node)
|
void *kzalloc_node(size_t size, gfp_t flags, int node)
|
||||||
{
|
{
|
||||||
return kzalloc(size, 0);
|
return kzalloc(size, 0);
|
||||||
@ -171,6 +177,17 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct kmem_cache *kmem_cache_create_usercopy(const char *name, size_t size,
|
||||||
|
size_t align, slab_flags_t flags,
|
||||||
|
size_t useroffset, size_t usersize,
|
||||||
|
void (*ctor)(void *))
|
||||||
|
{
|
||||||
|
/* XXX copied from above */
|
||||||
|
enum { SLAB_LX_DMA = 0x80000000ul, };
|
||||||
|
return new (Lx::Malloc::mem()) kmem_cache(size, flags & SLAB_LX_DMA, ctor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void kmem_cache_destroy(struct kmem_cache *cache)
|
void kmem_cache_destroy(struct kmem_cache *cache)
|
||||||
{
|
{
|
||||||
destroy(Lx::Malloc::mem(), cache);
|
destroy(Lx::Malloc::mem(), cache);
|
||||||
|
@ -15,9 +15,6 @@
|
|||||||
#include <lx_kit/timer.h>
|
#include <lx_kit/timer.h>
|
||||||
|
|
||||||
|
|
||||||
void init_timer(struct timer_list *timer) { }
|
|
||||||
|
|
||||||
|
|
||||||
int mod_timer(struct timer_list *timer, unsigned long expires)
|
int mod_timer(struct timer_list *timer, unsigned long expires)
|
||||||
{
|
{
|
||||||
if (!Lx::timer().find(timer))
|
if (!Lx::timer().find(timer))
|
||||||
@ -27,12 +24,12 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setup_timer(struct timer_list *timer,void (*function)(unsigned long),
|
void timer_setup(struct timer_list *timer,
|
||||||
unsigned long data)
|
void (*function)(struct timer_list *),
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
timer->function = function;
|
timer->function = function;
|
||||||
timer->data = data;
|
timer->flags = flags;
|
||||||
init_timer(timer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -59,7 +56,7 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, enum hrtimer_mode m
|
|||||||
int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
|
int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
|
||||||
unsigned long delta_ns, const enum hrtimer_mode mode)
|
unsigned long delta_ns, const enum hrtimer_mode mode)
|
||||||
{
|
{
|
||||||
unsigned long expires = tim.tv64 / (NSEC_PER_MSEC * HZ);
|
unsigned long expires = tim / (NSEC_PER_MSEC * HZ);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prevent truncation through rounding the values by adding 1 jiffy
|
* Prevent truncation through rounding the values by adding 1 jiffy
|
||||||
@ -74,6 +71,12 @@ int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool hrtimer_active(const struct hrtimer *timer)
|
||||||
|
{
|
||||||
|
return Lx::timer().find(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int hrtimer_cancel(struct hrtimer *timer)
|
int hrtimer_cancel(struct hrtimer *timer)
|
||||||
{
|
{
|
||||||
int rv = Lx::timer().del(timer);
|
int rv = Lx::timer().del(timer);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include <lx_kit/scheduler.h>
|
#include <lx_kit/scheduler.h>
|
||||||
|
|
||||||
|
|
||||||
void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *w, int state)
|
void prepare_to_wait(wait_queue_head_t *q, wait_queue_entry_t *w, int state)
|
||||||
{
|
{
|
||||||
if (!q) { return; }
|
if (!q) { return; }
|
||||||
|
|
||||||
@ -26,13 +26,13 @@ void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *w, int state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *w, int state)
|
void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_entry_t *w, int state)
|
||||||
{
|
{
|
||||||
prepare_to_wait(q, w, state);
|
prepare_to_wait(q, w, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void finish_wait(wait_queue_head_t *q, wait_queue_t *w)
|
void finish_wait(wait_queue_head_t *q, wait_queue_entry_t *w)
|
||||||
{
|
{
|
||||||
if (!q) { return; }
|
if (!q) { return; }
|
||||||
|
|
||||||
|
@ -27,6 +27,13 @@ bool queue_work(struct workqueue_struct *wq, struct work_struct *work)
|
|||||||
{
|
{
|
||||||
work->wq = wq;
|
work->wq = wq;
|
||||||
|
|
||||||
|
/* a invalid func pointer will lead to pagefault with ip=0 sp=0 */
|
||||||
|
if (!work || !work->func) {
|
||||||
|
Genode::error("invalid work, called from ",
|
||||||
|
__builtin_return_address(0));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* check for separate work queue task */
|
/* check for separate work queue task */
|
||||||
if (wq && wq->task) {
|
if (wq && wq->task) {
|
||||||
Lx::Work *lx_work = (Lx::Work *)wq->task;
|
Lx::Work *lx_work = (Lx::Work *)wq->task;
|
||||||
@ -41,20 +48,10 @@ bool queue_work(struct workqueue_struct *wq, struct work_struct *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _schedule_delayed_work(unsigned long w)
|
void delayed_work_timer_fn(struct timer_list *t)
|
||||||
{
|
{
|
||||||
delayed_work *work = (delayed_work *)w;
|
struct delayed_work *dwork = from_timer(dwork, t, timer);
|
||||||
workqueue_struct *wq = work->wq;
|
queue_work(dwork->wq, &dwork->work);
|
||||||
|
|
||||||
/* check for separate work queue task */
|
|
||||||
if (wq && wq->task) {
|
|
||||||
Lx::Work *lx_work = (Lx::Work *)wq->task;
|
|
||||||
lx_work->schedule_delayed(work, 0);
|
|
||||||
lx_work->unblock();
|
|
||||||
} else {
|
|
||||||
Lx::Work::work_queue().schedule_delayed(work, 0);
|
|
||||||
Lx::Work::work_queue().unblock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -65,10 +62,10 @@ bool queue_delayed_work(struct workqueue_struct *wq,
|
|||||||
|
|
||||||
/* treat delayed work without delay like any other work */
|
/* treat delayed work without delay like any other work */
|
||||||
if (delay == 0) {
|
if (delay == 0) {
|
||||||
_schedule_delayed_work((unsigned long)dwork);
|
delayed_work_timer_fn(&dwork->timer);
|
||||||
} else {
|
} else {
|
||||||
setup_timer(&dwork->timer, _schedule_delayed_work, (unsigned long)dwork);
|
timer_setup(&dwork->timer, delayed_work_timer_fn, 0);
|
||||||
mod_timer(&dwork->timer, delay);
|
mod_timer(&dwork->timer, jiffies + delay);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -82,7 +79,13 @@ int schedule_delayed_work(struct delayed_work *dwork, unsigned long delay)
|
|||||||
|
|
||||||
bool cancel_work_sync(struct work_struct *work)
|
bool cancel_work_sync(struct work_struct *work)
|
||||||
{
|
{
|
||||||
return Lx::Work::work_queue().cancel_work(work, true);
|
/* check for separate work queue task */
|
||||||
|
if (work->wq && work->wq->task) {
|
||||||
|
Lx::Work *lx_work = (Lx::Work *)work->wq->task;
|
||||||
|
|
||||||
|
return lx_work->cancel_work(work, true);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -101,12 +104,8 @@ bool cancel_delayed_work_sync(struct delayed_work *dwork)
|
|||||||
bool pending = cancel_delayed_work(dwork);
|
bool pending = cancel_delayed_work(dwork);
|
||||||
|
|
||||||
if (pending) {
|
if (pending) {
|
||||||
Genode::warning("WARN: delayed_work ", dwork, " is executed directly in "
|
|
||||||
"current '", Lx::scheduler().current()->name(), "' routine");
|
|
||||||
|
|
||||||
dwork->work.func(&dwork->work);
|
dwork->work.func(&dwork->work);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pending;
|
return pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
#define IORESOURCE_IO 0x00000100
|
#define IORESOURCE_IO 0x00000100
|
||||||
#define IORESOURCE_MEM 0x00000200
|
#define IORESOURCE_MEM 0x00000200
|
||||||
#define IORESOURCE_IRQ 0x00000400
|
#define IORESOURCE_IRQ 0x00000400
|
||||||
|
#define IORESOURCE_UNSET 0x20000000
|
||||||
|
|
||||||
|
#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
|
||||||
|
|
||||||
struct resource
|
struct resource
|
||||||
{
|
{
|
||||||
@ -31,6 +34,20 @@ struct resource
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* helpers to define resources */
|
||||||
|
#define DEFINE_RES_NAMED(_start, _size, _name, _flags) \
|
||||||
|
{ \
|
||||||
|
.start = (_start), \
|
||||||
|
.end = (_start) + (_size) - 1, \
|
||||||
|
.name = (_name), \
|
||||||
|
.flags = (_flags), \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_RES_MEM_NAMED(_start, _size, _name) \
|
||||||
|
DEFINE_RES_NAMED((_start), (_size), (_name), IORESOURCE_MEM)
|
||||||
|
#define DEFINE_RES_MEM(_start, _size) \
|
||||||
|
DEFINE_RES_MEM_NAMED((_start), (_size), NULL)
|
||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
|
|
||||||
struct resource *request_region(resource_size_t start, resource_size_t n,
|
struct resource *request_region(resource_size_t start, resource_size_t n,
|
||||||
@ -44,4 +61,22 @@ struct resource * devm_request_mem_region(struct device *dev, resource_size_t st
|
|||||||
void release_region(resource_size_t start, resource_size_t n);
|
void release_region(resource_size_t start, resource_size_t n);
|
||||||
void release_mem_region(resource_size_t start, resource_size_t n);
|
void release_mem_region(resource_size_t start, resource_size_t n);
|
||||||
|
|
||||||
resource_size_t resource_size(const struct resource *res);
|
static inline resource_size_t resource_size(const struct resource *res)
|
||||||
|
{
|
||||||
|
return res->end - res->start + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned long resource_type(const struct resource *res)
|
||||||
|
{
|
||||||
|
return res->flags & IORESOURCE_TYPE_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* True iff r1 completely contains r2 */
|
||||||
|
static inline bool resource_contains(struct resource *r1, struct resource *r2)
|
||||||
|
{
|
||||||
|
if (resource_type(r1) != resource_type(r2))
|
||||||
|
return false;
|
||||||
|
if (r1->flags & IORESOURCE_UNSET || r2->flags & IORESOURCE_UNSET)
|
||||||
|
return false;
|
||||||
|
return r1->start <= r2->start && r1->end >= r2->end;
|
||||||
|
}
|
||||||
|
@ -19,9 +19,13 @@
|
|||||||
** linux/kconfig.h **
|
** linux/kconfig.h **
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
#define IS_ENABLED(x) x
|
#define __ARG_PLACEHOLDER_1 0,
|
||||||
#define IS_BUILTIN(x) x
|
#define __take_second_arg(__ignored, val, ...) val
|
||||||
|
#define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0)
|
||||||
|
#define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val)
|
||||||
|
#define __is_defined(x) ___is_defined(x)
|
||||||
|
#define IS_BUILTIN(option) __is_defined(option)
|
||||||
|
#define IS_ENABLED(option) IS_BUILTIN(option)
|
||||||
|
|
||||||
/********************
|
/********************
|
||||||
** linux/kernel.h **
|
** linux/kernel.h **
|
||||||
@ -185,3 +189,4 @@ void might_sleep();
|
|||||||
#define swap(a, b) \
|
#define swap(a, b) \
|
||||||
do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
|
do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
|
||||||
|
|
||||||
|
#define max3(x, y, z) max((typeof(x))max(x, y), z)
|
||||||
|
@ -31,10 +31,11 @@
|
|||||||
#define LIST_POISON1 nullptr
|
#define LIST_POISON1 nullptr
|
||||||
#define LIST_POISON2 nullptr
|
#define LIST_POISON2 nullptr
|
||||||
#else
|
#else
|
||||||
#define LIST_POISON1 ((void *)0x00100100)
|
#define LIST_POISON1 ((void *)0x00000100)
|
||||||
#define LIST_POISON2 ((void *)0x00200200)
|
#define LIST_POISON2 ((void *)0x00000200)
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#define POISON_INUSE 0x5a
|
||||||
|
|
||||||
/******************
|
/******************
|
||||||
** linux/list.h **
|
** linux/list.h **
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
|
|
||||||
struct module;
|
struct module;
|
||||||
#define module_init(fn) void module_##fn(void) { fn(); }
|
#define module_init(fn) int module_##fn(void) { return fn(); }
|
||||||
#define module_exit(fn) void module_exit_##fn(void) { fn(); }
|
#define module_exit(fn) void module_exit_##fn(void) { fn(); }
|
||||||
void module_put_and_exit(int);
|
void module_put_and_exit(int);
|
||||||
|
|
||||||
|
@ -26,7 +26,9 @@ typedef struct pm_message { int event; } pm_message_t;
|
|||||||
struct dev_pm_info
|
struct dev_pm_info
|
||||||
{
|
{
|
||||||
pm_message_t power_state;
|
pm_message_t power_state;
|
||||||
bool is_prepared;
|
bool is_prepared:1;
|
||||||
|
bool is_suspended:1;
|
||||||
|
atomic_t usage_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dev_pm_ops {
|
struct dev_pm_ops {
|
||||||
|
@ -30,5 +30,6 @@ void down_read(struct rw_semaphore *sem);
|
|||||||
void up_read(struct rw_semaphore *sem);
|
void up_read(struct rw_semaphore *sem);
|
||||||
void down_write(struct rw_semaphore *sem);
|
void down_write(struct rw_semaphore *sem);
|
||||||
void up_write(struct rw_semaphore *sem);
|
void up_write(struct rw_semaphore *sem);
|
||||||
|
int down_write_killable(struct rw_semaphore *);
|
||||||
|
|
||||||
#define __RWSEM_INITIALIZER(name) { 0 }
|
#define __RWSEM_INITIALIZER(name) { 0 }
|
||||||
|
@ -20,10 +20,12 @@
|
|||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
typedef struct spinlock { unsigned unused; } spinlock_t;
|
typedef struct spinlock { unsigned unused; } spinlock_t;
|
||||||
|
typedef struct raw_spinlock { unsigned dummy; } raw_spinlock_t;
|
||||||
#define DEFINE_SPINLOCK(name) spinlock_t name
|
#define DEFINE_SPINLOCK(name) spinlock_t name
|
||||||
|
|
||||||
void spin_lock(spinlock_t *lock);
|
void spin_lock(spinlock_t *lock);
|
||||||
void spin_lock_nested(spinlock_t *lock, int subclass);
|
void spin_lock_nested(spinlock_t *lock, int subclass);
|
||||||
|
void spin_lock_irqsave_nested(spinlock_t *lock, unsigned flags, int subclass);
|
||||||
void spin_unlock(spinlock_t *lock);
|
void spin_unlock(spinlock_t *lock);
|
||||||
void spin_lock_init(spinlock_t *lock);
|
void spin_lock_init(spinlock_t *lock);
|
||||||
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
|
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
|
||||||
@ -36,6 +38,8 @@ void spin_lock_bh(spinlock_t *lock);
|
|||||||
void spin_unlock_bh(spinlock_t *lock);
|
void spin_unlock_bh(spinlock_t *lock);
|
||||||
int spin_trylock(spinlock_t *lock);
|
int spin_trylock(spinlock_t *lock);
|
||||||
|
|
||||||
|
void raw_spin_lock_init(raw_spinlock_t *);
|
||||||
|
#define __RAW_SPIN_LOCK_UNLOCKED(raw_spinlock_t) {0}
|
||||||
|
|
||||||
/****************************
|
/****************************
|
||||||
** linux/spinlock_types.h **
|
** linux/spinlock_types.h **
|
||||||
|
@ -50,9 +50,21 @@ enum {
|
|||||||
** linux/ktime.h **
|
** linux/ktime.h **
|
||||||
*******************/
|
*******************/
|
||||||
|
|
||||||
union ktime { s64 tv64; };
|
typedef s64 ktime_t;
|
||||||
|
|
||||||
typedef union ktime ktime_t;
|
static inline int ktime_compare(const ktime_t cmp1, const ktime_t cmp2)
|
||||||
|
{
|
||||||
|
if (cmp1 < cmp2)
|
||||||
|
return -1;
|
||||||
|
if (cmp1 > cmp2)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2)
|
||||||
|
{
|
||||||
|
return ktime_compare(cmp1, cmp2) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);
|
ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);
|
||||||
|
|
||||||
@ -61,29 +73,35 @@ static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec)
|
|||||||
return ktime_add_ns(kt, usec * 1000);
|
return ktime_add_ns(kt, usec * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline ktime_t ktime_add_ms(const ktime_t kt, const u64 msec)
|
||||||
|
{
|
||||||
|
return ktime_add_ns(kt, msec * NSEC_PER_MSEC);
|
||||||
|
}
|
||||||
|
|
||||||
static inline ktime_t ktime_get(void)
|
static inline ktime_t ktime_get(void)
|
||||||
{
|
{
|
||||||
return (ktime_t){ .tv64 = (s64)jiffies * HZ * NSEC_PER_MSEC /* ns */ };
|
return (ktime_t){ (s64)jiffies * HZ * NSEC_PER_MSEC /* ns */ };
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ktime_t ktime_set(const long sec, const unsigned long nsec)
|
static inline ktime_t ktime_set(const long sec, const unsigned long nsec)
|
||||||
{
|
{
|
||||||
return (ktime_t){ .tv64 = (s64)sec * NSEC_PER_SEC + (s64)nsec /* ns */ };
|
return (ktime_t){ (s64)sec * NSEC_PER_SEC + (s64)nsec /* ns */ };
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ktime_t ktime_add(const ktime_t a, const ktime_t b)
|
static inline ktime_t ktime_add(const ktime_t a, const ktime_t b)
|
||||||
{
|
{
|
||||||
return (ktime_t){ .tv64 = a.tv64 + b.tv64 /* ns */ };
|
return (ktime_t){ a + b /* ns */ };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s64 ktime_ms_delta(const ktime_t, const ktime_t);
|
||||||
s64 ktime_us_delta(const ktime_t later, const ktime_t earlier);
|
s64 ktime_us_delta(const ktime_t later, const ktime_t earlier);
|
||||||
|
|
||||||
static inline struct timeval ktime_to_timeval(const ktime_t kt)
|
static inline struct timeval ktime_to_timeval(const ktime_t kt)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
tv.tv_sec = kt.tv64 / NSEC_PER_SEC;
|
tv.tv_sec = kt / NSEC_PER_SEC;
|
||||||
tv.tv_usec = (kt.tv64 - (tv.tv_sec * NSEC_PER_SEC)) / NSEC_PER_USEC;
|
tv.tv_usec = (kt - (tv.tv_sec * NSEC_PER_SEC)) / NSEC_PER_USEC;
|
||||||
return tv;
|
return tv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,3 +109,4 @@ ktime_t ktime_get_real(void);
|
|||||||
ktime_t ktime_sub(const ktime_t, const ktime_t);
|
ktime_t ktime_sub(const ktime_t, const ktime_t);
|
||||||
ktime_t ktime_get_monotonic_offset(void);
|
ktime_t ktime_get_monotonic_offset(void);
|
||||||
|
|
||||||
|
ktime_t ktime_get_boottime(void);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
* \author Sebastian Sumpf
|
* \author Sebastian Sumpf
|
||||||
* \author Josef Soentgen
|
* \author Josef Soentgen
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2014-08-21
|
* \date 2014-08-21
|
||||||
*
|
*
|
||||||
* Based on the prototypes found in the Linux kernel's 'include/'.
|
* Based on the prototypes found in the Linux kernel's 'include/'.
|
||||||
@ -24,38 +25,40 @@ extern struct tvec_base boot_tvec_bases; /* needed by 'dwc_common_linux.c' */
|
|||||||
|
|
||||||
struct timer_list
|
struct timer_list
|
||||||
{
|
{
|
||||||
void (*function)(unsigned long);
|
|
||||||
unsigned long data;
|
|
||||||
void *timer;
|
|
||||||
unsigned long expires;
|
unsigned long expires;
|
||||||
struct tvec_base *base; /* needed by 'dwc_common_linux.c' */
|
void (*function)(struct timer_list*);
|
||||||
|
unsigned int flags;
|
||||||
|
|
||||||
|
unsigned long data; /* keep for compat with 4.4.3 drivers */
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_timer(struct timer_list *);
|
int mod_timer(struct timer_list *timer, unsigned long expires);
|
||||||
void init_timer_deferrable(struct timer_list *);
|
int del_timer(struct timer_list * timer);
|
||||||
int mod_timer(struct timer_list *timer, unsigned long expires);
|
void timer_setup(struct timer_list *timer,
|
||||||
int del_timer(struct timer_list * timer);
|
void (*callback)(struct timer_list *), unsigned int flags);
|
||||||
void setup_timer(struct timer_list *timer, void (*function)(unsigned long),
|
int timer_pending(const struct timer_list * timer);
|
||||||
unsigned long data);
|
|
||||||
|
|
||||||
int timer_pending(const struct timer_list * timer);
|
|
||||||
unsigned long round_jiffies(unsigned long j);
|
unsigned long round_jiffies(unsigned long j);
|
||||||
unsigned long round_jiffies_relative(unsigned long j);
|
unsigned long round_jiffies_relative(unsigned long j);
|
||||||
unsigned long round_jiffies_up(unsigned long j);
|
unsigned long round_jiffies_up(unsigned long j);
|
||||||
|
static inline void add_timer(struct timer_list *timer) {
|
||||||
void set_timer_slack(struct timer_list *time, int slack_hz);
|
mod_timer(timer, timer->expires); }
|
||||||
static inline void add_timer(struct timer_list *timer) { mod_timer(timer, timer->expires); }
|
static inline int del_timer_sync(struct timer_list * timer) {
|
||||||
|
return del_timer(timer); }
|
||||||
static inline
|
|
||||||
int del_timer_sync(struct timer_list * timer) { return del_timer(timer); }
|
|
||||||
|
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
** linux/hrtimer.h **
|
** linux/hrtimer.h **
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
enum hrtimer_mode { HRTIMER_MODE_ABS = 0 };
|
enum hrtimer_mode {
|
||||||
enum hrtimer_restart { HRTIMER_NORESTART = 0 };
|
HRTIMER_MODE_ABS = 0,
|
||||||
|
HRTIMER_MODE_REL = 0x1,
|
||||||
|
HRTIMER_MODE_REL_PINNED = 0x03,
|
||||||
|
};
|
||||||
|
enum hrtimer_restart {
|
||||||
|
HRTIMER_NORESTART,
|
||||||
|
HRTIMER_RESTART,
|
||||||
|
};
|
||||||
|
|
||||||
struct hrtimer
|
struct hrtimer
|
||||||
{
|
{
|
||||||
@ -64,8 +67,9 @@ struct hrtimer
|
|||||||
void *timer;
|
void *timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
int hrtimer_start_range_ns(struct hrtimer *, ktime_t,
|
int hrtimer_start_range_ns(struct hrtimer *, ktime_t,
|
||||||
unsigned long, const enum hrtimer_mode);
|
unsigned long, const enum hrtimer_mode);
|
||||||
|
|
||||||
void hrtimer_init(struct hrtimer *, clockid_t, enum hrtimer_mode);
|
void hrtimer_init(struct hrtimer *, clockid_t, enum hrtimer_mode);
|
||||||
int hrtimer_cancel(struct hrtimer *);
|
int hrtimer_cancel(struct hrtimer *);
|
||||||
|
bool hrtimer_active(const struct hrtimer *);
|
||||||
|
@ -106,3 +106,5 @@ typedef u16 wchar_t;
|
|||||||
* XXX 'mode_t' is 'unsigned int' on x86_64
|
* XXX 'mode_t' is 'unsigned int' on x86_64
|
||||||
*/
|
*/
|
||||||
typedef unsigned short mode_t;
|
typedef unsigned short mode_t;
|
||||||
|
|
||||||
|
typedef unsigned slab_flags_t;
|
||||||
|
@ -20,8 +20,10 @@
|
|||||||
***********************/
|
***********************/
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
WQ_MEM_RECLAIM,
|
WQ_FREEZABLE = 1 << 2,
|
||||||
WQ_CPU_INTENSIVE,
|
WQ_MEM_RECLAIM = 1 << 3,
|
||||||
|
WQ_HIGHPRI = 1 << 4,
|
||||||
|
WQ_CPU_INTENSIVE = 1 << 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct work_struct;
|
struct work_struct;
|
||||||
@ -45,13 +47,14 @@ struct delayed_work {
|
|||||||
bool cancel_work_sync(struct work_struct *work);
|
bool cancel_work_sync(struct work_struct *work);
|
||||||
bool cancel_delayed_work_sync(struct delayed_work *work);
|
bool cancel_delayed_work_sync(struct delayed_work *work);
|
||||||
bool cancel_delayed_work(struct delayed_work *dwork);
|
bool cancel_delayed_work(struct delayed_work *dwork);
|
||||||
int schedule_delayed_work(struct delayed_work *work, unsigned long delay);
|
int schedule_delayed_work(struct delayed_work *work, unsigned long delay);
|
||||||
int schedule_work(struct work_struct *work);
|
int schedule_work(struct work_struct *work);
|
||||||
void flush_scheduled_work(void);
|
void flush_scheduled_work(void);
|
||||||
|
|
||||||
bool flush_work(struct work_struct *work);
|
bool flush_work(struct work_struct *work);
|
||||||
bool flush_work_sync(struct work_struct *work);
|
bool flush_work_sync(struct work_struct *work);
|
||||||
|
|
||||||
|
void delayed_work_timer_fn(struct timer_list *t);
|
||||||
|
|
||||||
#define PREPARE_WORK(_work, _func) \
|
#define PREPARE_WORK(_work, _func) \
|
||||||
do { (_work)->func = (_func); } while (0)
|
do { (_work)->func = (_func); } while (0)
|
||||||
@ -71,7 +74,7 @@ bool flush_work_sync(struct work_struct *work);
|
|||||||
#define INIT_DELAYED_WORK(_work, _func) \
|
#define INIT_DELAYED_WORK(_work, _func) \
|
||||||
do { \
|
do { \
|
||||||
INIT_WORK(&(_work)->work, (_func)); \
|
INIT_WORK(&(_work)->work, (_func)); \
|
||||||
init_timer(&(_work)->timer); \
|
timer_setup(&(_work)->timer, delayed_work_timer_fn, 0); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
@ -87,6 +90,8 @@ void flush_workqueue(struct workqueue_struct *wq);
|
|||||||
bool queue_delayed_work(struct workqueue_struct *, struct delayed_work *, unsigned long);
|
bool queue_delayed_work(struct workqueue_struct *, struct delayed_work *, unsigned long);
|
||||||
bool flush_delayed_work(struct delayed_work *dwork);
|
bool flush_delayed_work(struct delayed_work *dwork);
|
||||||
bool queue_work(struct workqueue_struct *wq, struct work_struct *work);
|
bool queue_work(struct workqueue_struct *wq, struct work_struct *work);
|
||||||
|
struct work_struct *current_work(void);
|
||||||
|
void drain_workqueue(struct workqueue_struct *);
|
||||||
|
|
||||||
#define DECLARE_DELAYED_WORK(n, f) \
|
#define DECLARE_DELAYED_WORK(n, f) \
|
||||||
struct delayed_work n = { .work = { .func = f }, .timer = { .function = 0 } }
|
struct delayed_work n = { .work = { .func = f }, .timer = { .function = 0 } }
|
||||||
@ -100,6 +105,8 @@ static inline struct delayed_work *to_delayed_work(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern struct workqueue_struct *system_wq;
|
extern struct workqueue_struct *system_wq;
|
||||||
|
extern struct workqueue_struct *system_unbound_wq;
|
||||||
|
extern struct workqueue_struct *system_long_wq;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
WORK_STRUCT_STATIC = 0,
|
WORK_STRUCT_STATIC = 0,
|
||||||
@ -138,28 +145,31 @@ enum {
|
|||||||
** linux/wait.h **
|
** linux/wait.h **
|
||||||
******************/
|
******************/
|
||||||
|
|
||||||
typedef struct wait_queue wait_queue_t;
|
typedef struct wait_queue_entry wait_queue_entry_t;
|
||||||
typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
|
typedef int (*wait_queue_func_t)(wait_queue_entry_t *, unsigned, int, void *);
|
||||||
typedef struct wait_queue_head { void *list; } wait_queue_head_t;
|
typedef struct wait_queue_head { void *list; } wait_queue_head_t;
|
||||||
struct wait_queue
|
struct wait_queue_entry {
|
||||||
{
|
unsigned int flags;
|
||||||
wait_queue_func_t func;
|
void *private;
|
||||||
void *private;
|
wait_queue_func_t func;
|
||||||
|
struct list_head entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void init_wait_entry(struct wait_queue_entry *, int);
|
||||||
|
|
||||||
#define DEFINE_WAIT(name) \
|
#define DEFINE_WAIT(name) \
|
||||||
wait_queue_t name;
|
wait_queue_entry_t name;
|
||||||
|
|
||||||
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { 0 }
|
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { 0 }
|
||||||
|
|
||||||
#define DECLARE_WAITQUEUE(name, tsk) \
|
#define DECLARE_WAITQUEUE(name, tsk) \
|
||||||
wait_queue_t name
|
wait_queue_entry_t name
|
||||||
|
|
||||||
#define DECLARE_WAIT_QUEUE_HEAD(name) \
|
#define DECLARE_WAIT_QUEUE_HEAD(name) \
|
||||||
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
|
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
|
||||||
|
|
||||||
#define DEFINE_WAIT_FUNC(name, function) \
|
#define DEFINE_WAIT_FUNC(name, function) \
|
||||||
wait_queue_t name
|
wait_queue_entry_t name
|
||||||
|
|
||||||
/* simplified signature */
|
/* simplified signature */
|
||||||
void __wake_up(wait_queue_head_t *q, bool all);
|
void __wake_up(wait_queue_head_t *q, bool all);
|
||||||
@ -176,14 +186,14 @@ int waitqueue_active(wait_queue_head_t *);
|
|||||||
void wake_up_interruptible_sync_poll(wait_queue_head_t *, int);
|
void wake_up_interruptible_sync_poll(wait_queue_head_t *, int);
|
||||||
void wake_up_interruptible_poll(wait_queue_head_t *, int);
|
void wake_up_interruptible_poll(wait_queue_head_t *, int);
|
||||||
|
|
||||||
void prepare_to_wait(wait_queue_head_t *, wait_queue_t *, int);
|
void prepare_to_wait(wait_queue_head_t *, wait_queue_entry_t *, int);
|
||||||
void prepare_to_wait_exclusive(wait_queue_head_t *, wait_queue_t *, int);
|
void prepare_to_wait_exclusive(wait_queue_head_t *, wait_queue_entry_t *, int);
|
||||||
void finish_wait(wait_queue_head_t *, wait_queue_t *);
|
void finish_wait(wait_queue_head_t *, wait_queue_entry_t *);
|
||||||
|
|
||||||
int autoremove_wake_function(wait_queue_t *, unsigned, int, void *);
|
int autoremove_wake_function(wait_queue_entry_t *, unsigned, int, void *);
|
||||||
void add_wait_queue(wait_queue_head_t *, wait_queue_t *);
|
void add_wait_queue(wait_queue_head_t *, wait_queue_entry_t *);
|
||||||
void add_wait_queue_exclusive(wait_queue_head_t *, wait_queue_t *);
|
void add_wait_queue_exclusive(wait_queue_head_t *, wait_queue_entry_t *);
|
||||||
void remove_wait_queue(wait_queue_head_t *, wait_queue_t *);
|
void remove_wait_queue(wait_queue_head_t *, wait_queue_entry_t *);
|
||||||
|
|
||||||
/* our wait event implementation - it's okay as value */
|
/* our wait event implementation - it's okay as value */
|
||||||
void ___wait_event(wait_queue_head_t*);
|
void ___wait_event(wait_queue_head_t*);
|
||||||
|
@ -76,6 +76,8 @@ class Lx::Addr_to_page_mapping : public Lx_kit::List<Addr_to_page_mapping>::Elem
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct page* find_page_by_paddr(unsigned long paddr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +59,8 @@ class Lx::Io_port
|
|||||||
case 1: _port->outb(port, val); break;
|
case 1: _port->outb(port, val); break;
|
||||||
case 2: _port->outw(port, val); break;
|
case 2: _port->outw(port, val); break;
|
||||||
case 4: _port->outl(port, val); break;
|
case 4: _port->outl(port, val); break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -74,6 +76,8 @@ class Lx::Io_port
|
|||||||
case 1: *val = _port->inb(port); break;
|
case 1: *val = _port->inb(port); break;
|
||||||
case 2: *val = _port->inw(port); break;
|
case 2: *val = _port->inw(port); break;
|
||||||
case 4: *val = _port->inl(port); break;
|
case 4: *val = _port->inl(port); break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -35,12 +35,14 @@ namespace Lx {
|
|||||||
/**
|
/**
|
||||||
* Return singleton 'Platform::Connection'
|
* Return singleton 'Platform::Connection'
|
||||||
*
|
*
|
||||||
* Implementation must be privided by the driver.
|
* Implementation must be provided by the driver.
|
||||||
*/
|
*/
|
||||||
Platform::Connection *pci();
|
Platform::Connection *pci();
|
||||||
|
|
||||||
template <typename FUNC>
|
template <typename FUNC>
|
||||||
static inline void for_each_pci_device(FUNC const &func);
|
static inline void for_each_pci_device(FUNC const &func,
|
||||||
|
unsigned const device_class = 0,
|
||||||
|
unsigned const class_mask = 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -220,7 +222,8 @@ class Lx::Pci_dev : public pci_dev, public Lx_kit::List<Pci_dev>::Element
|
|||||||
* released at the platform driver.
|
* released at the platform driver.
|
||||||
*/
|
*/
|
||||||
template <typename FUNC>
|
template <typename FUNC>
|
||||||
void Lx::for_each_pci_device(FUNC const &func)
|
void Lx::for_each_pci_device(FUNC const &func, unsigned const device_class,
|
||||||
|
unsigned const class_mask)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Obtain first device, the operation may exceed the session quota.
|
* Obtain first device, the operation may exceed the session quota.
|
||||||
@ -228,7 +231,7 @@ void Lx::for_each_pci_device(FUNC const &func)
|
|||||||
*/
|
*/
|
||||||
Platform::Device_capability cap =
|
Platform::Device_capability cap =
|
||||||
Lx::pci()->with_upgrade([&] () {
|
Lx::pci()->with_upgrade([&] () {
|
||||||
return Lx::pci()->first_device(); });
|
return Lx::pci()->first_device(device_class, class_mask); });
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate over the devices of the platform session.
|
* Iterate over the devices of the platform session.
|
||||||
@ -247,7 +250,7 @@ void Lx::for_each_pci_device(FUNC const &func)
|
|||||||
*/
|
*/
|
||||||
Platform::Device_capability next_cap =
|
Platform::Device_capability next_cap =
|
||||||
Lx::pci()->with_upgrade([&] () {
|
Lx::pci()->with_upgrade([&] () {
|
||||||
return pci()->next_device(cap); });
|
return pci()->next_device(cap, device_class, class_mask); });
|
||||||
|
|
||||||
Lx::pci()->release_device(cap);
|
Lx::pci()->release_device(cap);
|
||||||
cap = next_cap;
|
cap = next_cap;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
/* Linux emulation environment includes */
|
/* Linux emulation environment includes */
|
||||||
#include <lx_kit/pci.h>
|
#include <lx_kit/pci.h>
|
||||||
#include <lx_kit/internal/pci_dev.h>
|
#include <lx_kit/internal/pci_dev.h>
|
||||||
|
#include <io_port_session/connection.h>
|
||||||
|
|
||||||
namespace Lx {
|
namespace Lx {
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ namespace Lx {
|
|||||||
*
|
*
|
||||||
* Implementation must be provided by the driver.
|
* Implementation must be provided by the driver.
|
||||||
*/
|
*/
|
||||||
Pci_dev_registry *pci_dev_registry();
|
Pci_dev_registry *pci_dev_registry(Genode::Env *env = nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -35,15 +36,23 @@ class Lx::Pci_dev_registry
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Lx_kit::List<Pci_dev> _devs;
|
Lx_kit::List<Pci_dev> _devs;
|
||||||
|
Genode::Env &_env;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
Pci_dev_registry(Genode::Env &env) : _env(env) { }
|
||||||
|
|
||||||
void insert(Pci_dev *pci_dev)
|
void insert(Pci_dev *pci_dev)
|
||||||
{
|
{
|
||||||
_devs.insert(pci_dev);
|
_devs.insert(pci_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remove(Pci_dev *pci_dev)
|
||||||
|
{
|
||||||
|
_devs.remove(pci_dev);
|
||||||
|
}
|
||||||
|
|
||||||
Pci_dev* first() { return _devs.first(); }
|
Pci_dev* first() { return _devs.first(); }
|
||||||
|
|
||||||
Genode::Io_mem_dataspace_capability io_mem(Genode::addr_t phys,
|
Genode::Io_mem_dataspace_capability io_mem(Genode::addr_t phys,
|
||||||
@ -89,17 +98,50 @@ class Lx::Pci_dev_registry
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Genode::Io_port_connection iox(_env, port, sizeof(T));
|
||||||
|
switch (sizeof(T)) {
|
||||||
|
case 1:
|
||||||
|
return iox.inb(port);
|
||||||
|
case 2:
|
||||||
|
return iox.inw(port);
|
||||||
|
case 4:
|
||||||
|
return iox.inl(port);
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
Genode::error("unknown exception io_read");
|
||||||
|
}
|
||||||
|
|
||||||
Genode::warning("I/O port(", port, ") read failed");
|
Genode::warning("I/O port(", port, ") read failed");
|
||||||
return (T)~0;
|
|
||||||
|
return (T)~0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void io_write(unsigned port, T value)
|
void io_write(unsigned port, T value)
|
||||||
{
|
{
|
||||||
/* try I/O access on all PCI devices, return on first success */
|
/* try I/O access on all PCI devices, return on first success */
|
||||||
for (Pci_dev *d = _devs.first(); d; d = d->next())
|
for (Pci_dev *d = _devs.first(); d; d = d->next()) {
|
||||||
if (d->io_port().out<T>(port, value))
|
if (d->io_port().out<T>(port, value))
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Genode::Io_port_connection iox(_env, port, sizeof(T));
|
||||||
|
switch (sizeof(T)) {
|
||||||
|
case 1:
|
||||||
|
iox.outb(port, value);
|
||||||
|
return;
|
||||||
|
case 2:
|
||||||
|
iox.outw(port, value);
|
||||||
|
return;
|
||||||
|
case 4:
|
||||||
|
iox.outl(port, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
Genode::error("unknown exception io_write");
|
||||||
|
}
|
||||||
|
|
||||||
Genode::warning("I/O port(", port, ") write failed");
|
Genode::warning("I/O port(", port, ") write failed");
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
namespace Lx {
|
namespace Lx {
|
||||||
class Work;
|
class Work;
|
||||||
|
class Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -34,16 +35,23 @@ class Lx::Work
|
|||||||
*/
|
*/
|
||||||
virtual void unblock() = 0;
|
virtual void unblock() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute all queued work items
|
||||||
|
*
|
||||||
|
* The calling task is woken up afterwards.
|
||||||
|
*/
|
||||||
|
virtual void flush(Task &) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wakeup calling task after work item was executed
|
||||||
|
*/
|
||||||
|
virtual void wakeup_for(void const * const, Task &) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule work
|
* Schedule work
|
||||||
*/
|
*/
|
||||||
virtual void schedule(struct ::work_struct *) = 0;
|
virtual void schedule(struct ::work_struct *) = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedule delayed work
|
|
||||||
*/
|
|
||||||
virtual void schedule_delayed(struct ::delayed_work *, unsigned long delay) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule delayed work
|
* Schedule delayed work
|
||||||
*/
|
*/
|
||||||
@ -53,6 +61,11 @@ class Lx::Work
|
|||||||
* Cancel work item
|
* Cancel work item
|
||||||
*/
|
*/
|
||||||
virtual bool cancel_work(struct ::work_struct *, bool sync = false) = 0;
|
virtual bool cancel_work(struct ::work_struct *, bool sync = false) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if work is currently queued
|
||||||
|
*/
|
||||||
|
virtual bool work_queued(void const * const) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return task name
|
* Return task name
|
||||||
|
@ -90,6 +90,8 @@ void Lx::pci_init(Genode::Env &env, Genode::Ram_session &ram,
|
|||||||
_global_pci.construct(env);
|
_global_pci.construct(env);
|
||||||
_global_ram = &ram;
|
_global_ram = &ram;
|
||||||
_global_md_alloc = &md_alloc;
|
_global_md_alloc = &md_alloc;
|
||||||
|
|
||||||
|
Lx::pci_dev_registry(&env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -99,9 +101,9 @@ Platform::Connection *Lx::pci()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Lx::Pci_dev_registry *Lx::pci_dev_registry()
|
Lx::Pci_dev_registry *Lx::pci_dev_registry(Genode::Env *env)
|
||||||
{
|
{
|
||||||
static Lx::Pci_dev_registry _pci_dev_registry;
|
static Lx::Pci_dev_registry _pci_dev_registry(*env);
|
||||||
return &_pci_dev_registry;
|
return &_pci_dev_registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ class Lx::Format_command
|
|||||||
if (!format[++consumed]) return;
|
if (!format[++consumed]) return;
|
||||||
|
|
||||||
/* check for %$x syntax */
|
/* check for %$x syntax */
|
||||||
prefix = (format[consumed] == '#');
|
prefix = (format[consumed] == '#') || (format[consumed] == '.');
|
||||||
if (prefix && !format[++consumed]) return;
|
if (prefix && !format[++consumed]) return;
|
||||||
|
|
||||||
/* heading zero indicates zero-padding */
|
/* heading zero indicates zero-padding */
|
||||||
|
@ -61,7 +61,7 @@ class Lx_kit::Timer : public Lx::Timer
|
|||||||
{
|
{
|
||||||
timer_list *t = static_cast<timer_list *>(timer);
|
timer_list *t = static_cast<timer_list *>(timer);
|
||||||
if (t->function)
|
if (t->function)
|
||||||
t->function(t->data);
|
t->function(t);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ class Lx_kit::Work : public Lx::Work
|
|||||||
*/
|
*/
|
||||||
struct Context : public Lx_kit::List<Context>::Element
|
struct Context : public Lx_kit::List<Context>::Element
|
||||||
{
|
{
|
||||||
|
Lx::Task *waiting_task { nullptr };
|
||||||
|
|
||||||
void *work;
|
void *work;
|
||||||
enum Type { NORMAL, DELAYED, TASKLET } type;
|
enum Type { NORMAL, DELAYED, TASKLET } type;
|
||||||
|
|
||||||
@ -86,6 +88,9 @@ class Lx_kit::Work : public Lx::Work
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
Lx::Task *_waiting_task = nullptr;
|
||||||
|
|
||||||
|
|
||||||
Work(Genode::Allocator &alloc, char const *name = "work_queue")
|
Work(Genode::Allocator &alloc, char const *name = "work_queue")
|
||||||
: _task(Work::run_work, reinterpret_cast<void*>(this), name,
|
: _task(Work::run_work, reinterpret_cast<void*>(this), name,
|
||||||
Lx::Task::PRIORITY_2, Lx::scheduler()),
|
Lx::Task::PRIORITY_2, Lx::scheduler()),
|
||||||
@ -99,6 +104,12 @@ class Lx_kit::Work : public Lx::Work
|
|||||||
while (Context *c = _list.first()) {
|
while (Context *c = _list.first()) {
|
||||||
_list.remove(c);
|
_list.remove(c);
|
||||||
c->exec();
|
c->exec();
|
||||||
|
|
||||||
|
if (c->waiting_task) {
|
||||||
|
c->waiting_task->unblock();
|
||||||
|
c->waiting_task = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
destroy(&_work_alloc, c);
|
destroy(&_work_alloc, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,6 +119,12 @@ class Lx_kit::Work : public Lx::Work
|
|||||||
Work *work_queue = reinterpret_cast<Work*>(wq);
|
Work *work_queue = reinterpret_cast<Work*>(wq);
|
||||||
while (1) {
|
while (1) {
|
||||||
work_queue->exec();
|
work_queue->exec();
|
||||||
|
|
||||||
|
if (work_queue->_waiting_task) {
|
||||||
|
work_queue->_waiting_task->unblock();
|
||||||
|
work_queue->_waiting_task = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Lx::scheduler().current()->block_and_schedule();
|
Lx::scheduler().current()->block_and_schedule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,15 +133,41 @@ class Lx_kit::Work : public Lx::Work
|
|||||||
** Lx::Work interface **
|
** Lx::Work interface **
|
||||||
************************/
|
************************/
|
||||||
|
|
||||||
void unblock() { _task.unblock(); }
|
void unblock()
|
||||||
|
{
|
||||||
|
_task.unblock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush(Lx::Task &task)
|
||||||
|
{
|
||||||
|
_task.unblock();
|
||||||
|
|
||||||
|
_waiting_task = &task;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wakeup_for(void const * const work, Lx::Task &task)
|
||||||
|
{
|
||||||
|
Context *ctx = nullptr;
|
||||||
|
|
||||||
|
for (Context *c = _list.first(); c; c = c->next()) {
|
||||||
|
if (c->work == work) {
|
||||||
|
ctx = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
Genode::error("BUG: no work queued for wakeup_for call");
|
||||||
|
Genode::sleep_forever();
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->waiting_task = &task;
|
||||||
|
_task.unblock();
|
||||||
|
}
|
||||||
|
|
||||||
void schedule(struct work_struct *work) {
|
void schedule(struct work_struct *work) {
|
||||||
_schedule(work); }
|
_schedule(work); }
|
||||||
|
|
||||||
void schedule_delayed(struct delayed_work *work,
|
|
||||||
unsigned long /*delay*/) {
|
|
||||||
_schedule(work); }
|
|
||||||
|
|
||||||
void schedule_tasklet(struct tasklet_struct *tasklet) {
|
void schedule_tasklet(struct tasklet_struct *tasklet) {
|
||||||
_schedule(tasklet); }
|
_schedule(tasklet); }
|
||||||
|
|
||||||
@ -144,6 +187,17 @@ class Lx_kit::Work : public Lx::Work
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool work_queued(void const * const work)
|
||||||
|
{
|
||||||
|
for (Context *c = _list.first(); c; c = c->next()) {
|
||||||
|
if (c->work == work) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
char const *task_name() override { return _task.name(); }
|
char const *task_name() override { return _task.name(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user