00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "converse.h"
00010 #include "cklists.h"
00011 #include <string.h>
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <strings.h>
00015 #include <errno.h>
00016
00017 #include "charm.h"
00018 #include "pup.h"
00019
00020 #if CMK_HAS_ELF_H
00021 #include <elf.h>
00022
00023 #define DEBUG_GOT_MANAGER 0
00024
00025 #if !CMK_SHARED_VARS_UNAVAILABLE
00026 # error "Global-elfcopy won't work properly under smp version: -copyglobals disabled"
00027 #endif
00028
00029 CpvDeclare(int, CmiPICMethod);
00030
00031 #if CMK_AMD64 || CMK_CRAYXT
00032 typedef Elf64_Addr ELFXX_TYPE_Addr;
00033 typedef Elf64_Dyn ELFXX_TYPE_Dyn;
00034 typedef Elf64_Rela ELFXX_TYPE_Rel;
00035 typedef Elf64_Sym ELFXX_TYPE_Sym;
00036 #define ELFXX_R_TYPE ELF64_R_TYPE
00037 #define ELFXX_R_SYM ELF64_R_SYM
00038 #define ELFXX_ST_TYPE ELF64_ST_TYPE
00039 #define CMK_DT_REL DT_RELA
00040 #define CMK_DT_RELSZ DT_RELASZ
00041 #define is_elf_global(x) ((x) == R_X86_64_GLOB_DAT)
00042 #elif CMK_IA64
00043 #error "NOT SUPPORTED"
00044 #else
00045 typedef Elf32_Addr ELFXX_TYPE_Addr;
00046 typedef Elf32_Dyn ELFXX_TYPE_Dyn;
00047 typedef Elf32_Rel ELFXX_TYPE_Rel;
00048 typedef Elf32_Sym ELFXX_TYPE_Sym;
00049 #define ELFXX_R_TYPE ELF32_R_TYPE
00050 #define ELFXX_R_SYM ELF32_R_SYM
00051 #define ELFXX_ST_TYPE ELF32_ST_TYPE
00052 #define CMK_DT_REL DT_REL
00053 #define CMK_DT_RELSZ DT_RELSZ
00054 #define is_elf_global(x) ((x) == R_386_GLOB_DAT)
00055 #endif
00056
00057 extern ELFXX_TYPE_Dyn _DYNAMIC[];
00058
00059
00063 class CtgGlobalList
00064 {
00065 int datalen;
00066 struct CtgRec {
00067 void *got;
00068 int off;
00069 int size;
00070 CtgRec() {got=NULL;}
00071 CtgRec(void *got_,int off_,int size_) :got(got_), off(off_), size(size_) {}
00072 };
00073 CkVec<CtgRec> rec;
00074 int nRec;
00075 public:
00081 CtgGlobalList();
00082
00084 inline int getSize(void) const {return datalen;}
00085
00088 void read(void *datav) const;
00089
00091 inline void install(void *datav) const {
00092 char *data=(char *)datav;
00093 for (int i=0;i<nRec;i++) {
00094 memcpy((void *)rec[i].got, data+rec[i].off, rec[i].size);
00095 }
00096 }
00097
00098 inline void install_var(void *datav, void *ptr) const {
00099 char *data=(char *)datav;
00100 for (int i=0;i<nRec;i++) {
00101 long offset = (char*)ptr-(char *)rec[i].got;
00102 if (offset >= 0 && offset < rec[i].size) {
00103 memcpy((void *)rec[i].got, data+rec[i].off, rec[i].size);
00104 break;
00105 }
00106 }
00107 }
00108
00109 void read_var(void *datav, void *ptr) const;
00110
00111 private:
00112
00113
00114
00115 int isUserSymbol(const char *name);
00116 };
00117
00118 int CtgGlobalList::isUserSymbol(const char *name) {
00119
00120 if((strncmp("_", name, 1) == 0) || (strncmp("Cpv_", name, 4) == 0)
00121 || (strncmp("Csv_", name, 4) == 0) || (strncmp("Ctv_", name, 4) == 0)
00122 || (strncmp("Bnv_", name, 4) == 0) || (strncmp("Bpv_", name, 4) == 0)
00123 || (strncmp("ckout", name, 5) == 0) || (strncmp("stdout", name, 6) == 0)
00124 || (strncmp("environ", name, 7) == 0)
00125 || (strncmp("stderr", name, 6) == 0) || (strncmp("stdin", name, 5) == 0))
00126 return 0;
00127
00128 return 1;
00129 }
00130
00131 void CtgGlobalList::read(void *datav) const {
00132 char *data=(char *)datav;
00133 for (int i=0;i<nRec;i++) {
00134 memcpy(data+rec[i].off, (void *)rec[i].got, rec[i].size);
00135 }
00136 }
00137
00138 void CtgGlobalList::read_var(void *datav, void *ptr) const {
00139 char *data=(char *)datav;
00140 for (int i=0;i<nRec;i++) {
00141 long offset = (char*)ptr-(char *)rec[i].got;
00142 if (offset >= 0 && offset < rec[i].size) {
00143 memcpy(data+rec[i].off, (void *)rec[i].got, rec[i].size);
00144 break;
00145 }
00146 }
00147 }
00148
00149 CkVec<char *> _namelist;
00150 static int loaded = 0;
00151
00152 extern "C" int lookup_obj_sym(char *name, unsigned long *val, int *size);
00153
00154
00155 static void readGlobals()
00156 {
00157 if (loaded) return;
00158 const char *fname = "globals";
00159 printf("Loading globals from file \"%s\" ... \n", fname);
00160 FILE *gf = fopen(fname, "r");
00161 if (gf == NULL) {
00162 CmiAbort("Failed to load globals, file may not exist!");
00163 }
00164 while (!feof(gf))
00165 {
00166 char name[1024];
00167 fscanf(gf, "%s\n", name);
00168 _namelist.push_back(strdup(name));
00169 }
00170 fclose(gf);
00171 loaded = 1;
00172 }
00173
00174
00180 CtgGlobalList::CtgGlobalList() {
00181 datalen=0;
00182 nRec=0;
00183
00184 int count;
00185 for (count = 0; count < _namelist.size(); count ++)
00186 {
00187 unsigned long addr;
00188 int size;
00189 if (0 > lookup_obj_sym(_namelist[count], &addr, &size)) {
00190 fprintf(stderr, "%s: no such symbol\n", _namelist[count]);
00191 continue;
00192 }
00193 void *ptr = (void *)addr;
00194 int gSize = ALIGN8(size);
00195
00196
00197 printf(" -> %s is a user global, of size %d, at %p\n",
00198 _namelist[count], size, ptr);
00199
00200
00201 rec.push_back(CtgRec(ptr,datalen,size));
00202 datalen+=gSize;
00203 }
00204
00205 nRec=rec.size();
00206
00207 #if DEBUG_GOT_MANAGER
00208 printf("relt has %d entries, %d of which are user globals\n\n",
00209 relt_size,nRec);
00210 #endif
00211 }
00212
00213
00214 CpvStaticDeclare(CtgGlobals,_curCtg);
00215
00216 struct CtgGlobalStruct {
00217 public:
00218
00219 int installed;
00220 int inited;
00221
00222
00223 void *data_seg;
00224 int seg_size;
00225
00226 void allocate(int size, CthThread tid) {
00227 seg_size=size;
00228
00229 if (CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC))
00230 data_seg=CmiIsomalloc(seg_size,tid);
00231 else
00232 data_seg=malloc(seg_size);
00233 inited = 0;
00234 }
00235
00236 CtgGlobalStruct(void) {
00237 installed=0;
00238 data_seg=0;
00239 }
00240 ~CtgGlobalStruct() {
00241 if (!CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC)) {
00242 if (data_seg) {
00243 free(data_seg);
00244 }
00245 }
00246 }
00247
00248 void pup(PUP::er &p);
00249 };
00250
00251 void CtgGlobalStruct::pup(PUP::er &p) {
00252 p | seg_size;
00253
00254 if (CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC))
00255 #if CMK_USE_MEMPOOL_ISOMALLOC
00256 pup_bytes(&p, &data_seg, sizeof(void*));
00257 #else
00258 CmiIsomallocPup(&p, &data_seg);
00259 #endif
00260 else {
00261 if (p.isUnpacking()) allocate(seg_size, NULL);
00262 p((char *)data_seg, seg_size);
00263 }
00264 }
00265
00267 static CtgGlobalList *_ctgList=NULL;
00269 static CtgGlobalStruct *_ctgListGlobals=NULL;
00270
00271 extern "C" int init_symtab(char *exename);
00272
00274 void CtgInit(void) {
00275 CpvInitialize(int, CmiPICMethod);
00276 CpvAccess(CmiPICMethod) = 2;
00277 CpvInitialize(CtgGlobal,_curCtg);
00278
00279 if (!_ctgList)
00280 {
00281
00282
00283
00284 readGlobals();
00285 init_symtab(CkGetArgv()[0]);
00286
00287 CtgGlobalList *l=new CtgGlobalList;
00288 CtgGlobalStruct *g=new CtgGlobalStruct;
00289 if (CmiMyNode()==0) {
00290 CmiPrintf("CHARM> -copyglobals enabled\n");
00291 }
00292
00293 g->allocate(l->getSize(),NULL);
00294 l->read(g->data_seg);
00295 l->install(g->data_seg);
00296 _ctgList=l;
00297 _ctgListGlobals=g;
00298 }
00299
00300
00301 CpvAccess(_curCtg)=_ctgListGlobals;
00302 }
00303
00305 CtgGlobals CtgCreate(CthThread tid) {
00306 CtgGlobalStruct *g=new CtgGlobalStruct;
00307 g->allocate(_ctgList->getSize(), tid);
00308 _ctgList->read(g->data_seg);
00309 return g;
00310 }
00311
00313 CtgGlobals CtgPup(pup_er pv, CtgGlobals g) {
00314 PUP::er *p=(PUP::er *)pv;
00315 if (p->isUnpacking()) g=new CtgGlobalStruct;
00316 if (g->installed)
00317 CmiAbort("CtgPup called on currently installed globals!\n");
00318 g->pup(*p);
00319 if (g->seg_size!=_ctgList->getSize())
00320 CmiAbort("CtgPup: global variable size changed during migration!\n");
00321 return g;
00322 }
00323
00325 void CtgInstall(CtgGlobals g) {
00326 CtgGlobals *cur=&CpvAccess(_curCtg);
00327 CtgGlobals oldG=*cur;
00328 if (g==NULL) g=_ctgListGlobals;
00329 if (g == oldG) return;
00330 if (oldG) {
00331 _ctgList->read(oldG->data_seg);
00332 }
00333 *cur=g;
00334 oldG->installed=0;
00335 _ctgList->install(g->data_seg);
00336 g->installed=1;
00337 }
00338
00340 void CtgFree(CtgGlobals g) {
00341 if (g->installed) CmiAbort("CtgFree called on currently installed globals!\n");
00342 delete g;
00343 }
00344
00345 CtgGlobals CtgCurrentGlobals(void){
00346 return CpvAccess(_curCtg);
00347 }
00348
00349 void CtgInstall_var(CtgGlobals g, void *ptr) {
00350 CtgGlobals *cur=&CpvAccess(_curCtg);
00351 CtgGlobals oldG = *cur;
00352 if (oldG)
00353 _ctgList->read_var(oldG->data_seg, ptr);
00354 _ctgList->install_var(g->data_seg, ptr);
00355 }
00356
00357 void CtgUninstall_var(CtgGlobals g, void *ptr) {
00358 CtgGlobals *cur=&CpvAccess(_curCtg);
00359 CtgGlobals oldG = *cur;
00360 if (oldG)
00361 _ctgList->read_var(g->data_seg, ptr);
00362 _ctgList->install_var(oldG->data_seg, ptr);
00363 }
00364
00365 #else
00366
00367 #include "global-nop.c"
00368
00369 #endif