 6f77685609
			
		
	
	
		6f77685609
		
	
	
	
	
		
			
			mainly in the kernel and headers. This split based on work by Ingmar Alting <iaalting@cs.vu.nl> done for his Minix PowerPC architecture port. . kernel does not program the interrupt controller directly, do any other architecture-dependent operations, or contain assembly any more, but uses architecture-dependent functions in arch/$(ARCH)/. . architecture-dependent constants and types defined in arch/$(ARCH)/include. . <ibm/portio.h> moved to <minix/portio.h>, as they have become, for now, architecture-independent functions. . int86, sdevio, readbios, and iopenable are now i386-specific kernel calls and live in arch/i386/do_* now. . i386 arch now supports even less 86 code; e.g. mpx86.s and klib86.s have gone, and 'machine.protected' is gone (and always taken to be 1 in i386). If 86 support is to return, it should be a new architecture. . prototypes for the architecture-dependent functions defined in kernel/arch/$(ARCH)/*.c but used in kernel/ are in kernel/proto.h . /etc/make.conf included in makefiles and shell scripts that need to know the building architecture; it defines ARCH=<arch>, currently only i386. . some basic per-architecture build support outside of the kernel (lib) . in clock.c, only dequeue a process if it was ready . fixes for new include files files deleted: . mpx/klib.s - only for choosing between mpx/klib86 and -386 . klib86.s - only for 86 i386-specific files files moved (or arch-dependent stuff moved) to arch/i386/: . mpx386.s (entry point) . klib386.s . sconst.h . exception.c . protect.c . protect.h . i8269.c
		
			
				
	
	
		
			188 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * This file contains several functions and variables used for system
 | |
|  * profiling.
 | |
|  *
 | |
|  * Statistical Profiling:
 | |
|  *   The interrupt handler for profiling clock. 
 | |
|  *
 | |
|  * Call Profiling:
 | |
|  *   The table used for profiling data and a function to get its size.
 | |
|  *
 | |
|  *   The function used by kernelspace processes to register the locations
 | |
|  *   of their control struct and profiling table.
 | |
|  *
 | |
|  * Changes:
 | |
|  *   14 Aug, 2006   Created, (Rogier Meurs)
 | |
|  */
 | |
| 
 | |
| #include <minix/config.h>
 | |
| 
 | |
| #if SPROFILE || CPROFILE
 | |
| 
 | |
| #include <minix/profile.h>
 | |
| #include <minix/portio.h>
 | |
| #include "kernel.h"
 | |
| #include "profile.h"
 | |
| #include "proc.h"
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #if SPROFILE
 | |
| 
 | |
| #include <string.h>
 | |
| 
 | |
| /* Function prototype for the profiling clock handler. */ 
 | |
| FORWARD _PROTOTYPE( int profile_clock_handler, (irq_hook_t *hook) );
 | |
| 
 | |
| /* A hook for the profiling clock interrupt handler. */
 | |
| PRIVATE irq_hook_t profile_clock_hook;
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			init_profile_clock				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC void init_profile_clock(u32_t freq)
 | |
