Added args to lock() and unlock() to tell them apart, for use

when lock timing is enabled in minix/config.h.

Added phys_zero() routine to klib386.s that zeroes a range of memory, and
added corresponding system call.
This commit is contained in:
Ben Gras 2005-06-01 09:37:52 +00:00
parent b4335679cb
commit c977bd8709
17 changed files with 236 additions and 35 deletions

View file

@ -33,6 +33,7 @@
*/
#include "kernel.h"
#include "debug.h"
#include "proc.h"
#include <signal.h>
#include <minix/com.h>
@ -107,10 +108,10 @@ PUBLIC void clock_task()
receive(ANY, &m);
/* Transfer ticks seen by the low level handler. */
lock();
lock(8, "realtime");
realtime += pending_ticks;
pending_ticks = 0;
unlock();
unlock(8);
/* Handle the request. */
switch (m.m_type) {
@ -267,9 +268,9 @@ PUBLIC clock_t get_uptime()
*/
clock_t uptime;
lock();
lock(9, "get_uptime");
uptime = realtime + pending_ticks;
unlock();
unlock(9);
return(uptime);
}
@ -348,11 +349,11 @@ PUBLIC unsigned long read_clock()
*/
unsigned count;
lock();
lock(10, "read_clock");
outb(TIMER_MODE, LATCH_COUNT);
count = inb(TIMER0);
count |= (inb(TIMER0) << 8);
unlock();
unlock(10);
return count;
}

View file

@ -3,6 +3,7 @@
#include <ibm/interrupt.h> /* interrupt numbers and hardware vectors */
#include <ibm/ports.h> /* port addresses and magic numbers */
#include <ibm/bios.h> /* BIOS addresses, sizes and magic numbers */
#include <minix/config.h>
/* To translate an address in kernel space to a physical address. This is
* the same as umap_local(proc_ptr, D, vir, sizeof(*vir)), but less costly.
@ -61,9 +62,17 @@
#define IF_MASK 0x00000200
#define IOPL_MASK 0x003000
#if ENABLE_LOCK_TIMING
#define locktimestart(c, v) timer_start(c, v)
#define locktimeend(c) timer_end(c)
#else
#define locktimestart(c, v)
#define locktimeend(c)
#endif
/* Disable/Enable hardware interrupts. */
#define lock() intr_disable()
#define unlock() intr_enable()
#define lock(c, v) do { intr_disable(); locktimestart(c, v); } while(0);
#define unlock(c) do { locktimeend(c); intr_enable(); } while(0);
/* Sizes of memory tables. The boot monitor distinguishes three memory areas,
* namely low mem below 1M, 1M-16M, and mem after 16M. More chunks are needed
@ -77,3 +86,7 @@
/* M68000 specific constants go here. */
#endif /* (CHIP == M68000) */
#if ENABLE_INT_TIMING
#define INT_TIMING_BITS 12
#define INT_TIMING_ELEMENTS (1L << 12)
#endif

16
kernel/debug.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef DEBUG_H
#define DEBUG_H
#include <minix/config.h>
#if ENABLE_LOCK_TIMING
_PROTOTYPE( void timer_start, (int cat, char *name) );
_PROTOTYPE( void timer_end, (int cat) );
#endif
#if ENABLE_K_DEBUGGING /* debugging */
_PROTOTYPE( void check_runqueues, (char *when) );
#endif
#endif /* DEBUG_H */

View file

@ -9,6 +9,7 @@
#include "kernel.h"
#include <signal.h>
#include "proc.h"
#include "debug.h"
/*==========================================================================*
* exception *
@ -56,7 +57,7 @@ unsigned vec_nr;
}
if (k_reenter == 0 && ! istaskp(saved_proc)) {
unlock(); /* this is protected like sys_call() */
unlock(7); /* this is protected like sys_call() */
cause_sig(proc_nr(saved_proc), ep->signum);
return;
}

View file

@ -7,6 +7,9 @@
#define EXTERN
#endif
#include "const.h"
#include <minix/config.h>
/* MINIX' shutdown sequence uses watchdog timers to stop system services. The
* flag shutting_down must be initialized to FALSE. We rely on the compiler's
* default initialization (0) of global variables here.
@ -42,6 +45,11 @@ EXTERN irq_hook_t *irq_handlers[NR_IRQ_VECTORS];/* list of IRQ handlers */
EXTERN int irq_actids[NR_IRQ_VECTORS]; /* IRQ ID bits active */
EXTERN int irq_use; /* bit map of all in-use irq's */
/* lock() timing data. */
#if ENABLE_LOCK_TIMING
EXTERN struct lock_timedata timingdata[TIMING_CATEGORIES];
#endif
/* Miscellaneous. */
EXTERN reg_t mon_ss, mon_sp; /* monitor stack */
EXTERN int mon_return; /* true if return to the monitor possible */
@ -58,4 +66,3 @@ EXTERN _PROTOTYPE( void (*level0_func), (void) );
/* M68000 specific variables go here. */
#endif

