#define _PROCESS_0

/*
#undef DEBUG
#undef DBGLVL
#define DEBUG 0
#define DBGLVL -1
*/

#include "includes.h"
#include "forker.h"
#include "pcoreipc.h"

size_t	shm_size = SHM_SIZE ;	/* size of shared memory */
char *	shm_base ;		/* base of shared memory */
void *	MallocedMemBase ;	/* base of malloc'ed memory */

#if 0
key_t	pcore_shm_key ;		/* key for accessing shm ressources */
key_t	pcore_sem_key ;		/* key for accessing sem ressources */
key_t	pcore_msg_key ;		/* key for accessing msg ressources */
#else
#  define pcore_shm_key IPC_PRIVATE
#  define pcore_sem_key IPC_PRIVATE
#  define pcore_msg_key IPC_PRIVATE
#endif

int	pcore_shm_id ;		/* shm descriptor */
int	pcore_sem_id ;		/* sem descriptor */
int	pcore_msg_id ;		/* msg descriptor */


/********************** Shared Memory ***************************/

static void pcore_attach_shm (void) {
  void * result ;

 ___(5,"Process %d attaching shared memory segment\n",current_process) ;

  result = shmat (pcore_shm_id,shm_base,0) ;

  if ( (long)result == -1 ) {
   ___(3,"shmat() error: ") ;
    perror(NULL) ;
   ___(3,"Attach failed, exiting !\n") ;
    exit (100) ;
  }
 ___(4,"shmat() succeeded at [0x%08lX]\n",(long)result) ;

  shm_base = result ;
}


static void free_shm (void) {
 ___(11,"Process %d destroying the shared memory segment.\n",current_process) ;
  shmctl ( pcore_shm_id,IPC_RMID,NULL ) ;
}


static void creat_shm (void) {
  int	  flags = 0644 | IPC_CREAT | IPC_EXCL;	/* permissions */

 ___(2,"Creating new shared memory segment.\n") ;
  TRYM1( pcore_shm_id = shmget (pcore_shm_key, shm_size, flags) );

/**** I couldn't get it to work by malloc'ing 256 KB ! ****/
/*
 ___(2,"Mapping it to process memory.\n") ;
  TRY0 ( MallocedMemBase = malloc (shm_size+SHMLBA) ) ;
  shm_base = (char*)
		(((long)(MallocedMemBase + SHM_PAGE_MASK)) & SHM_PAGE_MASK) ;
 ___(3,"Allocated 0x%08lX byte block at [0x%08lX] for it.\n",
     (long)shm_size,(long)shm_base) ;
*/
  shm_base = 0 ;

  pcore_attach_shm () ;

  TRYM1( atexit (free_shm) );
}

/********************* Messages *********************/

static void free_msg (void) {
 ___(11,"Process %d Destroying the message resource.\n",current_process) ;
  msgctl ( pcore_msg_id,IPC_RMID,NULL ) ;
}

static void creat_msg (void) {
  int	  flags = 0644 | IPC_CREAT | IPC_EXCL;	/* permissions */
 ___(2,"Creating new message resource.\n") ;
  TRYM1( pcore_msg_id = msgget (pcore_msg_key, flags) );
  TRYM1( atexit (free_msg) );
}



/******************** Semaphores *********************/

static void free_sem (void) {
 ___(11,"Process %d Destroying the semaphore resource.\n",current_process) ;
 semctl ( pcore_sem_id,0,IPC_RMID,(union semun)0 ) ;
}

static void creat_sem (void) {
  int	  flags = 0644 | IPC_CREAT | IPC_EXCL;	/* permissions */
 ___(2,"Creating new semaphore resource.\n") ;
  TRYM1( pcore_sem_id = semget (pcore_sem_key, PCORE_NSEMS, flags) );
}



/* Note: those atexit()'ed functions will be done thrice. Better than once. */


/***************** Initializing *******************/

static void init_msg (void) {
}
static void init_sem (void) {
  /* say that all those processes are busy */
  struct sembuf semops [2] = { 
    {sem_runloop_busy,+1,0},
    {sem_timer_busy,  +1,0}
  };
 TRYM1( semop (pcore_sem_id,semops,2) );
}
static void init_shm (void) {
  SHM_G(runloop_ready) = 0 ;
  SHM_G(io_ready)      = 0 ;
  SHM_G(timer_ready)   = 0 ;
  SHM_G(terminating)   = 0 ;
  SHM_G(ipc_test_flag) = -10 ;
  shm_base[10000] = -10 ;
}

/************ main procedures ***************/
void pcore_init_ipc (void) {

 /* Keys for IPC */
 /* finally, we use IPC_PRIVATE !
  char	  keystr [80] ;				/ * session-dependent key * /
  sprintf (keystr,"OSL pcore %05d",getpid()) ;

  pcore_shm_key = ftok (keystr,PCORE_SHM_KEY) ;
  pcore_sem_key = ftok (keystr,PCORE_SEM_KEY) ;
  pcore_msg_key = ftok (keystr,PCORE_MSG_KEY) ;
 */

 ___(1,"Create the resources.\n") ;
  creat_shm () ;		/* Init the shared memory */
  creat_sem () ;		/* Init the semaphores */
  creat_msg () ;		/* Init the messages */

 ___(1,"Initialize the resources.\n") ;
  init_shm () ;
  init_sem () ;
  init_msg () ;
}


void pcore_free_ipc (void) {
  free_msg ();
  free_sem ();
  free_shm ();
}
