/* 
 * process.h
 *
 * x-kernel v3.3
 *
 * Copyright (c) 1993,1991,1990,1996  Arizona Board of Regents
 *
 * $Revision: 1.2 $
 * $Date: 1996/01/31 16:23:54 $
 */

#ifndef process_h
#define process_h

#include <thread.h>
#include <stdarg.h>

#include "xtype.h"

/* 
 * in Solaris default prio is always 0, higher numbers have higher priority.
 * range is typically -20 to + 20 but this can be changed - check with
 * priocntl -l
 *
 */
#define STD_PRIO       0
#define THREAD_MAXPRIO 20
#define THREAD_MINPRIO (-20)

#ifndef NULL
#define NULL 0
#endif

#if (defined(USE_GC) && !defined(sparc))        /* not for sparc */
#define malloc(X) gc_malloc(X)
#define free(X) gc_free(X)
#endif

typedef void (*CreateProcFunc) ( int, ... );

#define CreateProcess0 CreateProcess
#define CreateProcess1 CreateProcess
#define CreateProcess2 CreateProcess
#define CreateProcess3 CreateProcess
#define CreateProcess4 CreateProcess
#define CreateProcess5 CreateProcess
#define CreateProcess6 CreateProcess
#define xCreateProcess CreateProcess

#if 0
typedef struct {
#ifdef sun
  int pc, smask, onstack;
  int d2, d3, d4, d5, d6, d7;
  int a2, a3, a4, a5, a6;
  long *sp;
#endif
#ifdef vax
  long *pc, *sp, *fp, *ap;
  int r6, r7, r8, r9, r10, r11;
#endif
} jmp_buf;
#endif

typedef struct _Process {
#if 0
  jmp_buf		jb;
#endif
  long 			*stack, *stacklimit;
  short			prio;
  struct _Process *	link;
  int			extrastuff;
  int			index;
#ifdef MUTS
  void *muts;
#endif
  thread_t		thread;
} Process;

#define STACKSIZE (32*1024)

typedef sema_t Semaphore;

extern Process *Active;
extern int      SignalsPossible;

#define kSwitch() Yield()

/* The -DXKLOCKDEBUG switch provides for counting the locking depth, and
   complaining if it isn't 1.  It has a bug, in that the increment & decrement
   instructions aren't atomic in RISC architectures.  Presumably, the occasions
   where this fails are rare.  */

#ifdef XKLOCKDEBUG
extern int xklockdepthreq;
extern int xklockdepth;
extern int tracexklock;
#endif

/* the master concurrency locks */
extern mutex_t sledgehammer_concurrency_control;

#ifndef XKLOCKDEBUG

#define MASTER_LOCK mutex_lock(&sledgehammer_concurrency_control)
#define MASTER_UNLOCK mutex_unlock(&sledgehammer_concurrency_control)

#else	/* XKLOCKDEBUG */

#define MASTER_LOCK                                                           \
{xklockdepthreq++;                                                            \
 xTrace1(xklock,TR_EVENTS,"requesting xklock, depthreq %d",xklockdepthreq);   \
 mutex_lock(&sledgehammer_concurrency_control);                                \
 xklockdepth++;                                                               \
 if (xklockdepth!=1)                                                          \
 { xTrace1(xklock,TR_ERRORS,"got xklock, wrong depth %d",xklockdepth); };     \
 xTrace2(xklock,TR_EVENTS,"got xklock, depth %d, depthreq %d",                \
         xklockdepth,xklockdepthreq); }
#define MASTER_UNLOCK                                                         \
{if (xklockdepth!=1)                                                          \
 {xTrace1(xklock,TR_ERRORS,"giving up xklock, wrong depth %d",xklockdepth); };\
 xTrace2(xklock,TR_EVENTS,"giving up xklock, depth %d, depthreq %d",          \
         xklockdepth,xklockdepthreq);                                         \
 xklockdepth--;       
 mutex_unlock(&sledgehammer_concurrency_control);                              \
 xTrace1(xklock,TR_EVENTS,"gave up xklock, depthreq %d",xklockdepthreq);      \
 xklockdepthreq--; }

#endif XKLOCKDEBUG

#ifdef __STDC__


void    xk_master_lock( void );
void    xk_master_unlock( void );
void    xkIncreaseCthreadLimit( int );
void    xkThreadDumpStats( void );
void semWait(Semaphore *s);
void semSignal(Semaphore *s);
void semInit(Semaphore *s,unsigned n);
void Yield(void);

bool CreateProcess(void *, int, int, ... );
void threadInit( void );

#else

void    xk_master_lock( );
void    xk_master_unlock( );
void    xkIncreaseCthreadLimit( );
void    xkThreadDumpStats( );
void semWait( );
void semSignal( );
void semInit( );
void Yield( );

bool CreateProcess( );
void threadInit( );

#endif
#endif 