View file

@ -7,6 +7,7 @@
#include "kernel.h"
#include "proc.h"
#include "debug.h"
#include <minix/com.h>
#define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
@ -48,7 +49,7 @@ int mine;
*/
int i;
lock();
lock(6, "intr_init");
if (machine.protected) {
/* The AT and newer PS/2 have two interrupt controllers, one master,
* one slaved at IRQ 2. (We don't have to deal with the PC that

View file

@ -26,6 +26,7 @@
.define _enable_irq ! enable an irq at the 8259 controller
.define _disable_irq ! disable an irq
.define _phys_copy ! copy data from anywhere to anywhere in memory
.define _phys_zero ! zero data anywhere in memory
.define _mem_rdw ! copy one word from [segment:offset]
.define _reset ! reset the system
.define _idle_task ! task executed when there is no work
@ -437,6 +438,36 @@ pc_small:
pop esi
ret
!*===========================================================================*
!* phys_zero *
!*===========================================================================*
! PUBLIC void phys_zero(phys_bytes source, phys_bytes bytecount);
! Zero a block of physical memory.
.align 16
_phys_zero:
push ebp
mov ebp, esp
push esi
push ebx
push ds
mov esi, 8(ebp)
mov eax, 12(ebp)
mov ebx, FLAT_DS_SELECTOR
mov ds, bx
shr eax, 2
zero_start:
mov (esi), 0
add esi, 4
dec eax
jnz zero_start
zero_done:
pop ds
pop ebx
pop esi
pop ebp
ret
!*===========================================================================*
!* mem_rdw *
@ -501,7 +532,7 @@ _level0:
!*===========================================================================*
!* read_tsc *
!*===========================================================================*
! PUBLIC void read_tsc(unsigned long *low, unsigned long *high);
! PUBLIC void read_tsc(unsigned long *high, unsigned long *low);
! Read the cycle counter of the CPU. Pentium and up.
.align 16
_read_tsc:

View file

@ -46,6 +46,7 @@
#include <minix/callnr.h>
#include <minix/com.h>
#include "proc.h"
#include "debug.h"
#include "ipc.h"
#include "sendmask.h"
@ -440,11 +441,11 @@ message *m_ptr; /* pointer to message buffer */
int result;
struct proc *caller_ptr;
lock();
lock(0, "notify");
kinfo.lock_notify ++;
caller_ptr = (k_reenter >= 0) ? proc_addr(HARDWARE) : proc_ptr;
result = mini_notify(caller_ptr, dst, m_ptr);
unlock();
unlock(0);
return(result);
}
@ -637,9 +638,9 @@ int queue;
PUBLIC void lock_pick_proc()
{
/* Safe gateway to pick_proc() for tasks. */
lock();
lock(1, "pick_proc");
pick_proc();
unlock();
unlock(1);
}
@ -652,10 +653,10 @@ message *m_ptr; /* pointer to message buffer */
{
/* Safe gateway to mini_send() for tasks. */
int result;
lock();
lock(2, "send");
kinfo.lock_send ++;
result = mini_send(proc_ptr, dst, m_ptr, NON_BLOCKING);
unlock();
unlock(2);
return(result);
}
@ -667,9 +668,9 @@ PUBLIC void lock_ready(rp)
struct proc *rp; /* this process is now runnable */
{
/* Safe gateway to ready() for tasks. */
lock();
lock(3, "ready");
ready(rp);
unlock();
unlock(3);
}
/*==========================================================================*
@ -679,9 +680,9 @@ PUBLIC void lock_unready(rp)
struct proc *rp; /* this process is no longer runnable */
{
/* Safe gateway to unready() for tasks. */
lock();
lock(4, "unready");
unready(rp);
unlock();
unlock(4);
}
/*==========================================================================*
@ -691,8 +692,8 @@ PUBLIC void lock_sched(queue)
int queue;
{
/* Safe gateway to sched() for tasks. */
lock();
lock(5, "sched");
sched(queue);
unlock();
unlock(5);
}

View file

