📄 checkpoint.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. * *//***************************************************************** * checkpoint.c * * Generic checkpoint handling code. *****************************************************************/#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>#include "sim.h"#include "simutil.h"#include "sim_error.h"#include "cpu_interface.h"#include "remote_access.h"#include "checkpoint.h"#include "cpu_interface.h"#include "machine_params.h"#include "params.h"#define MAX_GROUPS 50#define MAX_LENGTH 128#define IS_REMOTE_CPT(NAME) (strchr(NAME,':') != NULL)typedef enum cpttype {CPT_INTEGER = 0, CPT_STRING, CPT_BLOCK} CptType;static char lineFormat[3][20] = {"%s = %s", "%s [%d] = %s", "%s [%d,%d] = %s"};#ifdef __alpha#define INT_FORMAT "int:%ld"#define HEX_FORMAT "int:0x%lx"#define BLOCK_FORMAT "binary:position=%ld,size=%ld;"typedef long cptlong;#else#define INT_FORMAT "int:%lld"#define HEX_FORMAT "int:0x%llx"#define BLOCK_FORMAT "binary:position=%lld,size=%lld;"typedef int64 cptlong;#endif#define STRING_FORMAT "string:%s"typedef struct compressiondata { CptCompression type; char compress[MAX_PATH_LENGTH]; char decompress[MAX_PATH_LENGTH]; char extender[10];} CompressionData;typedef struct cptentry { char *name; int i1, i2; CptType type; bool optional; int64 intval; int64 ptrval; struct cptentry *prev; struct cptentry *next;} CptEntry;typedef struct cptgroup { char *tag; FILE *stream; int binfd; int binpos; int failure; CptCompression compressCpt[2]; CptCompression compressBin[2]; CptEntry *tail; CptEntry *hint; CptCallback *callback[NUM_CPU_TYPES];} CptGroup;static CptGroup cptGroup[MAX_GROUPS];static int cptNumGroups;static bool cptRemote;static CompressionData compression[] = { { NO_COMPRESSION, "cat", "cat", "" }, { GZIP, "gzip", "gunzip", ".gz" }, { COMPRESS, "compress", "zcat", ".Z" }};typedef enum {ITER_CPT, ITER_LOG, NUM_ITERS} CptIter;static CptGroup *NewGroup(char *tag);static CptGroup *FindGroup(char *tag);static CptGroup *IterGroup(CptIter num);static CptEntry *NewEntry(char *name, int i1, int i2, CptType type);static void AddEntry(CptGroup *group, CptEntry *entry);static void FreeEntry(CptEntry *entry);static CptEntry *FindEntryInList(CptGroup *group, char *name, int i1, int i2);static CptEntry *FindEntryInFile(CptGroup *group, char *name, int i1, int i2);static bool ParseInteger(char *str, cptlong *val);static bool ParseBlock(char *str, cptlong *ptr, cptlong *val);static bool ParseString(char *str, char *val);static int64 ReadInteger(CptGroup *group, char *name, int i1, int i2);static char *ReadString(CptGroup *group, char *name, int i1, int i2);static int64 ReadBlock(CptGroup *group, char *name, int i1, int i2, int *size);static void WriteHexInteger(CptGroup *group, char *name, int i1, int i2, int64 val);static void WriteInteger(CptGroup *group, char *name, int i1, int i2, int64 val);static void WriteString(CptGroup *group, char *name, int i1, int i2, char *ptr);static void WriteBlock(CptGroup *group, char *name, int i1, int i2, int64 pos, int64 val);static CptCallback LogCheckpointCB;static FILE *OpenFile(CptMode mode, char *filename, CptCompression compress);static FILE *OpenCompressedFile(CptMode mode, CptCompression c, FILE *fp);static void OpenCptFile(CptMode mode, CptGroup *group);static void OpenBinFile(CptMode mode, CptGroup *group);static void CloseCptFile(CptGroup *group);static void CloseBinFile(CptGroup *group);static void SaveLine(CptGroup *group, char *name, int i1, int i2, char *valstring);static int RestoreLine(CptGroup *group, char *name, int *i1, int *i2, char *valstring);static void SaveBlock(CptGroup *group, caddr_t addr, int size);static int RestoreBlock(CptGroup *group, caddr_t addr, int pos, int size);static int outputFD = -1;static int compressPID = -1;char *CheckpointID;int CheckpointCompress;char *cptSaveDir;char cptName[MAX_PATH_LENGTH];CptVersion cptVersion;voidSimcpt_Init(void){ cptSaveDir = SaveString("."); cptNumGroups = 0; cptVersion.saveVer = CPT_VERSION; cptVersion.saveSub = CPT_SUB_VERSION; Simcpt_Register("log", LogCheckpointCB, ALL_CPUS);}extern char *EthersimHostname; /* crissy */extern char *EtherAddress; /* 8:1:2:3:4:60 */voidSimcpt_Register(char *tag, CptCallback *callback, CPUType cputype){ CptGroup *group = NewGroup(tag); if (group != NULL) { if (cputype == ALL_CPUS) { for (cputype = BASE; cputype < NUM_CPU_TYPES; cputype++) { group->callback[cputype] = callback; } } else if (cputype != NO_CPU) { group->callback[cputype] = callback; } }}voidSimcpt_UseCompression(char *name, CptCompression compress, CptCompressMode mode){ CptGroup *group = FindGroup(name); if (!CheckpointCompress) return; if (group != NULL) { if (mode != CPT_FILE_ONLY) group->compressBin[CPT_SAVE] = compress; if (mode != BIN_FILE_ONLY) group->compressCpt[CPT_SAVE] = compress; }}intCheckpointFile(CptMode mode, CptGroup *group){ CptDescriptor cptd; int retval = 0; CPUType cputype = (mode == CPT_SAVE)?simosCPUType:BASE; /* CPUType cputype = CPUVec.cpuType;*/ cptd.mode = mode; cptd.group = group; SIM_DEBUG(('g', "CPT: %s checkpoint file %s\n", mode == CPT_SAVE ? "Saving" : "Restoring", group->tag)); cptd.group->failure = FALSE; /* Ugly hack -- when restoring the execstate, always use the base mode callback */ if (!strcmp(group->tag, "execstate") && (mode == CPT_RESTORE)) cputype = BASE; /* Even uglier hack: Tcl manages the file itself, so don't go * through the usual opening/closing stuff. */ if (!strcmp(group->tag, "tcl")) { ASSERT(group->callback[cputype]); retval = (group->callback[cputype])(&cptd); goto done; } if (group->callback[cputype] == NULL) { if (!strcmp(group->tag,"HOHA")) { /* * I guess that HOHA already stands for horrible hack anyway */ return 0; } CPUWarning("CPT: Cpt failed -- no callback registered for %s in %s\n", group->tag, simName[cputype]); return -1; } Simcpt_Begin(&cptd); retval = (group->callback[cputype])(&cptd); Simcpt_End(&cptd);done: group->failure = group->failure || (retval != 0); if (group->failure) CPUError("CPT: Checkpoint failed, tag = %s\n", group->tag); SIM_DEBUG(('g', "CPT: Done %s checkpoint file %s\n", mode == CPT_SAVE ? "saving" : "restoring", group->tag)); return (group->failure) ? -1 : 0;}voidSimcpt_Checkpoint(CptMode mode, char *name){ CptGroup *group; if (mode == CPT_SAVE) { int num; char pathname[MAX_PATH_LENGTH]; /* Check if the checkpoint save directory exists and is writeable */ if (access(cptSaveDir, F_OK | W_OK | X_OK) != 0) { CPUWarning("CPT: Bad checkpoint save directory %s\n",cptSaveDir); perror("CPT: Cannot write checkpoint"); CPUWarning("\n"); return; } /* Search for an unused checkpoint number */ for (num = 1; ; num++) { sprintf(cptName, "CPT.%s.%03d", CheckpointID, num); sprintf(pathname, "%s/%s.log", cptSaveDir, cptName); if (access(pathname, F_OK) != 0) break; } cptRemote = FALSE; } else if (IS_REMOTE_CPT(name)) { Simrmt_cptinit(name, cptName); cptRemote = TRUE; } else { strcpy(cptName, name); cptRemote = FALSE; } CPUWarning("CPT: %s checkpoint %s\n", mode == CPT_SAVE ? "Saving" : "Restoring", cptName); if (mode == CPT_SAVE) { while ((group = IterGroup(ITER_CPT)) != NULL) { CheckpointFile(mode, group); } CPUWarning("CPT: End checkpoint save\n"); } else { CheckpointFile(mode, FindGroup("log")); } }intSimcpt_Restore(char *tag){ CptGroup *group = FindGroup(tag); if (group != NULL) { return CheckpointFile(CPT_RESTORE, group); } else { CPUWarning("CPT: Checkpoint file %s has not been restored\n", tag); return -1; }}voidSimcpt_Begin(CptDescriptor *cptd){ SIM_DEBUG(('g', "CPT: Simcpt_Begin %s\n", cptd->group->tag)); OpenCptFile(cptd->mode, cptd->group);}voidSimcpt_End(CptDescriptor *cptd){ CloseCptFile(cptd->group); if (cptd->group->binfd > 0) CloseBinFile(cptd->group); SIM_DEBUG(('g', "CPT: Simcpt_End %s\n", cptd->group->tag)); if (cptd->mode == CPT_RESTORE) { /* Verify that all data were used here and free the entries */ if (cptd->group->tail != NULL) { CptEntry *entry = cptd->group->tail; CptEntry *oldentry; do { if (!entry->optional) { CPUWarning("CPT: Entry %s [%d,%d] in file %s not used\n", entry->name, entry->i1, entry->i2, cptd->group->tag); } oldentry = entry; entry = oldentry->next; FreeEntry(oldentry); } while (entry != cptd->group->tail); cptd->group->tail = NULL; } SIM_DEBUG(('g', "CPT: Done restoring from checkpoint file %s\n", cptd->group->tag)); }} static CptGroup *NewGroup(char *tag) { CptGroup *group = FindGroup(tag); if (group != NULL) { return group; } else if (cptNumGroups == MAX_GROUPS) { CPUWarning("CPT: Too many cpt groups -- creation of group %s failed\n", tag); return NULL; } else { group = cptGroup + cptNumGroups++; group->tag = SaveString(tag); group->binfd = -1; return group; }}static CptGroup *FindGroup(char *tag) { int g; CptGroup *group = cptGroup; for (g = 0; g < cptNumGroups; g++, group++) { if (!strcmp(group->tag, tag)) return group; } return NULL;}static CptGroup *IterGroup(CptIter num){ static int currentGroup[NUM_ITERS]; if (currentGroup[num] == cptNumGroups) { currentGroup[num] = 0; return NULL; } else { return cptGroup + currentGroup[num]++; }}static CptEntry *NewEntry(char *name, int i1, int i2, CptType type){ CptEntry *entry = (CptEntry *) MALLOC(sizeof(CptEntry), name); entry->name = SaveString(name); entry->i1 = i1; entry->i2 =i2; entry->type = type; entry->optional = FALSE; return entry;}static voidAddEntry(CptGroup *group, CptEntry *entry)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -