New coroutine mechanism incorporated
This commit is contained in:
		
							parent
							
								
									7b2e749b0d
								
							
						
					
					
						commit
						ebce0b4a18
					
				
					 5 changed files with 254 additions and 29 deletions
				
			
		| 
						 | 
				
			
			@ -28,7 +28,8 @@ absf.e
 | 
			
		|||
absi.c
 | 
			
		||||
absl.c
 | 
			
		||||
halt.c
 | 
			
		||||
transfer.e
 | 
			
		||||
SYSTEM.c
 | 
			
		||||
par_misc.e
 | 
			
		||||
init.c
 | 
			
		||||
sigtrp.c
 | 
			
		||||
store.c
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										118
									
								
								lang/m2/libm2/SYSTEM.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								lang/m2/libm2/SYSTEM.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,118 @@
 | 
			
		|||
/*
 | 
			
		||||
  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
			
		||||
  See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Module:	SYSTEM
 | 
			
		||||
  Author:	Ceriel J.H. Jacobs
 | 
			
		||||
  Version:	$Header$
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	An implementation of the Modula-2 NEWPROCESS and TRANSFER facilities
 | 
			
		||||
	using the topsize, topsave, and topload facilities.
 | 
			
		||||
	For each coroutine, a proc structure is built. For the main routine,
 | 
			
		||||
	a static space is declared to save its stack. For the other coroutines,
 | 
			
		||||
	the user specifies this space.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <m2_traps.h>
 | 
			
		||||
 | 
			
		||||
#if EM_WSIZE == EM_PSIZE
 | 
			
		||||
#define ptrsiz unsigned
 | 
			
		||||
#else
 | 
			
		||||
#define ptrsiz unsigned long
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MAXMAIN	2048
 | 
			
		||||
 | 
			
		||||
struct proc {
 | 
			
		||||
	ptrsiz size;		/* size of saved stackframe(s) */
 | 
			
		||||
	int (*proc)();		/* address of coroutine procedure */
 | 
			
		||||
	char *brk;		/* stack break of this coroutine */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct proc mainproc[MAXMAIN/sizeof(struct proc) + 1];
 | 
			
		||||
 | 
			
		||||
static struct proc *curproc = 0;/* current coroutine */
 | 
			
		||||
extern char *MainLB;		/* stack break of main routine */
 | 
			
		||||
 | 
			
		||||
