📄 simutil.c
字号:
/* * 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. * *//***************************************************************** * simutil.c * * Random generic utilities * * $Author: bosch $ * $Date: 1998/02/10 00:28:42 $ ****************************************************************/#include <errno.h>#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <sys/mman.h>#include <sys/time.h>#include <unistd.h>#include <ctype.h>#include "syslimits.h"#include "sim_error.h"#include "machine_params.h"#include "simutil.h"#include "cpu_interface.h"char *simName[NUM_CPU_TYPES] = SIM_NAME_INIT;/***************************************************************** * GetLineFromFile -- * Read a line from the specified file into a buffer. * * Results: * The length of the line in characters: -1 on error, 0 on end of file. * *****************************************************************/intGetLineFromFile(FILE *f, char *buffer, int bufsize){ int i; int n; for (i = 0; i < bufsize-1; i++) { n = fgetc(f); if (n == EOF) { if (i != 0) break; return 0; } buffer[i] = n; if (n == '\n') break; } if (i== bufsize-1) { CPUError("GetLineFromFile: buffer too small \n"); } buffer[i] = '\000'; return i+1;}/* ********************************************************************* * Numerical functions * *********************************************************************/int GetLog2(int x){ int i; int r=0; for(i=1;i<x;i*=2) r++; if( i != x ) { CPUError("Warning: GetLog2(%i) is undefined \n",x); } return r;}SimTime NanoSecsToCycles(SimTime time){ int clock = CPU_CLOCK; SimTime retval; if (!clock) { CPUError("NanoSecsToCycles: CpuClock must have a non-zero value\n"); } retval = time /*nano*/ * clock /* Mhz */ / 1000; return retval;}SimTime CyclesToNanoSecs(SimTime cycles){ int clock = CPU_CLOCK; SimTime retval; ASSERT(clock != 0); retval = (cycles / clock) * 1000; return retval;}void SaveTimeDelay(TimeDelay *t,SimTime delay){ if( !delay ) { t->count++; t->zerocount++; } else { if( t->count==t->zerocount ) { t->min = delay; t->max = delay; } else { if( t->min > delay ) t->min = delay; if( t->max < delay ) t->max = delay; } t->count++; t->total += delay; t->total2 += (uint64) delay*(uint64) delay; }}void PrintTimeDelay(FILE *f,char *s,TimeDelay *t){ char out[128]; SubstituteLLx(out, "%s=(%lld,%lld,%lld,%lld,%lld,%lld) ", 128); fprintf(f,out, s, (uint64)t->count, (uint64)t->min, (uint64)t->max, (uint64)t->total, (uint64)t->total2, (uint64)t->zerocount);}/* ******************************************************************** * MallocShared can only be called before the processes are forked. It is * called by the original process to allocated shared backdoor space. * **********************************************************************/void *MallocShared(unsigned size, char *name){ int pagesize = getpagesize(); char *retval, *start; int num_pages, zfd; num_pages = (size+pagesize-1)/pagesize; retval = MemAlign(pagesize, num_pages*pagesize); if (retval == NULL) { CPUError("MallocShared: Out of shared space\n"); } zfd = open("/dev/zero",O_RDWR,0); start = (char *) mmap((void *)retval,num_pages*pagesize, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, zfd, 0); if (start != retval) { CPUError("Mallocshared: mmap failed\n"); } close(zfd); return retval;}char *SaveString(char *name) { char *retval; retval = (char *) ckalloc(strlen(name) + 1); if (retval == NULL) { CPUError("Couldn't malloc space in SaveString\n"); } strcpy(retval, name); return retval;}void *MemAlign(int alignment, int size){#ifdef __alpha void *ptr = malloc(alignment + size); uint64 x = PTR_TO_UINT64(ptr); x = x + (alignment -1); x = (x/alignment) * alignment; return UINT64_TO_PTR(x);#else return memalign(alignment,size);#endif}/*************************** * file name manipulation **************************/char *StripPath(char *string){ char *p; char *ret = string; for (p=string; *p; p++) { if (*p == '/') { ret = p + 1; } } return ret;}#ifdef __alphavoid SubstituteLLx(char *out, const char *text, int maxlen){ char *ptr = (char *)text; char *optr = out; char *tok; int len; while ((ptr != NULL) && ((ptr - text) < maxlen)) { tok = strstr(ptr, "ll"); if (tok == NULL) { /* no more lls */ strcpy(optr, ptr); return; } len = tok - ptr; strncpy(optr, ptr, len); ptr = tok; optr += len; if (tok != text) { /* have to discount a starting ll */ tok--; while ((*tok != '%') && (tok != text)) { if (((*tok >= '0') && (*tok <= '9')) || (*tok == '.') || (*tok == '+') || (*tok == '-')) { /* acceptable token */ tok--; } else { break; } } } ptr += 2; if ((*tok == '%') && ((*ptr == 'd') || (*ptr == 'x') || (*ptr == 'u') || (*ptr=='i'))) { /* make the substitution */ *optr = 'l'; optr++; } else { *optr = 'l'; optr++; *optr = 'l'; optr++; } }} #elsevoid SubstituteLLx(char *out, const char *text, int maxlen){ int i; for(i=0;i<maxlen &&text[i];i++) { out[i] = text[i]; } out[i] = text[i];}#endif/* * belong in simutil.c */int PrintLLD(char *string,int64 val){#ifdef __alpha return sprintf(string,"%ld",(long)val);#else return sprintf(string,"%lld",val);#endif} int PrintLLU(char *string,uint64 val){#ifdef __alpha return sprintf(string,"%lu",(long)val);#else return sprintf(string,"%llu",val);#endif} int PrintLLX(char *string, int64 val){#ifdef __alpha return sprintf(string,"0x%lx",(long)val);#else return sprintf(string,"0x%llx",val);#endif} /***************************************************************** * Print the current real-life time. This can be used for timing * simulation events. It will simply print out seconds since 1970 in * the log. *****************************************************************/void PrintRealTime(char *string) { struct timeval t; gettimeofday(&t, (struct timezone*)0); CPUPrint("%s: %ld s %ld us\n", string, t.tv_sec, t.tv_usec);}int OpenTmpFile(char * name){ extern char *MemFileDir; int fd; char nameBuf[256]; sprintf(nameBuf, "%s/.%s_XXXXXX", MemFileDir,name); mktemp(nameBuf); if((fd = open(nameBuf, O_RDWR|O_CREAT|O_TRUNC , 0)) == -1) { CPUError("Could not open shadow file %s\n", nameBuf); return -1; } unlink(nameBuf); CPUPrint("OpenTmpFile %s \n",nameBuf); return fd;}/* *************************************************************************** * AllocZeroMem & InitZeroMem * * This is called by ZALLOC_PERM in the case where we want to map /dev/zero * to allocate initialized storememory without having to allocate the backing * store. * ***************************************************************************/#define SIMUTIL_ALLOC_UNIT (512*1024)static struct { /* * parameters set by InitZeroMem */ char *startAddr; char *endAddr; int redzone; char *cur; char *nextPageAddrToAlloc; int zfd;} zeroMem;void InitZeroMem(char * start,char * end, int redzone){ int pageSzLessOne = getpagesize()-1; zeroMem.startAddr = start; zeroMem.endAddr = (char *) UINT64_TO_PTR((PTR_TO_UINT64(end) + pageSzLessOne) & ~pageSzLessOne); zeroMem.redzone = redzone; zeroMem.cur = (char *)0;}void *AllocZeroMem(int memSize, char *name) { int len, flags; char *memPtr, *memEndPtr; long offset = 0;#ifdef SIMOS_PURE /* * Should never be called in this case */ CPUError("Cannot use AllocZeroMem with SIMOS_PURE defined! \n");#endif#ifdef __alpha_not if (memSize > 1024 *1024) { /* * gross hack. Assume that this will be clean (zero) memory */ memPtr = malloc(memSize); if (!memPtr) { perror("AllocZeroMem::malloc"); CPUError("AllocZeroMem (malloc) of %lld bytes failed \n",memSize); } return memPtr; }#endif /* Initialization needed ? */ if (!zeroMem.cur) { int pageSize = getpagesize()-1; ASSERT (zeroMem.startAddr); zeroMem.cur = zeroMem.startAddr; zeroMem.nextPageAddrToAlloc = zeroMem.startAddr;#ifdef __alpha zeroMem.zfd = -1; /* zeroMem.zfd = OpenTmpFile("zeromem"); */#else zeroMem.zfd = open("/dev/zero", O_RDWR, 0); if (zeroMem.zfd <= 0) { CPUWarning("opening /dev/zero in AlloczeroMem failed"); ASSERT(0); }#endif /* * redzone the end of the mappable region. This is * to prevent the stack to grow below the end of the * mappable region. * Note that this only has an effect if the allocator * is used. Hence the delay. */ if (zeroMem.redzone) { if( mmap( (void*)zeroMem.endAddr, pageSize, PROT_NONE ,MAP_PRIVATE|MAP_FIXED, zeroMem.zfd,0) != (void*)zeroMem.endAddr){ perror("Redzoning Stack Failed"); ASSERT (0); } } } memPtr = zeroMem.cur; memEndPtr = memPtr + memSize - 1; CPUPrint("ZeroMem: %-20s 0x%x - 0x%x size=%8d\n",name,memPtr,memEndPtr,memSize); if (memEndPtr > zeroMem.endAddr) { CPUError("ZeroMem overflow. Move the memory file down \n "); } if (memEndPtr < zeroMem.nextPageAddrToAlloc) { zeroMem.cur = memPtr + memSize; return (void*)memPtr; } /* allocate next chunk */ for (len = 0; len < memSize; len +=SIMUTIL_ALLOC_UNIT) continue; if (zeroMem.nextPageAddrToAlloc+ len >= zeroMem.endAddr) { len = zeroMem.endAddr - zeroMem.nextPageAddrToAlloc; } flags = MAP_PRIVATE|MAP_FIXED;#ifdef sgi flags |= MAP_AUTORESRV; /* Improve startup time on sgi. */#endif#ifdef __alpha if (zeroMem.zfd >0) { long checkOffset; char foobar[2]; flags &= ~MAP_PRIVATE; flags |= MAP_FILE|MAP_SHARED; offset = zeroMem.nextPageAddrToAlloc - zeroMem.startAddr; checkOffset = lseek(zeroMem.zfd,zeroMem.nextPageAddrToAlloc - zeroMem.startAddr + len,SEEK_SET); ASSERT( checkOffset == zeroMem.nextPageAddrToAlloc - zeroMem.startAddr + len); foobar[0] = '\0'; write(zeroMem.zfd,foobar,1); } else { flags |= MAP_ANONYMOUS; }#endif if (mmap(zeroMem.nextPageAddrToAlloc, len, PROT_READ|PROT_WRITE, flags, zeroMem.zfd, offset) != zeroMem.nextPageAddrToAlloc) { perror("AllocZeroMem"); CPUError("Can't allocate memory in AlloczeroMem addr=0x%llx len=0x%llx\n ", zeroMem.nextPageAddrToAlloc, len); } else { CPUPrint("zeroMem: Mapping /dev/zero at 0x%llx for %ld KB fd=%d offset=%d \n", zeroMem.nextPageAddrToAlloc, len / 1024, zeroMem.zfd, offset); *(char *) zeroMem.nextPageAddrToAlloc = '\0'; } zeroMem.nextPageAddrToAlloc += len; zeroMem.cur = memPtr + memSize; return (void*)memPtr;}voidtoLowerStr(char *dest, char *src){ int len; int i; len = strlen(src); for (i = 0; i <= len; i++) dest[i] = tolower(src[i]);}voidtoUpperStr(char *dest, char *src){ int len; int i; len = strlen(src); for (i = 0; i <= len; i++) dest[i] = toupper(src[i]);}uint64 EndianSwapDouble(uint64 x){ uint64 val64 = x; char *ptr = (char *) &val64; char out[8]; int i; for (i=0;i<8;i++) { out[i] = ptr[7-i]; } return (uint64) *(uint64 *)out;}#ifdef for_some_platforms_onlyintgetpagesize(void) { return (int)sysconf (_SC_PAGESIZE);} /* getpagesize () */#endif/****************************************************************************//* zero-filled file operations *//* * Create a file in the specified directory, of the specified length containing * all zeros, and optionally unlink the file. */intMakeFile(char *directoryname, char *filename, int length, int unlinkit){ int fd; static char namebuf[1024]; static int nextid = 0; if (filename == NULL) { sprintf(namebuf, "%s/%d.%d.%d", directoryname, (int)getpid(), (int)time(0), nextid++); filename = namebuf; } /* * Create the file, we set the permissions so only the owner can access * it. This is necessary due to a bug in NFS that prohibits * ftruncates() on files that the user doesn't have write perimission * on. */ fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0700); if (fd < 0) { perror( filename); return -1; } /* * Remove the directory entry. This means that when we exit or crash * the file is deleted. */ if (unlinkit && (unlink(filename) < 0)) { perror( filename); /* Let this error pass. */ } if (length > 0) { /* * Grow the file to the specified size. */ if (lseek(fd, (int)length-1, SEEK_SET) != (int)(length-1)) { perror( filename); (void) close(fd); return -1; } if (write(fd, "\000", 1) != 1) { perror( filename); (void) close(fd); return -1; } } return fd;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -