/* $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

#ident	"$Header: team.h 1.1 89/04/17 $"

/*
 * team scheduling structure
 */

#define	VOLATILE
#define	_UC	unsigned char
/* alignment on cache block boundary is essential */
struct teamblock {
	/* very volatile cache block */
	VOLATILE _UC teamsize;	/* no. processes currently in team */
	VOLATILE _UC unused1;	
	VOLATILE _UC chunk_shift;	/* shift count for chunk "divide" */
	VOLATILE _UC initial_teamsize;	/* no. iterations preassigned */
	/* word boundary */
	VOLATILE unsigned int bar_trip;	/* barrier trip counter */
	VOLATILE int tripcounter;	/* number of iterations left */
	int unused2;
	/* fairly stable cache block (seldom changed) */
	struct teamblock *free;		/* pointer free teamblock structure */
	int initial_tripcounter;	/* initial trip counter */
	VOLATILE int initial_chunk; /* chunk size for preassigned iterations */
	int static_link;		/* static link for fork proc */
	/* cache block boundary */
	/* very sensitive cache block--don't read or write unless forking
		or waiting for a fork */
	VOLATILE int (*fork_address)();	/* don't store unless new address */
	VOLATILE unsigned int fork_trip; /* address valid if == bar_trip */
	int unused3[2];
	/* cache block boundary */
	/* each processor accesses one or two cells per barrier using
		locked instructions */
	struct barrier_cell {
		_UC N;
		_UC NP;
		_UC D;
		_UC count;
		int unused[3];
	} cells[7];
	/* qued locks */
	/* cache block boundary */
	VOLATILE int teamlock;
	VOLATILE int triplock;
	VOLATILE int userlock;
	VOLATILE int userlock2;
	/* cache block boundary */
	int lock_cache_blocks[30][4];
	/* end of qued lock structure */
	/* cache block boundary */
	/* this block is usually changed only by one processor */
	struct private_cell {
		int bar_cell_offset;
		int in_team_id;
		int work_cell;	/* save old trip counter, barrier trip */
		struct teamblock *prev;	/* previous team before this one */
	} pcells[30];
};

#ifndef	lint

asm	atomic_decl(integer)
{
%mem integer;
	movl	integer,%ecx
	lock
	decl	(%ecx)
}

asm	atomic_incl(integer)
{
%mem integer;
	movl	integer,%ecx
	lock
	incl	(%ecx)
}

asm	atomic_exchange(integer, value)
{
%mem value, integer;
	movl	integer,%ecx
	movl	value, %eax
	xchgl	%eax,(%ecx)
}

asm	atomic_addl_nonzero(integer, value)
{
%mem integer, value;
	movl	value,%eax
	movl	integer,%ecx
	lock
	addl	%eax,(%ecx)
	movl	$0,%eax
	setne	%al
}

asm	atomic_addl(integer, value)
{
%mem integer, value;
	movl	integer,%ecx
	movl	value, %eax
	lock
	addl	%eax,(%ecx)
}

asm	atomic_incb(integer)
{
%mem integer;
	movl	integer,%ecx
	lock
	incb	(%ecx)
}

asm	atomic_decb(integer)
{
%mem integer;
	movl	integer,%ecx
	lock
	decb	(%ecx)
}

asm	atomic_decb_nonzero(integer)
{
%mem integer;
	movl	integer,%ecx
	subl	%eax,%eax
	lock
	decb	(%ecx)
	setne	%al
}

asm	atomic_barrier_reset(integer)
{
%mem integer;
	movl	integer,%ecx
	movw	(%ecx),%ax
	lock
	addw	%ax, 2(%ecx)
}

asm	my_return_address()
{
	movl	4(%ebp),%eax
}

asm	my_frame_pointer()
{
	movl	0(%ebp),%eax
}

asm	set_return_address(x)
{
%reg x;
	movl	x,4(%ebp)
%mem x;
	movl	x,%eax
	movl	%eax,4(%ebp)
}

asm	set_frame_pointer(x)
{
%reg x;
	movl	x,0(%ebp)
%mem x;
	movl	x,%eax
	movl	%eax,0(%ebp)
}

asm	load_stack_pointer(value)
{
%mem value;
	movl	value,%esp
}

asm	allocsp(n)
{
%mem n;
	subl	n,%esp
	movl	%esp,%eax
%reg n;
	subl	n,%esp
	movl	%esp,%eax
}
void asm	m_spin(n)
{
%mem n;
/PEEPOFF
/PEEPON
%reg n;
/PEEPOFF
/PEEPON
}
#endif	/* !lint */


extern	private	int	m_myid;


int asm _m_scan_ne(key, a, n)
{
%mem key, a, n;
	movl	key,%eax
	movl	%edi,%edx
	movl	a,%edi
	movl	n,%ecx
	cld
	repe
	scasl
	movl	%ecx,%eax
	setne	%al
	movl	%edx,%edi
}
