* Fixed bug relating to nested locking in interrupt handlers. The nested lock
caused interrupts to be reenabled (due to unlock), which caused a race. The problems were especially visible on slower machines. * Relocated free memory parsing to process manager. This saved quite some code at the kernel level. Text size was reduced by about 650 bytes. * Removed locks for updating the realtime in the clock's main loop and the get_uptime function. Interrupts are no longer reentrant, so realtime is immediately updated.
This commit is contained in:
parent
90b80ad31e
commit
e0a98a4d65
13 changed files with 76 additions and 206 deletions
|
@ -1,3 +1,4 @@
|
|||
#define NEW_TIME_COUNT 1
|
||||
/* The file contais the clock task, which handles all time related functions.
|
||||
* Important events that are handled by the CLOCK include alarm timers and
|
||||
* (re)scheduling user processes.
|
||||
|
@ -84,7 +85,9 @@ PRIVATE clock_t realtime; /* real time clock */
|
|||
|
||||
/* Variables for and changed by the CLOCK's interrupt handler. */
|
||||
PRIVATE irq_hook_t clock_hook;
|
||||
#if ! NEW_TIME_COUNT
|
||||
PRIVATE clock_t pending_ticks; /* ticks seen by low level only */
|
||||
#endif
|
||||
PRIVATE int sched_ticks = SCHED_RATE; /* counter: when 0, call scheduler */
|
||||
PRIVATE struct proc *prev_ptr; /* last user process run by clock */
|
||||
|
||||
|
@ -107,11 +110,13 @@ PUBLIC void clock_task()
|
|||
/* Go get a message. */
|
||||
receive(ANY, &m);
|
||||
|
||||
#if ! NEW_TIME_COUNT
|
||||
/* Transfer ticks seen by the low level handler. */
|
||||
lock(8, "realtime");
|
||||
realtime += pending_ticks;
|
||||
pending_ticks = 0;
|
||||
unlock(8);
|
||||
#endif
|
||||
|
||||
/* Handle the request. */
|
||||
switch (m.m_type) {
|
||||
|
@ -202,10 +207,12 @@ irq_hook_t *hook;
|
|||
* The variables which are changed require more care:
|
||||
* rp->p_user_time, rp->p_sys_time:
|
||||
* These are protected by explicit locks in system.c.
|
||||
#if ! NEW_TIME_COUNT
|
||||
* pending_ticks:
|
||||
* This is protected by explicit locks in clock.c. Don't
|
||||
* update realtime directly, since there are too many
|
||||
* references to it to guard conveniently.
|
||||
#endif
|
||||
* lost_ticks:
|
||||
* Clock ticks counted outside the clock task.
|
||||
* sched_ticks, prev_ptr:
|
||||
|
@ -222,7 +229,9 @@ irq_hook_t *hook;
|
|||
register struct proc *rp;
|
||||
register unsigned ticks;
|
||||
message m;
|
||||
#if ! NEW_TIME_COUNT
|
||||
clock_t now;
|
||||
#endif
|
||||
|
||||
/* Acknowledge the PS/2 clock interrupt. */
|
||||
if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);
|
||||
|
@ -232,10 +241,16 @@ irq_hook_t *hook;
|
|||
* 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.
|
||||
*/
|
||||
#if NEW_TIME_COUNT
|
||||
ticks = lost_ticks + 1;
|
||||
lost_ticks = 0;
|
||||
realtime += ticks;
|
||||
#else
|
||||
ticks = lost_ticks + 1;
|
||||
lost_ticks = 0;
|
||||
pending_ticks += ticks;
|
||||
now = realtime + pending_ticks;
|
||||
#endif
|
||||
|
||||
/* Update administration. */
|
||||
proc_ptr->p_user_time += ticks;
|
||||
|
@ -244,11 +259,15 @@ irq_hook_t *hook;
|
|||
/* Check if do_clocktick() must be called. Done for alarms and scheduling.
|
||||
* If bill_ptr == prev_ptr, there are no ready users so don't need sched().
|
||||
*/
|
||||
#if NEW_TIME_COUNT
|
||||
if (next_timeout <= realtime || (sched_ticks == 1 && bill_ptr == prev_ptr
|
||||
#else
|
||||
if (next_timeout <= now || (sched_ticks == 1 && bill_ptr == prev_ptr
|
||||
#endif
|
||||
&& rdy_head[PPRI_USER] != NIL_PROC))
|
||||
{
|
||||
m.NOTIFY_TYPE = HARD_INT;
|
||||
lock_notify(CLOCK, &m);
|
||||
int_notify(CLOCK, &m);
|
||||
}
|
||||
else if (--sched_ticks <= 0) {
|
||||
sched_ticks = SCHED_RATE; /* reset the quantum */
|
||||
|
@ -266,12 +285,16 @@ PUBLIC clock_t get_uptime()
|
|||
/* Get and return the current clock uptime in ticks.
|
||||
* Be careful about pending_ticks.
|
||||
*/
|
||||
#if NEW_TIME_COUNT
|
||||
return(realtime);
|
||||
#else
|
||||
clock_t uptime;
|
||||
|
||||
lock(9, "get_uptime");
|
||||
uptime = realtime + pending_ticks;
|
||||
unlock(9);
|
||||
return(uptime);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ unsigned vec_nr;
|
|||
ep = &ex_data[vec_nr];
|
||||
|
||||
if (vec_nr == 2) { /* spurious NMI on some machines */
|
||||
kprintf("got spurious NMI\n",NO_ARG);
|
||||
kprintf("got spurious NMI\n",NO_NUM);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -68,19 +68,7 @@ unsigned vec_nr;
|
|||
kprintf("pc = %d:", (unsigned) saved_proc->p_reg.cs);
|
||||
kprintf("0x%x\n", (unsigned) saved_proc->p_reg.pc);
|
||||
|
||||
/* If the exception originates in the kernel, shut down MINIX. Otherwise,
|
||||
* kill the process that caused it. If MINIX is shut down and the stop
|
||||
* sequence is skipped, the kprintf() output cannot be flushed by the TTY
|
||||
* driver. This leaves the user with a hanging system without proper
|
||||
* notification ...
|
||||
*/
|
||||
if (istaskp(saved_proc)) { /* serious problem */
|
||||
kernel_exception = TRUE; /* directly shutdown */
|
||||
panic("exception in a kernel task", NO_NUM);
|
||||
} else {
|
||||
clear_proc(saved_proc->p_nr);
|
||||
kprintf("%s was killed by MINIX due to an exception",
|
||||
karg(saved_proc->p_name));
|
||||
}
|
||||
kernel_exception = TRUE; /* directly shutdown */
|
||||
panic("exception in a kernel task", NO_NUM);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ EXTERN struct kinfo kinfo; /* kernel information for users */
|
|||
EXTERN struct machine machine; /* machine information for users */
|
||||
EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
|
||||
EXTERN struct randomness krandom; /* gather kernel random information */
|
||||
EXTERN struct memory mem[NR_MEMS]; /* base and size of chunks of memory */
|
||||
|
||||
/* Process scheduling information and the kernel reentry count. */
|
||||
EXTERN struct proc *proc_ptr; /* pointer to currently running process */
|
||||
|
|
|
@ -45,7 +45,7 @@ int mine;
|
|||
/* Initialize the 8259s, finishing with all interrupts disabled. This is
|
||||
* only done in protected mode, in real mode we don't touch the 8259s, but
|
||||
* use the BIOS locations instead. The flag "mine" is set if the 8259s are
|
||||
* to be programmed for Minix, or to be reset to what the BIOS expects.
|
||||
* to be programmed for MINIX, or to be reset to what the BIOS expects.
|
||||
*/
|
||||
int i;
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
* kstrcmp: lexicographical comparison of two strings
|
||||
* kstrlen: get number of non-null characters in string
|
||||
* kstrncpy: copy string and pad or copy up to n chars
|
||||
* kstrtoulb: convert string to unsigned long value
|
||||
*
|
||||
* This file contains the routines that take care of kernel messages, i.e.,
|
||||
* diagnostic output within the kernel. Kernel messages are not directly
|
||||
|
@ -152,7 +151,7 @@ PRIVATE void kputc(c)
|
|||
int c; /* character to append */
|
||||
{
|
||||
/* Accumulate a single character for a kernel message. Send a notification
|
||||
* the to TTY driver if the buffer if a END_OF_KMESS is encountered.
|
||||
* the to TTY driver if an END_OF_KMESS is encountered.
|
||||
*/
|
||||
message m;
|
||||
if (c != END_OF_KMESS) {
|
||||
|
@ -225,45 +224,3 @@ PUBLIC char *kstrncpy(char *ret, register const char *s2, register size_t n)
|
|||
}
|
||||
|
||||
|
||||
/*=========================================================================*
|
||||
* kstrtoul *
|
||||
*=========================================================================*/
|
||||
PUBLIC unsigned long kstrtoul(strptr, endptr, base)
|
||||
const char *strptr; /* pointer to string to be parsed */
|
||||
char ** const endptr; /* store pointer to end here */
|
||||
int base;
|
||||
{
|
||||
/* A simplified version of strtoul() for the kernel to prevent including the
|
||||
* one in the ASNI library. No whitespaces are skipped, the numeric value is
|
||||
* expected at the start of 'string'.
|
||||
*/
|
||||
register unsigned long val = 0;
|
||||
register int c;
|
||||
register unsigned int v;
|
||||
int overflow = 0;
|
||||
|
||||
/* Get rid of 0x or 0X for hexidecimal values. */
|
||||
if (base==16 && *strptr=='0' && (*++strptr=='x' || *strptr=='X'))
|
||||
strptr++;
|
||||
|
||||
/* Now parse the actual unsigned long number. */
|
||||
for (;;) {
|
||||
c = *strptr;
|
||||
if ('0' <= c && c <= '9') v = c - '0';
|
||||
else if ('a' <= c && c <= 'z') v = c - 'a' + 0xa;
|
||||
else if ('A' <= c && c <= 'Z') v = c - 'A' + 0xA;
|
||||
else break; /* end of number */
|
||||
if (v >= base) break; /* end of number */
|
||||
if (val > (ULONG_MAX - v) / base) overflow = 1;
|
||||
val = (val*base) + v;
|
||||
strptr++;
|
||||
}
|
||||
|
||||
/* Tell caller where parsing ended unless a NULL pointer was passed. */
|
||||
if (endptr) *endptr = (char *) strptr;
|
||||
|
||||
/* Done, return parsed value or maximum value on overflow. */
|
||||
return (overflow) ? ULONG_MAX : val;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -114,19 +114,6 @@ PUBLIC void main()
|
|||
rp->p_memmap[S].mem_phys = text_base + text_clicks + data_clicks;
|
||||
rp->p_memmap[S].mem_vir = data_clicks; /* empty - stack is in data */
|
||||
|
||||
/* Remove server memory from the free memory list. The boot monitor
|
||||
* promises to put processes at the start of memory chunks. The
|
||||
* tasks all use same base address, so only the first task changes
|
||||
* the memory lists. The servers and init have their own memory
|
||||
* spaces and their memory will be removed from the list.
|
||||
*/
|
||||
for (memp = mem; memp < &mem[NR_MEMS]; memp++) {
|
||||
if (memp->base == text_base) {
|
||||
memp->base += text_clicks + data_clicks;
|
||||
memp->size -= text_clicks + data_clicks;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set initial register values. The processor status word for tasks
|
||||
* is different from that of other processes because tasks can
|
||||
* access I/O; this is not allowed to less-privileged processes
|
||||
|
@ -144,7 +131,6 @@ PUBLIC void main()
|
|||
}
|
||||
|
||||
/* Set ready. The HARDWARE task is never ready. */
|
||||
|
||||
#if ENABLE_K_DEBUGGING
|
||||
rp->p_ready = 0;
|
||||
#endif
|
||||
|
@ -163,30 +149,16 @@ PUBLIC void main()
|
|||
hdrindex ++;
|
||||
phys_copy(aout + hdrindex * A_MINHDR,vir2phys(&e_hdr),(phys_bytes) A_MINHDR);
|
||||
if (e_hdr.a_flags & A_IMG) {
|
||||
|
||||
kinfo.bootdev_base = e_hdr.a_syms;
|
||||
kinfo.bootdev_size = e_hdr.a_data;
|
||||
|
||||
/* Remove from free list, to prevent being overwritten. */
|
||||
bootdev_base = e_hdr.a_syms >> CLICK_SHIFT;
|
||||
bootdev_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
|
||||
for (memp = mem; memp < &mem[NR_MEMS]; memp++) {
|
||||
if (memp->base == bootdev_base) {
|
||||
memp->base += bootdev_clicks;
|
||||
memp->size -= bootdev_clicks;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This actually is not needed, because ready() already set 'proc_ptr.' */
|
||||
lock_pick_proc();
|
||||
bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
|
||||
|
||||
/* MINIX is now ready. Display the startup banner to the user and return
|
||||
* to the assembly code to start running the current process.
|
||||
/* MINIX is now ready. All boot image processes are on the ready queue.
|
||||
* Return to the assembly code to start running the current process.
|
||||
*/
|
||||
announce();
|
||||
bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
|
||||
announce(); /* print MINIX startup banner */
|
||||
restart();
|
||||
}
|
||||
|
||||
|
@ -199,7 +171,7 @@ PRIVATE void announce(void)
|
|||
{
|
||||
/* Display the MINIX startup banner. */
|
||||
kprintf("MINIX %s. Copyright 2001 Prentice-Hall, Inc.\n",
|
||||
karg(kinfo.version));
|
||||
karg(OS_RELEASE "." OS_VERSION));
|
||||
|
||||
#if (CHIP == INTEL)
|
||||
/* Real mode, or 16/32-bit protected mode? */
|
||||
|
@ -249,10 +221,10 @@ int how; /* 0 = halt, 1 = reboot, 2 = panic!, ... */
|
|||
shutting_down = TRUE; /* flag for sys_exit() */
|
||||
tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */
|
||||
if (kernel_exception) { /* set in exception() */
|
||||
kprintf("\nAn exception occured; skipping stop sequence.\n", NO_ARG);
|
||||
kprintf("\nAn exception occured; skipping stop sequence.\n", NO_NUM);
|
||||
shutdown(&shutdown_timer); /* TTY isn't scheduled */
|
||||
} else {
|
||||
kprintf("\nNotifying system services about MINIX shutdown.\n", NO_ARG);
|
||||
kprintf("\nNotifying system services about MINIX shutdown.\n", NO_NUM);
|
||||
set_timer(&shutdown_timer, get_uptime(), stop_sequence);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ int n;
|
|||
if (s != NULL) {
|
||||
kprintf("\nKernel panic: %s", karg(s));
|
||||
if (n != NO_NUM) kprintf(" %d", n);
|
||||
kprintf("\n",NO_ARG);
|
||||
kprintf("\n",NO_NUM);
|
||||
}
|
||||
prepare_shutdown(RBT_PANIC);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#define NEW_ELOCKED_CHECK 1
|
||||
#define NEW_SCHED_Q 1
|
||||
#define NEW_SCHED_Q 0
|
||||
#define OLD_SEND 0
|
||||
#define OLD_RECV 0
|
||||
/* This file contains essentially all of the process and message handling.
|
||||
|
@ -11,11 +11,11 @@
|
|||
* As well as several entry points used from the interrupt and task level:
|
||||
*
|
||||
* lock_notify: send a notification to inform a process of a system event
|
||||
* int_notify: same as above, but from an interrupt handler (no locking)
|
||||
* lock_send: send a message to a process
|
||||
* lock_ready: put a process on one of the ready queues so it can be run
|
||||
* lock_unready: remove a process from the ready queues
|
||||
* lock_sched: a process has run too long; schedule another one
|
||||
* lock_pick_proc: pick a process to run (used by system initialization)
|
||||
*
|
||||
* Changes:
|
||||
* , 2005 better protection in sys_call() (Jorrit N. Herder)
|
||||
|
@ -438,13 +438,12 @@ PUBLIC int lock_notify(dst, m_ptr)
|
|||
int dst; /* to whom is message being sent? */
|
||||
message *m_ptr; /* pointer to message buffer */
|
||||
{
|
||||
/* Safe gateway to mini_notify() for tasks and interrupt handlers. This
|
||||
* function checks if it is called from an interrupt handler and ensures
|
||||
* that the correct message source is put on the notification.
|
||||
/* Safe gateway to mini_notify() for tasks. Don't use this function from the
|
||||
* interrupt level, as it will reenable interrupts (because of the unlock()
|
||||
* call). For interrupt handlers, int_notify() is available.
|
||||
*/
|
||||
int result;
|
||||
struct proc *caller_ptr;
|
||||
|
||||
register struct proc *caller_ptr;
|
||||
lock(0, "notify");
|
||||
caller_ptr = (k_reenter >= 0) ? proc_addr(HARDWARE) : proc_ptr;
|
||||
result = mini_notify(caller_ptr, dst, m_ptr);
|
||||
|
@ -452,6 +451,24 @@ message *m_ptr; /* pointer to message buffer */
|
|||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/*==========================================================================*
|
||||
* int_notify *
|
||||
*==========================================================================*/
|
||||
PUBLIC int int_notify(dst, m_ptr)
|
||||
int dst; /* to whom is message being sent? */
|
||||
message *m_ptr; /* pointer to message buffer */
|
||||
{
|
||||
/* Gateway to mini_notify() for interrupt handlers. This function doesn't
|
||||
* use lock() and unlock() because interrupts are already disabled.
|
||||
*/
|
||||
int result;
|
||||
register struct proc *caller_ptr = proc_addr(HARDWARE);
|
||||
result = mini_notify(caller_ptr, dst, m_ptr);
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* pick_proc *
|
||||
*===========================================================================*/
|
||||
|
@ -627,25 +644,14 @@ int queue;
|
|||
xp->p_nextready = NIL_PROC; /* mark new end of queue */
|
||||
|
||||
#else
|
||||
rdy_tail[queue]->p_nextready = rdy_head[queue];
|
||||
rdy_tail[queue] = rdy_head[queue];
|
||||
rdy_head[queue] = rdy_head[queue]->p_nextready;
|
||||
rdy_tail[queue]->p_nextready = NIL_PROC;
|
||||
rdy_tail[queue]->p_nextready = rdy_head[queue]; /* add expired to end */
|
||||
rdy_tail[queue] = rdy_head[queue]; /* set new tail */
|
||||
rdy_head[queue] = rdy_head[queue]->p_nextready; /* set new head */
|
||||
rdy_tail[queue]->p_nextready = NIL_PROC; /* mark new end */
|
||||
#endif
|
||||
pick_proc();
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* lock_pick_proc *
|
||||
*==========================================================================*/
|
||||
PUBLIC void lock_pick_proc()
|
||||
{
|
||||
/* Safe gateway to pick_proc() for tasks. */
|
||||
lock(1, "pick_proc");
|
||||
pick_proc();
|
||||
unlock(1);
|
||||
}
|
||||
|
||||
|
||||
/*==========================================================================*
|
||||
* lock_send *
|
||||
|
|
|
@ -25,9 +25,6 @@ _PROTOTYPE( int kstrncmp,
|
|||
(register const char *s1, register const char *s2, register size_t n));
|
||||
_PROTOTYPE( char *kstrncpy,
|
||||
(char *s1, register const char *s2, register const size_t n));
|
||||
_PROTOTYPE( unsigned long kstrtoul,
|
||||
(const char *string, char ** const end, int base) );
|
||||
#define NO_ARG 0
|
||||
#define karg(arg) (karg_t) (arg)
|
||||
_PROTOTYPE( void kprintf, (const char *fmt, karg_t arg) );
|
||||
|
||||
|
@ -44,8 +41,8 @@ _PROTOTYPE( void free_bit, (bit_t nr, bitchunk_t *map, bit_t nr_bits) );
|
|||
/* proc.c */
|
||||
_PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr) );
|
||||
_PROTOTYPE( int lock_notify, (int dst, message *m_ptr) );
|
||||
_PROTOTYPE( int int_notify, (int dst, message *m_ptr) );
|
||||
_PROTOTYPE( int lock_send, (int dst, message *m_ptr) );
|
||||
_PROTOTYPE( void lock_pick_proc, (void) );
|
||||
_PROTOTYPE( void lock_ready, (struct proc *rp) );
|
||||
_PROTOTYPE( void lock_sched, (int queue) );
|
||||
_PROTOTYPE( void lock_unready, (struct proc *rp) );
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "protect.h"
|
||||
#include "proc.h"
|
||||
|
||||
FORWARD _PROTOTYPE( void mem_init, (_CONST char *params));
|
||||
FORWARD _PROTOTYPE( char *get_value, (_CONST char *params, _CONST char *key));
|
||||
|
||||
/*==========================================================================*
|
||||
|
@ -57,7 +56,8 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
|
|||
/* Record miscellaneous information for user-space servers. */
|
||||
kinfo.nr_procs = NR_PROCS;
|
||||
kinfo.nr_tasks = NR_TASKS;
|
||||
kstrncpy(kinfo.version, OS_RELEASE "." OS_VERSION, 6);
|
||||
kstrncpy(kinfo.release, OS_RELEASE, 4);
|
||||
kstrncpy(kinfo.version, OS_VERSION, 4);
|
||||
kinfo.proc_addr = (vir_bytes) proc;
|
||||
kinfo.kmem_base = vir2phys(0);
|
||||
kinfo.kmem_size = (phys_bytes) &end;
|
||||
|
@ -84,79 +84,12 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
|
|||
if (kstrcmp(value, "ega") == 0) machine.vdu_ega = TRUE;
|
||||
if (kstrcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
|
||||
|
||||
/* Initialize free memory list from size passed by boot monitor. */
|
||||
mem_init(params);
|
||||
|
||||
/* Return to assembler code to switch to protected mode (if 286),
|
||||
* reload selectors and call main().
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* In real mode only 1M can be addressed, and in 16-bit protected we can go
|
||||
* no further than we can count in clicks. (The 286 is further limited by
|
||||
* its 24 bit address bus, but we can assume in that case that no more than
|
||||
* 16M memory is reported by the BIOS.)
|
||||
*/
|
||||
#define MAX_REAL 0x00100000L
|
||||
#define MAX_16BIT (0xFFF0L << CLICK_SHIFT)
|
||||
|
||||
/*=========================================================================*
|
||||
* mem_init *
|
||||
*=========================================================================*/
|
||||
PRIVATE void mem_init(params)
|
||||
_CONST char *params; /* boot monitor parameters */
|
||||
{
|
||||
/* Initialize the free memory list from the 'memory' boot variable. Translate
|
||||
* the byte offsets and sizes in this list to clicks, properly truncated. Also
|
||||
* make sure that we don't exceed the maximum address space of the 286 or the
|
||||
* 8086, i.e. when running in 16-bit protected mode or real mode.
|
||||
*/
|
||||
long base, size, limit;
|
||||
char *s, *end; /* use to parse boot variable */
|
||||
int i;
|
||||
struct memory *memp;
|
||||
#if _WORD_SIZE == 2
|
||||
unsigned long max_address;
|
||||
#endif
|
||||
|
||||
/* The available memory is determined by MINIX' boot loader as a list of
|
||||
* (base:size)-pairs in boothead.s. The 'memory' boot variable is set in
|
||||
* in boot.s. The format is "b0:s0,b1:s1,b2:s2", where b0:s0 is low mem,
|
||||
* b1:s1 is mem between 1M and 16M, b2:s2 is mem above 16M. Pairs b1:s1
|
||||
* and b2:s2 are combined if the memory is adjacent.
|
||||
*/
|
||||
s = get_value(params, "memory"); /* get memory boot variable */
|
||||
for (i = 0; i < NR_MEMS; i++) {
|
||||
memp = &mem[i]; /* next mem chunk is stored here */
|
||||
base = size = 0; /* initialize next base:size pair */
|
||||
if (*s != 0) { /* get fresh data, unless at end */
|
||||
|
||||
/* Read fresh base and expect colon as next char. */
|
||||
base = kstrtoul(s, &end, 0x10); /* get number */
|
||||
if (end != s && *end == ':') s = ++end; /* skip ':' */
|
||||
else *s=0; /* terminate, should not happen */
|
||||
|
||||
/* Read fresh size and expect comma or assume end. */
|
||||
size = kstrtoul(s, &end, 0x10); /* get number */
|
||||
if (end != s && *end == ',') s = ++end; /* skip ',' */
|
||||
else *s=0; /* found end */
|
||||
}
|
||||
limit = base + size; /* limit is used for validity check */
|
||||
#if _WORD_SIZE == 2
|
||||
max_address = kinfo.protected ? MAX_16BIT : MAX_REAL;
|
||||
if (limit > max_address) limit = max_address;
|
||||
#endif
|
||||
base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1);
|
||||
limit &= ~(long)(CLICK_SIZE-1);
|
||||
if (limit <= base) continue;
|
||||
memp->base = base >> CLICK_SHIFT;
|
||||
memp->size = (limit - base) >> CLICK_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*==========================================================================*
|
||||
* get_value *
|
||||
*==========================================================================*/
|
||||
|
|
|
@ -296,7 +296,7 @@ irq_hook_t *hook;
|
|||
/* Build notification message and return. */
|
||||
m.NOTIFY_TYPE = HARD_INT;
|
||||
m.NOTIFY_ARG = hook->irq;
|
||||
lock_notify(hook->proc_nr, &m);
|
||||
int_notify(hook->proc_nr, &m);
|
||||
return(hook->policy & IRQ_REENABLE);
|
||||
}
|
||||
|
||||
|
@ -308,11 +308,11 @@ PUBLIC void cause_sig(proc_nr, sig_nr)
|
|||
int proc_nr; /* process to be signalled */
|
||||
int sig_nr; /* signal to be sent, 1 to _NSIG */
|
||||
{
|
||||
/* A task wants to send a signal to a process. Examples of such tasks are:
|
||||
/* A system process wants to send a signal to a process. Examples are:
|
||||
* TTY wanting to cause SIGINT upon getting a DEL
|
||||
* CLOCK wanting to cause SIGALRM when timer expires
|
||||
* FS also uses this to send a signal, via the SYS_KILL message. Signals are
|
||||
* handled by sending a message to PM. This central function handles the
|
||||
* FS wanting to cause SIGPIPE for a broken pipe
|
||||
* Signals are handled by sending a message to PM. This function handles the
|
||||
* signals and makes sure the PM gets them by sending a notification. The
|
||||
* process being signaled is blocked while PM has not finished all signals
|
||||
* for it. These signals are counted in p_pendcount, and the SIG_PENDING
|
||||
|
@ -487,7 +487,7 @@ vir_bytes bytes; /* # of bytes to copy */
|
|||
|
||||
/* Check copy count. */
|
||||
if (bytes <= 0) {
|
||||
kprintf("v_cp: copy count problem <= 0\n", NO_ARG);
|
||||
kprintf("v_cp: copy count problem <= 0\n", NO_NUM);
|
||||
return(EDOM);
|
||||
}
|
||||
|
||||
|
@ -523,7 +523,7 @@ vir_bytes bytes; /* # of bytes to copy */
|
|||
|
||||
/* Check if mapping succeeded. */
|
||||
if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) {
|
||||
kprintf("v_cp: Mapping failed ... phys <= 0\n", NO_ARG);
|
||||
kprintf("v_cp: Mapping failed ... phys <= 0\n", NO_NUM);
|
||||
return(EFAULT);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ register message *m_ptr; /* pointer to request message */
|
|||
/* Check if process number was given implictly with SELF and is valid. */
|
||||
if (vir_addr[i].proc_nr == SELF) vir_addr[i].proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG) {
|
||||
kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_ARG);
|
||||
kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_NUM);
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ register message *m_ptr; /* pointer to request message */
|
|||
* vir_bytes. Especially copying by the PM on do_fork() is affected.
|
||||
*/
|
||||
if (bytes != (vir_bytes) bytes) {
|
||||
kprintf("do_vircopy: overflow\n", NO_ARG);
|
||||
kprintf("do_vircopy: overflow\n", NO_NUM);
|
||||
return(E2BIG);
|
||||
}
|
||||
|
||||
|
|
|
@ -105,11 +105,6 @@ register message *m_ptr; /* pointer to request message */
|
|||
src_phys = vir2phys(irq_hooks);
|
||||
break;
|
||||
}
|
||||
case GET_MEMCHUNKS: {
|
||||
length = sizeof(struct memory) * NR_MEMS;
|
||||
src_phys = vir2phys(mem);
|
||||
break;
|
||||
}
|
||||
case GET_SCHEDINFO: {
|
||||
/* This is slightly complicated because we need two data structures
|
||||
* at once, otherwise the scheduling information may be incorrect.
|
||||
|
|
Loading…
Reference in a new issue