_SYSTEM__NEWPROCESS(p, a, n, p1)
 | 
			
		||||
	int (*p)();		/* coroutine procedure */
 | 
			
		||||
	struct proc *a;		/* pointer to area for saved stack-frame */
 | 
			
		||||
	unsigned n;		/* size of this area */
 | 
			
		||||
	struct proc **p1;	/* where to leave coroutine descriptor,
 | 
			
		||||
				   in this implementation the address of
 | 
			
		||||
				   the area for saved stack-frame(s) */
 | 
			
		||||
{
 | 
			
		||||
	/*	This procedure creates a new coroutine, but does not
 | 
			
		||||
		transfer control to it. The routine "topsize" will compute the
 | 
			
		||||
		stack break, which will be the local base of this routine.
 | 
			
		||||
		Notice that we can do this because we do not need the stack
 | 
			
		||||
		above this point for this coroutine. In Modula-2, coroutines
 | 
			
		||||
		must be level 0 procedures without parameters.
 | 
			
		||||
	*/
 | 
			
		||||
	char *brk = 0;
 | 
			
		||||
	ptrsiz sz = topsize(&brk);
 | 
			
		||||
 | 
			
		||||
	if (sz + sizeof(struct proc) > n) {
 | 
			
		||||
		/* not enough space */
 | 
			
		||||
		TRP(M2_TOOLARGE);
 | 
			
		||||
	}
 | 
			
		||||
	a->size = n;
 | 
			
		||||
	a->proc = p;
 | 
			
		||||
	a->brk = brk;
 | 
			
		||||
	*p1 = a;
 | 
			
		||||
	if (topsave(brk, a+1))
 | 
			
		||||
		/* stack frame saved; now just return */
 | 
			
		||||
		;
 | 
			
		||||
	else {
 | 
			
		||||
		/* We get here through the first transfer to the coroutine
 | 
			
		||||
		   created above.
 | 
			
		||||
		   This also means that curproc is now set to this coroutine.
 | 
			
		||||
		   We cannot trust the parameters anymore.
 | 
			
		||||
		   Just call the coroutine procedure.
 | 
			
		||||
		*/
 | 
			
		||||
		(*(curproc->proc))();
 | 
			
		||||
		_exit(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_SYSTEM__TRANSFER(a, b)
 | 
			
		||||
	struct proc **a, **b;
 | 
			
		||||
{
 | 
			
		||||
	/*	transfer from one coroutine to another, saving the current
 | 
			
		||||
		descriptor in the space indicated by "a", and transfering to
 | 
			
		||||
		the coroutine in descriptor "b".
 | 
			
		||||
	*/
 | 
			
		||||
	ptrsiz size;
 | 
			
		||||
 | 
			
		||||
	if (! curproc) {
 | 
			
		||||
		/* the current coroutine is the main process;
 | 
			
		||||
		   initialize a coroutine descriptor for it ...
 | 
			
		||||
		*/
 | 
			
		||||
		mainproc[0].brk = MainLB;
 | 
			
		||||
		mainproc[0].size = sizeof(mainproc);
 | 
			
		||||
		curproc = &mainproc[0];
 | 
			
		||||
	}
 | 
			
		||||
	*a = curproc;		/* save current descriptor in "a" */
 | 
			
		||||
	if (*b == curproc) {
 | 
			
		||||
		/* transfer to itself is a no-op */
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	size = topsize(&(curproc->brk));
 | 
			
		||||
	if (size + sizeof(struct proc) > curproc->size) {
 | 
			
		||||
		TRP(M2_TOOLARGE);
 | 
			
		||||
	}
 | 
			
		||||
	if (topsave(curproc->brk, curproc+1)) {
 | 
			
		||||
		/* stack top saved. Now restore context of target
 | 
			
		||||
		   coroutine
 | 
			
		||||
		*/
 | 
			
		||||
		curproc = *b;
 | 
			
		||||
		topload(curproc+1);
 | 
			
		||||
		/* we never get here ... */
 | 
			
		||||
	}
 | 
			
		||||
	/* but we do get here, when a transfer is done to the coroutine in "a".
 | 
			
		||||
	*/
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -11,47 +11,22 @@
 | 
			
		|||
 | 
			
		||||
 mes 2,EM_WSIZE,EM_PSIZE
 | 
			
		||||
 | 
			
		||||
#define STACKSIZE	2048	/* maximum stack size for a coroutine */
 | 
			
		||||
 | 
			
		||||
 exa handler
 | 
			
		||||
 exa environ
 | 
			
		||||
 exa argv
 | 
			
		||||
 exa argc
 | 
			
		||||
 exa CurrentProcess
 | 
			
		||||
 exa MainProcess
 | 
			
		||||
 exa StackBase
 | 
			
		||||
 exa MainLB
 | 
			
		||||
 exa StackSize
 | 
			
		||||
 exp $catch
 | 
			
		||||
 exp $init
 | 
			
		||||
 inp $trap_handler
 | 
			
		||||
 | 
			
		||||
mainroutine
 | 
			
		||||
 bss 2*EM_PSIZE,0,0
 | 
			
		||||
 | 
			
		||||
 exp $m_a_i_n
 | 
			
		||||
 pro $m_a_i_n, STACKSIZE
 | 
			
		||||
 | 
			
		||||
 loc STACKSIZE
 | 
			
		||||
 ste StackSize
 | 
			
		||||
 pro $m_a_i_n, 0
 | 
			
		||||
 | 
			
		||||
 lor 0
 | 
			
		||||
 lae MainLB
 | 
			
		||||
 sti EM_PSIZE
 | 
			
		||||
 | 
			
		||||
 lal -EM_WSIZE
 | 
			
		||||
 adp EM_WSIZE
 | 
			
		||||
 lae StackBase
 | 
			
		||||
 sti EM_PSIZE
 | 
			
		||||
 | 
			
		||||
 lae mainroutine
 | 
			
		||||
 adp 2*EM_PSIZE
 | 
			
		||||
 dup EM_PSIZE
 | 
			
		||||
 lae CurrentProcess
 | 
			
		||||
 sti EM_PSIZE
 | 
			
		||||
 lae MainProcess
 | 
			
		||||
 sti EM_PSIZE
 | 
			
		||||
 | 
			
		||||
 lal EM_WSIZE+EM_PSIZE
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 lae environ		; save environment pointer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,5 +56,5 @@ extern int catch();
 | 
			
		|||
 | 
			
		||||
int (*handler)() = catch;
 | 
			
		||||
char **argv = 0, **environ = 0;
 | 
			
		||||
int argc = 0, StackSize = 0;
 | 
			
		||||
char *CurrentProcess = 0, MainProcess = 0, StackBase = 0, MainLB = 0;
 | 
			
		||||
int argc = 0;
 | 
			
		||||
char *MainLB = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										131
									
								
								lang/m2/libm2/par_misc.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								lang/m2/libm2/par_misc.e
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,131 @@
 | 
			
		|||
#
 | 
			
		||||
;
 | 
			
		||||
; (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
			
		||||
; See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
;
 | 
			
		||||
; Module:	coroutine primitives
 | 
			
		||||
; Author:	Kees Bot, Edwin Scheffer, Ceriel Jacobs
 | 
			
		||||
; Version:	$Header$
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
 mes 2,EM_WSIZE,EM_PSIZE
 | 
			
		||||
 | 
			
		||||
 ; topsize takes care of two things:
 | 
			
		||||
 ; - given a stack-break,
 | 
			
		||||
 ;   it computes the size of the chunk of memory needed to save the stack;
 | 
			
		||||
 ; - also, if this stack-break = 0, it creates one, assuming that caller is
 | 
			
		||||
 ;   the stack-break.
 | 
			
		||||
 ;
 | 
			
		||||
 ; This implementation assumes a continuous stack growing downwards
 | 
			
		||||
 | 
			
		||||
 exp $topsize
 | 
			
		||||
 pro $topsize, 2*EM_WSIZE+4*EM_PSIZE
 | 
			
		||||
 ; local space for line-number, ignoremask, filename, stack-break, size,
 | 
			
		||||
 ; and stack-pointer (see the topsave routine)
 | 
			
		||||
 mes 11
 | 
			
		||||
 lal 0
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 loi EM_PSIZE		; stack-break or 0
 | 
			
		||||
 zer EM_PSIZE
 | 
			
		||||
 cmp
 | 
			
		||||
 zne *1
 | 
			
		||||
 lxl 0
 | 
			
		||||
 dch			; local base of caller
 | 
			
		||||
 lal 0
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 sti EM_PSIZE
 | 
			
		||||
1
 | 
			
		||||
 lal 0
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 lpb			; convert this local base to an argument base.
 | 
			
		||||
			; An implementation of a sort of "topsize" EM
 | 
			
		||||
			; instruction should take a local base, and save
 | 
			
		||||
			; the whole frame.
 | 
			
		||||
 | 
			
		||||
 lor 1			; stack-break  SP
 | 
			
		||||
 sbs EM_PSIZE		; stack-break-SP
 | 
			
		||||
 ret EM_PSIZE		; return size of block to be saved
 | 
			
		||||
 end 2*EM_WSIZE+4*EM_PSIZE
 | 
			
		||||
 | 
			
		||||
 exp $topsave
 | 
			
		||||
 pro $topsave, 0
 | 
			
		||||
 mes 11
 | 
			
		||||
 loe 0
 | 
			
		||||
 lae 4			; load line number and file name
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 lim			; ignore mask
 | 
			
		||||
 lor 0			; LB
 | 
			
		||||
 lal 0
 | 
			
		||||
 loi EM_PSIZE		; stack-break
 | 
			
		||||
 lpb
 | 
			
		||||
 lor 1
 | 
			
		||||
 sbs EM_PSIZE
 | 
			
		||||
 loc EM_PSIZE
 | 
			
		||||
 adu EM_PSIZE		; gives size
 | 
			
		||||
 dup EM_PSIZE
 | 
			
		||||
 lal 0
 | 
			
		||||
 sti EM_PSIZE		; save size
 | 
			
		||||
 lor 1			; SP (the SP BEFORE pushing)
 | 
			
		||||
 lor 1			; SP (address of stack top to save)
 | 
			
		||||
 lal EM_PSIZE		; area
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 lal 0			; size
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 bls EM_PSIZE		; move whole block
 | 
			
		||||
 asp 4*EM_PSIZE+2*EM_WSIZE	; remove the lot from the stack
 | 
			
		||||
 loc 1
 | 
			
		||||
 ret EM_WSIZE			; return 1
 | 
			
		||||
 end 0
 | 
			
		||||
 | 
			
		||||
sv
 | 
			
		||||
 bss EM_PSIZE,0,0
 | 
			
		||||
 | 
			
		||||
 exp $topload
 | 
			
		||||
 pro $topload, 0
 | 
			
		||||
 | 
			
		||||
 lal 0
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 lae sv
 | 
			
		||||
 sti EM_PSIZE		; saved parameter
 | 
			
		||||
 | 
			
		||||
 lxl 0
 | 
			
		||||
2
 | 
			
		||||
 dup EM_PSIZE
 | 
			
		||||
 lal 0
 | 
			
		||||
 loi EM_PSIZE		; compare target SP with current LB to see if we must
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 cmp			; find another LB first
 | 
			
		||||
 zgt *1
 | 
			
		||||
 dch			; just follow dinamic chain to make sure we find
 | 
			
		||||
			; a legal one
 | 
			
		||||
 bra *2
 | 
			
		||||
1
 | 
			
		||||
 str 0
 | 
			
		||||
 | 
			
		||||
 lae sv
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 loi EM_PSIZE		; load indirect to
 | 
			
		||||
 str 1			; restore SP
 | 
			
		||||
 asp -EM_PSIZE		; to stop int from complaining about non-existent memory
 | 
			
		||||
 lae sv
 | 
			
		||||
 loi EM_PSIZE		; source address
 | 
			
		||||
 lor 1
 | 
			
		||||
 adp EM_PSIZE		; destimation address
 | 
			
		||||
 lae sv
 | 
			
		||||
 loi EM_PSIZE
 | 
			
		||||
 adp EM_PSIZE
 | 
			
		||||
 loi EM_PSIZE		; size of block
 | 
			
		||||
 bls EM_PSIZE		; move block back (SP becomes the SP AFTER again, 
 | 
			
		||||
			; because of the asp -EM_PSIZE!)
 | 
			
		||||
 asp 2*EM_PSIZE		; drop size + SP
 | 
			
		||||
 str 0			; restore local base
 | 
			
		||||
 sim			; ignore mask
 | 
			
		||||
 lae 4
 | 
			
		||||
 sti EM_PSIZE
 | 
			
		||||
 ste 0			; line and file
 | 
			
		||||
 loc 0
 | 
			
		||||
 ret EM_WSIZE		; return 0
 | 
			
		||||
 end 0
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue