[comp.os.minix] profil system call implementation 1/2

veench@cs.vu.nl (Veen van CH) (03/03/88)

In this article and the following article is an implementation of the
profil system call for PC-MINIX.  All diffs are relative to MINIX 1.2.
See the README file and man pages for more information.

				Dick van Veen
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	README
#	h/callnr.h.diff
#	h/com.h.diff
#	h/type.h.diff
#	kernel/clock.c.diff
#	kernel/dmp.c.diff
#	kernel/klib88.s.diff
#	kernel/main.c.diff
#	kernel/proc.h.diff
#	kernel/system.c.diff
#	kernel/tty.c.diff
#	mm/break.c.diff
#	mm/mproc.h.diff
#	mm/param.h.diff
#	mm/table.c.diff
#	mm/utility.c.diff
# This archive created: Wed Mar 02 09:01:59 1988
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(1713 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
cat << \SHAR_EOF > 'README'
This file contains a installation description for this package.

This package implements the profil system call, monitor libraray call
and monitor system on MINIX.

All diffs are relative to MINIX 1.2.

The directories h, kernel, mm, fs contain diff files for the files
in the KERNEL, MM, FS and H directory that must be changed.
Note that the FS does not have to be changed but it must be recompiled
because the communication with the clock task has been changed.
It is not necessary to fix tty.c and dmp.c, these only define 
an extra F-key, the fix to tty.c includes ansi support.

The lib directory contains sources for the library calls monitor(),
profil() and monstartup().
Use the -LIB and -c flag of cc when compiling these sources.
The end.s and mrtso.s file must be copied to /usr/lib.
The a.out.h file must be copied to the /usr/include directory and is used 
by the programs in the src directory.
The last file to be mentioned in lib is make, this is a shell-script
that rebuilds the C-library with the new system calls included.

The directory src contains sources of the programs ast, nm, strip and prof.
In this directory are also diff files for cc.
There are 2 diff files, the first contains the diffs to the 1.1 compiler,
the second contains the diffs to the 1.2 compiler.
Note that after using these diffs, cc.c must be edited, the location of the
library and the passes of the compiler must be hard-coded.

The man directory contains the man-pages of the included programs.

IMPORTANT:
after compiling a program that must be profiled, use the command:
	ast -X a.out
to add a symbol table to the executable.
The -X removes the compiler generated symbols.

				Dick van Veen.
				veench@cs.vu.nl
SHAR_EOF
fi
echo shar: "extracting 'h/callnr.h.diff'" '(37 characters)'
if test -f 'h/callnr.h.diff'
then
	echo shar: "will not over-write existing file 'h/callnr.h.diff'"
else
cat << \SHAR_EOF > 'h/callnr.h.diff'
36a37
> #define PROFIL            44
SHAR_EOF
fi
echo shar: "extracting 'h/com.h.diff'" '(1044 characters)'
if test -f 'h/com.h.diff'
then
	echo shar: "will not over-write existing file 'h/com.h.diff'"
else
cat << \SHAR_EOF > 'h/com.h.diff'
25a26
> #	define SET_PROFIL  5	/* fnc code to CLOCK, set profile */
51,55c52,60
< #define DELTA_TICKS    m6_l1	/* alarm interval in clock ticks */
< #define FUNC_TO_CALL   m6_f1	/* pointer to function to call */
< #define NEW_TIME       m6_l1	/* value to set clock to (SET_TIME) */
< #define CLOCK_PROC_NR  m6_i1	/* which proc (or task) wants the alarm? */
< #define SECONDS_LEFT   m6_l1	/* how many seconds were remaining */
---
> #define DELTA_TICKS    m7_l1	/* alarm interval in clock ticks */
> #define FUNC_TO_CALL   m7_f1	/* pointer to function to call */
> #define NEW_TIME       m7_l1	/* value to set clock to (SET_TIME) */
> #define CLOCK_PROC_NR  m7_i1	/* which proc (or task) wants the alarm? */
> #define SECONDS_LEFT   m7_l1	/* how many seconds were remaining */
> #define PROF_BUFF      m7_p1	/* start of profile buffer in user process */
> #define PROF_BUFSIZ    m7_i2	/* size of profile buffer */
> #define PROF_OFFSET    m7_i3	/* lowest address to be profiled */
> #define PROF_SCALE     m7_i4	/* scale factor for profiling */
SHAR_EOF
fi
echo shar: "extracting 'h/type.h.diff'" '(353 characters)'
if test -f 'h/type.h.diff'
then
	echo shar: "will not over-write existing file 'h/type.h.diff'"
else
cat << \SHAR_EOF > 'h/type.h.diff'
53a54
> typedef struct {int m7i1, m7i2, m7i3, m7i4; long m7l1; int (*m7f1)(); char *m7p1;} mess_7;
64a66
> 	mess_7 m_m7;
110a113,120
> #define m7_i1  m_u.m_m7.m7i1
> #define m7_i2  m_u.m_m7.m7i2
> #define m7_i3  m_u.m_m7.m7i3
> #define m7_i4  m_u.m_m7.m7i4
> #define m7_l1  m_u.m_m7.m7l1
> #define m7_f1  m_u.m_m7.m7f1
> #define m7_p1  m_u.m_m7.m7p1
> 
SHAR_EOF
fi
echo shar: "extracting 'kernel/clock.c.diff'" '(4899 characters)'
if test -f 'kernel/clock.c.diff'
then
	echo shar: "will not over-write existing file 'kernel/clock.c.diff'"
else
cat << \SHAR_EOF > 'kernel/clock.c.diff'
8,9c8,10
<  *
<  * The input message is format m6.  The parameters are as follows:
---
>  *   SET_PROFIL:  a process wants to be profiled
>  *
>  * The input message is format m7.  The parameters are as follows:
79a81
> 	case SET_PROFIL: do_profile(&mc);	break;
85c87
<     if (opcode != CLOCK_TICK) send(mc.m_source, &mc);
---
>     if (opcode != CLOCK_TICK && opcode != SET_PROFIL) send(mc.m_source, &mc);
168a171
> 		if (rp->p_flags & P_SLOT_FREE) continue;
203,220d205
< 
< }
< 
< /*===========================================================================*
<  *				accounting				     *
<  *===========================================================================*/
< PRIVATE accounting()
< {
< /* Update user and system accounting times.  The variable 'bill_ptr' is always
<  * kept pointing to the process to charge for CPU usage.  If the CPU was in
<  * user code prior to this clock tick, charge the tick as user time, otherwise
<  * charge it as system time.
<  */
< 
<   if (prev_proc >= LOW_USER)
< 	bill_ptr->user_time++;	/* charge CPU time */
<   else
< 	bill_ptr->sys_time++;	/* charge system time */
224,241c209,296
< #ifdef i8088
< /*===========================================================================*
<  *				init_clock				     *
<  *===========================================================================*/
< PRIVATE init_clock()
< {
< /* Initialize channel 2 of the 8253A timer to e.g. 60 Hz. */
< 
<   unsigned int count, low_byte, high_byte;
< 
<   count = (unsigned) (IBM_FREQ/HZ);	/* value to load into the timer */
<   low_byte = count & BYTE;		/* compute low-order byte */
<   high_byte = (count >> 8) & BYTE;	/* compute high-order byte */
<   port_out(TIMER_MODE, SQUARE_WAVE);	/* set timer to run continuously */
<   port_out(TIMER0, low_byte);		/* load timer low byte */
<   port_out(TIMER0, high_byte);		/* load timer high byte */
< }
< #endif
---
> /*===========================================================================*
>  *				do_profile				     *
>  *===========================================================================*/
> PRIVATE do_profile(m_ptr)
> message *m_ptr;			/* pointer to request message */
> {
> /* Set profile on for named proces.
>  * The accounting is done at each clocktick for the current process.
>  */
>   register struct proc *rp;
>   extern phys_bytes umap();
> 
>   /* Copy information to proc table. */
>   rp = proc_addr(m_ptr->CLOCK_PROC_NR);
>   rp->p_buff   = m_ptr->PROF_BUFF;
>   rp->p_bufsiz = m_ptr->PROF_BUFSIZ;
>   rp->p_offset = m_ptr->PROF_OFFSET;
>   rp->p_scale  = m_ptr->PROF_SCALE;
> 
>   check_profil();
> }
> 
> /*===========================================================================*
>  *				accounting				     *
>  *===========================================================================*/
> PRIVATE accounting()
> {
> /* Update user and system accounting times.  The variable 'bill_ptr' is always
>  * kept pointing to the process to charge for CPU usage.  If the CPU was in
>  * user code prior to this clock tick, charge the tick as user time, otherwise
>  * charge it as system time.
>  */
>   register struct proc *rp;
>   register unsigned int pc;
>   long tmp;
>   unsigned int *tmpptr = (unsigned int *) &tmp;
> 
>   if (prev_proc >= LOW_USER)
> 	bill_ptr->user_time++;	/* charge CPU time */
>   else
> 	bill_ptr->sys_time++;	/* charge system time */
> 
>   rp = proc_addr(prev_proc);
>   if (rp->p_scale != 0) {
> 					/* do profile for current process */
> 	pc = ((unsigned int) rp->p_pcpsw.pc);
> 	if (pc >= rp->p_offset) {
> 		pc -= rp->p_offset;
> 		tmp = ((long) pc) * rp->p_scale;
> 		pc = (unsigned int) tmpptr[1] & ~0x01;
> 					/* make it a word boundary */
> 		if (pc <= rp->p_bufsiz) {
> 			inc_word(rp->p_map[D].mem_phys,
> 				rp->p_buff + pc);
> 		}
> 	}
>   }
> }
> 
> 
> /*===========================================================================*
>  *				check_profil				     *
>  *===========================================================================*/
> PUBLIC check_profil(rp)
> register struct proc *rp;
> {
>   if (umap(rp, D, rp->p_buff, rp->p_bufsiz) == 0) rp->p_scale = 0;
> }
> 
> 
> #ifdef i8088
> /*===========================================================================*
>  *				init_clock				     *
>  *===========================================================================*/
> PRIVATE init_clock()
> {
> /* Initialize channel 2 of the 8253A timer to e.g. 60 Hz. */
> 
>   unsigned int count, low_byte, high_byte;
> 
>   count = (unsigned) (IBM_FREQ/HZ);	/* value to load into the timer */
>   low_byte = count & BYTE;		/* compute low-order byte */
>   high_byte = (count >> 8) & BYTE;	/* compute high-order byte */
>   port_out(TIMER_MODE, SQUARE_WAVE);	/* set timer to run continuously */
>   port_out(TIMER0, low_byte);		/* load timer low byte */
>   port_out(TIMER0, high_byte);		/* load timer high byte */
> }
> #endif
SHAR_EOF
fi
echo shar: "extracting 'kernel/dmp.c.diff'" '(2941 characters)'
if test -f 'kernel/dmp.c.diff'
then
	echo shar: "will not over-write existing file 'kernel/dmp.c.diff'"
else
cat << \SHAR_EOF > 'kernel/dmp.c.diff'
99,135c99,172
< char *nayme[]= {"PRINTR", "TTY   ", "WINCHE", "FLOPPY", "RAMDSK", "CLOCK ", 
< 		"SYS   ", "HARDWR", "MM    ", "FS    ", "INIT  "};
< prname(i)
< int i;
< {
<   if (i == ANY+NR_TASKS)
< 	printf("ANY   ");
<   else if (i >= 0 && i <= NR_TASKS+2)
< 	printf("%s",nayme[i]);
<   else
< 	printf("%4d  ", i-NR_TASKS);
< }
< 
< set_name(proc_nr, ptr)
< int proc_nr;
< char *ptr;
< {
< /* When an EXEC call is done, the kernel is told about the stack pointer.
<  * It uses the stack pointer to find the command line, for dumping
<  * purposes.
<  */
< 
<   extern phys_bytes umap();
<   phys_bytes src, dst, count;
< 
<   if (ptr == (char *) 0) {
< 	aout[proc_nr] = (phys_bytes) 0;
< 	return;
<   }
< 
<   src = umap(proc_addr(proc_nr), D, ptr + 2, 2);
<   if (src == 0) return;
<   dst = umap(proc_addr(SYSTASK), D, &vargv, 2);
<   phys_copy(src, dst, 2L);
< 
<   aout[proc_nr] = umap(proc_addr(proc_nr), D, vargv, NSIZE);
< }
---
> prof_dmp()
> {
>   register struct proc *rp;
>   vir_bytes base, limit, first, last;
>   int index;
>   char *np;
>   phys_bytes ltmp, dst, umap();
> 
>   dst = umap(proc_addr(SYSTASK), D, nbuff, NSIZE);
> 
>   printf("\nPROC    BUFF  BUFSIZ  OFFSET   SCALE  ------DATA------  command\n");
>   for (rp = &proc[NR_TASKS]; rp < &proc[NR_TASKS+NR_PROCS]; rp++)  {
> 	if (rp->p_flags & P_SLOT_FREE) continue;
> 	prname(rp-proc);
> 	printf(" %5d   %5d   %5d   %5d %5d %5d %5d  ",
> 	   rp->p_buff, rp->p_bufsiz, rp->p_offset, rp->p_scale,
> 	   rp->p_map[D].mem_phys, rp->p_map[D].mem_len,
> 	   rp->p_map[D].mem_phys + rp->p_map[D].mem_len
> 	   );
> 
> 	/* Fetch the command string from the user process. */
> 	index = rp - proc - NR_TASKS;
> 	if (index > LOW_USER && aout[index] != 0) {
> 		phys_copy(aout[index], dst, (long) NSIZE);
> 		aout[NSIZE] = 0;
> 		for (np = &nbuff[0]; np < &nbuff[NSIZE]; np++)
> 			if (*np <= ' ' || *np >= 0177) *np = 0;
> 		if (index == LOW_USER + 1)
> 			printf("/bin/sh");
> 		else
> 			printf("%s", nbuff);
> 	}
> 	printf("\n");
>   }
> }
> 
> 
> char *nayme[]= {"PRINTR", "TTY   ", "WINCHE", "FLOPPY", "RAMDSK", "CLOCK ", 
> 		"SYS   ", "HARDWR", "MM    ", "FS    ", "INIT  "};
> prname(i)
> int i;
> {
>   if (i == ANY+NR_TASKS)
> 	printf("ANY   ");
>   else if (i >= 0 && i <= NR_TASKS+2)
> 	printf("%s",nayme[i]);
>   else
> 	printf("%4d  ", i-NR_TASKS);
> }
> 
> set_name(proc_nr, ptr)
> int proc_nr;
> char *ptr;
> {
> /* When an EXEC call is done, the kernel is told about the stack pointer.
>  * It uses the stack pointer to find the command line, for dumping
>  * purposes.
>  */
> 
>   extern phys_bytes umap();
>   phys_bytes src, dst, count;
> 
>   if (ptr == (char *) 0) {
> 	aout[proc_nr] = (phys_bytes) 0;
> 	return;
>   }
> 
>   src = umap(proc_addr(proc_nr), D, ptr + 2, 2);
>   if (src == 0) return;
>   dst = umap(proc_addr(SYSTASK), D, &vargv, 2);
>   phys_copy(src, dst, 2L);
> 
>   aout[proc_nr] = umap(proc_addr(proc_nr), D, vargv, NSIZE);
> }
SHAR_EOF
fi
echo shar: "extracting 'kernel/klib88.s.diff'" '(858 characters)'
if test -f 'kernel/klib88.s.diff'
then
	echo shar: "will not over-write existing file 'kernel/klib88.s.diff'"
else
cat << \SHAR_EOF > 'kernel/klib88.s.diff'
18a19
> |   inc_word:	increment a word in the data space of a user program
28a30
> .globl _inc_word
578a581,601
> |*===========================================================================*
> |*				inc_word				     *
> |*===========================================================================*
> | This routine is used to increment a word anywhere in memory.
> | The call is:
> |     inc_word(seg, off)
> | where
> |     'seg' is the value to put in es
> |     'off' is the offset from the es value
> _inc_word:
> 	push bp			| save bp
> 	mov bp,sp		| we need to access parameters
> 	push es			| save es
> 	mov es,4(bp)		| load es with segment value
> 	mov bx,6(bp)		| load bx with offset from segment
> 	seg es			| go increment the word
> 	inc (bx)		| bx points to word
> 	pop es			| restore es
> 	pop bp			| restore bp
> 	ret			| return to caller
> 
SHAR_EOF
fi
echo shar: "extracting 'kernel/main.c.diff'" '(31 characters)'
if test -f 'kernel/main.c.diff'
then
	echo shar: "will not over-write existing file 'kernel/main.c.diff'"
else
cat << \SHAR_EOF > 'kernel/main.c.diff'
173a174
>   unready(proc_ptr);
SHAR_EOF
fi
echo shar: "extracting 'kernel/proc.h.diff'" '(240 characters)'
if test -f 'kernel/proc.h.diff'
then
	echo shar: "will not over-write existing file 'kernel/proc.h.diff'"
else
cat << \SHAR_EOF > 'kernel/proc.h.diff'
22a23,27
>   vir_bytes p_buff;		/* start of profile buffer in data space */
>   vir_bytes p_bufsiz;		/* size of profile buffer */
>   vir_bytes p_offset;		/* start of profile area */
>   unsigned p_scale;		/* scale factor for profile */
> 
SHAR_EOF
fi
echo shar: "extracting 'kernel/system.c.diff'" '(130 characters)'
if test -f 'kernel/system.c.diff'
then
	echo shar: "will not over-write existing file 'kernel/system.c.diff'"
else
cat << \SHAR_EOF > 'kernel/system.c.diff'
189a190
>   check_profil(rp);
212a214
>   rp->p_scale = 0;		/* reset profile */
270a273
>   rp->p_scale = 0;		/* reset profile */
SHAR_EOF
fi
echo shar: "extracting 'kernel/tty.c.diff'" '(8093 characters)'
if test -f 'kernel/tty.c.diff'
then
	echo shar: "will not over-write existing file 'kernel/tty.c.diff'"
else
cat << \SHAR_EOF > 'kernel/tty.c.diff'
64a65
> #define MAX_ESC_PARMS      2	/* number of escape sequence parameters allowed */
74,75c75,80
< #define DEL_CODE   (char) 83	/* DEL for use in CTRL-ALT-DEL reboot */
< #define AT_SIGN         0220	/* code to yield for CTRL-@ */
---
> #define AT_SIGN         0220	/* code to yield for CTRL-@ */
> #define SCODE1            71	/* scan code for Home on numeric pad */
> #define SCODE2            81	/* scan code for PgDn on numeric pad */
> #define DEL_CODE   (char) 83	/* DEL for use in CTRL-ALT-DEL reboot */
> #define ESC       (char) 033	/* escape */
> #define BRACKET          '['	/* Part of the ESC [ letter escape seq */
78a84
> #define F3                61	/* scan code for function key F3 */
96,97c102,105
<   char tty_esc_state;		/* 0=normal, 1 = ESC seen, 2 = ESC + x seen */
<   char tty_echar;		/* first character following an ESC */
---
>   char tty_esc_state;		/* 0=normal, 1=ESC, 2=ESC[ */
>   char tty_esc_intro;		/* Distinguishing character following ESC */
>   int tty_esc_parmv[MAX_ESC_PARMS];	/* list of escape parameters */
>   int *tty_esc_parmp;		/* pointer to current escape parameter */
104c112
<   int tty_row;			/* current row (0 at bottom of screen) */
---
>   int tty_row;			/* current row (0 at top of screen) */
201a210
> char scode_map[] = {'H', 'A', 'V', 'S', 'D', 'G', 'C', 'T', 'Y', 'B', 'U'};
294,295c303,306
<   int mode, sig;
<   char make_break();
---
>   int mode, sig, scode;
>   char make_break();
> 
>   scode = ch;			/* save the scan code */
386a398,415
> 
>   /* The numeric pad generates ASCII escape sequences: ESC [ letter */
>   if (scode >= SCODE1 && scode <= SCODE2 && 
> 		shift1 == 0 && shift2 == 0 && numlock == 0 ) {
> 	/* This key is to generate a three-character escape sequence. */
> 	*tp->tty_inhead++ = ESC; /* put ESC in the input queue */
> 	if (tp->tty_inhead == &tp->tty_inqueue[TTY_IN_BYTES])
> 		tp->tty_inhead = tp->tty_inqueue;      /* handle wraparound */
> 	tp->tty_incount++;
> 	echo(tp, 'E');
> 	*tp->tty_inhead++ = BRACKET; /* put ESC in the input queue */
> 	if (tp->tty_inhead == &tp->tty_inqueue[TTY_IN_BYTES])
> 		tp->tty_inhead = tp->tty_inqueue;      /* handle wraparound */
> 	tp->tty_incount++;
> 	echo(tp, BRACKET);
> 	ch = scode_map[scode-SCODE1];	/* generate the letter */
>   }
> 
957,967c986,989
< /* Output a character on the console. Check for escape sequences, including
<  *   ESC 32+x 32+y to move cursor to (x, y)
<  *   ESC ~ 0       to clear from cursor to end of screen
<  *   ESC ~ 1       to reverse scroll the screen 1 line
<  *   ESC z x       to set the attribute byte to x (z is a literal here)
<  */
< 
<   /* Check to see if we are part way through an escape sequence. */
<   if (tp->tty_esc_state == 1) {
< 	tp->tty_echar = c;
< 	tp->tty_esc_state = 2;
---
> /* Output a character on the console.  Check for escape sequences first. */
> 
>   if (tp->tty_esc_state > 0) {
> 	parse_escape(tp, c);
971,976d992
<   if (tp->tty_esc_state == 2) {
< 	escape(tp, tp->tty_echar, c);
< 	tp->tty_esc_state = 0;
< 	return;
<   }
< 
984c1000
< 		move_to(tp, tp->tty_column, tp->tty_row + 1);
---
> 		move_to(tp, tp->tty_column, tp->tty_row - 1);
1001,1004c1017,1020
< 		if (tp->tty_row == 0) 
< 			scroll_screen(tp, GO_FORWARD);
< 		else
< 			tp->tty_row--;
---
> 		if (tp->tty_row == SCR_LINES-1) 
> 			scroll_screen(tp, GO_FORWARD);
> 		else
> 			tp->tty_row++;
1019c1035
< 		/* Ignore tab is XTABS is off--video RAM has no hardware tab */
---
> 		/* Ignore tab if XTABS is off--video RAM has no hardware tab */
1030c1046
< 		tp->tty_ramqueue[tp->tty_rwords++] = tp->tty_attribute | c;
---
> 		tp->tty_ramqueue[tp->tty_rwords++]=tp->tty_attribute|(c & BYTE);
1096c1112
< int y;				/* row (0 <= y <= 24, 0 at bottom) */
---
> int y;				/* row (0 <= y <= 24, 0 at top) */
1104c1120
<   tp->tty_vid = (tp->tty_org + 2*(SCR_LINES-1-y)*LINE_WIDTH + 2*x);
---
>   tp->tty_vid = (tp->tty_org + 2*y*LINE_WIDTH + 2*x);
1112,1148c1128,1238
< PRIVATE escape(tp, x, y)
< register struct tty_struct *tp;	/* pointer to tty struct */
< char x;				/* escape sequence is ESC x y; this is x */
< char y;				/* escape sequence is ESC x y; this is y */
< {
< /* Handle an escape sequence. */
< 
<   int n, ct, vx;
< 
< 
<   /* Check for ESC z attribute - used to change attribute byte. */
<   if (x == 'z') {
< 	/* Set attribute byte */
< 	tp->tty_attribute = y << 8;
< 	return;
<   }
<   /* Check for ESC ~ n -  used for clear screen, reverse scroll. */
<   if (x == '~') {
< 	if (y == '0') {
< 		/* Clear from cursor to end of screen */
< 		n = 2 * LINE_WIDTH * (tp->tty_row + 1) - 2 * tp->tty_column;
< 		vx = tp->tty_vid;
< 		while (n > 0) {
< 			ct = MIN(n, vid_retrace);
< 			vid_copy(NIL_PTR, vid_base, vx, ct/2);
< 			vx += ct;
< 			n -= ct;
< 		}
< 	} else if (y == '1') {
< 		/* Reverse scroll. */
< 		scroll_screen(tp, GO_BACKWARD);
< 	}
< 	return;
<   }
< 
<   /* Must be cursor movement (or invalid). */
<   move_to(tp, x - 32, y - 32);
---
> 
> PRIVATE parse_escape(tp, c)
> register struct tty_struct *tp;	/* pointer to tty struct */
> char c;				/* next character in escape sequence */
> {
> /* The following ANSI escape sequences are currently supported:
>  *   ESC M         to reverse index the screen
>  *   ESC [ y ; x H to move cursor to (x, y) [default (1,1)]
>  *   ESC [ 0 J     to clear from cursor to end of screen
>  *   ESC [ n m     to set the screen rendition
>  *			n: 0 = normal [default]
>  *			   7 = reverse
>  */
> 
>   switch (tp->tty_esc_state) {
> 	case 1: 		/* ESC seen */
> 		tp->tty_esc_intro = '\0';
> 		tp->tty_esc_parmp = tp->tty_esc_parmv;
> 		tp->tty_esc_parmv[0] = tp->tty_esc_parmv[1] = 0;
> 		switch (c) {
> 		  case '[': 	/* Control Sequence Introducer */
> 			tp->tty_esc_intro = c;
> 			tp->tty_esc_state = 2; 
> 			break;
> 		  case 'M': 	/* Reverse Index */
> 			do_escape(tp, c);
> 			break;
> 		  default: 
> 			tp->tty_esc_state = 0; 
> 			break;
> 		}
> 		break;
> 
> 	case 2: 		/* ESC [ seen */
> 		if (c >= '0' && c <= '9') {
> 			if (tp->tty_esc_parmp 
> 					< tp->tty_esc_parmv + MAX_ESC_PARMS)
> 				*tp->tty_esc_parmp =
> 				  *tp->tty_esc_parmp * 10 + (c - '0');
> 			break;
> 		}
> 		else if (c == ';') {
> 			if (++tp->tty_esc_parmp 
> 					< tp->tty_esc_parmv + MAX_ESC_PARMS)
> 				*tp->tty_esc_parmp = 0;
> 			break;
> 		}
> 		else {
> 			do_escape(tp, c);
> 		}
> 		break;
> 	default:		/* illegal state */
> 		tp->tty_esc_state = 0;
> 		break;
>   }
> }
> 
> PRIVATE do_escape(tp, c)
> register struct tty_struct *tp;	/* pointer to tty struct */
> char c;				/* next character in escape sequence */
> {
>   int n, ct, vx;
> 
>   /* Handle a sequence beginning with just ESC */
>   if (tp->tty_esc_intro == '\0') {
>     switch (c) {
> 	case 'M':		/* Reverse Index */
> 		if (tp->tty_row == 0)
> 			scroll_screen(tp, GO_BACKWARD);
> 		else
> 			tp->tty_row--;
> 		move_to(tp, tp->tty_column, tp->tty_row);
> 		break;
> 	default: break;
>     }
>   }
>   else
>   /* Handle a sequence beginning with ESC [ and parameters */
>   if (tp->tty_esc_intro == '[') {
>     switch (c) {
> 	case 'H':		/* Position cursor */
> 		move_to(tp, 
> 			MAX(1, MIN(LINE_WIDTH, tp->tty_esc_parmv[1])) - 1,
> 			MAX(1, MIN(SCR_LINES, tp->tty_esc_parmv[0])) - 1 );
> 		break;
> 	case 'J':		/* Clear from cursor to end of screen */
> 		if (tp->tty_esc_parmv[0] == 0) {
> 			n = 2 * ((SCR_LINES - (tp->tty_row + 1)) * LINE_WIDTH
> 				+ LINE_WIDTH - (tp->tty_column + 1));
> 			vx = tp->tty_vid;
> 			while (n > 0) {
> 				ct = MIN(n, vid_retrace);
> 				vid_copy(NIL_PTR, vid_base, vx, ct/2);
> 				vx += ct;
> 				n -= ct;
> 			}
> 		}
> 		break;
> 	case 'm':		/* Set graphic rendition */
>  		switch (tp->tty_esc_parmv[0]) {
>  			case 7:	tp->tty_attribute = 0160 << 8;
>  				break;
>  			default: tp->tty_attribute = 0007 << 8;
>  				break;
>  		}
> 		break;
> 	default:
> 		break;
>     }
>   }
>   tp->tty_esc_state = 0;
1247c1337
<   move_to(&tty_struct[0], 0, 0);	/* move cursor to lower left corner */
---
>   move_to(&tty_struct[0], 0, SCR_LINES-1); /* move cursor to lower left corner */
1284a1375
>   if (ch == F3) prof_dmp();	/* print profile map */
SHAR_EOF
fi
echo shar: "extracting 'mm/break.c.diff'" '(2068 characters)'
if test -f 'mm/break.c.diff'
then
	echo shar: "will not over-write existing file 'mm/break.c.diff'"
else
cat << \SHAR_EOF > 'mm/break.c.diff'
12a13
>  *   do_profil:	  perform the profil system call
32,43c33,39
<  *				do_brk  				     *
<  *===========================================================================*/
< PUBLIC int do_brk()
< {
< /* Perform the brk(addr) system call.
<  *
<  * The call is complicated by the fact that on some machines (e.g., 8088),
<  * the stack pointer can grow beyond the base of the stack segment without
<  * anybody noticing it.    For a file not using separate I & D space,
<  * the parameter, 'addr' is to the total size, text + data.  For a file using
<  * separate text and data spaces, it is just the data size. Files using
<  * separate I & D space have the SEPARATE bit in mp_flags set.
---
>  *				do_profil  				     *
>  *===========================================================================*/
> PUBLIC int do_profil()
> {
> /* Perform the profil(buff, bufsiz, offset, scale) system call.
>  *
>  * If the scale factor is 0 or 1, the profiling is turned off.
46a43,70
> 
>   rmp = mp;
>   if (scale == 1 || bufsiz < 0) /* don't allow big buffer yet */
> 	scale = 0;
>   rmp->mp_buff   = buff;	/* need info to recheck after sbrk */
>   rmp->mp_bufsiz = bufsiz;
>   rmp->mp_offset = offset;
>   rmp->mp_scale  = scale;
>   send_clock();			/* send information through to clock task */
>   return(OK);
> }
> 
> /*===========================================================================*
>  *				do_brk  				     *
>  *===========================================================================*/
> PUBLIC int do_brk()
> {
> /* Perform the brk(addr) system call.
>  *
>  * The call is complicated by the fact that on some machines (e.g., 8088),
>  * the stack pointer can grow beyond the base of the stack segment without
>  * anybody noticing it.    For a file not using separate I & D space,
>  * the parameter, 'addr' is to the total size, text + data.  For a file using
>  * separate text and data spaces, it is just the data size. Files using
>  * separate I & D space have the SEPARATE bit in mp_flags set.
>  */
> 
>   register struct mproc *rmp;
SHAR_EOF
fi
echo shar: "extracting 'mm/mproc.h.diff'" '(285 characters)'
if test -f 'mm/mproc.h.diff'
then
	echo shar: "will not over-write existing file 'mm/mproc.h.diff'"
else
cat << \SHAR_EOF > 'mm/mproc.h.diff'
21a22,27
>   /* Information for profil system call */
>   vir_bytes mp_buff;		/* start of profile buffer in data space */
>   vir_bytes mp_bufsiz;		/* size of profile buffer */
>   vir_bytes mp_offset;		/* start of profile area */
>   int mp_scale;			/* scale factor for profile */
> 
SHAR_EOF
fi
echo shar: "extracting 'mm/param.h.diff'" '(189 characters)'
if test -f 'mm/param.h.diff'
then
	echo shar: "will not over-write existing file 'mm/param.h.diff'"
else
cat << \SHAR_EOF > 'mm/param.h.diff'
2a3,4
> #define buff		mm_in.m1_p1
> #define bufsiz		mm_in.m1_i1
9c11,13
< #define pid		mm_in.m1_i1
---
> #define offset		mm_in.m1_i2
> #define pid		mm_in.m1_i1
> #define scale		mm_in.m1_i3
SHAR_EOF
fi
echo shar: "extracting 'mm/table.c.diff'" '(209 characters)'
if test -f 'mm/table.c.diff'
then
	echo shar: "will not over-write existing file 'mm/table.c.diff'"
else
cat << \SHAR_EOF > 'mm/table.c.diff'
25c25
< extern do_signal(), do_kill(), do_pause(), do_alarm();
---
> extern do_profil(), do_signal(), do_kill(), do_pause(), do_alarm();
73c73
< 	no_sys,		/* 44 = (prof)	*/
---
> 	do_profil,	/* 44 = profil	*/
SHAR_EOF
fi
echo shar: "extracting 'mm/utility.c.diff'" '(644 characters)'
if test -f 'mm/utility.c.diff'
then
	echo shar: "will not over-write existing file 'mm/utility.c.diff'"
else
cat << \SHAR_EOF > 'mm/utility.c.diff'
3a4
>  *   send_clock: send a profile message to the CLOCK task
22a24,38
>  *				send_clock				     *
>  *===========================================================================*/
> PUBLIC send_clock()
> {
> /* Make a message for the CLOCK task telling to profile a process */
>   copy_mess.m_type = SET_PROFIL;
>   copy_mess.CLOCK_PROC_NR = who;
>   copy_mess.PROF_BUFF	  = mp->mp_buff;
>   copy_mess.PROF_BUFSIZ	  = mp->mp_bufsiz;
>   copy_mess.PROF_OFFSET	  = mp->mp_offset;
>   copy_mess.PROF_SCALE	  = mp->mp_scale;
>   send(CLOCK, &copy_mess);
> }
>   
> /*===========================================================================*
SHAR_EOF
fi
exit 0
#	End of shell archive