mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Added a new system call sys_timer.
sys_timer accumulates timer ticks into seconds, minutes, hours and days. It's left to the user to calculate from days into a date. It is not yet known if the calculation is even roughly correct. Reduced 2 kmem_reclaim/grant calls into one kmem_control call.
This commit is contained in:
@@ -83,33 +83,28 @@ int validate_granted_pages(unsigned long pfn, int npages)
|
||||
* this memory is used for thread creation and memory mapping, (e.g. new
|
||||
* page tables, page middle directories, per-task kernel stack etc.)
|
||||
*/
|
||||
int sys_kmem_grant(struct syscall_args *regs)
|
||||
int sys_kmem_control(struct syscall_args *regs)
|
||||
{
|
||||
unsigned long pfn = (unsigned long)regs->r0;
|
||||
int npages = (int)regs->r1;
|
||||
int grant = (int)regs->r2;
|
||||
|
||||
/*
|
||||
* Check if given set of pages are outside the pages already
|
||||
* owned by the kernel.
|
||||
*/
|
||||
if (validate_granted_pages(pfn, npages) < 0)
|
||||
return -EINVAL;
|
||||
/* Pager is granting us pages */
|
||||
if (grant) {
|
||||
/*
|
||||
* Check if given set of pages are outside the pages already
|
||||
* owned by the kernel.
|
||||
*/
|
||||
if (validate_granted_pages(pfn, npages) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Add the granted pages to the allocator */
|
||||
if (pgalloc_add_new_grant(pfn, npages))
|
||||
/* Add the granted pages to the allocator */
|
||||
if (pgalloc_add_new_grant(pfn, npages))
|
||||
BUG();
|
||||
} else /* Reclaim not implemented yet */
|
||||
BUG();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME:
|
||||
* The pager reclaims memory from the kernel whenever it thinks this is just.
|
||||
*/
|
||||
int sys_kmem_reclaim(struct syscall_args *regs)
|
||||
{
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ BEGIN_PROC(arm_system_calls)
|
||||
swi 0x14 @ memory_control /* 0x20 */
|
||||
swi 0x14 @ getid /* 0x24 */
|
||||
swi 0x14 @ kread /* 0x28 */
|
||||
swi 0x14 @ kmem_grant /* 0x2C */
|
||||
swi 0x14 @ kmem_reclaim /* 0x30 */
|
||||
swi 0x14 @ kmem_control /* 0x2C */
|
||||
swi 0x14 @ time /* 0x30 */
|
||||
END_PROC(arm_system_calls)
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
#include <l4/generic/irq.h>
|
||||
#include <l4/generic/scheduler.h>
|
||||
#include <l4/generic/time.h>
|
||||
#include <l4/generic/space.h>
|
||||
#include INC_ARCH(exception.h)
|
||||
#include <l4/api/syscall.h>
|
||||
#include <l4/api/errno.h>
|
||||
|
||||
/* TODO:
|
||||
* 1) Add RTC support.
|
||||
@@ -18,7 +21,7 @@
|
||||
* 3) Jiffies must be initialised to a reasonable value.
|
||||
*/
|
||||
|
||||
volatile u32 jiffies;
|
||||
volatile u32 jiffies = 0;
|
||||
|
||||
static inline void increase_jiffies(void)
|
||||
{
|
||||
@@ -26,36 +29,75 @@ static inline void increase_jiffies(void)
|
||||
}
|
||||
|
||||
|
||||
static int noticks_noresched = 0;
|
||||
/* Represents time since epoch */
|
||||
struct time_info {
|
||||
int reader;
|
||||
u32 thz; /* Ticks in this hertz so far */
|
||||
u32 sec;
|
||||
u32 min;
|
||||
u32 hour;
|
||||
u64 day;
|
||||
};
|
||||
|
||||
static struct time_info systime = { 0 };
|
||||
|
||||
/*
|
||||
* Check preemption anomalies:
|
||||
*
|
||||
* This checks how many times no rescheduling has occured even though ticks
|
||||
* reached zero. This suggests that preemption was enabled for more than a timer
|
||||
* interval. Normally, even if a preemption irq occured during a non-preemptive
|
||||
* state, preemption is *guaranteed* to occur before the next irq, provided that
|
||||
* the non-preemptive period is less than a timer irq interval (and it must be).
|
||||
*
|
||||
* Time:
|
||||
*
|
||||
* |-|---------------------|-|-------------------->
|
||||
* | V | V
|
||||
* | Preemption irq() | Next irq.
|
||||
* V V
|
||||
* preempt_disabled() preempt_enabled() && preemption;
|
||||
* A terribly basic (probably erroneous)
|
||||
* rule-of-thumb time calculation.
|
||||
*/
|
||||
void check_noticks_noresched(void)
|
||||
void update_system_time(void)
|
||||
{
|
||||
if (!current->ticks_left)
|
||||
noticks_noresched++;
|
||||
/* Did we interrupt a reader? Tell it to retry */
|
||||
if (systime.reader)
|
||||
systime.reader = 0;
|
||||
|
||||
if (noticks_noresched >= 2) {
|
||||
printk("Warning, no ticks and yet no rescheduling "
|
||||
"for %d times.\n", noticks_noresched);
|
||||
printk("Spending more than a timer period"
|
||||
" as nonpreemptive!!!\n");
|
||||
/* Increase just like jiffies, but reset every HZ */
|
||||
systime.thz++;
|
||||
|
||||
if (systime.thz == HZ) {
|
||||
systime.thz = 0;
|
||||
systime.sec++;
|
||||
}
|
||||
if (systime.sec == 60) {
|
||||
systime.sec = 0;
|
||||
systime.min++;
|
||||
}
|
||||
if (systime.min == 60) {
|
||||
systime.min = 0;
|
||||
systime.hour++;
|
||||
}
|
||||
if (systime.hour == 24) {
|
||||
systime.hour = 0;
|
||||
systime.day++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read system time */
|
||||
int sys_time(struct syscall_args *args)
|
||||
{
|
||||
struct time_info *ti = (struct time_info *)args->r0;
|
||||
int retries = 20;
|
||||
|
||||
if (check_access((unsigned long)ti, sizeof(*ti), MAP_USR_RW_FLAGS) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
while(retries > 0) {
|
||||
systime.reader = 1;
|
||||
memcpy(ti, &systime, sizeof(*ti));
|
||||
retries--;
|
||||
|
||||
if (systime.reader)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* No need to reset reader since it will be reset
|
||||
* on next timer. If no retries return busy.
|
||||
*/
|
||||
if (!retries)
|
||||
return -EBUSY;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void update_process_times(void)
|
||||
@@ -64,17 +106,10 @@ void update_process_times(void)
|
||||
|
||||
BUG_ON(cur->ticks_left < 0);
|
||||
|
||||
/*
|
||||
* If preemption is disabled we stop reducing ticks when it reaches 0
|
||||
* but set need_resched so that as soon as preempt-enabled, scheduling
|
||||
* occurs.
|
||||
*/
|
||||
if (cur->ticks_left == 0) {
|
||||
need_resched = 1;
|
||||
// check_noticks_noresched();
|
||||
return;
|
||||
}
|
||||
// noticks_noresched = 0;
|
||||
|
||||
if (in_kernel())
|
||||
cur->kernel_time++;
|
||||
@@ -91,6 +126,8 @@ int do_timer_irq(void)
|
||||
{
|
||||
increase_jiffies();
|
||||
update_process_times();
|
||||
update_system_time();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ void kip_init_syscalls(void)
|
||||
kip.thread_switch = ARM_SYSCALL_PAGE + sys_thread_switch_offset;
|
||||
kip.schedule = ARM_SYSCALL_PAGE + sys_schedule_offset;
|
||||
kip.getid = ARM_SYSCALL_PAGE + sys_getid_offset;
|
||||
kip.kmem_grant = ARM_SYSCALL_PAGE + sys_kmem_grant_offset;
|
||||
kip.kmem_reclaim = ARM_SYSCALL_PAGE + sys_kmem_reclaim_offset;
|
||||
kip.kmem_control = ARM_SYSCALL_PAGE + sys_kmem_control_offset;
|
||||
kip.time = ARM_SYSCALL_PAGE + sys_time_offset;
|
||||
}
|
||||
|
||||
/* Jump table for all system calls. */
|
||||
@@ -47,11 +47,11 @@ void syscall_init()
|
||||
syscall_table[sys_getid_offset >> 2] = (syscall_fn_t)sys_getid;
|
||||
syscall_table[sys_unmap_offset >> 2] = (syscall_fn_t)sys_unmap;
|
||||
syscall_table[sys_space_control_offset >> 2] = (syscall_fn_t)sys_space_control;
|
||||
syscall_table[sys_ipc_control_offset >> 2] = (syscall_fn_t)sys_ipc_control;
|
||||
syscall_table[sys_ipc_control_offset >> 2] = (syscall_fn_t)sys_ipc_control;
|
||||
syscall_table[sys_map_offset >> 2] = (syscall_fn_t)sys_map;
|
||||
syscall_table[sys_kread_offset >> 2] = (syscall_fn_t)sys_kread;
|
||||
syscall_table[sys_kmem_grant_offset >> 2] = (syscall_fn_t)sys_kmem_grant;
|
||||
syscall_table[sys_kmem_reclaim_offset >> 2] = (syscall_fn_t)sys_kmem_reclaim;
|
||||
syscall_table[sys_kmem_control_offset >> 2] = (syscall_fn_t)sys_kmem_control;
|
||||
syscall_table[sys_time_offset >> 2] = (syscall_fn_t)sys_time;
|
||||
|
||||
add_mapping(virt_to_phys(&__syscall_page_start),
|
||||
ARM_SYSCALL_PAGE, PAGE_SIZE, MAP_USR_RO_FLAGS);
|
||||
|
||||
Reference in New Issue
Block a user