[comp.lang.c++] Changes for C++ on Sun 3/280

bradley@uiucdcsm.cs.uiuc.edu (02/04/88)

Many apologies for the delays in getting this out.  

Here are the modified files we used to build C++ 1.2.1 on our 3/280.
We didn't build the scratch compiler.  We used cfront on a Multimax
that already had a working version of C++ instead.  Still, the files
that follow may be helpful.  The three files that were changed were
stdio.h, task.c, and signal.h.

There were also some changes to the makefile (SHELL=/bin/sh) and to CC
(fixing basename).  These should be obvious.

One thing we noticed but haven't done anything about:  Some special
values in math.h, like MAX_FLOAT and HUGE_FLOAT (or something like
that), are different in the "native" include file that comes with the
Suns than in the file that comes with C++.  Since we're not running any
numerical applications we haven't worried about fixing these.  You may
want to look at these.

Another observation:  Don't change the putc and getc macro definitions
in stdio.h!  I tried to be clever and change them to match the Sun versions
of getc and putc.  It didn't work!  Remember that the getc and putc macros
work with the I/O routines in libC.a, not libc.a.  It's OK if they're
different.  (This cost me a lot of time!)

The stdio.h and task.c that are included below were modified by someone in
another department here at the U of I.  I'm leaving his name out on purpose
so that he doesn't get flooded with mail messages (like I have).  This
doesn't mean that we aren't grateful!


David Bradley

bradley@a.cs.uiuc.edu
Picasso Project -- "Better living through parallel processing."
Department of Computer Science
University of Illinois at Urbana-Champaign  (Where it's snowing like the
					     Dickens now.)


#! /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 the files:
#	signal.h
#	stdio.h
#	task.c
# This archive created: Wed Feb  3 15:41:38 1988
export PATH; PATH=/bin:$PATH
if test -f 'signal.h'
then
	echo shar: will not over-write existing file "'signal.h'"
else
cat << \SHAR_EOF > 'signal.h'
/*	@(#)signal.h 1.1 86/07/07 SMI; from UCB 6.7 85/06/08	*/

/*
 * Copyright (c) 1982 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

/*
 * Copyright (c) 1986 by Sun Microsystems, Inc.
 */

#ifndef	NSIG
#define NSIG	32

