c_support.c 4.87 KB
/*
 * Copyright (C) 1996-1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * 
 * This file is part of the SimOS distribution. 
 * See LICENSE file for terms of the license. 
 *
 */

/*****************************************************************
 * c_support.c
 *
 * Routines that are linked in with an application. These routines
 * include those used by IRIX and some C-routines that are to be
 * emulated by solo mipsy. Backdoor solo routines are found in
 * solo_anl.c.
 *****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <unistd.h>

#include "solo_interface.h"
#include "sys/prctl.h"

static CommArea *comm;

static pid_t firstPID;
static pid_t currentTID;
unsigned int PIDLock; 

/* Prototypes for Irix routines */
static void IrixCreate( void (*func)() );
static unsigned long long IrixCurrentTime(void);
static void IrixExit(void);
static int  IrixGetCPUNum(void);
static void IrixIOMap(unsigned, long long);

static void IrixWaitForEnd(int numProcs);
static void IrixPlaceRange(unsigned start, unsigned stop, int node);

static void IrixNull(void);
static int  IrixNullIntPtr(void *);
static int  IrixNullInt(void);
/*****************************************************************
 * IrixSetupCommArea
 * 
 * This sets up the pointers will be called when an application is
 * running under IRIX. 
 *****************************************************************/
void
IrixSetupCommArea(void)
{
   char *addr;
   int fd, length;

   /* 
    * Allocate a file to be mapped and used as a shared memory region 
    * for communication between solo mipsy and the application 
    */
   fd = open("/dev/zero", O_RDWR);
   if (fd == -1) {
      perror("Mapping /dev/zero open (for comm area mapping)");
      exit(-1);
   }
   length = COMM_LENGTH;
   
   addr = (char *) mmap((void *) COMM_START, length,
                        PROT_READ|PROT_WRITE,
                        MAP_SHARED|MAP_FIXED, fd, 0);
   
   if (addr != (char *) COMM_START) {
      perror("Mapping communication area.\n");
      (void) close(fd);
   }


   comm = (CommArea *)addr;

   comm->WaitForEnd  = IrixWaitForEnd;
   comm->Create      = IrixCreate;
   comm->CurrentTime = IrixCurrentTime;
   comm->Exit        = IrixExit;
   comm->GetCPUNum   = IrixGetCPUNum;
   comm->PlaceRange  = IrixPlaceRange;

   /* Calls that are not supported in IRIX */
   comm->TurnOnCaches  = IrixNull;
   comm->TurnOffCaches = IrixNull;
   comm->ResetStats    = IrixNull;
   comm->ActiveProcs   = IrixNullInt;

   comm->Flush = IrixNullIntPtr;
   comm->IOMap = IrixIOMap;

   /* For GetCPUNum, we need to have the original pid of the process. */
   firstPID= getpid();
   ((struct prda *) PRDA)->usr_prda.fill[0] = currentTID = 0;
}


static void
IrixNull(void)
{

}

static int
IrixNullIntPtr(void *foo)
{

}

static int
IrixNullInt(void)
{

}

static void 
IrixCreate(void (*func)())
{
   int retval;
   if ((retval = sproc(func, PR_SADDR, NULL)) == -1) {
      fprintf(stderr,"WHOA! Sproc returned %d: \n",retval);
      perror("Sproc problem");
      exit (-1);
   }

   _LockEnter(&PIDLock);
   ((struct prda *) PRDA)->usr_prda.fill[0] = ++currentTID;
   printf("[Sproc() of task #%d, PID %d)]\n",
	  (struct prda *) PRDA->usr_prda.fill[0],
	  (int)getpid());
   _Unlock(&PIDLock);
}


static unsigned long long
IrixCurrentTime(void)
{
   struct timeval time;

   if (gettimeofday (&time, (struct timezone *)0)) {
      perror ("CLOCK macro"); 
      exit (-1); 
   }
   return (unsigned long long) (time.tv_sec & 0x7ff)*1000000 + time.tv_usec;
}

static void
IrixExit(void)
{
   exit(0);
}

static int
IrixGetCPUNum(void)
{
   return (int)(((struct prda *) PRDA)->usr_prda.fill[0]);
}

static void 
IrixIOMap(unsigned a, long long b)
{
   fprintf(stderr, "IO Mapping is not currently supported\n");
}

static void 
IrixPlaceRange(unsigned start, unsigned stop, int node)
{  

}

static void
IrixWaitForEnd(int numProcs)
{
   int i;
   for (i=1; i<=numProcs; i++) 
      wait(0);

}

void
initMCSlock(MCSlock L)
{
   L->next = 0;
   L->locked = 0;
}


void
acquireMCSlock(volatile MCSlock L, volatile MCSlock I)
{
   volatile MCSlock pred;

/*   printf("before L = %x *L: %x I= %x\n",L,*L,I);  */
   I->next = NULL;
   pred = (MCSlock) _FetchAndStore((void *) L, (int) I);
/*   printf("after L = %x *L: %x I= %x\n",L,*L,I);  */
   if (pred) {
      I->locked = 1;
      pred->next = I;
      while (I->locked) {
      }
   }
}
   

void
releaseMCSlock(volatile MCSlock L, volatile MCSlock I)
{
   if (I->next == NULL) {
      if (_CompareAndSwap((void *) L, (int) I, (int) NULL)) {
	 return;
      }
      while ((I->next) == NULL) {
      }
   }
   I->next->locked = NULL;
}

#ifdef FLASHPOINT
void * non_instrumented_malloc(size_t size) {
  void * tmp = malloc(size);
  return tmp;
}
#endif