Various fixes and improvements.

- fixed bug that caused IDLE to panic (irq hook inconsistency);
- kprintf() now accepts multiple arguments; moved to utility.c;
- prepare_shutdown() signals system processes with SIGKSTOP;
- phys_fill() renamed to phys_memset(), argument order changed;
- kmemset() removed in favor of phys_kmemset();
- kstrncpy() removed in favor of phys_copy();
- katoi, kstrncmp replaced by normal library procedure again;
- rm_irq_handler() interface changed (simply pass hook pointer);
This commit is contained in:
Jorrit Herder 2005-07-20 15:25:38 +00:00
parent f8af4da472
commit c0718054e9
19 changed files with 243 additions and 318 deletions

View file

@ -14,7 +14,7 @@ CFLAGS = -I$i
LDFLAGS = -i LDFLAGS = -i
HEAD = mpx.o HEAD = mpx.o
OBJS = start.o protect.o klibc.o klib.o table.o main.o proc.o \ OBJS = start.o protect.o klib.o table.o main.o proc.o \
i8259.o exception.o system.o clock.o utility.o debug.o i8259.o exception.o system.o clock.o utility.o debug.o
SYSTEM = system.a SYSTEM = system.a
LIBS = -ltimers LIBS = -ltimers

View file

@ -53,7 +53,7 @@
* a system server is notified and a copy of the buffer can be retrieved to * a system server is notified and a copy of the buffer can be retrieved to
* display the message. The buffers size can safely be reduced. * display the message. The buffers size can safely be reduced.
*/ */
#define KMESS_BUF_SIZE 128 #define KMESS_BUF_SIZE 256
/* Buffer to gather randomness. This is used to generate a random stream by /* Buffer to gather randomness. This is used to generate a random stream by
* the MEMORY driver when reading from /dev/random. * the MEMORY driver when reading from /dev/random.

View file

@ -120,35 +120,35 @@ check_runqueues(char *when)
for (q=0; q < NR_SCHED_QUEUES; q++) { for (q=0; q < NR_SCHED_QUEUES; q++) {
if(rdy_head[q] && !rdy_tail[q]) { if(rdy_head[q] && !rdy_tail[q]) {
kprintf("head but no tail: %s", (karg_t) when); kprintf("head but no tail: %s", when);
panic("scheduling error", NO_NUM); panic("scheduling error", NO_NUM);
} }
if(!rdy_head[q] && rdy_tail[q]) { if(!rdy_head[q] && rdy_tail[q]) {
kprintf("tail but no head: %s", (karg_t) when); kprintf("tail but no head: %s", when);
panic("scheduling error", NO_NUM); panic("scheduling error", NO_NUM);
} }
if(rdy_tail[q] && rdy_tail[q]->p_nextready != NIL_PROC) { if(rdy_tail[q] && rdy_tail[q]->p_nextready != NIL_PROC) {
kprintf("tail and tail->next not null; %s", (karg_t) when); kprintf("tail and tail->next not null; %s", when);
panic("scheduling error", NO_NUM); panic("scheduling error", NO_NUM);
} }
for(xp = rdy_head[q]; xp != NIL_PROC; xp = xp->p_nextready) { for(xp = rdy_head[q]; xp != NIL_PROC; xp = xp->p_nextready) {
if (!xp->p_ready) { if (!xp->p_ready) {
kprintf("scheduling error: unready on runq: %s\n", (karg_t) when); kprintf("scheduling error: unready on runq: %s\n", when);
panic("found unready process on run queue", NO_NUM); panic("found unready process on run queue", NO_NUM);
} }
if(xp->p_priority != q) { if(xp->p_priority != q) {
kprintf("scheduling error: wrong priority: %s\n", (karg_t) when); kprintf("scheduling error: wrong priority: %s\n", when);
panic("wrong priority", NO_NUM); panic("wrong priority", NO_NUM);
} }
if(xp->p_found) { if(xp->p_found) {
kprintf("scheduling error: double scheduling: %s\n", (karg_t) when); kprintf("scheduling error: double scheduling: %s\n", when);
panic("proc more than once on scheduling queue", NO_NUM); panic("proc more than once on scheduling queue", NO_NUM);
} }
xp->p_found = 1; xp->p_found = 1;
if(xp->p_nextready == NIL_PROC && rdy_tail[q] != xp) { if(xp->p_nextready == NIL_PROC && rdy_tail[q] != xp) {
kprintf("scheduling error: last element not tail: %s\n", (karg_t) when); kprintf("scheduling error: last element not tail: %s\n", when);
panic("scheduling error", NO_NUM); panic("scheduling error", NO_NUM);
} }
if(l++ > PROCLIMIT) panic("loop in schedule queue?", NO_NUM); if(l++ > PROCLIMIT) panic("loop in schedule queue?", NO_NUM);
@ -157,7 +157,7 @@ check_runqueues(char *when)
for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) { for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
if(! isemptyp(xp) && xp->p_ready && ! xp->p_found) { if(! isemptyp(xp) && xp->p_ready && ! xp->p_found) {
kprintf("scheduling error: ready not on queue: %s\n", (karg_t) when); kprintf("scheduling error: ready not on queue: %s\n", when);
panic("ready proc not on scheduling queue", NO_NUM); panic("ready proc not on scheduling queue", NO_NUM);
if(l++ > PROCLIMIT) { panic("loop in proc.t?", NO_NUM); } if(l++ > PROCLIMIT) { panic("loop in proc.t?", NO_NUM); }
} }

View file

@ -65,13 +65,12 @@ unsigned vec_nr;
if (ep->msg == NIL_PTR || machine.processor < ep->minprocessor) if (ep->msg == NIL_PTR || machine.processor < ep->minprocessor)
kprintf("\nIntel-reserved exception %d\n", vec_nr); kprintf("\nIntel-reserved exception %d\n", vec_nr);
else else
kprintf("\n%s\n", karg(ep->msg)); kprintf("\n%s\n", ep->msg);
kprintf("process number %d ", proc_nr(saved_proc)); kprintf("k_reenter = %d ", k_reenter);
kprintf("(%s), ", saved_proc->p_name); kprintf("process %d (%s)", proc_nr(saved_proc), saved_proc->p_name);
kprintf("pc = %d:", (unsigned) saved_proc->p_reg.cs); kprintf("pc = %d:0x%x", (unsigned) saved_proc->p_reg.cs,
kprintf("0x%x\n", (unsigned) saved_proc->p_reg.pc); (unsigned) saved_proc->p_reg.pc);
kernel_exception = TRUE; /* directly shutdown */
panic("exception in a kernel task", NO_NUM); panic("exception in a kernel task", NO_NUM);
} }

View file

@ -123,29 +123,30 @@ irq_handler_t handler;
/*=========================================================================* /*=========================================================================*
* rm_irq_handler * * rm_irq_handler *
*=========================================================================*/ *=========================================================================*/
PUBLIC int rm_irq_handler(irq, id) PUBLIC void rm_irq_handler(hook)
int irq; irq_hook_t *hook;
int id;
{ {
/* Unregister an interrupt handler. */ /* Unregister an interrupt handler. */
int irq = hook->irq;
int id = hook->id;
irq_hook_t **line; irq_hook_t **line;
if (irq < 0 || irq >= NR_IRQ_VECTORS) return(EINVAL); if (irq < 0 || irq >= NR_IRQ_VECTORS)
panic("invalid call to rm_irq_handler", irq);
line = &irq_handlers[irq]; line = &irq_handlers[irq];
while (*line != NULL) { while (*line != NULL) {
if((*line)->id == id) { if((*line)->id == id) {
(*line) = (*line)->next; (*line) = (*line)->next;
if(! irq_handlers[irq]) if(! irq_handlers[irq]) irq_use &= ~(1 << irq);
irq_use &= ~(1 << irq); return;
return(OK);
} }
line = &(*line)->next; line = &(*line)->next;
} }
/* When the handler is not found, normally return here. */
return(ENOENT);
} }
/*==========================================================================* /*==========================================================================*
* intr_handle * * intr_handle *
*==========================================================================*/ *==========================================================================*/

View file

@ -26,7 +26,7 @@
.define _enable_irq ! enable an irq at the 8259 controller .define _enable_irq ! enable an irq at the 8259 controller
.define _disable_irq ! disable an irq .define _disable_irq ! disable an irq
.define _phys_copy ! copy data from anywhere to anywhere in memory .define _phys_copy ! copy data from anywhere to anywhere in memory
.define _phys_fill ! zero data anywhere in memory .define _phys_memset ! write pattern anywhere in memory
.define _mem_rdw ! copy one word from [segment:offset] .define _mem_rdw ! copy one word from [segment:offset]
.define _reset ! reset the system .define _reset ! reset the system
.define _idle_task ! task executed when there is no work .define _idle_task ! task executed when there is no work
@ -440,25 +440,24 @@ pc_small:
ret ret
!*===========================================================================* !*===========================================================================*
!* phys_fill * !* phys_memset *
!*===========================================================================* !*===========================================================================*
! PUBLIC void phys_fill(phys_bytes source, phys_bytes bytecount, ! PUBLIC void phys_memset(phys_bytes source, unsigned long pattern,
! unsigned long pattern); ! phys_bytes bytecount);
! Fill a block of physical memory with pattern. ! Fill a block of physical memory with pattern.
.align 16 .align 16
_phys_memset:
_phys_fill:
push ebp push ebp
mov ebp, esp mov ebp, esp
push esi push esi
push ebx push ebx
push ds push ds
mov esi, 8(ebp) mov esi, 8(ebp)
mov eax, 12(ebp) mov eax, 16(ebp)
mov ebx, FLAT_DS_SELECTOR mov ebx, FLAT_DS_SELECTOR
mov ds, bx mov ds, bx
mov ebx, 16(ebp) mov ebx, 12(ebp)
shr eax, 2 shr eax, 2
fill_start: fill_start:
mov (esi), ebx mov (esi), ebx
@ -466,12 +465,12 @@ fill_start:
dec eax dec eax
jnz fill_start jnz fill_start
! Any remaining bytes? ! Any remaining bytes?
mov eax, 12(ebp) mov eax, 16(ebp)
and eax, 3 and eax, 3
remain_fill: remain_fill:
cmp eax, 0 cmp eax, 0
jz fill_done jz fill_done
movb bl, 16(ebp) movb bl, 12(ebp)
movb (esi), bl movb (esi), bl
add esi, 1 add esi, 1
inc ebp inc ebp

View file

@ -1,177 +0,0 @@
/* This file contains simplified versions of the standard libary functions for
* use with the kernel. This way the kernel sources remain separate from user
* sources and can easily be verified. Note that the functionality provided
* can be slightly different.
* March 2005, Jorrit N. Herder.
* Entrypoints into this file:
* kmemcpy: copy n bytes from pointer p1 to pointer p2
* kmemset: set n bytes to c starting at pointer p
* kprintf: printf for the kernel (see working below)
* kstrcmp: lexicographical comparison of two strings
* kstrncpy: copy string and pad or copy up to n chars
*
* This file contains the routines that take care of kernel messages, i.e.,
* diagnostic output within the kernel. Kernel messages are not directly
* displayed on the console, because this must be done by the PRINT driver.
* Instead, the kernel accumulates characters in a buffer and notifies the
* output driver when a new message is ready.
*/
#include "kernel.h"
#include <signal.h>
#include <minix/com.h>
#define isdigit(c) ((unsigned) ((c) - '0') < (unsigned) 10)
#define END_OF_KMESS -1
FORWARD _PROTOTYPE(void kputc, (int c));
/*=========================================================================*
* kmemcpy *
*=========================================================================*/
PUBLIC void *kmemcpy(void *s1, const void *s2, register size_t n)
{
register char *p1 = s1;
register const char *p2 = s2;
while (n-- > 0)
*p1++ = *p2++;
return s1;
}
/*=========================================================================*
* kmemset *
*=========================================================================*/
PUBLIC void *kmemset(void *s, register int c, register size_t n)
{
register char *s1 = s;
if (n++>0) { /* optimized for speed */
while (--n > 0)
*s1++ = c;
}
return s;
}
/*===========================================================================*
* kprintf *
*===========================================================================*/
PUBLIC void kprintf(fmt, arg)
const char *fmt; /* format string to be printed */
karg_t arg; /* argument for format string */
{
int c; /* next character in fmt */
unsigned long u; /* hold number argument */
int base; /* base of number arg */
int negative = 0; /* print minus sign */
static char x2c[] = "0123456789ABCDEF"; /* nr conversion table */
char ascii[8 * sizeof(long) / 3 + 2]; /* string for ascii number */
char *s = NULL; /* string to be printed */
while((c=*fmt++) != 0) {
if (c == '%') { /* expect format '%key' */
switch(c = *fmt++) { /* determine what to do */
/* Known keys are %d, %u, %x, %s, and %%. This is easily extended
* with number types like %b and %o by providing a different base.
* Number type keys don't set a string to 's', but use the general
* conversion after the switch statement.
*/
case 'd': /* output decimal */
u = arg < 0 ? -arg : arg;
if (arg < 0) negative = 1;
base = 10;
break;
case 'u': /* output unsigned long */
u = (unsigned long) arg;
base = 10;
break;
case 'x': /* output hexadecimal */
u = (unsigned long) arg;
base = 0x10;
break;
case 's': /* output string */
if ((s=(char *)arg) == NULL)
s = "(null)";
break;
case '%': /* output percent */
s = "%";
break;
/* Unrecognized key. */
default: /* echo back %key */
s = "%?";
s[1] = c; /* set unknown key */
}
/* Assume a number if no string is set. Convert to ascii. */
if (s == NULL) {
s = ascii + sizeof(ascii)-1;
*s = 0;
do { *--s = x2c[(u % base)]; } /* work backwards */
while ((u /= base) > 0);
}
/* This is where the actual output for format "%key" is done. */
if (negative) kputc('-'); /* print sign if negative */
while(*s != 0) { kputc(*s++); } /* print string/ number */
}
else {
kputc(c); /* print and continue */
}
}
kputc(END_OF_KMESS); /* terminate output */
}
/*===========================================================================*
* kputc *
*===========================================================================*/
PRIVATE void kputc(c)
int c; /* character to append */
{
/* Accumulate a single character for a kernel message. Send a notification
* the to PRINTF_PROC driver if an END_OF_KMESS is encountered.
*/
if (c != END_OF_KMESS) {
kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
if (kmess.km_size < KMESS_BUF_SIZE)
kmess.km_size += 1;
kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
} else {
send_sig(PRINTF_PROC, SIGKMESS);
}
}
/*=========================================================================*
* kstrcmp *
*=========================================================================*/
int kstrcmp(register const char *s1, register const char *s2)
{
while (*s1 == *s2++)
if (*s1++ == '\0') return 0;
if (*s1 == '\0') return -1;
if (*--s2 == '\0') return 1;
return (unsigned char) *s1 - (unsigned char) *s2;
}
/*=========================================================================*
* kstrncpy *
*=========================================================================*/
PUBLIC char *kstrncpy(char *ret, register const char *s2, register ssize_t n)
{
register char *s1 = ret;
while((n-- > 0) && (*s1++ = *s2++)) /* copy up to n chars */
/* EMPTY */ ;
while(n-- > 0) /* possibly pad target */
*s1++ = '\0';
return ret;
}

View file

@ -14,6 +14,7 @@
*/ */
#include "kernel.h" #include "kernel.h"
#include <signal.h> #include <signal.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include <a.out.h> #include <a.out.h>
#include <minix/callnr.h> #include <minix/callnr.h>
@ -24,6 +25,8 @@
FORWARD _PROTOTYPE( void announce, (void)); FORWARD _PROTOTYPE( void announce, (void));
FORWARD _PROTOTYPE( void shutdown, (timer_t *tp)); FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
#define SHUTDOWN_TICKS 5 /* time allowed to do cleanup */
/*===========================================================================* /*===========================================================================*
* main * * main *
@ -31,15 +34,14 @@ FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
PUBLIC void main() PUBLIC void main()
{ {
/* Start the ball rolling. */ /* Start the ball rolling. */
register struct proc *rp; struct system_image *ip; /* boot image pointer */
register struct priv *sp; register struct proc *rp; /* process pointer */
register int i,s; register struct priv *sp; /* privilege structure pointer */
register int i, s;
int hdrindex; /* index to array of a.out headers */ int hdrindex; /* index to array of a.out headers */
phys_clicks text_base; phys_clicks text_base;
vir_clicks text_clicks; vir_clicks text_clicks, data_clicks;
vir_clicks data_clicks;
reg_t ktsb; /* kernel task stack base */ reg_t ktsb; /* kernel task stack base */
struct system_image *ip; /* boot image pointer */
struct exec e_hdr; /* for a copy of an a.out header */ struct exec e_hdr; /* for a copy of an a.out header */
/* Initialize the interrupt controller. */ /* Initialize the interrupt controller. */
@ -73,9 +75,13 @@ PUBLIC void main()
for (i=0; i < NR_BOOT_PROCS; ++i) { for (i=0; i < NR_BOOT_PROCS; ++i) {
ip = &image[i]; /* process' attributes */ ip = &image[i]; /* process' attributes */
(void) init_proc(ip->proc_nr, NONE); /* initialize new process */
rp = proc_addr(ip->proc_nr); /* get process pointer */ rp = proc_addr(ip->proc_nr); /* get process pointer */
kstrncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set name */ (void) init_proc(rp, NIL_SYS_PROC);
#if DEAD_CODE
(ip->flags & SYS_PROC) ?
NIL_SYS_PROC : NIL_PROC); /* initialize new process */
#endif
strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set name */
rp->p_name[P_NAME_LEN-1] = '\0'; /* just for safety */ rp->p_name[P_NAME_LEN-1] = '\0'; /* just for safety */
rp->p_max_priority = ip->priority; /* max scheduling priority */ rp->p_max_priority = ip->priority; /* max scheduling priority */
rp->p_priority = ip->priority; /* current priority */ rp->p_priority = ip->priority; /* current priority */
@ -106,7 +112,7 @@ PUBLIC void main()
/* Convert addresses to clicks and build process memory map */ /* Convert addresses to clicks and build process memory map */
text_base = e_hdr.a_syms >> CLICK_SHIFT; text_base = e_hdr.a_syms >> CLICK_SHIFT;
text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT; text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0; /* Common I&D */ if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0; /* common I&D */
data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT; data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
rp->p_memmap[T].mem_phys = text_base; rp->p_memmap[T].mem_phys = text_base;
rp->p_memmap[T].mem_len = text_clicks; rp->p_memmap[T].mem_len = text_clicks;
@ -168,13 +174,13 @@ PUBLIC void main()
PRIVATE void announce(void) PRIVATE void announce(void)
{ {
/* Display the MINIX startup banner. */ /* Display the MINIX startup banner. */
kprintf("MINIX %s. Copyright 2001 Prentice-Hall, Inc.\n", kprintf("MINIX %s.%s. Copyright 2001 Prentice-Hall, Inc.\n",
karg(OS_RELEASE "." OS_VERSION)); OS_RELEASE, OS_VERSION);
#if (CHIP == INTEL) #if (CHIP == INTEL)
/* Real mode, or 16/32-bit protected mode? */ /* Real mode, or 16/32-bit protected mode? */
kprintf("Executing in %s mode\n\n", kprintf("Executing in %s mode\n\n",
machine.protected ? karg("32-bit protected") : karg("real")); machine.protected ? "32-bit protected" : "real");
#endif #endif
} }
@ -189,6 +195,7 @@ int how; /* reason to shut down */
* sure it is only executed once. Unless a CPU exception occurred, the * sure it is only executed once. Unless a CPU exception occurred, the
*/ */
static timer_t shutdown_timer; /* timer for watchdog function */ static timer_t shutdown_timer; /* timer for watchdog function */
register struct proc *rp;
message m; message m;
/* Show debugging dumps on panics. Make sure that the TTY task is still /* Show debugging dumps on panics. Make sure that the TTY task is still
@ -201,21 +208,26 @@ int how; /* reason to shut down */
return; /* await sys_abort() from TTY */ return; /* await sys_abort() from TTY */
} }
/* Send signal to TTY so that it can switch to the primary console. */ /* Send a signal to all system processes that are still alive to inform
send_sig(TTY, SIGKSTOP); * them that the MINIX kernel is shutting down. A proper shutdown sequence
* should be implemented by a user-space server. This mechanism is useful
/* Allow processes to be scheduled to clean up, unless a CPU exception * as a backup in case of system panics, so that system processes can still
* occurred. This is done by setting a timer. The timer argument passes * run their shutdown code, e.g, to synchronize the FS or to let the TTY
* the shutdown status. * switch to the first console.
*/ */
tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */ for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
if (kernel_exception) { /* set in exception() */ if (! isemptyp(rp) && (priv(rp)->s_flags & SYS_PROC) && ! iskernelp(rp))
kprintf("\nAn exception occured; skipping stop sequence.\n", NO_NUM); send_sig(proc_nr(rp), SIGKSTOP);
shutdown(&shutdown_timer); /* TTY isn't scheduled */
} else {
kprintf("\nNotifying system services about MINIX shutdown.\n", NO_NUM);
set_timer(&shutdown_timer, get_uptime(), shutdown);
} }
/* Notify system processes of the upcoming shutdown and allow them to be
* scheduled by setting a watchog timer that calls shutdown(). The timer
* argument passes the shutdown status.
*/
kprintf("Informed system about upcoming shutdown with SIGKSTOP signal.\n");
kprintf("Time for cleanup is allowed. MINIX will now be brought down.\n");
tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */
set_timer(&shutdown_timer, get_uptime() + SHUTDOWN_TICKS, shutdown);
} }

View file

@ -61,7 +61,9 @@ struct priv {
EXTERN struct priv priv[NR_SYS_PROCS]; /* system properties table */ EXTERN struct priv priv[NR_SYS_PROCS]; /* system properties table */
EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */ EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */
/* Unprivileged user processes all share the same privilege structure. */ /* Unprivileged user processes all share the same privilege structure.
* This id must be fixed because it is used to check send mask entries.
*/
#define USER_PRIV_ID 0 #define USER_PRIV_ID 0
/* Make sure the system can boot. The following sanity check verifies that /* Make sure the system can boot. The following sanity check verifies that

View file

@ -88,6 +88,7 @@ struct proc {
#define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS]) #define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS])
#define NIL_PROC ((struct proc *) 0) #define NIL_PROC ((struct proc *) 0)
#define NIL_SYS_PROC ((struct proc *) 1)
#define cproc_addr(n) (&(proc + NR_TASKS)[(n)]) #define cproc_addr(n) (&(proc + NR_TASKS)[(n)])
#define proc_addr(n) (pproc_addr + NR_TASKS)[(n)] #define proc_addr(n) (pproc_addr + NR_TASKS)[(n)]
#define proc_nr(p) ((p)->p_nr) #define proc_nr(p) ((p)->p_nr)

View file

@ -15,24 +15,14 @@ _PROTOTYPE( unsigned long read_clock, (void) );
_PROTOTYPE( void set_timer, (struct timer *tp, clock_t t, tmr_func_t f) ); _PROTOTYPE( void set_timer, (struct timer *tp, clock_t t, tmr_func_t f) );
_PROTOTYPE( void reset_timer, (struct timer *tp) ); _PROTOTYPE( void reset_timer, (struct timer *tp) );
/* klibc.c */
_PROTOTYPE( void *kmemcpy, (void *s1, const void *s2, register size_t n));
_PROTOTYPE( void *kmemset, (void *s, register int c, register size_t n));
_PROTOTYPE( int kstrcmp, (register const char *s1, register const char *s2));
_PROTOTYPE( char *kstrncpy,
(char *s1, register const char *s2, register const ssize_t n));
#define karg(arg) (karg_t) (arg)
_PROTOTYPE( void kprintf, (const char *fmt, karg_t arg) );
/* main.c */ /* main.c */
_PROTOTYPE( void main, (void) ); _PROTOTYPE( void main, (void) );
_PROTOTYPE( void prepare_shutdown, (int how) ); _PROTOTYPE( void prepare_shutdown, (int how) );
_PROTOTYPE( void stop_sequence, (struct timer *tp) ); _PROTOTYPE( void stop_sequence, (struct timer *tp) );
/* utility.c */ /* utility.c */
_PROTOTYPE( void kprintf, (const char *fmt, ...) );
_PROTOTYPE( void panic, (_CONST char *s, int n) ); _PROTOTYPE( void panic, (_CONST char *s, int n) );
_PROTOTYPE( void safe_lock, (int c, char *v) );
_PROTOTYPE( void safe_unlock, (void) );
_PROTOTYPE( int alloc_bit, (bitchunk_t *map, bit_t nr_bits) ); _PROTOTYPE( int alloc_bit, (bitchunk_t *map, bit_t nr_bits) );
_PROTOTYPE( void free_bit, (bit_t nr, bitchunk_t *map, bit_t nr_bits) ); _PROTOTYPE( void free_bit, (bit_t nr, bitchunk_t *map, bit_t nr_bits) );
@ -51,8 +41,8 @@ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds,
/* system.c */ /* system.c */
_PROTOTYPE( void send_sig, (int proc_nr, int sig_nr) ); _PROTOTYPE( void send_sig, (int proc_nr, int sig_nr) );
_PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) ); _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) );
_PROTOTYPE( int init_proc, (int proc_nr, int proto_nr) ); _PROTOTYPE( int init_proc, (register struct proc *rc, struct proc *rp) );
_PROTOTYPE( void clear_proc, (int proc_nr) ); _PROTOTYPE( void clear_proc, (register struct proc *rc) );
_PROTOTYPE( phys_bytes numap_local, (int proc_nr, vir_bytes vir_addr, _PROTOTYPE( phys_bytes numap_local, (int proc_nr, vir_bytes vir_addr,
vir_bytes bytes) ); vir_bytes bytes) );
_PROTOTYPE( void sys_task, (void) ); _PROTOTYPE( void sys_task, (void) );
@ -77,7 +67,7 @@ _PROTOTYPE( void intr_init, (int mine) );
_PROTOTYPE( void intr_handle, (irq_hook_t *hook) ); _PROTOTYPE( void intr_handle, (irq_hook_t *hook) );
_PROTOTYPE( void put_irq_handler, (irq_hook_t *hook, int irq, _PROTOTYPE( void put_irq_handler, (irq_hook_t *hook, int irq,
irq_handler_t handler) ); irq_handler_t handler) );
_PROTOTYPE( int rm_irq_handler, (int irq, int id) ); _PROTOTYPE( void rm_irq_handler, (irq_hook_t *hook) );
/* klib*.s */ /* klib*.s */
_PROTOTYPE( void int86, (void) ); _PROTOTYPE( void int86, (void) );
@ -88,11 +78,12 @@ _PROTOTYPE( int disable_irq, (irq_hook_t *hook) );
_PROTOTYPE( u16_t mem_rdw, (U16_t segm, vir_bytes offset) ); _PROTOTYPE( u16_t mem_rdw, (U16_t segm, vir_bytes offset) );
_PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest, _PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
phys_bytes count) ); phys_bytes count) );
_PROTOTYPE( void phys_fill, (phys_bytes source, phys_bytes count, unsigned long pattern) ); _PROTOTYPE( void phys_memset, (phys_bytes source, unsigned long pattern,
phys_bytes count) );
_PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count) ); _PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) ); _PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count)); _PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count)); _PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void reset, (void) ); _PROTOTYPE( void reset, (void) );
_PROTOTYPE( void level0, (void (*func)(void)) ); _PROTOTYPE( void level0, (void (*func)(void)) );
_PROTOTYPE( void monitor, (void) ); _PROTOTYPE( void monitor, (void) );

View file

@ -12,6 +12,7 @@
#include "protect.h" #include "protect.h"
#include "proc.h" #include "proc.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
FORWARD _PROTOTYPE( char *get_value, (_CONST char *params, _CONST char *key)); FORWARD _PROTOTYPE( char *get_value, (_CONST char *params, _CONST char *key));
@ -56,9 +57,9 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
/* Record miscellaneous information for user-space servers. */ /* Record miscellaneous information for user-space servers. */
kinfo.nr_procs = NR_PROCS; kinfo.nr_procs = NR_PROCS;
kinfo.nr_tasks = NR_TASKS; kinfo.nr_tasks = NR_TASKS;
kstrncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release)); strncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));
kinfo.release[sizeof(kinfo.release)-1] = '\0'; kinfo.release[sizeof(kinfo.release)-1] = '\0';
kstrncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version)); strncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
kinfo.version[sizeof(kinfo.version)-1] = '\0'; kinfo.version[sizeof(kinfo.version)-1] = '\0';
kinfo.proc_addr = (vir_bytes) proc; kinfo.proc_addr = (vir_bytes) proc;
kinfo.kmem_base = vir2phys(0); kinfo.kmem_base = vir2phys(0);
@ -75,16 +76,16 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
/* XT, AT or MCA bus? */ /* XT, AT or MCA bus? */
value = get_value(params, "bus"); value = get_value(params, "bus");
if (value == NIL_PTR || kstrcmp(value, "at") == 0) { if (value == NIL_PTR || strcmp(value, "at") == 0) {
machine.pc_at = TRUE; /* PC-AT compatible hardware */ machine.pc_at = TRUE; /* PC-AT compatible hardware */
} else if (kstrcmp(value, "mca") == 0) { } else if (strcmp(value, "mca") == 0) {
machine.pc_at = machine.ps_mca = TRUE; /* PS/2 with micro channel */ machine.pc_at = machine.ps_mca = TRUE; /* PS/2 with micro channel */
} }
/* Type of VDU: */ /* Type of VDU: */
value = get_value(params, "video"); /* EGA or VGA video unit */ value = get_value(params, "video"); /* EGA or VGA video unit */
if (kstrcmp(value, "ega") == 0) machine.vdu_ega = TRUE; if (strcmp(value, "ega") == 0) machine.vdu_ega = TRUE;
if (kstrcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE; if (strcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
/* Return to assembler code to switch to protected mode (if 286), /* Return to assembler code to switch to protected mode (if 286),
* reload selectors and call main(). * reload selectors and call main().

View file

@ -92,7 +92,7 @@ PUBLIC void sys_task()
if (result != EDONTREPLY) { if (result != EDONTREPLY) {
m.m_type = result; /* report status of call */ m.m_type = result; /* report status of call */
if (OK != lock_send(m.m_source, &m)) { if (OK != lock_send(m.m_source, &m)) {
kprintf("Warning, SYSTASK couldn't reply to request from %d\n", kprintf("Warning, SYSTASK couldn't reply to request from %d.\n",
m.m_source); m.m_source);
} }
} }
@ -171,34 +171,36 @@ PRIVATE void initialize(void)
/*===========================================================================* /*===========================================================================*
* init_proc * * init_proc *
*===========================================================================*/ *===========================================================================*/
PUBLIC int init_proc(proc_nr, proto_nr) PUBLIC int init_proc(rc, rp)
int proc_nr; /* slot of process to initialize */ register struct proc *rc; /* new (child) process pointer */
int proto_nr; /* prototype process to copy from */ struct proc *rp; /* prototype (parent) process */
{ {
register struct proc *rc, *rp; register struct priv *sp; /* process' privilege structure */
register struct priv *sp;
int i; int i;
/* Get a pointer to the process to initialize. */
rc = proc_addr(proc_nr);
/* If there is a prototype process to initialize from, use it. Otherwise, /* If there is a prototype process to initialize from, use it. Otherwise,
* assume the caller will take care of initialization, but make sure that * assume the caller will take care of initialization, but make sure that
* the new process gets a pointer to a system properties structure. * the new process gets a pointer to a system properties structure.
*/ */
if (isokprocn(proto_nr)) { if (rp == NIL_PROC) { /* new user process */
kprintf("INIT proc from prototype %d\n", proto_nr); kprintf("init_proc() for new user proc %d\n", proc_nr(rc));
sp = &priv[USER_PRIV_ID];
} else { sp->s_proc_nr = ANY; /* misuse for users */
rc->p_priv = sp; /* assign to process */
return(OK);
} else if (rp == NIL_SYS_PROC) { /* new system process */
for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) { for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
if (sp->s_proc_nr == NONE) { /* found free slot */ if (sp->s_proc_nr == NONE) { /* found free slot */
sp->s_proc_nr = proc_nr; /* set association */ sp->s_proc_nr = proc_nr(rc); /* set association */
rc->p_priv = sp; /* assign to process */ rc->p_priv = sp; /* assign to process */
return(OK); return(OK);
} }
} }
kprintf("No free PRIV structure!\n", NO_NUM); kprintf("No free PRIV structure!\n", NO_NUM);
return(ENOSPC); /* out of resources */ return(ENOSPC); /* out of resources */
} else { /* forked process */
kprintf("init_proc() from prototype %d\n", proc_nr(rp));
} }
} }
@ -206,26 +208,22 @@ int proto_nr; /* prototype process to copy from */
/*===========================================================================* /*===========================================================================*
* clear_proc * * clear_proc *
*===========================================================================*/ *===========================================================================*/
PUBLIC void clear_proc(proc_nr) PUBLIC void clear_proc(rc)
int proc_nr; /* slot of process to clean up */ register struct proc *rc; /* slot of process to clean up */
{ {
register struct proc *rp, *rc; register struct proc *rp; /* iterate over process table */
register struct proc **xpp; /* iterate over caller queue */ register struct proc **xpp; /* iterate over caller queue */
int i; int i;
/* Get a pointer to the process that exited. */
rc = proc_addr(proc_nr);
/* Turn off any alarm timers at the clock. */ /* Turn off any alarm timers at the clock. */
reset_timer(&priv(rc)->s_alarm_timer); reset_timer(&priv(rc)->s_alarm_timer);
/* Make sure the exiting process is no longer scheduled. */ /* Make sure that the exiting process is no longer scheduled. */
if (rc->p_rts_flags == 0) lock_unready(rc); if (rc->p_rts_flags == 0) lock_unready(rc);
/* If the process being terminated happens to be queued trying to send a /* If the process being terminated happens to be queued trying to send a
* message (e.g., the process was killed by a signal, rather than it doing * message (e.g., the process was killed by a signal, rather than it doing
* an exit or it is forcibly shutdown in the stop sequence), then it must * a normal exit), then it must be removed from the message queues.
* be removed from the message queues.
*/ */
if (rc->p_rts_flags & SENDING) { if (rc->p_rts_flags & SENDING) {
/* Check all proc slots to see if the exiting process is queued. */ /* Check all proc slots to see if the exiting process is queued. */
@ -245,26 +243,19 @@ int proc_nr; /* slot of process to clean up */
/* Check the table with IRQ hooks to see if hooks should be released. */ /* Check the table with IRQ hooks to see if hooks should be released. */
for (i=0; i < NR_IRQ_HOOKS; i++) { for (i=0; i < NR_IRQ_HOOKS; i++) {
if (irq_hooks[i].proc_nr == proc_nr) if (irq_hooks[i].proc_nr == proc_nr(rc)) {
irq_hooks[i].proc_nr = NONE; rm_irq_handler(&irq_hooks[i]); /* remove interrupt handler */
irq_hooks[i].proc_nr = NONE; /* mark hook as free */
}
} }
#if TEMP_CODE
/* Check if there are pending notifications. Release the buffers. */
while (rc->p_ntf_q != NULL) {
i = (int) (rc->p_ntf_q - &notify_buffer[0]);
free_bit(i, notify_bitmap, NR_NOTIFY_BUFS);
rc->p_ntf_q = rc->p_ntf_q->n_next;
}
#endif
/* Now it is safe to release the process table slot. If this is a system /* Now it is safe to release the process table slot. If this is a system
* process, also release its privilege structure. Further cleanup is not * process, also release its privilege structure. Further cleanup is not
* needed at this point. All important fields are reinitialized when the * needed at this point. All important fields are reinitialized when the
* slots are assigned to another, new process. * slots are assigned to another, new process.
*/ */
rc->p_rts_flags = SLOT_FREE; rc->p_rts_flags = SLOT_FREE;
if (priv(rp)->s_flags & SYS_PROC) priv(rp)->s_proc_nr = NONE; if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
} }

View file

@ -8,6 +8,7 @@
* m1_p3: PR_IP_PTR (new instruction pointer) * m1_p3: PR_IP_PTR (new instruction pointer)
*/ */
#include "../system.h" #include "../system.h"
#include <string.h>
#include <signal.h> #include <signal.h>
#if USE_EXEC #if USE_EXEC
@ -35,7 +36,7 @@ register message *m_ptr; /* pointer to request message */
#endif #endif
#endif #endif
#if (CHIP == INTEL) /* wipe extra LDT entries */ #if (CHIP == INTEL) /* wipe extra LDT entries */
kmemset(&rp->p_ldt[EXTRA_LDT_INDEX], 0, phys_memset(vir2phys(&rp->p_ldt[EXTRA_LDT_INDEX]), 0,
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0])); (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
#endif #endif
rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */ rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */
@ -50,7 +51,7 @@ register message *m_ptr; /* pointer to request message */
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {} for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
*np = 0; /* mark end */ *np = 0; /* mark end */
} else { } else {
kstrncpy(rp->p_name, "<unset>", P_NAME_LEN); strncpy(rp->p_name, "<unset>", P_NAME_LEN);
} }
return(OK); return(OK);
} }

View file

@ -28,13 +28,13 @@ message *m_ptr; /* pointer to request message */
exit_proc_nr = m_ptr->PR_PROC_NR; /* get exiting process */ exit_proc_nr = m_ptr->PR_PROC_NR; /* get exiting process */
if (exit_proc_nr != SELF) { /* PM tries to exit self */ if (exit_proc_nr != SELF) { /* PM tries to exit self */
if (! isokprocn(exit_proc_nr)) return(EINVAL); if (! isokprocn(exit_proc_nr)) return(EINVAL);
clear_proc(exit_proc_nr); /* exit a user process */ clear_proc(proc_addr(exit_proc_nr)); /* exit a user process */
return(OK); /* report back to PM */ return(OK); /* report back to PM */
} }
} }
/* The PM or some other system process requested to be exited. */ /* The PM or some other system process requested to be exited. */
clear_proc(m_ptr->m_source); clear_proc(proc_addr(m_ptr->m_source));
return(EDONTREPLY); return(EDONTREPLY);
} }
#endif /* USE_EXIT */ #endif /* USE_EXIT */

View file

@ -80,9 +80,9 @@ register message *m_ptr; /* pointer to request message */
return(EINVAL); return(EINVAL);
} else if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) { } else if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) {
return(EPERM); return(EPERM);
} else {
r = rm_irq_handler(irq_vec, irq_hooks[irq_hook_id].id);
} }
/* Remove the handler and return. */
rm_irq_handler(&irq_hooks[irq_hook_id]);
break; break;
default: default:

View file

@ -18,10 +18,10 @@ PUBLIC int do_memset(m_ptr)
register message *m_ptr; register message *m_ptr;
{ {
/* Handle sys_memset(). */ /* Handle sys_memset(). */
unsigned long pat; unsigned long p;
unsigned char c = m_ptr->MEM_CHAR; unsigned char c = m_ptr->MEM_CHAR;
pat = c | (c << 8) | (c << 16) | (c << 24); p = c | (c << 8) | (c << 16) | (c << 24);
phys_fill((phys_bytes) m_ptr->MEM_PTR, (phys_bytes) m_ptr->MEM_COUNT, pat); phys_memset((phys_bytes) m_ptr->MEM_PTR, p, (phys_bytes) m_ptr->MEM_COUNT);
return(OK); return(OK);
} }

View file

@ -3,11 +3,6 @@
typedef _PROTOTYPE( void task_t, (void) ); typedef _PROTOTYPE( void task_t, (void) );
/* Type accepted by kprintf(). This is a hack to accept both integers and
* char pointers in the same argument.
*/
typedef long karg_t; /* use largest type here */
/* Process table and system property related types. */ /* Process table and system property related types. */
typedef int proc_nr_t; /* process table entry number */ typedef int proc_nr_t; /* process table entry number */
typedef short sys_id_t; /* system process index */ typedef short sys_id_t; /* system process index */

View file

@ -1,34 +1,143 @@
/* This file contains a collection of miscellaneous procedures: /* This file contains a collection of miscellaneous procedures:
* panic abort MINIX due to a fatal error * panic: abort MINIX due to a fatal error
* kprintf: diagnostic output for the kernel
*
* Changes:
* simple printing to circular buffer (Jorrit N. Herder)
*
* This file contains the routines that take care of kernel messages, i.e.,
* diagnostic output within the kernel. Kernel messages are not directly
* displayed on the console, because this must be done by the PRINT driver.
* Instead, the kernel accumulates characters in a buffer and notifies the
* output driver when a new message is ready.
*/ */
#include "kernel.h" #include "kernel.h"
#include "assert.h"
#include <unistd.h> #include <unistd.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <signal.h>
#include <minix/com.h> #include <minix/com.h>
#define END_OF_KMESS -1
FORWARD _PROTOTYPE(void kputc, (int c));
/*===========================================================================* /*===========================================================================*
* panic * * panic *
*===========================================================================*/ *===========================================================================*/
PUBLIC void panic(s,n) PUBLIC void panic(mess,nr)
_CONST char *s; _CONST char *mess;
int n; int nr;
{ {
/* The system has run aground of a fatal kernel error. Terminate execution. */ /* The system has run aground of a fatal kernel error. Terminate execution. */
static int panicking = 0; static int panicking = 0;
if (panicking ++) return; /* prevent recursive panics */ if (panicking ++) return; /* prevent recursive panics */
if (s != NULL) { if (mess != NULL) {
kprintf("\nKernel panic: %s", karg(s)); kprintf("\nKernel panic: %s", mess);
if (n != NO_NUM) kprintf(" %d", n); if (nr != NO_NUM) kprintf(" %d", nr);
kprintf("\n",NO_NUM); kprintf("\n",NO_NUM);
} }
prepare_shutdown(RBT_PANIC); prepare_shutdown(RBT_PANIC);
} }
/*===========================================================================*
* kprintf *
*===========================================================================*/
PUBLIC void kprintf(const char *fmt, ...) /* format to be printed */
{
int c; /* next character in fmt */
unsigned long u; /* hold number argument */
int base; /* base of number arg */
int negative = 0; /* print minus sign */
static char x2c[] = "0123456789ABCDEF"; /* nr conversion table */
char ascii[8 * sizeof(long) / 3 + 2]; /* string for ascii number */
char *s = NULL; /* string to be printed */
va_list argp; /* optional arguments */
va_start(argp, fmt); /* init variable arguments */
while((c=*fmt++) != 0) {
if (c == '%') { /* expect format '%key' */
switch(c = *fmt++) { /* determine what to do */
/* Known keys are %d, %u, %x, %s, and %%. This is easily extended
* with number types like %b and %o by providing a different base.
* Number type keys don't set a string to 's', but use the general
* conversion after the switch statement.
*/
case 'd': /* output decimal */
u = va_arg(argp, int);
if (u < 0) { negative = 1; u = -u; }
base = 10;
break;
case 'u': /* output unsigned long */
u = va_arg(argp, unsigned long);
base = 10;
break;
case 'x': /* output hexadecimal */
u = va_arg(argp, unsigned long);
base = 0x10;
break;
case 's': /* output string */
s = va_arg(argp, char *);
if (s == NULL) s = "(null)";
break;
case '%': /* output percent */
s = "%";
break;
/* Unrecognized key. */
default: /* echo back %key */
s = "%?";
s[1] = c; /* set unknown key */
}
/* Assume a number if no string is set. Convert to ascii. */
if (s == NULL) {
s = ascii + sizeof(ascii)-1;
*s = 0;
do { *--s = x2c[(u % base)]; } /* work backwards */
while ((u /= base) > 0);
}
/* This is where the actual output for format "%key" is done. */
if (negative) kputc('-'); /* print sign if negative */
while(*s != 0) { kputc(*s++); } /* print string/ number */
}
else {
kputc(c); /* print and continue */
}
}
kputc(END_OF_KMESS); /* terminate output */
va_end(argp); /* end variable arguments */
}
/*===========================================================================*
* kputc *
*===========================================================================*/
PRIVATE void kputc(c)
int c; /* character to append */
{
/* Accumulate a single character for a kernel message. Send a notification
* the to PRINTF_PROC driver if an END_OF_KMESS is encountered.
*/
if (c != END_OF_KMESS) {
kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
if (kmess.km_size < KMESS_BUF_SIZE)
kmess.km_size += 1;
kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
} else {
send_sig(PRINTF_PROC, SIGKMESS);
}
}
#if TEMP_CODE #if TEMP_CODE