#define	SIGHUP	1	/* hangup */
#define	SIGINT	2	/* interrupt */
#define	SIGQUIT	3	/* quit */
#define	SIGILL	4	/* illegal instruction (not reset when caught) */
#ifdef vax
#define     ILL_RESAD_FAULT	0x0	/* reserved addressing fault */
#define     ILL_PRIVIN_FAULT	0x1	/* privileged instruction fault */
#define     ILL_RESOP_FAULT	0x2	/* reserved operand fault */
/* CHME, CHMS, CHMU are not yet given back to users reasonably */
#endif vax
#ifdef mc68000
#define     ILL_ILLINSTR_FAULT	0x10	/* illegal instruction fault */
#define     ILL_PRIVVIO_FAULT	0x20	/* privilege violation fault */
#define     ILL_COPROCERR_FAULT	0x34	/* [coprocesser protocol error fault] */
#define     ILL_TRAP1_FAULT	0x84	/* trap #1 fault */
#define     ILL_TRAP2_FAULT	0x88	/* trap #2 fault */
#define     ILL_TRAP3_FAULT	0x8c	/* trap #3 fault */
#define     ILL_TRAP4_FAULT	0x90	/* trap #4 fault */
#define     ILL_TRAP5_FAULT	0x94	/* trap #5 fault */
#define     ILL_TRAP6_FAULT	0x98	/* trap #6 fault */
#define     ILL_TRAP7_FAULT	0x9c	/* trap #7 fault */
#define     ILL_TRAP8_FAULT	0xa0	/* trap #8 fault */
#define     ILL_TRAP9_FAULT	0xa4	/* trap #9 fault */
#define     ILL_TRAP10_FAULT	0xa8	/* trap #10 fault */
#define     ILL_TRAP11_FAULT	0xac	/* trap #11 fault */
#define     ILL_TRAP12_FAULT	0xb0	/* trap #12 fault */
#define     ILL_TRAP13_FAULT	0xb4	/* trap #13 fault */
#define     ILL_TRAP14_FAULT	0xb8	/* trap #14 fault */
#endif mc68000
#define	SIGTRAP	5	/* trace trap (not reset when caught) */
#define	SIGIOT	6	/* IOT instruction */
#define	SIGEMT	7	/* EMT instruction */
#ifdef mc68000
#define     EMT_EMU1010		0x28	/* line 1010 emulator trap */
#define     EMT_EMU1111		0x2c	/* line 1111 emulator trap */
#endif mc68000
#define	SIGFPE	8	/* floating point exception */
#ifdef vax
#define     FPE_INTOVF_TRAP	0x1	/* integer overflow */
#define     FPE_INTDIV_TRAP	0x2	/* integer divide by zero */
#define     FPE_FLTOVF_TRAP	0x3	/* floating overflow */
#define     FPE_FLTDIV_TRAP	0x4	/* floating/decimal divide by zero */
#define     FPE_FLTUND_TRAP	0x5	/* floating underflow */
#define     FPE_DECOVF_TRAP	0x6	/* decimal overflow */
#define     FPE_SUBRNG_TRAP	0x7	/* subscript out of range */
#define     FPE_FLTOVF_FAULT	0x8	/* floating overflow fault */
#define     FPE_FLTDIV_FAULT	0x9	/* divide by zero floating fault */
#define     FPE_FLTUND_FAULT	0xa	/* floating underflow fault */
#endif vax
#ifdef mc68000
#define     FPE_INTDIV_TRAP	0x14	/* integer divide by zero */
#define     FPE_CHKINST_TRAP	0x18	/* CHK [CHK2] instruction */
#define     FPE_TRAPV_TRAP	0x1c	/* TRAPV [cpTRAPcc TRAPcc] instr */
#define     FPE_FLTBSUN_TRAP	0xc0	/* [branch or set on unordered cond] */
#define     FPE_FLTINEX_TRAP	0xc4	/* [floating inexact result] */
#define     FPE_FLTDIV_TRAP	0xc8	/* [floating divide by zero] */
#define     FPE_FLTUND_TRAP	0xcc	/* [floating underflow] */
#define     FPE_FLTOPERR_TRAP	0xd0	/* [floating operand error] */
#define     FPE_FLTOVF_TRAP	0xd4	/* [floating overflow] */
#define     FPE_FLTNAN_TRAP	0xd8	/* [floating Not-A-Number] */
#ifdef sun
#define     FPE_FPA_ENABLE	0x400	/* [FPA not enabled] */
#define     FPE_FPA_ERROR	0x404	/* [FPA arithmetic exception] */
#endif sun
#endif mc68000
#define	SIGKILL	9	/* kill (cannot be caught or ignored) */
#define	SIGBUS	10	/* bus error */
#define	SIGSEGV	11	/* segmentation violation */
#define	SIGSYS	12	/* bad argument to system call */
#define	SIGPIPE	13	/* write on a pipe with no one to read it */
#define	SIGALRM	14	/* alarm clock */
#define	SIGTERM	15	/* software termination signal from kill */
#define	SIGURG	16	/* urgent condition on IO channel */
#define	SIGSTOP	17	/* sendable stop signal not from tty */
#define	SIGTSTP	18	/* stop signal from tty */
#define	SIGCONT	19	/* continue a stopped process */
#define	SIGCHLD	20	/* to parent on child stop or exit */
#define	SIGCLD	20	/* System V name for SIGCHLD */
#define	SIGTTIN	21	/* to readers pgrp upon background tty read */
#define	SIGTTOU	22	/* like TTIN for output if (tp->t_local&LTOSTOP) */
#define	SIGIO	23	/* input/output possible signal */
#define	SIGPOLL	SIGIO	/* System V name for SIGIO */
#define	SIGXCPU	24	/* exceeded CPU time limit */
#define	SIGXFSZ	25	/* exceeded file size limit */
#define	SIGVTALRM 26	/* virtual time alarm */
#define	SIGPROF	27	/* profiling time alarm */
#define	SIGWINCH 28	/* window changed */
#define	SIGLOST 29	/* resource lost (eg, record-lock lost) */
#define SIGUSR1 30	/* user defined signal 1 */
#define SIGUSR2 31	/* user defined signal 2 */

#if 0
// removed to work with /usr/include/CC/signal.h   dkb
#ifndef KERNEL
int	(*signal())();
#endif !KERNEL
#endif 0

#ifndef LOCORE
/*
 * Signal vector "template" used in sigvec call.
 */
struct	sigvec {
	int	(*sv_handler)();	/* signal handler */
	int	sv_mask;		/* signal mask to apply */
	int	sv_flags;		/* see signal options below */
};
#define SV_ONSTACK	0x0001	/* take signal on signal stack */
#define SV_INTERRUPT	0x0002	/* do not restart system on signal return */
#define SV_RESETHAND	0x0004	/* reset signal handler to SIG_DFL when signal taken */
#define sv_onstack sv_flags	/* isn't compatibility wonderful! */

/*
 * Structure used in sigstack call.
 */
struct	sigstack {
	char	*ss_sp;			/* signal stack pointer */
	int	ss_onstack;		/* current status */
};

/*
 * Information pushed on stack when a signal is delivered.
 * This is used by the kernel to restore state following
 * execution of the signal handler.  It is also made available
 * to the handler to allow it to properly restore state if
 * a non-standard exit is performed.
 */
struct	sigcontext {
	int	sc_onstack;		/* sigstack state to restore */
	int	sc_mask;		/* signal mask to restore */
	int	sc_sp;			/* sp to restore */
	int	sc_pc;			/* pc to retore */
	int	sc_ps;			/* psl to restore */
};
#endif !LOCORE

#define	BADSIG		(int (*)())-1
#define	SIG_DFL		(int (*)())0
#define	SIG_IGN		(int (*)())1

#ifdef KERNEL
#define	SIG_CATCH	(int (*)())2
#define	SIG_HOLD	(int (*)())3
#endif KERNEL
#endif !NSIG

/*
 * Macro for converting signal number to a mask suitable for sigblock().
 */
#define sigmask(m)	(1 << ((m)-1))
SHAR_EOF
fi # end of overwriting check
if test -f 'stdio.h'
then
	echo shar: will not over-write existing file "'stdio.h'"
else
cat << \SHAR_EOF > 'stdio.h'
#ifndef BSD
#define BSD
#endif
/* @(#) stdio.h 1.14 2/16/87 11:02:31 */
/*ident	"@(#)cfront:incl/stdio.h	1.14"*/

#ifndef STDIOH
#define STDIOH

#define	BUFSIZ 1024
#define	_NFILE 20

# ifndef FILE
extern	struct	_iobuf {
#if vax || u3b || u3b2 || u3b5 || mc68k || mc68020 || sun
	int	_cnt;
	unsigned char	*_ptr;
#else
	unsigned char 	*_ptr;
	int 	_cnt;
#endif
	char	*_base;
#   ifdef BSD
	int	_bufsiz;
	short	_flag;
#   else
	char	_flag;
#   endif
	char	_file;
} _iob[_NFILE];
# endif

#define _IOFBF    0000
#define	_IOREAD   0001
#define	_IOWRT    0002
#define	_IONBF    0004
#define	_IOMYBUF  0010
#define	_IOEOF    0020
#define	_IOERR    0040
#define	_IOLBF    0100
#define	_IORW     0200
#define	NULL 0
#define	FILE struct _iobuf
#define	EOF (-1)

extern int _flsbuf(unsigned,FILE*);
extern int _filbuf(FILE*);

#define	stdin (&_iob[0])
#define	stdout (&_iob[1])
#define	stderr (&_iob[2])

#define	getc(p) (--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p))
#define	getchar() getc(stdin)
#define putc(x,p) (--(p)->_cnt>=0? ((int)(*(p)->_ptr++=(unsigned)(x))):_flsbuf((unsigned)(x),p))
#define	putchar(x) putc(x,stdout)
#define	feof(p) (((p)->_flag&_IOEOF)!=0)
#define	ferror(p) (((p)->_flag&_IOERR)!=0)
#define	fileno(p) ((p)->_file)

extern FILE* fopen(const char*, const char*);
extern FILE* fdopen(int, const char*);
extern FILE* freopen(const char*, const char*, FILE*);
extern long ftell(const FILE*);
extern char* fgets(char*, int, FILE*);

#define L_ctermid	9
#define L_cuserid	9
#define	P_tmpdir "/tmp/"
#define	L_tmpnam (sizeof(P_tmpdir) + 15)

extern char* gets(char*);
extern int puts(const char*);
extern int fputs(const char*, FILE*);
extern int printf(const char* ...);
extern int fprintf(FILE*, const char* ...);
extern int sprintf(char*, const char* ...);
extern int scanf(const char* ...);
extern int fscanf(FILE*, const char* ...);
extern int sscanf(char*, const char* ...);
extern int fread(char*, unsigned int, int, FILE*);
extern int fwrite(const char*, unsigned int, int, FILE*);
extern int fclose(FILE*);
extern int fflush(FILE*);
extern void clearerr(FILE*);
extern int fseek(FILE*, long, int);
extern void rewind(FILE*);
extern int getw(FILE*);
extern int fgetc(FILE*);
extern FILE* popen(const char*, const char*);
extern int pclose(FILE*);
extern int putw(int, FILE*);
extern int fputc(int, FILE*);
extern void setbuf(FILE*, char*);
extern int ungetc(int, FILE*);

extern void exit(int);
extern int abort(...);

extern int atoi(const char*);
extern double atof(const char*);
extern long atol(const char*);

#define _bufend(p)	_bufendtab[(p)->_file]
#define _bufsiz(p)	(_bufend(p) - (p)->_base)

extern FILE     *tmpfile ();
extern char	*ctermid(char*),
                *cuserid(char*),
                *tempnam(char*, char*),
                *tmpnam(char*);

extern void perror (const char*);

extern int errno;
extern char* sys_errlist[];
extern int sys_nerr;
extern unsigned char *_bufendtab[];

#endif /* STDIOH */

#ifdef ZZZ

#define	BUFSIZ	1024
#define _SBFSIZ	8
extern	struct	_iobuf {
	int	_cnt;
	unsigned char *_ptr;
	unsigned char *_base;
	int	_bufsiz;
	short	_flag;
	char	_file;		/* should be short */
} _iob[];

#define	getc(p)		(--(p)->_cnt>=0? ((int)*(p)->_ptr++):_filbuf(p))
#define	getchar()	getc(stdin)
#define putc(x,p) (--(p)->_cnt>=0? (int)(*(p)->_ptr++=(unsigned char)(x)):_flsbuf((unsigned char)(x),p))
#define	putchar(x)	putc((x),stdout)

#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'task.c'
then
	echo shar: will not over-write existing file "'task.c'"
else
cat << \SHAR_EOF > 'task.c'
/*ident	"@(#)cfront:lib/task/task.c	1.6" */

#include "task.h"

/*	macros giving the addresses of the stack frame pointer
	and the program counter of the caller of the current function
	given the first local variable

	TOP points to the top of the current stack frame
	given the last local variable
*/

#ifdef pdp11

// STACK GROWS DOWN
#define FP(p)		( (int*)(&p+4) )
#define AP()		0	/* unnecessary on pdp11 */
#define OLD_FP(fp)	(*fp)
#define TOP(var9)	(&var9)

#define COPY_STACK(f,c,t)   while (c--) *t-- = *f--
#define ACTIVE_STK_SZ(b,t)  b - t + 1	/* size of active stack */
#define STACK_BASE(b,s)     b + s - 1
#define SAVED_AREA(b,s)     b - s + 1
#define FIX_FRAME(x)\
	OLD_FP(t_framep) = int(de_fp - x)
#define SETTRAP()	t_trap = *(t_basep - t_stacksize + 1)
#define CHECKTRAP()	if (t_trap != *(t_basep-t_stacksize+1))\
				 task_error(E_STACK,0)
#endif

#ifdef sun

// STACK GROWS DOWN
#define FP(p)		( (int*)(&p+1) )
#define AP()		0	/* unnecessary on sun */
#define OLD_AP(fp)	0	/* unnecessary on sun */
#define OLD_FP(fp)	(*fp)
#define TOP(p)		( (int *) (&p) )

#define COPY_STACK(f,c,t)   while (c--) *t-- = *f--
#define ACTIVE_STK_SZ(b,t)  b - t + 1	/* size of active stack */
#define STACK_BASE(b,s)     b + s - 1
#define SAVED_AREA(b,s)     b - s + 1
#define FIX_FRAME(x)\
	OLD_FP(t_framep) = int(de_fp - x)
#define SETTRAP()	t_trap = *(t_basep - t_stacksize + 1)
#define CHECKTRAP()	if (t_trap != *(t_basep-t_stacksize+1))\
				 task_error(E_STACK,0)
#endif

#ifdef vax

// STACK GROWS DOWN
#define FP(p)		( (int*)(&p+1) )
#define AP()		0	/* unnecessary on vax */
#define OLD_AP(fp)	(*(fp+2))
#define OLD_FP(fp)	(*(fp+3))
#define TOP(p)		top(&p)
extern int * top(...);

#define COPY_STACK(f,c,t)   while (c--) *t-- = *f--
#define ACTIVE_STK_SZ(b,t)  b - t + 1	/* size of active stack */
#define STACK_BASE(b,s)     b + s - 1
#define SAVED_AREA(b,s)     b - s + 1
#define FIX_FRAME(x)\
	OLD_AP(t_framep) = int(de_ap - x);\
	OLD_FP(t_framep) = int(de_fp - x)
#define SETTRAP()	t_trap = *(t_basep - t_stacksize + 1)
#define CHECKTRAP()	if (t_trap != *(t_basep-t_stacksize+1))\
				 task_error(E_STACK,0)
#endif


#if u3b | u3b5 | u3b2 | u3b15

// STACK GROWS UP
#define FP(p)		( (int*)&p )
extern int * AP();	/* AP of current frame */
#define TOP(x)		(int*)( (int*)&x + 1 )
#ifdef u3b
asm("	.text");
asm("	.globl	AP");
asm("	.align	4");
asm("AP:");
asm("	save &0");
asm("	movw	-48(%fp),%r0  # caller's ap");
asm("	ret &0");
#define OLD_FP(fp)	( *( (int*)fp - 11 ) )
#define OLD_AP(fp)	( *( (int*)fp - 12 ) )
#else
asm("	.text");
asm("	.globl	AP");
asm("	.align	4");
asm("AP:");
asm("	save &0");
asm("	movw	-32(%fp),%r0  # caller's ap");
asm("	ret &0");
#define OLD_FP(fp)	( *( (int*)fp - 7 ) )
#define OLD_AP(fp)	( *( (int*)fp - 8 ) )
#endif

#define COPY_STACK(f,c,t)   while (c--)  *t++ = *f++
#define ACTIVE_STK_SZ(b,t)  t - b + 1	/* size of active stack */
#define STACK_BASE(b,s)     b
#define SAVED_AREA(b,s)     b
#define FIX_FRAME(x)\
	t_ap = AP() - x;\
	OLD_AP(t_framep) = int(de_ap - x);\
	OLD_FP(t_framep) = int(de_fp - x)
#define SETTRAP()	t_trap = *(t_basep + t_stacksize - 1)
#define CHECKTRAP()	if (t_trap != *(t_basep+t_stacksize-1))\
				 task_error(E_STACK,0)
#endif


// ---- END OF MACROS ----

int _hwm = 1;

class team
{
friend task;
	int	no_of_tasks;
	task*	got_stack;
	int*	stack;
	team(task*, int = 0);
};

team.team(task* t, int stacksize) {
	stacksize += sizeof(team);	// alloc team and stack together
	this = (team*)new int[stacksize];
	while (this == 0) task_error(E_STORE,0);
	stack = (int*)this + sizeof(team);
	no_of_tasks = 1;
	got_stack = t;
}


void usemainstack()
/* fudge to allow simple stack overflow check */
{
	register v[SIZE+100];

	if (_hwm)
		for (register i=0;i<SIZE+100;i++) v[i] = UNTOUCHED;
	else
		v[0] = 0;
}

void copy_stack(register* f, register c, register* t)
/*
	copy c words down from f to t
	do NOT attempt to copy "copy_stack"'s own stackframe
*/
{
	DB(("   copying( %x, %x, %x )\n", f, c, t));
	COPY_STACK(f,c,t);
	DB(("   copied\n"));
}


#define ABSV(x) ( (x) > 0 ? (x) : -(x) )
task.task(char* name, int mode, int stacksize) : (TASK)
/*
	executed in the task creating a new task - thistask.
	1:	put thistask at head of scheduler queue,
	2:	create new task
	3:	transfer execution to new task
	derived::derived can never return - its return link is destroyed

	if thistask==0 then we are executing on main()'s stack and
	should turn it into the "main" task
*/
{
	int* p;
	int* ta_fp = (int*)FP(p);
	int* de_fp = (int*)OLD_FP(ta_fp);
	int* de_ap;
	de_ap = (int*)OLD_AP(ta_fp);
	int* pa_fp = (int*)OLD_FP(de_fp);
	int x;

	DB(("%x->task::task( %s, %x, %x )\n", this,name,mode,stacksize));
	t_name = name;
	t_mode = (mode) ? mode : DEDICATED;
	t_stacksize = (stacksize) ? stacksize : SIZE;
	t_size = 0;		/* avoid stack copy at initial restore */
	t_alert = 0;
	s_state = RUNNING;
	t_next = task_chain;
	task_chain = this;
	th = this;	/* fudged return value -- "returned" from swap */

	switch ((int)thistask) {
	case 0:
		/* initialize task system by creating "main" task */
		thistask = (task*) 1;
		DB(("   thistask = new task(\"main\")\n"));
		thistask = new task("main");
		break;
	case 1:
		/*	create "main" task	*/
		usemainstack();		/* ensure that store is allocated */
		t_basep = (int*)OLD_FP(pa_fp);	/* fudge, what if main
					   	   is already deeply nested
						*/
		t_team = new team(this);	/* don't allocate stack */
		t_team->no_of_tasks = 2;   	/* never deallocate */
		return;
	}
	thistask->th = this;	/* return pointer to "child" */
	thistask->t_framep = de_fp;  /* return to caller of derived ctor */
	thistask->t_ap = de_ap;
	thistask->insert(0,this);

	switch (t_mode) {
	case DEDICATED:
		t_team = new team(this,t_stacksize);
		t_basep = STACK_BASE(t_team->stack, t_stacksize);
		if (_hwm) for (x=0; x<t_stacksize; x++)
			t_team->stack[x] = UNTOUCHED;
		thistask = this;
		DB(("%x->task::task -- ta_fp = %x\n",this,ta_fp));
		DB(("%x->task::task -- ta_ap = %x\n",this,AP()));
		x = ACTIVE_STK_SZ(pa_fp, TOP(x));
		copy_stack(pa_fp, x, t_basep);
		x = pa_fp - t_basep;	/* distance from old stack to new */
		t_framep = ta_fp - x;	/* fp on new frame */
					/* now doctor the new frame */
		DB(("  OFP(t_framep),de_fp == %x,%x\n",OLD_FP(t_framep),de_fp));
		DB(("  OAP(t_framep),de_ap == %x,%x\n",OLD_AP(t_framep),de_ap));
		FIX_FRAME(x);
		restore();
	case SHARED:
		thistask->t_mode = SHARED; /* you cannot share on your own */
		t_basep = pa_fp;
		t_team = thistask->t_team;
		t_team->no_of_tasks++;
		t_framep = ta_fp;
		t_ap = AP();
		if (mode==0 && stacksize==0)
			t_stacksize = thistask->t_stacksize
					- ABSV(thistask->t_basep - t_basep);
		thistask = this;
		SETTRAP();	// normally done in restore()
		return;
	default:
		task_error(E_TASKMODE,this);
	}
}

void task.save()
/*
	save task's state so that ``restore'' can resume it later
	by returning from the function which called "save"
		- typically the scheduler
*/
{
	int* p = (int*)FP(p);

	DB(("%x->task::save()\n",this));
	t_framep = (int*)OLD_FP(p);
	t_ap = (int*)OLD_AP(p);

	CHECKTRAP();

	if (t_mode == SHARED) {
		register int sz;
		t_size = sz = ACTIVE_STK_SZ(t_basep, TOP(p));
		p = new int[sz];
		while (p == 0) task_error(E_STORE,0);
		t_savearea = STACK_BASE(p, sz);
		copy_stack(t_basep,sz,t_savearea);
	}
}

extern int rr2,rr3,rr4;
int rr2,rr3,rr4;

swap(task*);
sswap(task*);

void task.restore()
/*
	make "this" task run after suspension by returning from the frame
	denoted by "t_framep"

	the key function "swap" is written in assembly code,
	it returns from the function which "save"d the task
		- typically the scheduler

	"sswap" copies the stack back from the save area before "swap"ing
	arguments to "sswap" are passed in rr2,rr3,rr4 to avoid overwriting them
	it is equivallent to "copystack" followed by "swap".
*/
{
	register sz;

	SETTRAP();

	DB(("%x->task::restore()\n",this));
	if ((t_mode == SHARED) && (sz=t_size)){
		register* p = SAVED_AREA(t_savearea, sz); // get ptr for delete
		register x = (this != t_team->got_stack);
		t_team->got_stack = this;
		if (x) {
			DB(("	p		= x%x\n", p));
			DB(("	t_savearea	= x%x\n", t_savearea));
			DB(("	sz		= x%x\n", sz));
			DB(("	t_basep		= x%x\n", t_basep));
			delete p;
			rr4 = (int) t_savearea;
			rr3 = sz;
			rr2 = (int) t_basep;
			sswap(this);
		}
		else
			swap(this);
	}
	else
		swap(this);
}

void task.cancel(int val)
/*
	TERMINATE and free stack space
*/
{
	DB(("%x->task::cancel( %x )\n",this,val));
	sched::cancel(val);
	if (_hwm) t_size = curr_hwm();
	if (t_team->no_of_tasks-- == 1) delete t_team;
}

task.~task()
/*
	free stack space and remove task from task chain
*/
{
	DB(("%x->task::~task()\n",this));
	if (s_state != TERMINATED) task_error(E_TASKDEL,this);
	if (this == task_chain)
		task_chain = t_next;
	else {
		register task* t;
		register task* tt;

		for (t=task_chain; tt=t->t_next; t=tt)  
			if (tt == this) {
				t->t_next = t_next;
				break;
			}
	}

	if (this == thistask) {
		delete (int*) thistask;	/* fudge: free(_that) */
		thistask = 0;
		schedule();
	}
}

void task.resultis(int val)
{
	DB(("%x->task::resultis( %x )\n",this,val));
	cancel(val);
	if (this == thistask) schedule();
}

void task.sleep()
{
	DB(("%x->task::sleep()\n",this));
	if (s_state == RUNNING) remove();
	if (this == thistask) schedule();
}

void task.delay(int d)
{
	DB(("%x->task::delay( %x )\n",this,d));
	insert(d,this);
	if (thistask == this) schedule();
}

int task.preempt()
{
	DB(("%x->task::preempt()\n",this));
	if (s_state == RUNNING) {
		remove();
		return s_time-clock;
	}
	else {
		task_error(E_TASKPRE,this);
		return 0;
	}
}

char* state_string(int s)
{
	switch (s) {
	case IDLE:		return "IDLE";
	case TERMINATED:	return "TERMINATED";
	case RUNNING:		return "RUNNING";
	default:		return 0;
	}
}

char* mode_string(int m)
{
	switch(m) {
	case SHARED:		return "SHARED";
	case DEDICATED:		return "DEDICATED";
	default:		return 0;
	}
}

void task.print(int n)
/*
	``n'' values:	CHAIN,VERBOSE,STACK
*/
{
	char* ss = state_string(s_state);
	char* ns = (t_name) ? t_name : "";
	
	printf("task %s ",ns);
	if (this == thistask)
		printf("(is thistask):\n");
	else if (ss)
		printf("(%s):\n",ss);
	else
		printf("(state==%d CORRUPTED):\n",s_state);

	if (n&VERBOSE) {
		int res = (s_state==TERMINATED) ? (int) s_time : 0;
		char* ms = mode_string(t_mode);
		if (ms == 0) ms = "CORRUPTED";
		printf("\tthis==x%x mode=%s alert=x%x next=x%x result=%d\n",
			this,ms,t_alert,t_next,res);
	}

	if (n&STACK) {
		printf("\tstack: ");
		if (s_state == TERMINATED) {
			if (_hwm) printf("hwm=x%x",t_size);
			printf(" deleted\n");
		}
		else {
			int b = (int) t_basep;
			int x = ((this==thistask) || t_mode==DEDICATED)
				? ACTIVE_STK_SZ( b, (int)t_framep ) : t_size;
			printf("max=%d current=%d",t_stacksize,x);
			if (_hwm) printf(" hwm=x%x",curr_hwm());
			printf(" t_basep=x%x, t_framep=x%x, t_size=x%x\n",
				b,t_framep,t_size);
		}
	}

	if (n&CHAIN) {
		if (t_next) t_next->print(n);
	}
}

int task.curr_hwm()
{
	int* b = t_basep;
	int i;
	for (i=t_stacksize-1; 0<=i && *(b-i)==UNTOUCHED; i--) ;
	return i;
}

int task.waitlist(object* a)
{
	return waitvec(&a);
}

int task.waitvec(object* * v)
/*
	first determine if it is necessary to sleep(),
	return hint: who caused return
*/
{
	int i = 0;
	int r;
	object* ob;

	while (ob = v[i++]) {
		t_alert = ob;
		switch (ob->o_type) {
		case TASK:
		case TIMER:
			if (((sched*)ob)->s_state == TERMINATED) goto ex;
			break;
		case QHEAD:
			if (((qhead*)ob)->rdcount()) goto ex;
			break;
		case QTAIL:
			if (((qtail*)ob)->rdspace()) goto ex;
			break;
		}
		ob->remember(this);
	}
	if (i==2 && v[0]==(object*)thistask) task_error(E_WAIT,0);
	sleep();
ex:
	i = 0;
	while (ob = v[i++]) {
		ob->forget(this);
		if (ob == t_alert) r = i-1;
	}
	return r;
} 
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0