mirror of
https://github.com/drasko/codezero.git
synced 2026-01-20 06:43:16 +01:00
Kernel updates since December 2009
This commit is contained in:
@@ -9,6 +9,4 @@ unsigned long bootmem_free_pages(void);
|
||||
void *alloc_bootmem(int size, int alignment);
|
||||
pmd_table_t *alloc_boot_pmd(void);
|
||||
|
||||
extern pgd_table_t init_pgd;
|
||||
|
||||
#endif /* __BOOTMEM_H__ */
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
*/
|
||||
#define CAP_DEVTYPE_TIMER 1
|
||||
#define CAP_DEVTYPE_UART 2
|
||||
#define CAP_DEVTYPE_CLCD 3
|
||||
#define CAP_DEVTYPE_OTHER 0xF
|
||||
#define CAP_DEVTYPE_MASK 0xFFFF
|
||||
#define CAP_DEVNUM_MASK 0xFFFF0000
|
||||
@@ -102,6 +101,10 @@
|
||||
#define CAP_MAP_UNMAP (1 << 5)
|
||||
#define CAP_MAP_UTCB (1 << 6)
|
||||
|
||||
/* Cache operations, applicable to (virtual) memory regions */
|
||||
#define CAP_CACHE_INVALIDATE (1 << 7)
|
||||
#define CAP_CACHE_CLEAN (1 << 8)
|
||||
|
||||
/*
|
||||
* IRQ Control capability
|
||||
*/
|
||||
@@ -137,4 +140,6 @@
|
||||
#define CAP_CAP_DESTROY (1 << 6)
|
||||
#define CAP_CAP_MODIFY (CAP_CAP_DEDUCE | CAP_CAP_SPLIT \
|
||||
| CAP_CAP_DESTROY)
|
||||
|
||||
|
||||
#endif /* __CAP_TYPES_H__ */
|
||||
|
||||
@@ -104,6 +104,8 @@ struct capability *cap_find_by_capid(l4id_t capid, struct cap_list **clist);
|
||||
/* Capability checking on system calls */
|
||||
int cap_map_check(struct ktcb *task, unsigned long phys, unsigned long virt,
|
||||
unsigned long npages, unsigned int flags);
|
||||
int cap_unmap_check(struct ktcb *task, unsigned long virt,
|
||||
unsigned long npages);
|
||||
int cap_thread_check(struct ktcb *task, unsigned int flags,
|
||||
struct task_ids *ids);
|
||||
int cap_exregs_check(struct ktcb *task, struct exregs_data *exregs);
|
||||
@@ -114,5 +116,7 @@ int cap_mutex_check(unsigned long mutex_address, int mutex_op);
|
||||
|
||||
int cap_irq_check(struct ktcb *registrant, unsigned int req,
|
||||
unsigned int flags, l4id_t irq);
|
||||
int cap_cache_check(unsigned long start, unsigned long end,
|
||||
unsigned int flags);
|
||||
|
||||
#endif /* __GENERIC_CAPABILITY_H__ */
|
||||
|
||||
@@ -106,8 +106,7 @@ void kres_insert_container(struct container *c,
|
||||
|
||||
struct container *container_create(void);
|
||||
|
||||
int container_init_pagers(struct kernel_resources *kres,
|
||||
pgd_table_t *current_pgd);
|
||||
int container_init_pagers(struct kernel_resources *kres);
|
||||
|
||||
int init_containers(struct kernel_resources *kres);
|
||||
struct container *container_find(struct kernel_resources *kres, l4id_t cid);
|
||||
|
||||
162
include/l4/generic/debug.h
Normal file
162
include/l4/generic/debug.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Definitions for kernel entry accounting.
|
||||
*
|
||||
* Copyright (C) 2010 B Labs Ltd.
|
||||
*
|
||||
* Written by Bahadir Balban
|
||||
*/
|
||||
#ifndef __GENERIC_DEBUG_H__
|
||||
#define __GENERIC_DEBUG_H__
|
||||
|
||||
#include INC_ARCH(types.h)
|
||||
#include INC_SUBARCH(cache.h)
|
||||
#include <l4/lib/printk.h>
|
||||
|
||||
#if defined(CONFIG_DEBUG_ACCOUNTING)
|
||||
|
||||
struct exception_count {
|
||||
u64 syscall;
|
||||
u64 data_abort;
|
||||
u64 prefetch_abort;
|
||||
u64 irq;
|
||||
u64 undefined_abort;
|
||||
};
|
||||
|
||||
/*
|
||||
* Note these are packed to match systable offsets
|
||||
* so that they're incremented with an auccess
|
||||
*/
|
||||
struct syscall_count {
|
||||
u64 ipc;
|
||||
u64 tswitch;
|
||||
u64 tctrl;
|
||||
u64 exregs;
|
||||
u64 emtpy;
|
||||
u64 unmap;
|
||||
u64 irqctrl;
|
||||
u64 empty1;
|
||||
u64 map;
|
||||
u64 getid;
|
||||
u64 capctrl;
|
||||
u64 empty2;
|
||||
u64 time;
|
||||
u64 mutexctrl;
|
||||
u64 cachectrl;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct task_op_count {
|
||||
u64 context_switch;
|
||||
u64 space_switch;
|
||||
};
|
||||
|
||||
struct cache_op_count {
|
||||
u64 dcache_clean_mva;
|
||||
u64 dcache_inval_mva;
|
||||
u64 icache_clean_mva;
|
||||
u64 icache_inval_mva;
|
||||
u64 dcache_clean_setway;
|
||||
u64 dcache_inval_setway;
|
||||
u64 tlb_mva;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DEBUG_PERFMON_KERNEL)
|
||||
|
||||
/* Minimum, maximum and average timings for the call */
|
||||
struct syscall_timing {
|
||||
u64 total;
|
||||
u32 min;
|
||||
u32 max;
|
||||
u32 avg;
|
||||
};
|
||||
|
||||
struct syscall_timings {
|
||||
struct syscall_timing ipc;
|
||||
struct syscall_timing tswitch;
|
||||
struct syscall_timing tctrl;
|
||||
struct syscall_timing exregs;
|
||||
struct syscall_timing emtpy;
|
||||
struct syscall_timing unmap;
|
||||
struct syscall_timing irqctrl;
|
||||
struct syscall_timing empty1;
|
||||
struct syscall_timing map;
|
||||
struct syscall_timing getid;
|
||||
struct syscall_timing capctrl;
|
||||
struct syscall_timing empty2;
|
||||
struct syscall_timing time;
|
||||
struct syscall_timing mutexctrl;
|
||||
struct syscall_timing cachectrl;
|
||||
u64 all_total;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
extern struct syscall_timings syscall_timings;
|
||||
|
||||
|
||||
#endif /* End of CONFIG_DEBUG_PERFMON_KERNEL */
|
||||
|
||||
struct system_accounting {
|
||||
struct syscall_count syscalls;
|
||||
|
||||
#if defined(CONFIG_DEBUG_PERFMON_KERNEL)
|
||||
struct syscall_timings syscall_timings;
|
||||
#endif
|
||||
|
||||
struct exception_count exceptions;
|
||||
struct cache_op_count cache_ops;
|
||||
struct task_op_count task_ops;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
|
||||
extern struct system_accounting system_accounting;
|
||||
|
||||
static inline void system_account_dabort(void)
|
||||
{
|
||||
system_accounting.exceptions.data_abort++;
|
||||
}
|
||||
|
||||
static inline void system_account_pabort(void)
|
||||
{
|
||||
system_accounting.exceptions.prefetch_abort++;
|
||||
}
|
||||
|
||||
static inline void system_account_undef_abort(void)
|
||||
{
|
||||
system_accounting.exceptions.undefined_abort++;
|
||||
}
|
||||
|
||||
static inline void system_account_irq(void)
|
||||
{
|
||||
system_accounting.exceptions.irq++;
|
||||
}
|
||||
|
||||
static inline void system_account_syscall(void)
|
||||
{
|
||||
system_accounting.exceptions.syscall++;
|
||||
}
|
||||
|
||||
static inline void system_account_context_switch(void)
|
||||
{
|
||||
system_accounting.task_ops.context_switch++;
|
||||
}
|
||||
|
||||
static inline void system_account_space_switch(void)
|
||||
{
|
||||
system_accounting.task_ops.space_switch++;
|
||||
}
|
||||
|
||||
#include INC_SUBARCH(debug.h)
|
||||
|
||||
#else /* End of CONFIG_DEBUG_ACCOUNTING */
|
||||
|
||||
static inline void system_account_cache_op(int op) { }
|
||||
static inline void system_account_irq(void) { }
|
||||
static inline void system_account_syscall(void) { }
|
||||
static inline void system_account_dabort(void) { }
|
||||
static inline void system_account_pabort(void) { }
|
||||
static inline void system_account_undef_abort(void) { }
|
||||
static inline void system_account_space_switch(void) { }
|
||||
static inline void system_account_context_switch(void) { }
|
||||
|
||||
#endif /* End of !CONFIG_DEBUG_ACCOUNTING */
|
||||
|
||||
|
||||
#endif /* __GENERIC_DEBUG_H__ */
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
typedef void (*irq_op_t)(l4id_t irq);
|
||||
struct irq_chip_ops {
|
||||
void (*init)(void);
|
||||
l4id_t (*read_irq)(void);
|
||||
void (*init)();
|
||||
l4id_t (*read_irq)(void *data);
|
||||
irq_op_t ack_and_mask;
|
||||
irq_op_t unmask;
|
||||
};
|
||||
@@ -31,6 +31,7 @@ struct irq_chip {
|
||||
int cascade; /* The irq that lower chip uses on this chip */
|
||||
int start; /* The global irq offset for this chip */
|
||||
int end; /* End of this chip's irqs */
|
||||
void *data; /* Anything that a of interest to a driver */
|
||||
struct irq_chip_ops ops;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,21 +2,32 @@
|
||||
#define __PLATFORM_H__
|
||||
/*
|
||||
* Generic functions to be provided by every platform.
|
||||
*
|
||||
* Include only those API's that are needed by sources
|
||||
* outside the src/platform code.
|
||||
*/
|
||||
|
||||
#include <l4/generic/resource.h>
|
||||
|
||||
void platform_init(void);
|
||||
|
||||
/* Uart APIs */
|
||||
void uart_init(void);
|
||||
void uart_putc(char c);
|
||||
|
||||
/* Timer APIs */
|
||||
void timer_init(void);
|
||||
void timer_start(void);
|
||||
|
||||
/* IRQ controller */
|
||||
void irq_controller_init(void);
|
||||
void platform_irq_enable(int irq);
|
||||
void platform_irq_disable(int irq);
|
||||
|
||||
#define dprintk(str, val) \
|
||||
{ \
|
||||
print_early(str); \
|
||||
printhex8((val)); \
|
||||
print_early("\n"); \
|
||||
}
|
||||
|
||||
void print_early(char *str);
|
||||
void printhex8(unsigned int);
|
||||
|
||||
int platform_setup_device_caps(struct kernel_resources *kres);
|
||||
|
||||
void platform_test_cpucycles(void);
|
||||
|
||||
#endif /* __PLATFORM_H__ */
|
||||
|
||||
@@ -12,4 +12,5 @@ int preempt_count(void);
|
||||
int in_nested_irq_context(void);
|
||||
int in_irq_context(void);
|
||||
int in_task_context(void);
|
||||
|
||||
#endif /* __PREEMPT_H__ */
|
||||
|
||||
@@ -92,15 +92,20 @@ struct kernel_resources {
|
||||
struct mem_cache *cont_cache;
|
||||
|
||||
/* Zombie thread list */
|
||||
struct ktcb_list zombie_list;
|
||||
DECLARE_PERCPU(struct ktcb_list, zombie_list);
|
||||
|
||||
#if defined(CONFIG_SUBARCH_V7)
|
||||
/* Global page tables on split page tables */
|
||||
pgd_global_table_t *pgd_global;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct kernel_resources kernel_resources;
|
||||
|
||||
void free_pgd(void *addr);
|
||||
void free_pmd(void *addr);
|
||||
void free_space(void *addr);
|
||||
void free_ktcb(void *addr);
|
||||
void free_space(void *addr, struct ktcb *task);
|
||||
void free_ktcb(void *addr, struct ktcb *task);
|
||||
void free_capability(void *addr);
|
||||
void free_container(void *addr);
|
||||
void free_user_mutex(void *addr);
|
||||
@@ -118,4 +123,6 @@ int free_boot_memory(struct kernel_resources *kres);
|
||||
|
||||
int init_system_resources(struct kernel_resources *kres);
|
||||
|
||||
void setup_idle_caps(); /*TODO: Delete this when done with it */
|
||||
|
||||
#endif /* __RESOURCES_H__ */
|
||||
|
||||
@@ -7,8 +7,11 @@
|
||||
#define __SCHEDULER_H__
|
||||
|
||||
#include <l4/generic/tcb.h>
|
||||
#include <l4/generic/smp.h>
|
||||
#include INC_SUBARCH(cpu.h)
|
||||
#include INC_SUBARCH(mm.h)
|
||||
#include INC_GLUE(memory.h)
|
||||
#include INC_GLUE(smp.h)
|
||||
|
||||
/* Task priorities */
|
||||
#define TASK_PRIO_MAX 10
|
||||
@@ -19,14 +22,16 @@
|
||||
#define TASK_PRIO_LOW 2
|
||||
#define TASK_PRIO_TOTAL 30
|
||||
|
||||
/* Ticks per second, try ticks = 1000 + timeslice = 1 for regressed preemption test. */
|
||||
#define SCHED_TICKS 100
|
||||
/*
|
||||
* CONFIG_SCHED_TICKS gives ticks per second.
|
||||
* try ticks = 1000, and timeslice = 1 for regressed preemption test.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A task can run continuously at this granularity,
|
||||
* even if it has a greater total time slice.
|
||||
*/
|
||||
#define SCHED_GRANULARITY SCHED_TICKS/50
|
||||
#define SCHED_GRANULARITY CONFIG_SCHED_TICKS/10
|
||||
|
||||
static inline struct ktcb *current_task(void)
|
||||
{
|
||||
@@ -37,13 +42,13 @@ static inline struct ktcb *current_task(void)
|
||||
#define current current_task()
|
||||
#define need_resched (current->ts_need_resched)
|
||||
|
||||
#define SCHED_RQ_TOTAL 2
|
||||
|
||||
#define SCHED_RQ_TOTAL 2
|
||||
|
||||
/* A basic runqueue */
|
||||
struct runqueue {
|
||||
struct scheduler *sched;
|
||||
struct spinlock lock; /* Lock */
|
||||
struct link task_list; /* List of tasks in rq */
|
||||
struct link task_list; /* List of tasks in rq */
|
||||
unsigned int total; /* Total tasks */
|
||||
};
|
||||
|
||||
@@ -52,22 +57,25 @@ struct scheduler {
|
||||
struct runqueue sched_rq[SCHED_RQ_TOTAL];
|
||||
struct runqueue *rq_runnable;
|
||||
struct runqueue *rq_expired;
|
||||
struct ktcb *idle_task;
|
||||
|
||||
/* Total priority of all tasks in container */
|
||||
int prio_total;
|
||||
};
|
||||
extern struct scheduler scheduler;
|
||||
|
||||
void sched_init_runqueue(struct runqueue *rq);
|
||||
DECLARE_PERCPU(extern struct scheduler, scheduler);
|
||||
|
||||
void sched_init_runqueue(struct scheduler *sched, struct runqueue *rq);
|
||||
void sched_init_task(struct ktcb *task, int priority);
|
||||
void sched_prepare_sleep(void);
|
||||
void sched_exit_sync(void);
|
||||
void sched_suspend_sync(void);
|
||||
void sched_suspend_async(void);
|
||||
void sched_resume_sync(struct ktcb *task);
|
||||
void sched_resume_async(struct ktcb *task);
|
||||
void sched_enqueue_task(struct ktcb *first_time_runner, int sync);
|
||||
void scheduler_start(void);
|
||||
void schedule(void);
|
||||
void sched_init(struct scheduler *scheduler);
|
||||
void sched_init(void);
|
||||
void idle_task(void);
|
||||
|
||||
#endif /* __SCHEDULER_H__ */
|
||||
|
||||
23
include/l4/generic/smp.h
Normal file
23
include/l4/generic/smp.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010 B Labs Ltd.
|
||||
*
|
||||
* Author: Prem Mallappa <prem.mallappa@b-labs.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef __GENERIC_SMP_H__
|
||||
#define __GENERIC_SMP_H__
|
||||
|
||||
#include INC_SUBARCH(cpu.h)
|
||||
|
||||
/* IPIs, we define more as we go */
|
||||
/* we have limited IPI's on ARM, exactly 15 */
|
||||
#define IPI_TLB_FLUSH 0x00000001
|
||||
#define IPI_SCHEDULE 0x00000002
|
||||
#define IPI_CACH_FLUSH 0x00000003
|
||||
|
||||
#if !defined (CONFIG_NCPU)
|
||||
#define CONFIG_NCPU 1
|
||||
#define smp_get_cpuid() 0
|
||||
#endif
|
||||
|
||||
#endif /* __GENERIC_SMP_H__ */
|
||||
@@ -1,22 +1,31 @@
|
||||
/*
|
||||
* Generic address space related information.
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
* Copyright (C) 2007-2010 Bahadir Balban
|
||||
*/
|
||||
#ifndef __SPACE_H__
|
||||
#define __SPACE_H__
|
||||
|
||||
/* The flags not embedded in the name behave as expected. E.g USR_RW is also */
|
||||
#define MAP_USR_RW_FLAGS 0 /* CB as one would expect */
|
||||
#define MAP_USR_RO_FLAGS 1 /* CB as one would expect */
|
||||
#define MAP_SVC_RW_FLAGS 2 /* CB as one would expect */
|
||||
#define MAP_USR_IO_FLAGS 3 /* Non-CB, RW TODO: How about RO one? */
|
||||
#define MAP_SVC_IO_FLAGS 4 /* Non-CB, RW */
|
||||
/*
|
||||
* Generic mapping flags.
|
||||
*/
|
||||
#define MAP_FAULT 0
|
||||
#define MAP_USR_RW 1
|
||||
#define MAP_USR_RO 2
|
||||
#define MAP_KERN_RW 3
|
||||
#define MAP_USR_IO 4
|
||||
#define MAP_KERN_IO 5
|
||||
#define MAP_USR_RWX 6
|
||||
#define MAP_KERN_RWX 7
|
||||
#define MAP_USR_RX 8
|
||||
#define MAP_KERN_RX 9
|
||||
#define MAP_UNMAP 10 /* For unmap syscall */
|
||||
#define MAP_INVALID_FLAGS (1 << 31)
|
||||
|
||||
/* Some default aliases */
|
||||
#define MAP_USR_DEFAULT_FLAGS MAP_USR_RW_FLAGS
|
||||
#define MAP_SVC_DEFAULT_FLAGS MAP_SVC_RW_FLAGS
|
||||
#define MAP_IO_DEFAULT_FLAGS MAP_SVC_IO_FLAGS
|
||||
#define MAP_USR_DEFAULT MAP_USR_RW
|
||||
#define MAP_KERN_DEFAULT MAP_KERN_RW
|
||||
#define MAP_IO_DEFAULT MAP_KERN_IO
|
||||
|
||||
#if defined (__KERNEL__)
|
||||
|
||||
@@ -46,11 +55,14 @@ struct address_space_list {
|
||||
};
|
||||
|
||||
struct address_space *address_space_create(struct address_space *orig);
|
||||
void address_space_delete(struct address_space *space);
|
||||
void address_space_delete(struct address_space *space,
|
||||
struct ktcb *task_accounted);
|
||||
void address_space_attach(struct ktcb *tcb, struct address_space *space);
|
||||
struct address_space *address_space_find(l4id_t spid);
|
||||
void address_space_add(struct address_space *space);
|
||||
void address_space_remove(struct address_space *space);
|
||||
|
||||
struct container;
|
||||
void address_space_remove(struct address_space *space, struct container *cont);
|
||||
void init_address_space_list(struct address_space_list *space_list);
|
||||
int check_access(unsigned long vaddr, unsigned long size,
|
||||
unsigned int flags, int page_in);
|
||||
|
||||
@@ -28,15 +28,20 @@
|
||||
#define TASK_INTERRUPTED (1 << 0)
|
||||
#define TASK_SUSPENDING (1 << 1)
|
||||
#define TASK_RESUMING (1 << 2)
|
||||
#define TASK_EXITING (1 << 3)
|
||||
#define TASK_PENDING_SIGNAL (TASK_SUSPENDING | TASK_EXITING)
|
||||
#define TASK_PENDING_SIGNAL (TASK_SUSPENDING)
|
||||
|
||||
/*
|
||||
* This is to indicate a task (either current or one of
|
||||
* its children) exit has occured and cleanup needs to be
|
||||
* called
|
||||
*/
|
||||
#define TASK_EXITED (1 << 3)
|
||||
|
||||
/* Task states */
|
||||
enum task_state {
|
||||
TASK_INACTIVE = 0,
|
||||
TASK_SLEEPING = 1,
|
||||
TASK_RUNNABLE = 2,
|
||||
TASK_DEAD = 3,
|
||||
};
|
||||
|
||||
#define TASK_CID_MASK 0xFF000000
|
||||
@@ -82,6 +87,9 @@ struct ktcb {
|
||||
l4id_t tid; /* Global thread id */
|
||||
l4id_t tgid; /* Global thread group id */
|
||||
|
||||
/* CPU affinity */
|
||||
int affinity;
|
||||
|
||||
/* Other related threads */
|
||||
l4id_t pagerid;
|
||||
|
||||
@@ -94,6 +102,9 @@ struct ktcb {
|
||||
/* Lock for blocking thread state modifications via a syscall */
|
||||
struct mutex thread_control_lock;
|
||||
|
||||
/* To protect against thread deletion/modification */
|
||||
struct spinlock thread_lock;
|
||||
|
||||
u32 ts_need_resched; /* Scheduling flag */
|
||||
enum task_state state;
|
||||
|
||||
@@ -171,13 +182,14 @@ static inline void set_task_ids(struct ktcb *task, struct task_ids *ids)
|
||||
}
|
||||
|
||||
struct ktcb *tcb_find(l4id_t tid);
|
||||
struct ktcb *tcb_find_lock(l4id_t tid);
|
||||
void tcb_add(struct ktcb *tcb);
|
||||
void tcb_remove(struct ktcb *tcb);
|
||||
|
||||
void tcb_init(struct ktcb *tcb);
|
||||
struct ktcb *tcb_alloc_init(l4id_t cid);
|
||||
void tcb_delete(struct ktcb *tcb);
|
||||
|
||||
void tcb_delete_zombies(void);
|
||||
|
||||
void ktcb_list_remove(struct ktcb *task, struct ktcb_list *ktcb_list);
|
||||
void ktcb_list_add(struct ktcb *new, struct ktcb_list *ktcb_list);
|
||||
|
||||
@@ -11,6 +11,7 @@ void thread_id_pool_init(void);
|
||||
int thread_id_new(void);
|
||||
int thread_id_del(int tid);
|
||||
|
||||
void thread_setup_affinity(struct ktcb *task);
|
||||
void thread_destroy(struct ktcb *);
|
||||
|
||||
#endif /* __GENERIC_THREAD_H__ */
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*/
|
||||
|
||||
#ifndef __GENERIC_TIMER_H__
|
||||
#define __GENERIC_TIMER_H__
|
||||
#ifndef __GENERIC_TIME_H__
|
||||
#define __GENERIC_TIME_H__
|
||||
|
||||
/* Used by posix systems */
|
||||
struct timeval {
|
||||
@@ -17,4 +17,4 @@ extern volatile u32 jiffies;
|
||||
|
||||
int do_timer_irq(void);
|
||||
|
||||
#endif /* __GENERIC_TIMER_H__ */
|
||||
#endif /* __GENERIC_TIME_H__ */
|
||||
|
||||
Reference in New Issue
Block a user