/*
 *	cifccsp.h -- types/wotnot for the C interface to CCSP
 *	Copyright (C) 2002-2003 Fred Barnes <frmb2@ukc.ac.uk>
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; either version 2 of the License, or
 *	(at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program; if not, write to the Free Software
 *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef __CIFCCSP_H
#define __CIFCCSP_H

#ifdef __cplusplus
extern "C" {
#endif

/*{{{  some types */
typedef int Process;
typedef int Channel;
typedef void *MProcess;
#ifndef CIF_NO_TIMEDEF
typedef int Time;		/* regular occam time (us) */
#endif

typedef struct TAG_CTSem {	/* semaphore type (used by mobile channels) */
	void *fptr;
	void *bptr;
} CTSem;

typedef struct TAG_MBarrier {	/* mobile barrier type */
	int ecount;
	int scount;
	void *fptr;
	void *bptr;
	int refcount;
} MBarrier;

/*}}}*/
/*{{{  extern declarations*/
/* these are nasty.. */
extern int PPriority;		/* CCSP priority word */
/* us */
extern Process *cifccsp_wptr;	/* VERY MUCH NOT SMP SAFE! */
extern void *cifccsp_savevar;	/* likewise */


#ifdef HOSTOS_CYGWIN
#define CIFCCSP_WPTR "_cifccsp_wptr"
#define EXTERNAL_KILLCALL "__killcall"
#else	/* !HOSTOS_CYGWIN */
#define CIFCCSP_WPTR "cifccsp_wptr"
#define EXTERNAL_KILLCALL "_killcall"
#endif

/*}}}*/

/*
 * FIXME: we (expensively) push and pop ebp in here.  All the
 * version of my gcc compiler (2.95.4, 3.0.4 and 3.2.1-20021020)
 * don't respect "ebp" in the clobbered registers.  I'm compiling
 * with the -fomit-frame-pointer flag, which may be responsible
 * for some of this.  Maybe this is a known gcc bug...?
 */

/* plus, if optimisation is on, gcc expects input operands to
 * be preserved.  They're not, but we can't clobber them either.
 * hence these silly dummy values for output constraints (which
 * stops gcc expecting them to be preserved)
 */

/* assuming GNU C... */

/*
 * note: the API is taken from Jim's CCSP definitions in his Ph.D. thesis
 * extended with the new stuff
 */

/*
 * further point: this stuff will require FASTCALLS to be enabled in CCSP
 * in order to link properly (shouldn't be an issue, as that's the default
 * build anyway).
 */

/* separate compilation for the ASM just breaks things.. :(  need very explicit constraints */
/*{{{  ASM macros */
#define CIF_SAVE_OCCAM_STATE \
	"	movl	%%esp, 24(%%ebp)			\n" \
	"	movl	%%esi, 32(%%ebp)			\n" \
	"	movl	%%edi, 36(%%ebp)			\n"
#define CIF_RESTORE_OCCAM_STATE \
	"	movl	24(%%ebp), %%esp			\n" \
	"	movl	32(%%ebp), %%esi			\n" \
	"	movl	36(%%ebp), %%edi			\n"
#define CIF_SAVE_C_STATE \
	"	movl	" CIFCCSP_WPTR ", %%ebp			\n" \
	"	movl	$0, " CIFCCSP_WPTR "			\n" \
	"	movl	%%esp, 16(%%ebp)			\n" \
	"	movl	$0f, 28(%%ebp)				\n"
/*}}}*/
/*{{{  occstub_ChanOutChar(C,V) */
#if 0
#define occstub_ChanOutChar(C,V) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%ebx		# chan addr		\n" \
	"	pushl	%%eax		# value			\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_outbyte				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (V), "b" (C) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
#endif

#define occstub_ChanOutChar(C,V) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_Y_outbyte				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (V), "b" (C) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)

/*}}}*/
/*{{{  occstub_ChanInChar(C,P) */
#if 0
#define occstub_ChanInChar(C,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%eax		# dest addr		\n" \
	"	pushl	%%ebx		# chan addr		\n" \
	"	pushl	$1		# count			\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_in					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (P), "b" (C) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
#endif

#define occstub_ChanInChar(C,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_Y_in8					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (C), "b" (P) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)

/*}}}*/
/*{{{  occstub_ChanOutInt(C,V) */
#if 0
#define occstub_ChanOutInt(C,V) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%ebx		# chan addr		\n" \
	"	pushl	%%eax		# value			\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_outword				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (V), "b" (C) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
#endif

#define occstub_ChanOutInt(C,V) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_Y_outword				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (V), "b" (C) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)


/*}}}*/
/*{{{  occstub_ChanInInt(C,P) */
#if 0
#define occstub_ChanInInt(C,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%eax		# dest addr		\n" \
	"	pushl	%%ebx		# chan addr		\n" \
	"	pushl	$4		# count			\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_in					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (P), "b" (C) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
#endif

#define occstub_ChanInInt(C,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_Y_in32					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (C), "b" (P) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)


/*}}}*/
/*{{{  occstub_ChanOut(C,P,L) */
#if 0
#define occstub_ChanOut(C,P,L) \
	do { int CIF_dummy1, CIF_dummy2, CIF_dummy3; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%ebx		# dest addr		\n" \
	"	pushl	%%ecx		# chan addr		\n" \
	"	pushl	%%eax		# count			\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_out					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2), "=c" (CIF_dummy3) /* no outputs */ \
	: "a" (L), "b" (P), "c" (C) \
	: "edx", "esi", "edi", "cc", "memory"); } while (0)
#else
#define occstub_ChanOut(C,P,L) \
	do { int CIF_dummy1, CIF_dummy2, CIF_dummy3; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_Y_out					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2), "=c" (CIF_dummy3) /* no outputs */ \
	: "a" (L), "b" (C), "c" (P) \
	: "edx", "esi", "edi", "cc", "memory"); } while (0)
#endif
/*}}}*/
/*{{{  occstub_FastChanOut(C,P,L)*/
#define occstub_FastChanOut(C,P,L) \
	do { int CIF_dummy1, CIF_dummy2, CIF_dummy3; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_Y_fastout				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2), "=c" (CIF_dummy3) /* no outputs */ \
	: "a" (L), "b" (C), "c" (P) \
	: "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanIn(C,P,L) */
#if 0
#define occstub_ChanIn(C,P,L) \
	do { int CIF_dummy1, CIF_dummy2, CIF_dummy3; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%ebx		# dest addr		\n" \
	"	pushl	%%ecx		# chan addr		\n" \
	"	pushl	%%eax		# count			\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_in					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2), "=c" (CIF_dummy3) /* no outputs */ \
	: "a" (L), "b" (P), "c" (C) \
	: "edx", "esi", "edi", "cc", "memory"); } while (0)
#endif

#define occstub_ChanIn(C,P,L) \
	do { int CIF_dummy1, CIF_dummy2, CIF_dummy3; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_Y_in					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2), "=c" (CIF_dummy3) /* no outputs */ \
	: "a" (L), "b" (C), "c" (P) \
	: "edx", "esi", "edi", "cc", "memory"); } while (0)


/*}}}*/
/*{{{  occstub_FastChanIn(C,P,L)*/
#define occstub_FastChanIn(C,P,L) \
	do { int CIF_dummy1, CIF_dummy2, CIF_dummy3; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_Y_fastin				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2), "=c" (CIF_dummy3) /* no outputs */ \
	: "a" (L), "b" (C), "c" (P) \
	: "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ForkProcess(WP) */
#define occstub_ForkProcess(WP) \
	do { int CIF_dummy1; ((int *)WP)[-1] = (int)occstub_fork_entry; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, %%ebx		\n" \
	"	jmp	_Y_runp					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1) /* no outputs */ \
	: "a" (WP) \
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanMOut(C,P)*/
#define occstub_ChanMOut(C,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_X_mout					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (C), "b" (P) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanMIn(C,P)*/
#define occstub_ChanMIn(C,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_X_min					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (C), "b" (P) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanMOut64(C,P)*/
#define occstub_ChanMOut64(C,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_X_mout64				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (C), "b" (P) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanMIn64(C,P)*/
#define occstub_ChanMIn64(C,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_X_min64				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (C), "b" (P) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanMInN(C,P,WC)*/
#define occstub_ChanMInN(C,P,WC) \
	do { int CIF_dummy1, CIF_dummy2, CIF_dummy3; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_X_minn					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2), "=c" (CIF_dummy3) /* no outputs */ \
	: "a" (WC), "b" (C), "c" (P) \
	: "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanMOutN(C,P,WC)*/
#define occstub_ChanMOutN(C,P,WC) \
	do { int CIF_dummy1, CIF_dummy2, CIF_dummy3; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_X_moutn				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2), "=c" (CIF_dummy3) /* no outputs */ \
	: "a" (WC), "b" (C), "c" (P) \
	: "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanXAble(C)*/
#define occstub_ChanXAble(C) \
	do { int CIF_dummy1; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_X_xable				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1) /* no outputs */ \
	: "a" (C) \
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanXIn(C,P,L) */
#define occstub_ChanXIn(C,P,L) \
	do { int CIF_dummy1, CIF_dummy2, CIF_dummy3; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_X_xin					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2), "=c" (CIF_dummy3) /* no outputs */ \
	: "a" (L), "b" (C), "c" (P) \
	: "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanXMIn64(C,P)*/
#define occstub_ChanXMIn64(C,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_X_xmin64				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (C), "b" (P) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanXMInN(C,P,WC)*/
#define occstub_ChanXMInN(C,P,WC) \
	do { int CIF_dummy1, CIF_dummy2, CIF_dummy3; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, -4(%%ebp)	\n" \
	"	jmp	_X_xminn				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2), "=c" (CIF_dummy3) /* no outputs */ \
	: "a" (WC), "b" (C), "c" (P) \
	: "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ChanXEnd(C)*/
