Clock task split
- preemption handled in the clock timer interrupt handler, not in the clock task - more achitecture independent clock timer handling code - smp ready as each CPU can have its own timer
This commit is contained in:
parent
6eebc03f88
commit
f2a1f21a39
8 changed files with 195 additions and 172 deletions
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "../../kernel.h"
|
||||
|
||||
#include "../../clock.h"
|
||||
|
||||
#define CLOCK_ACK_BIT 0x80 /* PS/2 clock interrupt acknowledge bit */
|
||||
|
||||
/* Clock parameters. */
|
||||
|
@ -14,28 +16,30 @@
|
|||
#define SQUARE_WAVE 0x36 /* ccaammmb, a = access, m = mode, b = BCD */
|
||||
/* 11x11, 11 = LSB then MSB, x11 = sq wave */
|
||||
#define TIMER_FREQ 1193182 /* clock frequency for timer in PC and AT */
|
||||
#define TIMER_COUNT (TIMER_FREQ/system_hz) /* initial value for counter*/
|
||||
#define TIMER_COUNT(freq) (TIMER_FREQ/(freq)) /* initial value for counter*/
|
||||
|
||||
PRIVATE irq_hook_t pic_timer_hook; /* interrupt handler hook */
|
||||
|
||||
/*===========================================================================*
|
||||
* arch_init_clock *
|
||||
* init_8235A_timer *
|
||||
*===========================================================================*/
|
||||
PUBLIC int arch_init_clock(void)
|
||||
PUBLIC int init_8253A_timer(unsigned freq)
|
||||
{
|
||||
/* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz,
|
||||
* and register the CLOCK task's interrupt handler to be run
|
||||
* on every clock tick.
|
||||
*/
|
||||
outb(TIMER_MODE, SQUARE_WAVE); /* run continuously */
|
||||
outb(TIMER0, (TIMER_COUNT & 0xff)); /* timer low byte */
|
||||
outb(TIMER0, TIMER_COUNT >> 8); /* timer high byte */
|
||||
outb(TIMER0, (TIMER_COUNT(freq) & 0xff)); /* timer low byte */
|
||||
outb(TIMER0, TIMER_COUNT(freq) >> 8); /* timer high byte */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* clock_stop *
|
||||
* stop_8235A_timer *
|
||||
*===========================================================================*/
|
||||
PUBLIC void clock_stop(void)
|
||||
PUBLIC void stop_8253A_timer(void)
|
||||
{
|
||||
/* Reset the clock to the BIOS rate. (For rebooting.) */
|
||||
outb(TIMER_MODE, 0x36);
|
||||
|
@ -44,9 +48,9 @@ PUBLIC void clock_stop(void)
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* read_clock *
|
||||
* read_8235A_timer *
|
||||
*===========================================================================*/
|
||||
PUBLIC clock_t read_clock(void)
|
||||
PUBLIC clock_t read_8253A_timer(void)
|
||||
{
|
||||
/* Read the counter of channel 0 of the 8253A timer. This counter
|
||||
* counts down at a rate of TIMER_FREQ and restarts at
|
||||
|
@ -63,3 +67,26 @@ PUBLIC clock_t read_clock(void)
|
|||
return count;
|
||||
}
|
||||
|
||||
PUBLIC int arch_init_local_timer(unsigned freq)
|
||||
{
|
||||
init_8253A_timer(freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PUBLIC void arch_stop_local_timer(void)
|
||||
{
|
||||
stop_8253A_timer();
|
||||
}
|
||||
|
||||
PUBLIC int arch_register_local_timer_handler(irq_handler_t handler)
|
||||
{
|
||||
/* Using PIC, Initialize the CLOCK's interrupt hook. */
|
||||
pic_timer_hook.proc_nr_e = NONE;
|
||||
|
||||
put_irq_handler(&pic_timer_hook, CLOCK_IRQ, handler);
|
||||
put_irq_handler(&pic_timer_hook, CLOCK_IRQ,
|
||||
(irq_handler_t)bsp_timer_int_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
8
kernel/arch/i386/clock.h
Normal file
8
kernel/arch/i386/clock.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef __CLOCK_X86_H__
|
||||
#define __CLOCK_X86_H__
|
||||
|
||||
_PROTOTYPE(int init_8253A_timer, (unsigned freq));
|
||||
_PROTOTYPE(void stop_8253A_timer, (void));
|
||||
_PROTOTYPE(clock_t read_8253A_timer, (void));
|
||||
|
||||
#endif /* __CLOCK_X86_H__ */
|
275
kernel/clock.c
275
kernel/clock.c
|
@ -12,8 +12,8 @@
|
|||
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
|
||||
* Sep 24, 2004 redesigned alarm timers (Jorrit N. Herder)
|
||||
*
|
||||
* The function do_clocktick() is triggered by the clock's interrupt
|
||||
* handler when a watchdog timer has expired or a process must be scheduled.
|
||||
* Clock task is notified by the clock's interrupt handler when a timer
|
||||
* has expired.
|
||||
*
|
||||
* In addition to the main clock_task() entry point, which starts the main
|
||||
* loop, there are several other minor entry points:
|
||||
|
@ -24,7 +24,6 @@
|
|||
* read_clock: read the counter of channel 0 of the 8253A timer
|
||||
*
|
||||
* (+) The CLOCK task keeps tracks of watchdog timers for the entire kernel.
|
||||
* The watchdog functions of expired timers are executed in do_clocktick().
|
||||
* It is crucial that watchdog functions not block, or the CLOCK task may
|
||||
* be blocked. Do not send() a message when the receiver is not expecting it.
|
||||
* Instead, notify(), which always returns, should be used.
|
||||
|
@ -37,11 +36,11 @@
|
|||
#include <minix/endpoint.h>
|
||||
#include <minix/portio.h>
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
/* Function prototype for PRIVATE functions.
|
||||
*/
|
||||
FORWARD _PROTOTYPE( void init_clock, (void) );
|
||||
FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) );
|
||||
FORWARD _PROTOTYPE( void do_clocktick, (message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void load_update, (void));
|
||||
|
||||
/* The CLOCK's timers queue. The functions in <timers.h> operate on this.
|
||||
|
@ -57,7 +56,6 @@ PRIVATE clock_t next_timeout; /* realtime that next timer expires */
|
|||
/* The time is incremented by the interrupt handler on each clock tick.
|
||||
*/
|
||||
PRIVATE clock_t realtime = 0; /* real time clock */
|
||||
PRIVATE irq_hook_t clock_hook; /* interrupt handler hook */
|
||||
|
||||
/*===========================================================================*
|
||||
* clock_task *
|
||||
|
@ -83,7 +81,9 @@ PUBLIC void clock_task()
|
|||
if (is_notify(m.m_type)) {
|
||||
switch (_ENDPOINT_P(m.m_source)) {
|
||||
case HARDWARE:
|
||||
do_clocktick(&m); /* handle clock tick */
|
||||
tmrs_exptimers(&clock_timers, realtime, NULL);
|
||||
next_timeout = (clock_timers == NULL) ?
|
||||
TMR_NEVER : clock_timers->tmr_exp_time;
|
||||
break;
|
||||
default: /* illegal request type */
|
||||
kprintf("CLOCK: illegal notify %d from %d.\n",
|
||||
|
@ -98,169 +98,45 @@ PUBLIC void clock_task()
|
|||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_clocktick *
|
||||
*===========================================================================*/
|
||||
PRIVATE void do_clocktick(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
register struct proc *bill_copy = bill_ptr;
|
||||
|
||||
/* Despite its name, this routine is not called on every clock tick. It
|
||||
* is called on those clock ticks when a lot of work needs to be done.
|
||||
*/
|
||||
|
||||
/* A process used up a full quantum. The interrupt handler stored this
|
||||
* process in 'prev_ptr'. First make sure that the process is not on the
|
||||
* scheduling queues. Then announce the process ready again. Since it has
|
||||
* no more time left, it gets a new quantum and is inserted at the right
|
||||
* place in the queues. As a side-effect a new process will be scheduled.
|
||||
*/
|
||||
if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) {
|
||||
if(prev_ptr->p_rts_flags == 0) { /* if it was runnable .. */
|
||||
lock;
|
||||
{
|
||||
dequeue(prev_ptr); /* take it off the queues */
|
||||
enqueue(prev_ptr); /* and reinsert it again */
|
||||
}
|
||||
unlock;
|
||||
} else {
|
||||
kprintf("CLOCK: %d not runnable; flags: %x\n",
|
||||
prev_ptr->p_endpoint, prev_ptr->p_rts_flags);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if a process-virtual timer expired. Check prev_ptr, but also
|
||||
* bill_ptr - one process's user time is another's system time, and the
|
||||
* profile timer decreases for both! Do this before the queue operations
|
||||
* below, which may alter bill_ptr. Note the use a copy of bill_ptr, because
|
||||
* bill_ptr may have been changed above, and this code can't be put higher
|
||||
* up because otherwise cause_sig() may dequeue prev_ptr before we do.
|
||||
*/
|
||||
vtimer_check(prev_ptr);
|
||||
|
||||
if (prev_ptr != bill_copy)
|
||||
vtimer_check(bill_copy);
|
||||
|
||||
/* Check if a clock timer expired and run its watchdog function. */
|
||||
if (next_timeout <= realtime) {
|
||||
tmrs_exptimers(&clock_timers, realtime, NULL);
|
||||
next_timeout = (clock_timers == NULL) ?
|
||||
TMR_NEVER : clock_timers->tmr_exp_time;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* init_clock *
|
||||
*===========================================================================*/
|
||||
PRIVATE void init_clock()
|
||||
{
|
||||
/* First of all init the clock system.
|
||||
*
|
||||
* Here the (a) clock is set to produce a interrupt at
|
||||
* every 1/60 second (ea. 60Hz).
|
||||
*
|
||||
* Running right away.
|
||||
*/
|
||||
arch_init_clock(); /* architecture-dependent initialization. */
|
||||
|
||||
/* Initialize the CLOCK's interrupt hook. */
|
||||
clock_hook.proc_nr_e = CLOCK;
|
||||
|
||||
put_irq_handler(&clock_hook, CLOCK_IRQ, clock_handler);
|
||||
enable_irq(&clock_hook); /* ready for clock interrupts */
|
||||
|
||||
/* Set a watchdog timer to periodically balance the scheduling queues. */
|
||||
balance_queues(NULL); /* side-effect sets new timer */
|
||||
/* Set a watchdog timer to periodically balance the scheduling queues.
|
||||
Side-effect sets new timer */
|
||||
|
||||
balance_queues(NULL);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* clock_handler *
|
||||
*===========================================================================*/
|
||||
PRIVATE int clock_handler(hook)
|
||||
irq_hook_t *hook;
|
||||
{
|
||||
/* This executes on each clock tick (i.e., every time the timer chip generates
|
||||
* an interrupt). It does a little bit of work so the clock task does not have
|
||||
* to be called on every tick. The clock task is called when:
|
||||
*
|
||||
* (1) the scheduling quantum of the running process has expired, or
|
||||
* (2) a timer has expired and the watchdog function should be run.
|
||||
*
|
||||
* Many global global and static variables are accessed here. The safety of
|
||||
* this must be justified. All scheduling and message passing code acquires a
|
||||
* lock by temporarily disabling interrupts, so no conflicts with calls from
|
||||
* the task level can occur. Furthermore, interrupts are not reentrant, the
|
||||
* interrupt handler cannot be bothered by other interrupts.
|
||||
*
|
||||
* Variables that are updated in the clock's interrupt handler:
|
||||
* lost_ticks:
|
||||
* Clock ticks counted outside the clock task. This for example
|
||||
* is used when the boot monitor processes a real mode interrupt.
|
||||
* realtime:
|
||||
* The current uptime is incremented with all outstanding ticks.
|
||||
* proc_ptr, bill_ptr:
|
||||
* These are used for accounting and virtual timers. It does not
|
||||
* matter if proc.c is changing them, provided they are always
|
||||
* valid pointers, since at worst the previous process would be
|
||||
* billed.
|
||||
/*
|
||||
* The boot processor timer interrupt handler. In addition to non-boot cpus it
|
||||
* keeps real time and notifies the clock task if need be
|
||||
*/
|
||||
register unsigned ticks;
|
||||
register int expired;
|
||||
PUBLIC int bsp_timer_int_handler(void)
|
||||
{
|
||||
unsigned ticks;
|
||||
|
||||
if(minix_panicing) return;
|
||||
if(minix_panicing)
|
||||
return 0;
|
||||
|
||||
/* Get number of ticks and update realtime. */
|
||||
ticks = lost_ticks + 1;
|
||||
lost_ticks = 0;
|
||||
realtime += ticks;
|
||||
/* Get number of ticks and update realtime. */
|
||||
ticks = lost_ticks + 1;
|
||||
lost_ticks = 0;
|
||||
realtime += ticks;
|
||||
|
||||
/* Update user and system accounting times. Charge the current process for
|
||||
* user time. If the current process is not billable, that is, if a non-user
|
||||
* process is running, charge the billable process for system time as well.
|
||||
* Thus the unbillable process' user time is the billable user's system time.
|
||||
*/
|
||||
|
||||
proc_ptr->p_user_time += ticks;
|
||||
if (priv(proc_ptr)->s_flags & PREEMPTIBLE) {
|
||||
proc_ptr->p_ticks_left -= ticks;
|
||||
}
|
||||
if (! (priv(proc_ptr)->s_flags & BILLABLE)) {
|
||||
bill_ptr->p_sys_time += ticks;
|
||||
bill_ptr->p_ticks_left -= ticks;
|
||||
}
|
||||
ap_timer_int_handler();
|
||||
|
||||
/* Decrement virtual timers, if applicable. We decrement both the virtual
|
||||
* and the profile timer of the current process, and if the current process
|
||||
* is not billable, the timer of the billed process as well.
|
||||
* If any of the timers expire, do_clocktick() will send out signals.
|
||||
*/
|
||||
expired = 0;
|
||||
if ((proc_ptr->p_misc_flags & MF_VIRT_TIMER) &&
|
||||
(proc_ptr->p_virt_left -= ticks) <= 0) expired = 1;
|
||||
if ((proc_ptr->p_misc_flags & MF_PROF_TIMER) &&
|
||||
(proc_ptr->p_prof_left -= ticks) <= 0) expired = 1;
|
||||
if (! (priv(proc_ptr)->s_flags & BILLABLE) &&
|
||||
(bill_ptr->p_misc_flags & MF_PROF_TIMER) &&
|
||||
(bill_ptr->p_prof_left -= ticks) <= 0) expired = 1;
|
||||
/* if a timer expired, notify the clock task */
|
||||
if ((next_timeout <= realtime)) {
|
||||
mini_notify(proc_addr(HARDWARE), CLOCK); /* send notification */
|
||||
}
|
||||
|
||||
/* Update load average. */
|
||||
load_update();
|
||||
|
||||
/* Check if do_clocktick() must be called. Done for alarms and scheduling.
|
||||
* Some processes, such as the kernel tasks, cannot be preempted.
|
||||
*/
|
||||
if ((next_timeout <= realtime) || (proc_ptr->p_ticks_left <= 0) || expired) {
|
||||
prev_ptr = proc_ptr; /* store running process */
|
||||
mini_notify(proc_addr(HARDWARE), CLOCK); /* send notification */
|
||||
}
|
||||
if (do_serial_debug)
|
||||
do_ser_debug();
|
||||
|
||||
if (do_serial_debug)
|
||||
do_ser_debug();
|
||||
|
||||
return(1); /* reenable interrupts */
|
||||
return(1); /* reenable interrupts */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
@ -334,3 +210,92 @@ PRIVATE void load_update(void)
|
|||
kloadinfo.last_clock = realtime;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer interupt handler. This is the only think executed on non boot
|
||||
* processors. It is called by bsp_timer_int_handler() on the boot processor
|
||||
*/
|
||||
PUBLIC int ap_timer_int_handler(void)
|
||||
{
|
||||
|
||||
/* Update user and system accounting times. Charge the current process
|
||||
* for user time. If the current process is not billable, that is, if a
|
||||
* non-user process is running, charge the billable process for system
|
||||
* time as well. Thus the unbillable process' user time is the billable
|
||||
* user's system time.
|
||||
*/
|
||||
|
||||
unsigned ticks = 1;
|
||||
int expired = 0;
|
||||
struct proc * p, * billp;
|
||||
|
||||
/* Update user and system accounting times. Charge the current process
|
||||
* for user time. If the current process is not billable, that is, if a
|
||||
* non-user process is running, charge the billable process for system
|
||||
* time as well. Thus the unbillable process' user time is the billable
|
||||
* user's system time.
|
||||
*/
|
||||
|
||||
/* FIXME prepared for get_cpu_local_var() */
|
||||
p = proc_ptr;
|
||||
billp = bill_ptr;
|
||||
|
||||
p->p_user_time += ticks;
|
||||
if (priv(p)->s_flags & PREEMPTIBLE) {
|
||||
p->p_ticks_left -= ticks;
|
||||
}
|
||||
if (! (priv(p)->s_flags & BILLABLE)) {
|
||||
billp->p_sys_time += ticks;
|
||||
billp->p_ticks_left -= ticks;
|
||||
}
|
||||
|
||||
/* Decrement virtual timers, if applicable. We decrement both the
|
||||
* virtual and the profile timer of the current process, and if the
|
||||
* current process is not billable, the timer of the billed process as
|
||||
* well. If any of the timers expire, do_clocktick() will send out
|
||||
* signals.
|
||||
*/
|
||||
if ((p->p_misc_flags & MF_VIRT_TIMER) &&
|
||||
(p->p_virt_left -= ticks) <= 0) expired = 1;
|
||||
if ((p->p_misc_flags & MF_PROF_TIMER) &&
|
||||
(p->p_prof_left -= ticks) <= 0) expired = 1;
|
||||
if (! (priv(p)->s_flags & BILLABLE) &&
|
||||
(billp->p_misc_flags & MF_PROF_TIMER) &&
|
||||
(billp->p_prof_left -= ticks) <= 0) expired = 1;
|
||||
|
||||
/*
|
||||
* Check if a process-virtual timer expired. Check current process, but
|
||||
* also bill_ptr - one process's user time is another's system time, and
|
||||
* the profile timer decreases for both!
|
||||
*/
|
||||
vtimer_check(p);
|
||||
|
||||
if (p != billp)
|
||||
vtimer_check(billp);
|
||||
|
||||
/* Update load average. */
|
||||
load_update();
|
||||
|
||||
/* check if the process is still runnable after checking the vtimer */
|
||||
if (p->p_rts_flags == 0 && p->p_ticks_left <= 0 &&
|
||||
priv(p)->s_flags & PREEMPTIBLE) {
|
||||
proc_ptr = NULL; /* no process is scheduled for dequeue and
|
||||
enqueue */
|
||||
dequeue(p); /* take it off the queues */
|
||||
enqueue(p); /* and reinsert it again */
|
||||
proc_ptr = p; /* restore some consitent state */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
PUBLIC int boot_cpu_init_timer(unsigned freq)
|
||||
{
|
||||
if (arch_init_local_timer(freq))
|
||||
return -1;
|
||||
|
||||
if (arch_register_local_timer_handler(
|
||||
(irq_handler_t) bsp_timer_int_handler))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
16
kernel/clock.h
Normal file
16
kernel/clock.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef __CLOCK_H__
|
||||
#define __CLOCK_H__
|
||||
|
||||
#include "kernel.h"
|
||||
#include "arch/i386/clock.h"
|
||||
|
||||
_PROTOTYPE(int boot_cpu_init_timer, (unsigned freq));
|
||||
|
||||
_PROTOTYPE(int bsp_timer_int_handler, (void));
|
||||
_PROTOTYPE(int ap_timer_int_handler, (void));
|
||||
|
||||
_PROTOTYPE(int arch_init_local_timer, (unsigned freq));
|
||||
_PROTOTYPE(void arch_stop_local_timer, (void));
|
||||
_PROTOTYPE(int arch_register_local_timer_handler, (irq_handler_t handler));
|
||||
|
||||
#endif /* __CLOCK_H__ */
|
|
@ -32,7 +32,6 @@ EXTERN struct loadinfo kloadinfo; /* status of load average */
|
|||
/* Process scheduling information and the kernel reentry count. */
|
||||
EXTERN struct proc *proc_ptr; /* pointer to currently running process */
|
||||
EXTERN struct proc *next_ptr; /* next process to run after restart() */
|
||||
EXTERN struct proc *prev_ptr;
|
||||
EXTERN struct proc *bill_ptr; /* process to bill for clock ticks */
|
||||
EXTERN struct proc *vmrestart; /* first process on vmrestart queue */
|
||||
EXTERN struct proc *vmrequest; /* first process on vmrequest queue */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <minix/endpoint.h>
|
||||
#include "proc.h"
|
||||
#include "debug.h"
|
||||
#include "clock.h"
|
||||
|
||||
/* Prototype declarations for PRIVATE functions. */
|
||||
FORWARD _PROTOTYPE( void announce, (void));
|
||||
|
@ -195,6 +196,16 @@ PUBLIC void main()
|
|||
*/
|
||||
bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
|
||||
announce(); /* print MINIX startup banner */
|
||||
|
||||
/*
|
||||
* enable timer interrupts and clock task on the boot CPU
|
||||
*/
|
||||
if (boot_cpu_init_timer(system_hz)) {
|
||||
minix_panic("FATAL : failed to initialize timer interrupts, "
|
||||
"cannot continue without any clock source!",
|
||||
NO_NUM);
|
||||
}
|
||||
|
||||
/* Warnings for sanity checks that take time. These warnings are printed
|
||||
* so it's a clear warning no full release should be done with them
|
||||
* enabled.
|
||||
|
@ -208,6 +219,7 @@ PUBLIC void main()
|
|||
#if DEBUG_PROC_CHECK
|
||||
FIXME("PROC check enabled");
|
||||
#endif
|
||||
|
||||
restart();
|
||||
}
|
||||
|
||||
|
@ -257,7 +269,7 @@ timer_t *tp;
|
|||
* monitor), RBT_MONITOR (execute given code), RBT_RESET (hard reset).
|
||||
*/
|
||||
intr_init(INTS_ORIG);
|
||||
clock_stop();
|
||||
arch_stop_local_timer();
|
||||
arch_shutdown(tp ? tmr_arg(tp)->ta_int : RBT_PANIC);
|
||||
}
|
||||
|
||||
|
|
|
@ -1190,9 +1190,8 @@ register struct proc *rp; /* this process is now runnable */
|
|||
* process yet or current process isn't ready any more, or
|
||||
* it's PREEMPTIBLE.
|
||||
*/
|
||||
vmassert(proc_ptr);
|
||||
if((proc_ptr->p_priority > rp->p_priority) &&
|
||||
(priv(proc_ptr)->s_flags & PREEMPTIBLE))
|
||||
if(!proc_ptr || (proc_ptr->p_priority > rp->p_priority) ||
|
||||
(priv(proc_ptr)->s_flags & PREEMPTIBLE))
|
||||
pick_proc();
|
||||
|
||||
#if DEBUG_SCHED_CHECK
|
||||
|
|
|
@ -132,9 +132,6 @@ _PROTOTYPE( int vm_phys_memset, (phys_bytes source, u8_t pattern,
|
|||
phys_bytes count) );
|
||||
_PROTOTYPE( vir_bytes alloc_remote_segment, (u32_t *, segframe_t *,
|
||||
int, phys_bytes, vir_bytes, int));
|
||||
_PROTOTYPE( int arch_init_clock, (void) );
|
||||
_PROTOTYPE( clock_t read_clock, (void) );
|
||||
_PROTOTYPE( void clock_stop, (void) );
|
||||
_PROTOTYPE( int intr_init, (int) );
|
||||
_PROTOTYPE( int intr_disabled, (void) );
|
||||
_PROTOTYPE( void idle_task, (void) );
|
||||
|
|
Loading…
Reference in a new issue