| {
 | |
|   int r, irq;
 | |
| 
 | |
|   intr_disable();
 | |
| 
 | |
|   if((irq = arch_init_profile_clock(freq)) >= 0) {
 | |
| 	/* Register interrupt handler for statistical system profiling.  */
 | |
| 	profile_clock_hook.proc_nr_e = CLOCK;
 | |
| 	put_irq_handler(&profile_clock_hook, irq, profile_clock_handler);
 | |
| 	enable_irq(&profile_clock_hook);
 | |
|   }
 | |
| 
 | |
|   intr_enable();
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			profile_clock_stop				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC void stop_profile_clock()
 | |
| {
 | |
|   intr_disable();
 | |
|   arch_stop_profile_clock();
 | |
|   intr_enable();
 | |
| 
 | |
|   /* Unregister interrupt handler. */
 | |
|   disable_irq(&profile_clock_hook);
 | |
|   rm_irq_handler(&profile_clock_hook);
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			profile_clock_handler                           *
 | |
|  *===========================================================================*/
 | |
| PRIVATE int profile_clock_handler(hook)
 | |
| irq_hook_t *hook;
 | |
| {
 | |
| /* This executes on every tick of the CMOS timer. */
 | |
| 
 | |
|   /* Are we profiling, and profiling memory not full? */
 | |
|   if (!sprofiling || sprof_info.mem_used == -1) return (1);
 | |
| 
 | |
|   /* Check if enough memory available before writing sample. */
 | |
|   if (sprof_info.mem_used + sizeof(sprof_info) > sprof_mem_size) {
 | |
| 	sprof_info.mem_used = -1;
 | |
| 	return(1);
 | |
|   }
 | |
| 
 | |
|   /* All is OK */
 | |
| 
 | |
|   /* Idle process? */
 | |
|   if (priv(proc_ptr)->s_proc_nr == IDLE) {
 | |
| 	sprof_info.idle_samples++;
 | |
|   } else
 | |
|   /* Runnable system process? */
 | |
|   if (priv(proc_ptr)->s_flags & SYS_PROC && !proc_ptr->p_rts_flags) {
 | |
| 	/* Note: k_reenter is always 0 here. */
 | |
| 
 | |
| 	/* Store sample (process name and program counter). */
 | |
| 	phys_copy(vir2phys(proc_ptr->p_name),
 | |
| 		(phys_bytes) (sprof_data_addr + sprof_info.mem_used),
 | |
| 		(phys_bytes) strlen(proc_ptr->p_name));
 | |
| 
 | |
| 	phys_copy(vir2phys(&proc_ptr->p_reg.pc),
 | |
| 		(phys_bytes) (sprof_data_addr+sprof_info.mem_used +
 | |
| 					sizeof(proc_ptr->p_name)),
 | |
| 		(phys_bytes) sizeof(proc_ptr->p_reg.pc));
 | |
| 
 | |
| 	sprof_info.mem_used += sizeof(sprof_sample);
 | |
| 
 | |
| 	sprof_info.system_samples++;
 | |
|   } else {
 | |
| 	/* User process. */
 | |
| 	sprof_info.user_samples++;
 | |
|   }
 | |
|   
 | |
|   sprof_info.total_samples++;
 | |
| 
 | |
|   /* Acknowledge interrupt if necessary. */
 | |
|   arch_ack_profile_clock();
 | |
| 
 | |
|   return(1);                                    /* reenable interrupts */
 | |
| }
 | |
| 
 | |
| #endif /* SPROFILE */
 | |
| 
 | |
| 
 | |
| #if CPROFILE
 | |
| 
 | |
| /* 
 | |
|  * The following variables and functions are used by the procentry/
 | |
|  * procentry syslib functions when linked with kernelspace processes.
 | |
|  * For userspace processes, the same variables and function are defined
 | |
|  * elsewhere. This enables different functionality and variable sizes,
 | |
|  * which is needed is a few cases.
 | |
|  */
 | |
| 
 | |
| /* A small table is declared for the kernelspace processes. */
 | |
| struct cprof_tbl_s cprof_tbl[CPROF_TABLE_SIZE_KERNEL];
 | |
| 
 | |
| /* Function that returns table size. */
 | |
| PUBLIC int profile_get_tbl_size(void)
 | |
| {
 | |
|   return CPROF_TABLE_SIZE_KERNEL;
 | |
| }
 | |
| 
 | |
| /* Function that returns on which execution of procentry to announce. */
 | |
| PUBLIC int profile_get_announce(void)
 | |
| {
 | |
|   return CPROF_ACCOUNCE_KERNEL;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * The kernel "announces" its control struct and table locations
 | |
|  * to itself through this function.
 | |
|  */
 | |
| PUBLIC void profile_register(ctl_ptr, tbl_ptr)
 | |
| void *ctl_ptr;
 | |
| void *tbl_ptr;
 | |
| {
 | |
|   int len, proc_nr;
 | |
|   vir_bytes vir_dst;
 | |
|   struct proc *rp;                          
 | |
| 
 | |
|   /* Store process name, control struct, table locations. */
 | |
|   proc_nr = KERNEL;
 | |
|   rp = proc_addr(proc_nr);
 | |
| 
 | |
|   cprof_proc_info[cprof_procs_no].endpt = rp->p_endpoint;
 | |
|   cprof_proc_info[cprof_procs_no].name = rp->p_name;
 | |
| 
 | |
|   len = (phys_bytes) sizeof (void *);
 | |
| 
 | |
|   vir_dst = (vir_bytes) ctl_ptr;
 | |
|   cprof_proc_info[cprof_procs_no].ctl =
 | |
| 	  numap_local(proc_nr, vir_dst, len);
 | |
| 
 | |
|   vir_dst = (vir_bytes) tbl_ptr;
 | |
|   cprof_proc_info[cprof_procs_no].buf =
 | |
| 	  numap_local(proc_nr, vir_dst, len);
 | |
| 
 | |
|   cprof_procs_no++;
 | |
| }
 | |
| 
 | |
| #endif /* CPROFILE */
 | |
| 
 |