#define occstub_ChanXEnd(C) \
	do { int CIF_dummy1; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%eax		# chan addr		\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_xend					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1) /* no outputs */ \
	: "a" (C) \
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_StartProcess(WP,PO) */
#define occstub_StartProcess(WP,PO) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	subl	$occstub_resume_point,%%eax		\n" \
	"	pushl	%%eax		# process offset	\n" \
	"	pushl	%%ebx		# process workspace	\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_startp				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (PO), "b" (WP) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_EndProcess(SW) */
#define occstub_EndProcess(SW) \
	do { int CIF_dummy1; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%eax		# successor workspace	\n" \
	"	pushl	$0f		# return addr		\n" \
	"	jmp	_X_endp					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1) /* no outputs */ \
	: "a" (SW) \
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_RunProcess(WP) */
#define occstub_RunProcess(WP) \
	do { int CIF_dummy1; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point, %%ebx		\n" \
	"	jmp	_Y_runp					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1) /* no outputs */ \
	: "a" (WP) \
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_RunPriProcess(WP,P) */
#define occstub_RunPriProcess(WP,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	%%ebx, -12(%%ebp)			\n" \
	"	pushl	%%eax		# process workspace	\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_runp					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" (WP), "b" (P) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_StopProcess() */
#define occstub_StopProcess() \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point,0(%%ebp)		\n" \
	"	pushl	$0f	# return addr			\n" \
	"	jmp	_X_stopp				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: /* no outputs */ \
	: /* no inputs */ \
	: "eax", "ebx", "ecx", "edx", "esi", "edi", "cc", "memory")
/*}}}*/
/*{{{  occstub_ProcTime(TP) */
#define occstub_ProcTime(TP) \
	do { int CIF_dummy1; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%eax		# save result addr	\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	$occstub_resume_oneval			\n" \
	"	jmp	_X_ldtimer				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	"	popl	%%eax		# result addr		\n " \
	"	movl	%%ebx, (%%eax)				\n" \
	: "=a" (CIF_dummy1) /* no outputs */			\
	: "a" (TP) \
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_ProcAfter(T) */
#define occstub_ProcAfter(T) \
	do { int CIF_dummy1; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%eax		# save time		\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	$occstub_resume_oneval			\n" \
	"	jmp	_X_ldtimer				\n" \
	"0:				# result in ebx		\n" \
	"	popl	%%ebp					\n" \
	"	popl	%%eax		# time			\n" \
	"	addl	%%ebx,%%eax	# add current		\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%eax		# new time		\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_tin					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1) /* no outputs */			\
	: "a" (T)						\
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)

/*}}}*/
/*{{{  occstub_ProcTimeAfter(T) */
#define occstub_ProcTimeAfter(T) \
	do { int CIF_dummy1; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%eax		# time			\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_tin					\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1) /* no outputs */			\
	: "a" (T)						\
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_AltWait()*/
#define occstub_AltWait() \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_altwt				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: /* no outputs */					\
	: /* no inputs */					\
	: "eax", "ebx", "ecx", "edx", "esi", "edi", "cc", "memory")
/*}}}*/
/*{{{  occstub_Reschedule()*/
#define occstub_Reschedule() \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_resched				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: /* no outputs */					\
	: /* no inputs */					\
	: "eax", "ebx", "ecx", "edx", "esi", "edi", "cc", "memory")
/*}}}*/
/*{{{  occstub_StopP()*/
#define occstub_StopP() \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_stopp				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: /* no outputs */					\
	: /* no inputs */					\
	: "eax", "ebx", "ecx", "edx", "esi", "edi", "cc", "memory")
/*}}}*/
/*{{{  occstub_Seterr(F,L) */
#define occstub_Seterr(F,L) \
	do { int CIF_dummy1;					\
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	orl	$0xfb000000, %%eax			\n" \
	"	pushl	%%eax					\n" \
	"	pushl	$0					\n" \
	"	pushl	$1f					\n" \
	"	pushl	$2f					\n" \
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_X_Seterr				\n" \
	".align 4						\n" \
	"1:							\n" \
	"	.long 1, 8					\n" \
	"	.string \"" F "\"				\n" \
	".align 4						\n" \
	"2:							\n" \
	"	.long 1, 8					\n" \
	"	.string \"(external)\"				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1)					\
	: "a" (L)						\
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_SetPri(P)*/
#define occstub_SetPri(P) \
	do { int CIF_dummy1;					\
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	movl	$occstub_resume_point,-4(%%ebp)		\n" \
	"	jmp	_Y_setpri				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1) /* no outputs */			\
	: "a" (P)						\
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_SavePri(PL,P)*/
#define occstub_SavePri(PL,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_Y_savepri				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" ((PL)), "b" ((P)) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_StPriF(PL,P)*/
#define occstub_StPriF(PL,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_Y_stprif				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" ((PL)), "b" ((P)) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_StPriB(PL,P)*/
#define occstub_StPriB(PL,P) \
	do { int CIF_dummy1, CIF_dummy2; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	$occstub_resume_point			\n" \
	"	jmp	_Y_stprib				\n" \
	"0:							\n" \
	"	popl	%%ebp					\n" \
	: "=a" (CIF_dummy1), "=b" (CIF_dummy2) /* no outputs */ \
	: "a" ((PL)), "b" ((P)) \
	: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_DMemMalloc(L, P)*/
#define occstub_DMemMalloc(L, P) \
	do { int CIF_dummy1; \
	__asm__ __volatile__ ("					\n" \
	"	pushl	%%ebp					\n" \
	CIF_SAVE_C_STATE					\
	CIF_RESTORE_OCCAM_STATE					\
	"	pushl	%%eax					\n" \
	"	pushl	$occstub_resume_oneval			\n" \
	"	jmp	_X_malloc				\n" \
	"0:				# result in ebx		\n" \
	"	popl	%%ebp					\n" \
	"	movl	%%ebx, %%eax				\n" \
	: "=a" (CIF_dummy1)					\
	: "a" (L)						\
	: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory");	\
	*(void **)(P) = (void *)CIF_dummy1;				\
	} while (0)
/*}}}*/
/*{{{  occstub_DMemRelease(P)*/
#define occstub_DMemRelease(P) \
	do { int CIF_dummy1; \
		__asm__ __volatile__ ("					\n" \
		"	pushl	%%ebp					\n" \
		CIF_SAVE_C_STATE					\
		CIF_RESTORE_OCCAM_STATE					\
		"	pushl	%%eax					\n" \
		"	pushl	$occstub_resume_point			\n" \
		"	jmp	_X_mrelease				\n" \
		"0:							\n" \
		"	popl	%%ebp					\n" \
		: "=a" (CIF_dummy1)	/* no outputs */		\
		: "a" (P)						\
		: "ebx", "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/
/*{{{  occstub_blocking_kill_call(C,R)*/
#define occstub_blocking_kill_call(C,R) \
	do { int CIF_dummy1, CIF_dummy2; \
		__asm__ __volatile__ ("					\n" \
		"	pushl	%%ebp					\n" \
		CIF_SAVE_C_STATE					\
		CIF_RESTORE_OCCAM_STATE					\
		"	pushl	%%ebx					\n" \
		"	pushl	%%eax					\n" \
		"	movl	%%esp, %%eax				\n" \
		"	pushl	%%eax					\n" \
		"	pushl	$occstub_resume_point			\n" \
		"	jmp	" EXTERNAL_KILLCALL "			\n" \
		"0:							\n" \
		"	popl	%%ebp					\n" \
		: "=a" (CIF_dummy1), "=b" (CIF_dummy2)			\
		: "a" (C), "b" (R)					\
		: "ecx", "edx", "esi", "edi", "cc", "memory"); } while (0)
/*}}}*/


/*{{{  extern things*/
/* interface into the assembler bit -- only for address, don't call directly! */
extern void occstub_entry_point (void);
extern void occstub_fork_entry (void);


#ifdef KROC_USES_PTHREADS
/* this is needed because some C calls must execute in a pthread stack,
 * e.g. when errno is set from within glibc [that appeared to be causing
 * sprintf() to segfault]
 */
extern void occstub_external_call (void *lastarg, ...);
#endif
extern void occstub_blocking_call (void *lastarg, ...);
extern void occstub_blocking_killcall (void *lastarg, ...);

/* interface into the C bit */
extern Process *cifccsp_ProcAlloc (void (*)(void), int, int, ...);
extern Process *cifccsp_ProcInit (void (*)(void), int *, int, int, ...);
extern void cifccsp_ProcParam (Process *, ...);
extern void cifccsp_ProcAllocClean (Process *);

extern void cifccsp_ProcPar (Process *, ...);
extern void cifccsp_ProcPriPar (Process *, int, ...);
extern void cifccsp_ProcParList (Process **);
extern void cifccsp_ProcPriParList (Process **, int *);

extern Channel *cifccsp_ChanAlloc (void);
extern void cifccsp_ChanAllocClean (Channel *);

extern int cifccsp_ProcAlt (Channel *, ...);
extern int cifccsp_ProcAltList (Channel **);

extern int cifccsp_GetPri (void);
extern int cifccsp_ProcProcPriAlt (Channel *, ...);
extern int cifccsp_ProcProcPriAltList (Channel **);

extern void *cifccsp_DMemAlloc (int);
extern void cifccsp_DMemFree (void *);
extern void *cifccsp_CHK_DMemAlloc (int);
extern void cifccsp_CHK_DMemFree (void *);

extern void cifccsp_CTSemInit (CTSem *);
extern void cifccsp_CTSemClaim (CTSem *);
extern void cifccsp_CTSemRelease (CTSem *);

extern MBarrier *cifccsp_MBarrierAlloc (void);
extern void cifccsp_MBarrierAllocClean (MBarrier *);
extern void cifccsp_MBarrierInit (MBarrier *);
extern void cifccsp_MBarrierEnroll (MBarrier *, int);
extern void cifccsp_MBarrierResign (MBarrier *, int);
extern void cifccsp_MBarrierSync (MBarrier *);

extern void cifccsp_SaveL (Process **);
extern void cifccsp_StLF (Process *);
extern void cifccsp_StLB (Process *);

extern void cifccsp_blocking_killcall (Channel *, int *);

extern void cifccsp_MProcSerialise (MProcess *, char **, int *);
extern void cifccsp_MProcDeserialise (char *, int, MProcess **);
extern int cifccsp_MProcCheckRoutine (char *);
extern int cifccsp_MProcLoadLibrary (char *);
extern int cifccsp_MProcUnloadLibrary (char *);

/*}}}*/


/* API -- these are _all_ macros, either to ASM blocks or C functions, or direct for trivials */
#define ProcAlloc(F,S,W,args...)	cifccsp_ProcAlloc((void (*)(void))(F),(S),(W),##args)
#define ProcInit(F,SP,SS,W,args...)	cifccsp_ProcInit((void (*)(void))(F),(SP),(SS),(W),##args)
#define ProcParam(P,args...)		cifccsp_ProcParam((P),##args)
#define ProcAllocClean(P)		cifccsp_ProcAllocClean((P))
#define ProcInitClean(P)		cifccsp_ProcAllocClean((P))	/* checks inside */

#define ProcPar(P,args...)		cifccsp_ProcPar((P),##args)
#define ProcPriPar(P,L,args...)		cifccsp_ProcPriPar((P),(L),##args)
#define ProcParList(PL)			cifccsp_ProcParList((PL))
#define ProcPriParList(PL,PP)		cifccsp_ProcPriParList((PL),(PP))
#define ProcRun(P) 			occstub_RunProcess((P))
#define ProcFork(P) 			occstub_ForkProcess((P))
#define ProcPriRun(WP,P) 		occstub_RunPriProcess((WP),(P))
#define ProcStop()			occstub_StopProcess()

#define ProcTime(TP)			occstub_ProcTime((TP))
#define ProcAfter(T)			occstub_ProcAfter((T))
#define ProcTimePlus(T,S)		((T) + (S))
#define ProcTimeMinus(T,S)		((T) - (S))
#define ProcTimeAfter(T)		occstub_ProcTimeAfter((T))

#define ProcAlt(C,args...)		cifccsp_ProcAlt((C),##args)
#define ProcAltList(L)			cifccsp_ProcAltList(L)

#define	ChanAlloc()			cifccsp_ChanAlloc()
#define ChanAllocClean(C)		cifccsp_ChanAllocClean((C))
#define ChanInit(C)			(*(C) = (Channel)NULL)

#define ChanInChar(C,P)			occstub_ChanInChar((C),(unsigned int *)((unsigned char *)(P)))
#define ChanInInt(C,P)			occstub_ChanInInt((C),(unsigned int *)(P))
#define ChanIn(C,P,L)			occstub_ChanIn((C),(void *)(P),(int)(L))
#define ChanOutChar(C,V)		occstub_ChanOutChar((C),(unsigned int)((unsigned char)(V)))
#define ChanOutInt(C,V)			occstub_ChanOutInt((C),(unsigned int)(V))
#define ChanOut(C,P,L)			occstub_ChanOut((C),(void *)(P),(int)(L))

#define ChanMIn(C,P)			occstub_ChanMIn((C),(void **)(P))
#define ChanMOut(C,P)			occstub_ChanMOut((C),(void **)(P))
#define ChanMIn64(C,P)			occstub_ChanMIn64((C),(unsigned long long *)(P))
#define ChanMInN(C,P,WC)		occstub_ChanMInN((C),(void *)(P),(int)(WC))
#define ChanMOut64(C,P)			occstub_ChanMOut64((C),(unsigned long long *)(P))
#define ChanMOutN(C,P,WC)		occstub_ChanMOutN((C),(void *)(P),(int)(WC))

#define ChanXAble(C)			occstub_ChanXAble((C))
#define ChanXIn(C,P,L)			occstub_ChanXIn((C),(void *)(P),(int)(L))
#define ChanXMIn64(C,P)			occstub_ChanXMIn64((C),(unsigned long long *)(P))
#define ChanXMInN(C,P,WC)		occstub_ChanXMInN((C),(void *)(P),(int)(WC))
#define ChanXEnd(C)			occstub_ChanXEnd((C))

#define CTSemInit(S)			cifccsp_CTSemInit((S))
#define CTSemClaim(S)			cifccsp_CTSemClaim((S))
#define CTSemRelease(S)			cifccsp_CTSemRelease((S))

#define Reschedule()			occstub_Reschedule()
#define SetErr()			occstub_Seterr(__FILE__,__LINE__)

#define SaveL(PQ)			cifccsp_SaveL((Process **)(PQ))
#define StLF(P)				cifccsp_StLF((Process *)(P))
#define StLB(P)				cifccsp_StLB((Process *)(P))
#define SavePri(PL,PQ)			occstub_SavePri((PL),(PQ))
#define StPriF(PL,P)			occstub_StPriF((PL),(P))
#define StPriB(PL,P)			occstub_StPriB((PL),(P))

#define GetPri()			cifccsp_GetPri()
#define SetPri(P)			occstub_SetPri(P)
#define ProcProcPriAlt(C,args...)	cifccsp_ProcProcPriAlt((C),##args)
#define ProcProcPriAltList(L)		cifccsp_ProcProcPriAltList(L)

#define DMemAlloc(L)			cifccsp_DMemAlloc((L))
#define DMemFree(P)			cifccsp_DMemFree((P))

#define MBarrierAlloc()			cifccsp_MBarrierAlloc()
#define MBarrierAllocClean(B)		cifccsp_MBarrierAllocClean((B))
#define MBarrierInit(B)			cifccsp_MBarrierInit((B))
#define MBarrierEnroll(B,N)		cifccsp_MBarrierEnroll((B),(N))
#define MBarrierResign(B,N)		cifccsp_MBarrierResign((B),(N))
#define MBarrierSync(B)			cifccsp_MBarrierSync((B))

#define MProcSerialise(P,RA,RL)		cifccsp_MProcSerialise((P),(RA),(RL))
#define MProcDeserialise(A,L,P)		cifccsp_MProcDeserialise((A),(L),(P))
#define MProcCheckRoutine(PN)		cifccsp_MProcCheckRoutine((PN))
#define MProcLoadLibrary(LN)		cifccsp_MProcLoadLibrary((LN))
#define MProcUnloadLibrary(LN)		cifccsp_MProcUnloadLibrary((LN))


/* this deals with calling external C functions */
#ifdef KROC_USES_PTHREADS
#define EXTERNAL_CALLN(F,args...)	do { int dummy; dummy = (int)(F); \
						occstub_external_call (&dummy,F,##args); \
						} while(0)
#define EXTERNAL_CALL(F)		do { int dummy; dummy = (int)(F); \
						occstub_external_call (&dummy,F); \
						} while (0)
#else
#define EXTERNAL_CALLN(F,I,args...)	(F)((I),##args)
#define EXTERNAL_CALL(F)		(F)()
#endif

/* and this with external blocking C functions */
#define BLOCKING_CALLN(F,args...)	do { int dummy; dummy = (int)(F); \
						occstub_blocking_call (&dummy,F,##args); \
						} while (0)
#define BLOCKING_CALL(F)		do { int dummy; dummy = (int)(F); \
						occstub_blocking_call (&dummy, F); \
						} while (0)
#define BLOCKING_KILLCALLN(F,C,args...)	do { int dummy; dummy = (int)(F); \
						occstub_blocking_killcall (C,&dummy,F,##args); \
						} while (0)
#define BLOCKING_KILLCALL(F,C)		do { int dummy; dummy = (int)(F); \
						occstub_blocking_killcall (C,&dummy,F); \
						} while (0)

#ifdef KROC_USES_PTHREADS
#define BLOCKING_CALL_KILL(C,R)		occstub_blocking_kill_call((C),(R));
#else
#define BLOCKING_CALL_KILL(C,R)		cifccsp_blocking_killcall((C),(R))
#endif

/* some constants */
#define PROCESS_OFFSET_ADJUST	(8)

#ifdef __cplusplus
}	/* extern "C" */
#endif

#endif	/* !__CIFCCSP_H */
