size_t mwCountLinesInFile(FILE* f) { int c; size_t lineCount = 0; while ((c = fgetc(f)) != EOF) { if (c == '\n') { ++lineCount; } } if (!feof(f)) { mwPerror("Error counting file lines"); return 0; } if (fseek(f, 0L, SEEK_SET) < 0) { mwPerror("Error seeking file for counting"); return 0; } return lineCount; }
int writeCheckpoint(EvaluationState* es) { FILE* f; /* Avoid corrupting the checkpoint file by writing to a temporary file, and moving that */ f = mw_fopen(CHECKPOINT_FILE_TMP, "wb"); if (!f) { mwPerror("Opening checkpoint '%s'", CHECKPOINT_FILE_TMP); return 1; } es->lastCheckpointNuStep = es->nu_step; writeState(f, es); fclose(f); if (mw_rename(CHECKPOINT_FILE_TMP, resolvedCheckpointPath)) { mwPerror("Failed to update checkpoint file ('%s' to '%s')", CHECKPOINT_FILE_TMP, resolvedCheckpointPath ); return 1; } return 0; }
int mwWriteFile(const char* filename, const char* str) { FILE* f; int rc; if (!str || !filename) { return 1; } f = mw_fopen(filename, "wb"); if (!f) { mwPerror("Writing file '%s'", filename); return 1; } rc = fputs(str, f); if (rc == EOF) { mwPerror("Error writing file '%s'", filename); } fcloseVerbose(f, filename, "Closing write file"); return rc; }
int nbSetupCursesOutput(void) { int stderrTmp; int redirect; /* Will become stderr, let it "leak" */ /* Since we use stderr for everything, use stdout for curses stuff. We don't want the printed stuff to disappear at the end after endwin() clears. Redirect stderr to a temporary file and print that at the end. Ideally we would also prevent the initial clearing, but I can't figure out how to do that. Internet says you can't without dropping to a lower level of terminal controls. */ snprintf(stderrTmpFile, sizeof(stderrTmpFile), "stderr_tmp_%d", getpid()); fflush(stderr); stderrBack = dup(fileno(stderr)); if (stderrBack < 0) { mwPerror("dup() error on STDERR_FILENO"); return errno; } stderrTmp = open(stderrTmpFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (stderrTmp < 0) { mwPerror("Failed to get stderr dump file '%s'", stderrTmpFile); close(stderrBack); return errno; } redirect = dup2(stderrTmp, fileno(stderr)); if (redirect < 0) { mwPerror("dup2() error to stderr redirect"); close(stderrBack); return errno; } if (close(stderrTmp) < 0) { printf("Error closing stderrTmp: %s\n", strerror(errno)); /* Try to restore stderr to console */ dup2(stderrBack, fileno(stderr)); close(stderrBack); return errno; } initscr(); cursesSetup = TRUE; return 0; }
static scene_t* nbglConnectSharedScene(int instanceId) { int shmId; const int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; struct stat sb; char name[128]; scene_t* scene = NULL; if (snprintf(name, sizeof(name), "/milkyway_nbody_%d", instanceId) == sizeof(name)) { mw_panic("name buffer too small for shared memory name\n"); } shmId = shm_open(name, O_RDWR, mode); if (shmId < 0) { mwPerror("Error getting shared memory"); return NULL; } if (fstat(shmId, &sb) < 0) { mwPerror("shmem fstat"); shm_unlink(name); return NULL; } scene = (scene_t*) mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmId, 0); if (scene == MAP_FAILED) { mwPerror("mmap: Failed to mmap shared memory"); if (shm_unlink(name) < 0) { mwPerror("Unlink shared memory"); } return NULL; } if (sb.st_size < (ssize_t) sizeof(scene_t) || sb.st_size < (ssize_t) nbFindShmemSize(scene->nbody)) { mw_printf("Shared memory segment is impossibly small ("ZU")\n", (size_t) sb.st_size); if (shm_unlink(name) < 0) { mwPerror("Unlink shared memory"); } return NULL; } return scene; }
/* Take a program binary from clGetPropramInfo() and a replacement IL source as a string. Replace the .amdil section in the ELF image and return a new copy of the binary. */ unsigned char* getModifiedAMDBinary(unsigned char* bin, size_t binSize, int nStream, MWCALtargetEnum target, size_t* newBinSizeOut) { int fd = -1; int rc = 0; char tmpBinFile[128]; unsigned char* newBin = NULL; if (!bin) return NULL; getTmpBinaryName(tmpBinFile, sizeof(tmpBinFile)); /* Write binary to a temporary file since we need a file descriptor for libelf */ fd = open(tmpBinFile, openMode, openPermMode); if (fd < 0) { mwPerror("Failed to open AMD binary file '%s", tmpBinFile); return NULL; } if (write(fd, bin, binSize) <= 0) { mwPerror("Failed to write temporary binary file '%s'", tmpBinFile); return NULL; } rc = processElf(fd, nStream, target); if (rc == 0) { if (lseek(fd, 0, SEEK_SET) != 0) { mwPerror("Failed to seek temporary binary file '%s'", tmpBinFile); return NULL; } newBin = (unsigned char*) readFD(fd, newBinSizeOut); } if (close(fd) < 0) { mwPerror("Failed to close binary file '%s'", tmpBinFile); free(newBin); return NULL; } mw_remove(tmpBinFile); return newBin; }
/* Open a lua_State, bind run information such as server arguments and * BOINC status, and evaluate input script. */ static lua_State* separationOpenLuaStateWithScript(const SeparationFlags* sf) { int failed; char* script; lua_State* luaSt; luaSt = separationLuaOpen(FALSE); if (!luaSt) return NULL; script = mwReadFileResolved(sf->ap_file); if (!script) { mwPerror("Opening Lua script '%s'", sf->ap_file); lua_close(luaSt); return NULL; } failed = tryEvaluateScript(luaSt, script, sf); free(script); if (failed) { lua_close(luaSt); return NULL; } return luaSt; }
int nbDetachSharedScene(NBodyState* st) { #if USE_POSIX_SHMEM if (st->scene) { if (shm_unlink(st->scene->shmemName) < 0) { mwPerror("Closing shared scene memory '%s'", st->scene->shmemName); return 1; } } #elif USE_WIN32_SHARED_MAP if (st->scene) { if (!UnmapViewOfFile((LPCVOID) st->scene)) { mwPerrorW32("Error unmapping shared scene memory"); return 1; } } #endif /* USE_POSIX_SHMEM */ st->scene = NULL; return 0; }
void nbCleanupCursesOutput(void) { FILE* f; size_t readSize; char buf[4096]; if (!cursesSetup) { return; } if (endwin() != OK) { mw_printf("endwin() error\n"); } /* Restore stderr to the console */ fflush(stderr); if (dup2(stderrBack, fileno(stderr)) < 0) { printf("Error restoring stderr: %s\n", strerror(errno)); } if (close(stderrBack) < 0) { mwPerror("Error closing stderrBack"); } /* You can't seek on the redirected fd, so reopen the stderr tmp * file so we can print it. */ f = fopen(stderrTmpFile, "r"); if (!f) { mwPerror("Error reopening stderr log '%s'", stderrTmpFile); return; } /* Copy file contents to stderr */ while (!feof(f)) { readSize = fread(buf, 1, sizeof(buf), f); fwrite(buf, 1, readSize, stderr); } fclose(f); remove(stderrTmpFile); }
static char* readFD(int fd, size_t* lenOut) { char* strBuf = NULL; struct stat props; size_t len = 0; if (fd < 0) { return NULL; } if (fstat(fd, &props) < 0) { mwPerror("fstat on temporary AMD binary file"); } if (props.st_size <= 0) { mw_printf("Modified binary file is empty\n"); return NULL; } len = props.st_size + 1; strBuf = (char*) malloc(len); if (!strBuf) { mwPerror("Failed to allocate "ZU" for AMD binary file", len); return NULL; } strBuf[props.st_size] = '\0'; if (read(fd, strBuf, props.st_size) < 0) { mwPerror("Error reading from AMD Binary file"); free(strBuf); strBuf = NULL; } if (lenOut) { *lenOut = props.st_size; } return strBuf; }
static char* fcloseVerbose(FILE* f, const char* name, const char* err) { if (fclose(f)) { mwPerror("Error closing file '%s' while %s", name, err); } return NULL; }
int mwOSHasAVXSupport(void) { size_t len; char* kernelVersion; int major = 0; int minor = 0; int patchLevel = 0; static int mib[2] = { CTL_KERN, KERN_OSRELEASE }; if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0) { mwPerror("sysctl kernel version size"); return FALSE; } kernelVersion = malloc(len * sizeof(char)); if (!kernelVersion) { mwPerror("malloc"); return FALSE; } if (sysctl(mib, 2, kernelVersion, &len, NULL, 0) < 0) { mwPerror("sysctl kernel version"); free(kernelVersion); return FALSE; } if (sscanf(kernelVersion, "%d.%d.%d", &major, &minor, &patchLevel) != 3) { major = minor = patchLevel = 0; /* Old examples seem to say it was 2 digits */ if (sscanf(kernelVersion, "%d.%d", &major, &minor) != 2) { major = minor = patchLevel = 0; } } free(kernelVersion); /* AVX support added in 10.6.8, which has kernel 10.8 */ return (major >= 10 && minor >= 8); }
int mwSetProcessPriority(MWPriority priority) { int value = mwPriorityToNice(priority); if (setpriority(PRIO_PROCESS, getpid(), value)) { mwPerror("Setting process priority to %d", value); return 1; } return 0; }
char* mwFreadFileWithSize(FILE* f, const char* filename, size_t* sizeOut) { long fsize; size_t readSize; char* buf; if (!f) { return NULL; } /* Find size of file */ if (fseek(f, 0, SEEK_END) == -1) { return fcloseVerbose(f, filename, "seeking file end"); } fsize = ftell(f); if (fsize == -1) { return fcloseVerbose(f, filename, "getting file size"); } fseek(f, 0, SEEK_SET); buf = (char*) malloc((fsize + 1) * sizeof(char)); if (!buf) { return fcloseVerbose(f, filename, "closing read file"); } buf[fsize] = '\0'; readSize = fread(buf, sizeof(char), fsize, f); if (readSize != (size_t) fsize) { mwPerror("Failed to read file '%s': Expected to read %ld, but got "ZU, filename, fsize, readSize); free(buf); buf = NULL; } fcloseVerbose(f, filename, "closing read file"); if (sizeOut) *sizeOut = readSize; return buf; }
int mwGetHighResTime_RealTime(MWHighResTime* t) { struct timespec ts; if (clock_gettime(CLOCK_REALTIME, &ts)) { mwPerror("Error getting CLOCK_REALTIME"); return 1; } t->sec = (uint64_t) ts.tv_sec; t->nSec = (uint64_t) ts.tv_nsec; return 0; }
SeparationResults* readReferenceResults(const char* refFile, unsigned int nStream) { FILE* f; SeparationResults* refResults; f = fopen(refFile, "r"); if (!f) { mwPerror("Opening reference results '%s'", refFile); return NULL; } refResults = freadReferenceResults(f, nStream); fclose(f); return refResults; }
int nbDetachSharedScene(NBodyState* st) { (void) st; #if USE_SHMEM if (st->scene) { if (shm_unlink(st->scene->shmemName) < 0) { mwPerror("Closing shared scene memory '%s'", st->scene->shmemName); return 1; } st->scene = NULL; } #endif /* USE_SHMEM */ return 0; }
int readCheckpoint(EvaluationState* es) { int rc; FILE* f; f = mwOpenResolved(CHECKPOINT_FILE, "rb"); if (!f) { mwPerror("Opening checkpoint '%s'", CHECKPOINT_FILE); return 1; } rc = readState(f, es); if (rc) mw_printf("Failed to read state\n"); fclose(f); addTmpCheckpointSums(es); return rc; }
/* output: Print bodies */ static int nbOutputBodies(FILE* f, const NBodyCtx* ctx, const NBodyState* st, const NBodyFlags* nbf) { Body* p; mwvector lbr; const Body* endp = st->bodytab + st->nbody; nbPrintBodyOutputHeader(f, nbf->outputCartesian); for (p = st->bodytab; p < endp; p++) { fprintf(f, "%8d,", ignoreBody(p)); /* Print if model it belongs to is ignored */ if (nbf->outputCartesian) { fprintf(f, " %22.15f, %22.15f, %22.15f, %22.15f, %22.15f, %22.15f\n", X(Pos(p)), Y(Pos(p)), Z(Pos(p)), X(Vel(p)), Y(Vel(p)), Z(Vel(p))); } else { lbr = cartesianToLbr(Pos(p), ctx->sunGCDist); fprintf(f, " %22.15f, %22.15f, %22.15f, %22.15f, %22.15f, %22.15f\n", L(lbr), B(lbr), R(lbr), X(Vel(p)), Y(Vel(p)), Z(Vel(p))); } } if (fflush(f)) { mwPerror("Body output flush"); return TRUE; } return FALSE; }
/* From the extra parameters, read them as doubles */ real* mwReadRestArgs(const char** rest, unsigned int n) { unsigned int i; real* parameters = NULL; if (!rest) return NULL; parameters = (real*) mwMalloc(n * sizeof(real)); errno = 0; for (i = 0; i < n; ++i) { parameters[i] = (real) strtod(rest[i], NULL); if (errno) { mwPerror("Error parsing command line fit parameters at '%s'", rest[i]); free(parameters); return NULL; } } return parameters; }
int nbWriteBodies(const NBodyCtx* ctx, const NBodyState* st, const NBodyFlags* nbf) { FILE* f; int rc = 0; if (!nbf->outFileName) { return 1; } f = mwOpenResolved(nbf->outFileName, nbf->outputBinary ? "wb" : "w"); if (!f) { mw_printf("Failed to open output file '%s'\n", nbf->outFileName); return 1; } if (nbf->outputBinary) { mw_printf("Binary output unimplemented\n"); return 1; } else { mw_boinc_print(f, "<bodies>\n"); rc = nbOutputBodies(f, ctx, st, nbf); mw_boinc_print(f, "</bodies>\n"); } if (fclose(f) < 0) { mwPerror("Error closing output file '%s'", nbf->outFileName); } return rc; }
static scene_t* nbglLoadStaticSceneFromFile(const char* filename) { FILE* f; size_t lnCount; /* ~= nbody */ size_t line = 0; int nbody = 0; char lnBuf[4096]; int rc = 0; int ignore; double x, y, z; double vx, vy, vz; double lambda; FloatPos* r; int hasError = FALSE; scene_t* scene = NULL; f = fopen(filename, "r"); if (!f) { mwPerror("Failed to open file '%s'", filename); return NULL; } lnCount = mwCountLinesInFile(f); if (lnCount == 0) { mw_printf("Error counting lines from file '%s'\n", filename); fclose(f); return NULL; } scene = mwCalloc(sizeof(scene_t) + 1 * (lnCount * sizeof(FloatPos)), sizeof(char)); /* We don't need the buffering features so just use first buffer slot */ r = &scene->queue.bodyData[0]; scene->hasInfo = FALSE; scene->staticScene = TRUE; /* Make read data fake that we have 1 element in the queue */ OPA_store_int(&scene->queue.head, 0); OPA_store_int(&scene->queue.tail, 1); readCoordinateSystem = FALSE; readHasGalaxy = FALSE; readCenterOfMass = FALSE; while (fgets(lnBuf, (int) sizeof(lnBuf), f) && line < lnCount) { ++line; if (strlen(lnBuf) + 1 >= sizeof(lnBuf)) { mw_printf("Error reading histogram line "ZU" (Line buffer too small): %s", line, lnBuf); hasError = TRUE; break; } /* Skip comments and blank lines */ if (lnBuf[0] == '#' || lnBuf[0] == '\n') continue; if (nbglTryReadSceneItems(lnBuf, scene)) continue; rc = sscanf(lnBuf, "%d , %lf , %lf , %lf , %lf , %lf , %lf ", &ignore, &x, &y, &z, &vx, &vy, &vz); if (rc == 7) { /* May or may not be there */ rc = sscanf(lnBuf, " , %lf \n", &lambda); if (rc != 1) { sscanf(lnBuf, " \n"); } r[nbody].x = (float) x; r[nbody].y = (float) y; r[nbody].z = (float) z; ++nbody; } else { hasError = TRUE; } } if (fclose(f)) { mwPerror("Failed to close file '%s'", filename); } if (!readCoordinateSystem || !readHasGalaxy || !readCenterOfMass) { mw_printf("Warning: Failed to read some scene info items\n"); } scene->nbody = nbody; if (hasError) { free(scene); return NULL; } return scene; }
/* Create the next available segment of the form /milkyway_nbody_n n = 0 .. 127*/ int nbCreateSharedScene(NBodyState* st, const NBodyCtx* ctx) { size_t size = sizeof(scene_t) + st->nbody * sizeof(FloatPos); int shmId = -1; const int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; void* p = NULL; int instanceId = -1; char name[128]; /* Try looking for the next available segment of the form /milkyway_nbody_<n> */ while (shmId < 0 && instanceId < MAX_INSTANCES) { ++instanceId; if (snprintf(name, sizeof(name), "/milkyway_nbody_%d", instanceId) == sizeof(name)) mw_panic("Buffer too small for scared memory name\n"); shmId = shm_open(name, O_CREAT | O_RDWR | O_EXCL, mode); /* Try to open exclusively */ if (shmId < 0 && errno != EEXIST) /* Only failed if */ { mwPerror("Error creating shared memory '%s'", name); return 1; } } if (instanceId >= MAX_INSTANCES) { mw_printf("Could not open new shm segment in %d tries\n", MAX_INSTANCES); return 1; } if (ftruncate(shmId, size) < 0) /* Make the segment the correct size */ { mwPerror("Error ftruncate() shared memory"); if (shm_unlink(name) < 0) { mwPerror("Error unlinking shared memory '%s'", name); } return 1; } p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmId, 0); if (p == MAP_FAILED) { mwPerror("mmap: Failed to mmap shared memory"); if (shm_unlink(name) < 0) { mwPerror("Error unlinking shared memory '%s'", name); } return 1; } st->scene = (scene_t*) p; st->shmId = shmId; st->scene->instanceId = instanceId; strncpy(st->scene->shmemName, name, sizeof(st->scene->shmemName)); nbPrepareSceneFromState(ctx, st); return 0; }
void nbLaunchVisualizer(NBodyState* st, const char* visArgs) { pid_t pid; const char* path = NULL; char* newPath = NULL; int argc = 0; char* buf = NULL; char* p = NULL; char** argv = NULL; size_t argvSize = 0; size_t visArgsLen = 0; char idArg[128]; if (!st->scene) /* If there's no scene to share, there's no point */ return; if (st->usesExact) { mw_printf("Visualizer broken with Exact\n"); return; } pid = fork(); if (pid != 0) /* Parent */ return; /* Child */ /* Put places convenient for testing. Not essential, failure of * any of these is OK */ path = getenv("PATH"); if (!path) { mwPerror("Error getting PATH"); } else { if (asprintf(&newPath, ".:../bin/:%s", path) < 0) { mwPerror("Appending to path"); } else { if (setenv("PATH", newPath, TRUE) < 0) { mwPerror("Error setting PATH"); } free(newPath); } } if (snprintf(idArg, sizeof(idArg), "--instance-id=%d ", st->scene->instanceId) == sizeof(idArg)) mw_panic("Buffer too small for --instance-id visualizer argument\n"); /* Stick the program name at the head of the arguments passed in */ visArgsLen = visArgs ? strlen(visArgs) : 0; argvSize = visArgsLen + sizeof(idArg) + sizeof(nbodyGraphicsName) + 2; /* arguments + program name + space + null */ buf = mwCalloc(argvSize, sizeof(char)); p = stpcpy(buf, nbodyGraphicsName); p = stpcpy(p, " "); p = stpcpy(p, idArg); if (visArgs) { stpcpy(p, visArgs); } if (poptParseArgvString(buf, &argc, (const char***) &argv)) { mw_printf("Error parsing arguments for visualizer '%s'\n", visArgs); free(buf); return; } if (execvp(argv[0], argv) < 0) { mwPerror("Failed to launch visualizer '%s'", argv[0]); } free(buf); free(argv); mw_finish(EXIT_SUCCESS); /* Unnecessary */ }