From: Ben Gras Date: Wed, 1 Jun 2005 09:37:52 +0000 (+0000) Subject: Added args to lock() and unlock() to tell them apart, for use X-Git-Tag: v3.1.0~787 X-Git-Url: http://zhaoyanbai.com/repos/%22/xml/v3/status/static/gitweb.js?a=commitdiff_plain;h=c977bd870954adb7e7aac4bdcbafa365a9f35584;p=minix.git 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. --- diff --git a/kernel/clock.c b/kernel/clock.c index 1a10c2240..8ca80f5a9 100755 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -33,6 +33,7 @@ */ #include "kernel.h" +#include "debug.h" #include "proc.h" #include #include @@ -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; } diff --git a/kernel/const.h b/kernel/const.h index ae89e4f14..6fdb7207d 100755 --- a/kernel/const.h +++ b/kernel/const.h @@ -3,6 +3,7 @@ #include /* interrupt numbers and hardware vectors */ #include /* port addresses and magic numbers */ #include /* BIOS addresses, sizes and magic numbers */ +#include /* 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 diff --git a/kernel/debug.h b/kernel/debug.h new file mode 100644 index 000000000..3382330d4 --- /dev/null +++ b/kernel/debug.h @@ -0,0 +1,16 @@ + +#ifndef DEBUG_H +#define DEBUG_H + +#include + +#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 */ diff --git a/kernel/exception.c b/kernel/exception.c index 6f97dca54..9e49fce95 100755 --- a/kernel/exception.c +++ b/kernel/exception.c @@ -9,6 +9,7 @@ #include "kernel.h" #include #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; } diff --git a/kernel/glo.h b/kernel/glo.h index dfa59d313..fe4154b71 100755 --- a/kernel/glo.h +++ b/kernel/glo.h @@ -7,6 +7,9 @@ #define EXTERN #endif +#include "const.h" +#include + /* 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 - diff --git a/kernel/i8259.c b/kernel/i8259.c index e2781b8f2..7f60aaac5 100755 --- a/kernel/i8259.c +++ b/kernel/i8259.c @@ -7,6 +7,7 @@ #include "kernel.h" #include "proc.h" +#include "debug.h" #include #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 diff --git a/kernel/klib386.s b/kernel/klib386.s index 4bade860b..99efb682e 100755 --- a/kernel/klib386.s +++ b/kernel/klib386.s @@ -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: diff --git a/kernel/proc.c b/kernel/proc.c index d1a6cc6d7..a2be122e9 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -46,6 +46,7 @@ #include #include #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); } diff --git a/kernel/proto.h b/kernel/proto.h index 4c04b3e88..33f600918 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -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) ); diff --git a/kernel/system.c b/kernel/system.c index a60bf4e0f..4a5e581f9 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -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 */ diff --git a/kernel/system.h b/kernel/system.h index 403843f25..6f7ac9409 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -11,6 +11,7 @@ /* Common includes for the system library. */ #include +#include #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 */ diff --git a/kernel/system/clock.c b/kernel/system/clock.c index d096229ab..9a5223227 100644 --- a/kernel/system/clock.c +++ b/kernel/system/clock.c @@ -10,6 +10,7 @@ #include "../kernel.h" #include "../system.h" +#include "../debug.h" #include /*===========================================================================* @@ -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); diff --git a/kernel/system/copying.c b/kernel/system/copying.c index 3778e4ce6..566744bd2 100644 --- a/kernel/system/copying.c +++ b/kernel/system/copying.c @@ -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 diff --git a/kernel/system/debugging.c b/kernel/system/debugging.c index e683b4299..20b0f3f31 100644 --- a/kernel/system/debugging.c +++ b/kernel/system/debugging.c @@ -7,6 +7,102 @@ #include "../kernel.h" #include "../system.h" #include "../proc.h" +#include "../glo.h" +#include + +#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 */ diff --git a/kernel/system/devio.c b/kernel/system/devio.c index 0f5feb211..499148695 100644 --- a/kernel/system/devio.c +++ b/kernel/system/devio.c @@ -13,6 +13,7 @@ #include "../kernel.h" #include "../system.h" +#include "../debug.h" #include /*===========================================================================* @@ -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) diff --git a/kernel/system/misc.c b/kernel/system/misc.c index c48a2bb38..34f794667 100644 --- a/kernel/system/misc.c +++ b/kernel/system/misc.c @@ -1,6 +1,7 @@ #include "../kernel.h" #include "../system.h" #include +#include 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); } diff --git a/kernel/system/proctl.c b/kernel/system/proctl.c index 32caf06ea..42566983d 100644 --- a/kernel/system/proctl.c +++ b/kernel/system/proctl.c @@ -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.