	
;---;  tasks.r  ;--------------------------------------------------------------
*
*	****	SOME NIFTY LITTLE ROUTINES FOR TASKS    ****
*
*	Author		Stefan Walter
*	Version		1.00
*	Last Revision	21.07.92
*	Identifier	tsk_defined
*	Prefix		tsk_	(task tricks)
*				 ¯    ¯¯
*	Functions	DoesTaskExist, GetTaskAddrs, FreeTaskAddrs
*			(CreateTaskInfo)
*
*	Flags		tsk_CTITOO set 1 if info creation also needed
*
;------------------------------------------------------------------------------

;------------------
	ifnd	tsk_defined
tsk_defined	=1

;------------------
tsk_oldbase	equ __base
	base	tsk_base
tsk_base:


;------------------

;------------------------------------------------------------------------------
*
* DoesTaskExist	Test if a task is still in any of the two lists or in the
*		thistask field.
*
* INPUT:	a0	Task address
*
* RESULT:	ccr	EQ if not, NE if yes
*
* NOTE		This routine should be called under Forbid() to guarantee
*		the result at the end! A Disable() is not neccessary (see
*		FindTask in the autodocs).
*
;------------------------------------------------------------------------------

;------------------
DoesTaskExist:

;------------------
; Init everything.
;
\start:	movem.l	d0/a1/a6,-(sp)
	move.l	4.w,a6

;------------------
; Check both lists and thistask.
;
\look:	move.l	420(a6),d0		;waiting
	bsr.s	\test
	move.l	406(a6),d0		;ready
	bsr.s	\test
	cmp.l	$114(a6),a0		;thistask
	beq.s	\yes2

;------------------
; Results...
;
\no:	moveq	#0,d0
\exit:	movem.l	(sp)+,d0/a1/a6
	rts

\yes:	addq.l	#4,a7
\yes2:	moveq	#-1,d0
	bra.s	\exit

;------------------
; Test subroutine.
;
\test:	move.l	d0,a1
	move.l	(a1),d0
	beq.s	\done
	cmp.l	a1,a0
	bne.s	\test
	bra.s	\yes
\done:	rts


;------------------

;------------------------------------------------------------------------------
*
* GetTaskAddrs	Smartly get the addresses of all task info blocks. Therefore a
*		block of memory is allocated to contain all blocks.
*
* RESULT:	a0	Memory block
*		d0	#of tasks or 0 if no memory available for memory
*		ccr	On d0
*
* NOTE		When the caller reads out the fields, it should test if the
*		task still exists with DoesTaskExist. There it also should test
*		the state of the task!
*
;------------------------------------------------------------------------------

;------------------
GetTaskAddrs:

;------------------
; Init everything.
;
\start:	movem.l	d1-d7/a1-a6,-(sp)
	move.l	4.w,a6

;------------------
; Now quickly count all tasks.
;
\quick:	moveq	#-1,d7			;both \count add 1 too much
	jsr	-132(a6)		;Forbid()
	move.l	406(a6),d0		;ready
	bsr.s	\count
	move.l	420(a6),d0		;waiting
	bsr.s	\count
	bra.s	\alloc

\count:	move.l	d0,a1
	addq.l	#1,d7
	move.l	(a1),d0
	bne.s	\count
	rts

;------------------
; Allocate a memory block large enough for all counters.
;
\alloc:	move.l	d7,d0
	lsl.l	#2,d0
	moveq	#1,d1
	jsr	-198(a6)		;AllocMem
	tst.l	d0
	beq.s	\fail
	move.l	d0,a5

;------------------
; Get all tasks into the list. If their number has changed in the meantime,
; call FreeTaskAddrs and go to quickcount again.
;
\in:	move.l	d7,d6
	subq.l	#1,d6
	move.l	a5,a4
	move.l	406(a6),d0		;ready
	bsr.s	\fill
	move.l	420(a6),d0		;waiting
	bsr.s	\fill
	move.l	$114(a6),(a4)

;------------------
; Results.
;
\fine:	move.l	a5,a0
	move.l	d7,d0

\exit:	jsr	-138(a6)		;Permit()
	tst.l	d0
	movem.l	(sp)+,d1-d7/a1-a6
	rts

\fail:	moveq	#0,d0
	bra.s	\exit

;------------------
; Fill in table.
;
\fill:	move.l	d0,a1
	move.l	(a1),d0
	beq.s	\done
	move.l	a1,(a4)+
	bra.s	\fill
\done:	rts


;------------------

;------------------------------------------------------------------------------
*
* FreeTaskAddrs	Free the memory block generated by GetTaskAddrs.
*
* RESULT:	a0	Memory block
*		d0	#of tasks
*
;------------------------------------------------------------------------------

;------------------
FreeTaskAddrs