@ -93,6 +93,7 @@ _PROTOTYPE( int disable_irq, (irq_hook_t *hook) );
_PROTOTYPE( u16_t mem_rdw, (U16_t segm, vir_bytes offset) );
_PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
phys_bytes count) );
_PROTOTYPE( void phys_zero, (phys_bytes source, phys_bytes 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_outsb, (U16_t port, phys_bytes buf, size_t count));
@ -100,7 +101,7 @@ _PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count));
_PROTOTYPE( void reset, (void) );
_PROTOTYPE( void level0, (void (*func)(void)) );
_PROTOTYPE( void monitor, (void) );
_PROTOTYPE( void read_tsc, (unsigned long *low, unsigned long *high) );
_PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low) );
/* mpx*.s */
_PROTOTYPE( void idle_task, (void) );

View file

@ -162,6 +162,7 @@ PRIVATE void initialize(void)
map(SYS_UMAP, do_umap); /* map virtual to physical address */
map(SYS_VIRCOPY, do_vircopy); /* use pure virtual addressing */
map(SYS_PHYSCOPY, do_physcopy); /* use physical addressing */
map(SYS_PHYSZERO, do_physzero); /* zero physical memory region */
map(SYS_VIRVCOPY, do_virvcopy); /* vector with copy requests */
map(SYS_PHYSVCOPY, do_physvcopy); /* vector with copy requests */

View file

@ -11,6 +11,7 @@
/* Common includes for the system library. */
#include <minix/com.h>
#include <minix/config.h>
#include "proc.h"
#include "assert.h"
@ -61,12 +62,9 @@ _PROTOTYPE( int do_trace, (message *m_ptr) ); /* process tracing */
#define do_trace do_unused
#endif
#if ENABLE_K_DEBUGGING /* debugging */
_PROTOTYPE( void check_runqueues, (char *when) );
#endif
_PROTOTYPE( int do_vircopy, (message *m_ptr) );
_PROTOTYPE( int do_physcopy, (message *m_ptr) );
_PROTOTYPE( int do_physzero, (message *m_ptr) );
_PROTOTYPE( int do_biosio, (message *m_ptr) );
#endif /* SYSTEM_H */

View file

@ -10,6 +10,7 @@
#include "../kernel.h"
#include "../system.h"
#include "../debug.h"
#include <signal.h>
/*===========================================================================*
@ -27,11 +28,10 @@ register message *m_ptr; /* pointer to request message */
proc_nr = (m_ptr->T_PROC_NR == SELF) ? m_ptr->m_source : m_ptr->T_PROC_NR;
if (isokprocn(proc_nr)) {
rp = proc_addr(m_ptr->T_PROC_NR);
lock(); /* halt the volatile time counters in rp */
lock(11, "do_times"); /* halt the volatile time counters in rp */
m_ptr->T_USER_TIME = rp->p_user_time;
m_ptr->T_SYSTEM_TIME = rp->p_sys_time;
unlock();
unlock(11);
}
m_ptr->T_BOOT_TICKS = get_uptime();
return(OK);

View file

@ -1,5 +1,5 @@
/* The system call implemented in this file:
* m_type: SYS_VIRCOPY, SYS_PHYSCOPY
* m_type: SYS_VIRCOPY, SYS_PHYSCOPY, SYS_PHYSZERO
*
* The parameters for this system call are:
* m5_c1: CP_SRC_SPACE
@ -114,6 +114,17 @@ register message *m_ptr; /* pointer to request message */
return(OK);
}
/*===========================================================================*
* do_physzero *
*===========================================================================*/
PUBLIC int do_physzero(m_ptr)
register message *m_ptr;
{
/* Handle sys_physzero(). */
phys_zero((phys_bytes) m_ptr->PZ_MEM_PTR, (phys_bytes) m_ptr->PZ_COUNT);
return(OK);
}
/* The system call implemented in this file:
* m_type: SYS_UMAP

View file

@ -7,6 +7,102 @@
#include "../kernel.h"
#include "../system.h"
#include "../proc.h"
#include "../glo.h"
#include <limits.h>
#if ENABLE_LOCK_TIMING
static unsigned long starttimes[TIMING_CATEGORIES][2];
#define HIGHCOUNT 0
#define LOWCOUNT 1
void timer_start(int cat, char *name)
{
static int init = 0;
unsigned long h, l;
int i;
if(cat < 0 || cat >= TIMING_CATEGORIES) return;
for(i = 0; i < sizeof(timingdata[0].names) && *name; i++)
timingdata[cat].names[i] = *name++;
timingdata[0].names[sizeof(timingdata[0].names)-1] = '\0';
if(starttimes[cat][HIGHCOUNT]) { return; }
if(!init) {
int t, f;
init = 1;
for(t = 0; t < TIMING_CATEGORIES; t++) {
timingdata[t].lock_timings_range[0] = 0;
timingdata[t].resets = timingdata[t].misses =
timingdata[t].measurements = 0;
}
}
read_tsc(&starttimes[cat][HIGHCOUNT], &starttimes[cat][LOWCOUNT]);
return;
}
void timer_end(int cat)
{
unsigned long h, l, d = 0, binsize;
int bin;
read_tsc(&h, &l);
if(cat < 0 || cat >= TIMING_CATEGORIES) return;
if(!starttimes[cat][HIGHCOUNT]) {
timingdata[cat].misses++;
return;
}
if(starttimes[cat][HIGHCOUNT] == h) {
d = (l - starttimes[cat][1]);
} else if(starttimes[cat][HIGHCOUNT] == h-1 &&
starttimes[cat][LOWCOUNT] > l) {
d = ((ULONG_MAX - starttimes[cat][LOWCOUNT]) + l);
} else {
timingdata[cat].misses++;
return;
}
starttimes[cat][HIGHCOUNT] = 0;
if(!timingdata[cat].lock_timings_range[0] ||
d < timingdata[cat].lock_timings_range[0] ||
d > timingdata[cat].lock_timings_range[1]) {
int t;
if(!timingdata[cat].lock_timings_range[0] ||
d < timingdata[cat].lock_timings_range[0])
timingdata[cat].lock_timings_range[0] = d;
if(!timingdata[cat].lock_timings_range[1] ||
d > timingdata[cat].lock_timings_range[1])
timingdata[cat].lock_timings_range[1] = d;
for(t = 0; t < TIMING_POINTS; t++)
timingdata[cat].lock_timings[t] = 0;
timingdata[cat].binsize =
(timingdata[cat].lock_timings_range[1] -
timingdata[cat].lock_timings_range[0])/(TIMING_POINTS+1);
if(timingdata[cat].binsize < 1)
timingdata[cat].binsize = 1;
timingdata[cat].resets++;
}
bin = (d-timingdata[cat].lock_timings_range[0]) /
timingdata[cat].binsize;
if(bin < 0 || bin >= TIMING_POINTS) {
int t;
/* this indicates a bug, but isn't really serious */
for(t = 0; t < TIMING_POINTS; t++)
timingdata[cat].lock_timings[t] = 0;
timingdata[cat].misses++;
} else {
timingdata[cat].lock_timings[bin]++;
timingdata[cat].measurements++;
}
return;
}
#endif
#if ENABLE_K_DEBUGGING /* only include code if enabled */

View file

@ -13,6 +13,7 @@
#include "../kernel.h"
#include "../system.h"
#include "../debug.h"
#include <minix/devio.h>
/*===========================================================================*
@ -171,7 +172,7 @@ register message *m_ptr; /* pointer to request message */
* batch from being interrupted. It may be cleaner to do this just around
* the for loops, but this results in rather lenghty code.
*/
lock();
lock(13, "do_vdevio");
switch (m_ptr->DIO_TYPE) {
case DIO_BYTE: /* byte values */
pvb_pairs = (pvb_pair_t *) vdevio_pv_buf;
@ -204,7 +205,7 @@ register message *m_ptr; /* pointer to request message */
outl(pvb_pairs[i].port, pvl_pairs[i].value);
}
}
unlock();
unlock(13);
/* Almost done, copy back results for input requests. */
if (DIO_INPUT == m_ptr->REQUEST)

View file

@ -1,6 +1,7 @@
#include "../kernel.h"
#include "../system.h"
#include <unistd.h>
#include <minix/config.h>
INIT_ASSERT
@ -187,6 +188,13 @@ register message *m_ptr; /* pointer to request message */
src_phys = vir2phys(&kmess);
break;
}
#if ENABLE_LOCK_TIMING
case GET_LOCKTIMING: {
length = sizeof(timingdata);
src_phys = vir2phys(timingdata);
break;
}
#endif
default:
return(EINVAL);
}

View file

@ -14,6 +14,7 @@
#if (CHIP == INTEL)
#include "../protect.h"
#endif
#include "../debug.h"
INIT_ASSERT
@ -200,6 +201,19 @@ message *m_ptr; /* pointer to request message */
if (! isokprocn(exit_proc_nr)) return(EINVAL);
rc = proc_addr(exit_proc_nr);
#if DEAD_CODE
/* If this is a user process and the PM passed in a valid parent process,
* accumulate the child times at the parent.
*/
if (isuserp(rc) && isokprocn(m_ptr->PR_PPROC_NR)) {
rp = proc_addr(m_ptr->PR_PPROC_NR);
lock(15, "do_xit");
rp->child_utime += rc->user_time + rc->child_utime;
rp->child_stime += rc->sys_time + rc->child_stime;
unlock(15);
}
#endif
/* Now call the routine to clean up of the process table slot. This cancels
* outstanding timers, possibly removes the process from the message queues,
* and resets important process table fields.