	.include "DS.S"
#-----------------------------------------------
#	 C O N S T E L L A T I O N   O P E R A T I O N S
#-----------------------------------------------
	ARGS
	DS	ssl				# ssl switch
	DS	topo				# topology
# returns:	nothing
	PROLOC
	DL	this, ConstellationL		# this Constellation instance
	DL	thisP				# -->this Constellation
	DL	deP				# -->Debug
	DL	len
	DL	pid
	DL	stat
	DL	bad				# "some node BAD" exit indicator
	EPILOC
#-----------------------------------------------
	.global Constellation
Constellation:
	PROLOG
	lea	this(bp), b			# -->this Constellation
	mov	b, thisP(bp)			# save -->this Constellation
#	lea	this, b				# -->this inst
# set debid
	lea	Cn.debug(b), a			# -->Debug
	mov	a, deP(bp)			# save -->Debug locally
	mov	C.csP, c			# -->CS
	cmp	$Cn.ring, topo(bp)		# ring topology ?
	je	0f
	mov	C.mn(c), a			# num. of nodes
	mov	a, Cn.nodes(b)
	mov	C.mp0(c), a			# port # of fist node
	mov	a, Cn.first(b)
	movl	$Cn.mash, Cn.topo(b)
	push	$8f
	jmp	1f
0:	mov	C.rn(c), a			# num. of nodes
	mov	a, Cn.nodes(b)
	mov	C.rp0(c), a			# port # of fist node
	mov	a, Cn.first(b)
	movl	$Cn.ring, Cn.topo(b)
	push	$7f
1:	cmp	$0, ssl(bp)			# SSL ?
	jz	2f				# no
	movl	$1, Cn.ssl(b)
	addl	$500, Cn.first(b)		# first SSL port #
	push	$6f
	jmp	9f
2:	movl	$0, Cn.ssl(b)
	push	$5f
	jmp	9f
5:	.ascii	"non\0"
6:	.ascii	"\0"
7:	.ascii	"RING\0"
8:	.ascii	"MASH\0"
9:	DEBID	"%sSSL %s", 2
# check # of nodes
	movL	$0, bad(bp)
	cmp	$1, Cn.nodes(b)			# num of nodes
	jl	ConstellationR			# < 1 ? nothing to do
	jg	0f
	LOG	0, "1 node configuration not implemented yet"
	jmp	ConstellationR
0:	LOG	5, "initializing..."
# determine divisor for random next node choise
	mov     $1, a
        shl     $31, a
        not     a             			# MAX_INT
        xor     d, d
        divl    Cn.nodes(b)
        mov     a, Cn.div(b)			# save divisor (MAX_INT / nodes)
# allocate "forward" indicator shared by nodes in constellation
	push	$0
	push	$-1
	push	$0x21				# PROT_READ | PROT_WRITE
	push	$0x03				# MAP_SHARED | MAP_ANONYMOUS
	push	$4
	push	$0
	call	mmap
	cmp	$-1, a
	jne	0f
	SYSERR	"mmap"
0:	mov	thisP(bp), b
	mov	a, Cn.forwP(b)			# save -->forw
	movl	$1, (a)				# enable forwarding
	mov	C.csP, c			# -->CS
	push	C.ttl(c)
	push	Cn.nodes(b)
	LOG	1, "%d node(s), ttl=%d starting..."
# start processes for all nodes in constellation
	mov	Cn.first(b), d			# first node#
	mov	d, c
	add	Cn.nodes(b), c			# last node + 1
0:	pusha
	call	fork
	cmp	$0, a
	jnz	1f				# parent
	popa
	push	d				# node's port#
	push	b				# -->Cnstlln
	call	Node
1:	mov	a, pid(bp)
	popa
	push	pid(bp)				# nodes's pid
	push	d				# node's port#
	LOG	3, "node %u established in process %u", 2
	inc	d
	cmp	d, c				# last node ?
	jg	0b				# no, continue forking
# wait for completion of node processes
	LOG	5, "all nodes established, waiting for them to terminate..."
	movl	$0, bad(bp)
0:	lea	stat(bp), a
	cmp	$0, bad(bp)			# status still OK ?
	je	1f				# yes
	mov	Cn.forwP(b), a			# -->forward switch
	movl	$0, (a)				# disable forwarding
1:	mov	a, (sp)				# -->return status of task
	call	wait
	mov	thisP(bp), b
	cmp	$0, a				# normal return from wait?
	jl	3f				# no, all subtasks finshed
	mov	a, pid(bp)			# save subtask's pid
	mov	stat(bp), a
	test	$0x7f, a			# subtask ended by exit ?
	jnz	2f				# no, killed
	and	$0xff00, a			# extract subtask rc
	jz	1f				# rc = 0
	movl	$1, bad(bp)			# non zero rc, turn on BAD switch
1:	push	a				# rc
	push	pid(bp)				# pid
	LOG	4, "node process %u ended with exit(%d)"
	jmp	0b				# continue waiting for other subtasks
2:	movl	$1, bad(bp)			# subtask killed, turn on BAD switch
	push	pid(bp)
	LOG	4, "node process %u killed"
	jmp	0b				# continue waiting for other subtasks

# opers of all nodes finished
3:	cmp	$0, bad(bp)			# all nodes ended OK ?
	je	0f				# yes
	push	$7f
	jmp	9f
0:	push	$8f
	jmp	9f
7:	.ascii	"with ERROR\0"
8:	.ascii	"OK\0"
9:	LOG	1, "ENDED %s"
ConstellationR:
	push	bad(bp)
	call	exit
#-----------------------------------------------
	.end