;------------------
; Init everything.
;
\start:	movem.l	d0-a6,-(sp)
	move.l	4.w,a6
	move.l	a0,a1
	lsl.l	#2,d0
	jsr	-210(a6)
	movem.l	(sp)+,d0-a6
	rts


;------------------
	IFD	tsk_CTITOO

;------------------

;------------------------------------------------------------------------------
*
* CreateTaskInfo	Retrieve the standard information needed from a task
*			and prepare them for DoRawFmt and Print.
*
* INPUT:	a0	Task
*		a1	Buffer (80 bytes)
*
* RESULT	a0	Task
*		a1	DoRawFmt buffer
*		d0	0 if this task no longer exists, -1 if okay
*		ccr	on d0
*
;------------------------------------------------------------------------------

;------------------
CreateTaskInfo:

;------------------
; Init everything.
;
\start:	movem.l	d1-a6,-(sp)
	move.l	4.w,a6
	jsr	-132(a6)		;Forbid()
	lea	6*4(a1),a3

\exist:	bsr	DoesTaskExist
	beq	\fail

\gadr:	move.l	a0,(a1)+		;task address
	lea	tsk_objnames(pc),a2
	cmp.b	#13,8(a0)
	seq	d6
	bne.s	\gobj
	addq.l	#8,a2

\gobj:	move.l	a2,(a1)+
	moveq	#0,d0
	move.b	15(a0),d0
	cmp.b	#6,d0
	bls.s	\gstat
	moveq	#0,d0

\gstat:	mulu	#10,d0
	pea	tsk_statenames(pc)
	add.l	(sp)+,d0
	move.l	d0,(a1)+

\spri:	move.b	9(a0),d0
	ext.w	d0
	ext.l	d0
	move.l	d0,(a1)+
	
\gpri:	move.l	a3,(a1)+
	move.l	#"---"*256,(a3)+
	moveq	#0,d7
	tst.b	d6
	beq.s	\ncli
	tst.l	$8c(a0)
	beq.s	\ncli
	moveq	#-1,d7
	subq.l	#4,a3
	movem.l	d0-a5,-(sp)
	lea	$8c(a0),a1
	lea	tsk_dectext(pc),a0
	lea	\setin(pc),a2
	jsr	-522(a6)		;RawDoFmt()
	movem.l	(sp)+,d0-a5
\fz:	tst.b	(a3)+
	bne.s	\fz
	bra.s	\ncli

\setin:	move.b	d0,(a3)+
	rts

\ncli:	move.l	a3,(a1)+
	move.l	10(a0),a2
	move.w	tsk_namelen(pc),d5	;40 chars (-1 for 0)

\ct:	tst.b	(a2)
	beq.s	\cted
	move.b	(a2)+,d0
	bsr.s	\pbyt
	bra.s	\ct

\pbyt:	tst.b	d5
	beq.s	\pbyte
	cmp.b	#$d,d0
	beq.s	\pbyte
	cmp.b	#$a,d0
	beq.s	\pbyte
	subq.b	#1,d5
	cmp.b	#$d,d0
	beq.s	\pbyte
	move.b	d0,(a3)+
\pbyte:	rts

\cted:	tst.b	d7
	beq.s	\gname
	moveq	#" ",d0
	bsr.s	\pbyt
	moveq	#"[",d0
	bsr.s	\pbyt
	move.l	$ac(a0),d0
	lsl.l	#2,d0
	move.l	d0,a2
	move.l	$10(a2),d0
	lsl.l	#2,d0
	move.l	d0,a2
	move.b	(a2)+,d1
\cc:	tst.b	d1
	beq.s	\cced
	subq.b	#1,d1
	move.b	(a2)+,d0	
	bsr.s	\pbyt
	bra.s	\cc

\cced:	moveq	#"]",d0
	bsr.s	\pbyt
\gname:	clr.b	(a3)

\okay:	moveq	#-1,d0
\exit:	jsr	-138(a6)		;Permit()
	tst.l	d0
	movem.l	(sp)+,d1-a6
	rts

\fail:	moveq	#0,d0
	bra.s	\exit

;------------------

;--------------------------------------------------------------------

;------------------
tsk_statenames:	dc.b	"invalid  ",0
		dc.b	"added    ",0
		dc.b	"running  ",0
		dc.b	"ready    ",0
		dc.b	"waiting  ",0
		dc.b	"exception",0
		dc.b	"removed  ",0

tsk_objnames:	dc.b	"task   ",0
		dc.b	"process",0

tsk_dectext:	dc.b	"%3ld",0
		even

tsk_namelen:	dc.w	80		;change by software

;------------------
	ENDIF
;------------------

;--------------------------------------------------------------------

;------------------
	base	tsk_oldbase

;------------------
	endif

	end

