int isi_remove_sync(struct objtype *target) { struct isiNetSync *ns = 0; if(!isi_find_sync(target, &ns)) { isilog(L_DEBUG, "netsync: request to remove non-existent sync\n"); } isilog(L_DEBUG, "netsync: TODO remove sync\n"); return 0; }
int isi_set_devmemsync_extent(struct objtype *target, struct objtype *memtarget, uint32_t index, uint32_t base, uint32_t extent) { struct isiNetSync *ns = 0; if(memtarget->objtype < 0x2000 || memtarget->objtype > 0x2fff) return -1; if(!isi_find_devmem_sync(target, memtarget, &ns)) { isi_create_sync(&ns); ns->target.id = target->id; ns->target.objtype = target->objtype; ns->memobj.id = memtarget->id; ns->memobj.objtype = memtarget->objtype; ns->synctype = ISIN_SYNC_MEMDEV; ns->rate = 50000000; isi_synctable_add(ns); } if(index > 3) return -1; if(index+1 > ns->extents) ns->extents = index+1; if(ns->extents > 4) return -1; ns->ctl |= NSY_SYNCMEM; ns->ctl &= ~NSY_SYNCOBJ; if(ns->base[index] != base || ns->len[index] != extent) { ns->ctl &= ~(NSY_MEM | NSY_MEMVALID); isilog(L_DEBUG, "netsync: adding extent to sync [%d][0x%04x +0x%04x]\n", index, base, extent); ns->base[index] = base; ns->len[index] = extent; } return ns->extents - 1; }
void enter_service() { pid_t pid, sid; pid = fork(); if(pid < 0) { isilogerr("fork"); exit(1); } if(pid > 0) { isilog(L_INFO, "entering service\n"); exit(0); } umask(0); open_log(); /* if( (chdir("/")) < 0 ) { isilogerr("chdir"); }*/ sid = setsid(); if(sid < 0) { isilogerr("setsid"); exit(1); } close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); }
int isi_add_devsync(struct objtype *target, size_t rate) { struct isiNetSync *ns = 0; if(!isi_find_sync(target, &ns)) { isi_create_sync(&ns); ns->target.id = target->id; ns->target.objtype = target->objtype; isi_synctable_add(ns); ns->synctype = ISIN_SYNC_DEVR; ns->rate = rate; ns->ctl = 0; isilog(L_DEBUG, "netsync: adding dev sync, rate=%ld \n", rate); } else if(ns->rate != rate) { ns->rate = rate; isilog(L_DEBUG, "netsync: resetting memdev sync rate=%ld \n", rate); } ns->ctl &= ~NSY_SYNCOBJ; return 0; }
int isi_deattach(struct isiInfo *item, int32_t itempoint) { if(!item || itempoint < ISIAT_LIMIT || itempoint == ISIAT_APPEND) return ISIERR_INVALIDPARAM; if(item->id.objtype < 0x2f00) return ISIERR_INVALIDPARAM; /* can't process weird things */ struct isiInfo *dev = NULL; if(itempoint == ISIAT_UP) { dev = item->updev.t; } else if(itempoint == ISIAT_INSERTSTART) { return ISIERR_NOTSUPPORTED; } else if(isi_getindex_dev(item, itempoint, &dev)) { return ISIERR_FAIL; } int32_t rai; if(itempoint == ISIAT_UP) { rai = item->updev.i; item->updev.t = NULL; item->updev.i = -1; } else if(itempoint >= 0) { rai = item->busdev.table[itempoint].i; /* getindex_dev should make sure this is valid */ item->busdev.table[itempoint].t = NULL; item->busdev.table[itempoint].i = -1; /* collapse empty space at end of table */ for(int i = item->busdev.count; i-->0 && !item->busdev.table[i].t; item->busdev.count--); } else { isilog(L_WARN, "invalid local deattach point A=%d", itempoint); rai = -1; } isilog(L_DEBUG, "deattach call A=%d B=%d\n", itempoint, rai); if(dev->id.objtype < 0x2f00) return 0; /* weird thing, we're done */ if(rai == ISIAT_UP) { dev->updev.t = NULL; dev->updev.i = -1; } else if(rai >= 0 && !isi_getindex_dev(dev, rai, NULL)) { dev->busdev.table[rai].t = NULL; dev->busdev.table[rai].i = -1; /* collapse empty space at end of table */ for(int i = dev->busdev.count; i-->0 && !dev->busdev.table[i].t; dev->busdev.count--); } else { isilog(L_WARN, "invalid remote deattach point A=%d B=%d", itempoint, rai); } return 0; }
uint32_t isi_lookup_name(const char * name) { if(!name) return 0; for(uint32_t i = 0; i < allcon.count; i++) { if(!strcmp(allcon.table[i]->name, name)) { return allcon.table[i]->objtype; } } isilog(L_INFO, "object: lookup name failed for: %s\n", name); return 0; }
void open_log() { int lf; if( (lf = open("/var/log/isi.log", O_WRONLY | O_APPEND | O_CREAT, 0644)) > -1 ) { fdlog = lf; } else if( (lf = open("/var/lib/isicpu/isi.log", O_WRONLY | O_APPEND | O_CREAT, 0644)) > -1 ) { fdlog = lf; } else if( (lf = open("isi.log", O_WRONLY | O_APPEND | O_CREAT, 0644)) > -1 ) { fdlog = lf; isilog(L_WARN, "local dir log file\n"); } else fdlog = -1; }
int isi_add_devmemsync(struct objtype *target, struct objtype *memtarget, size_t rate) { struct isiNetSync *ns = 0; if(memtarget->objtype < 0x2000 || memtarget->objtype > 0x2fff) return -1; if(!isi_find_devmem_sync(target, memtarget, &ns)) { isi_create_sync(&ns); ns->target.id = target->id; ns->target.objtype = target->objtype; ns->memobj.id = memtarget->id; ns->memobj.objtype = memtarget->objtype; isi_synctable_add(ns); ns->synctype = ISIN_SYNC_MEMDEV; ns->rate = rate; isilog(L_DEBUG, "netsync: adding memdev sync, rate=%ld \n", rate); ns->ctl = 0; } else if(ns->rate != rate) { ns->rate = rate; isilog(L_DEBUG, "netsync: resetting memdev sync rate=%ld \n", rate); } ns->ctl |= NSY_SYNCMEM; ns->ctl &= ~NSY_SYNCOBJ; return 0; }
int isi_add_memsync(struct objtype *target, uint32_t base, uint32_t extent, size_t rate) { struct isiNetSync *ns = 0; if(target->objtype < 0x2000 || target->objtype > 0x2fff) return -1; if(!isi_find_sync(target, &ns)) { isi_create_sync(&ns); ns->memobj.id = target->id; ns->memobj.objtype = target->objtype; isi_synctable_add(ns); ns->synctype = ISIN_SYNC_MEM; } ns->rate = rate; if(ns->extents >= 4) return -1; isilog(L_DEBUG, "netsync: adding extent to sync [0x%04x +0x%04x]\n", base, extent); ns->base[ns->extents] = base; ns->len[ns->extents] = extent; ns->extents++; ns->ctl = 0; return ns->extents; }
int isi_set_sync_extent(struct objtype *target, uint32_t index, uint32_t base, uint32_t extent) { struct isiNetSync *ns = 0; if(target->objtype < 0x2000 || target->objtype > 0x2fff) return -1; if(!isi_find_sync(target, &ns)) { isi_create_sync(&ns); ns->memobj.id = target->id; ns->memobj.objtype = target->objtype; isi_synctable_add(ns); ns->rate = 10000; ns->synctype = ISIN_SYNC_MEM; } if(index > 3) return -1; if(index+1 > ns->extents) ns->extents = index+1; if(ns->extents > 4) return -1; isilog(L_DEBUG, "netsync: adding extent to sync [%d][0x%04x +0x%04x]\n", index, base, extent); ns->base[index] = base; ns->len[index] = extent; ns->ctl = 0; return ns->extents - 1; }
int isi_register(struct isiConstruct *obj) { int itype; int inum; if(!obj) return -1; if(!obj->name) return -1; if(!obj->objtype) return -1; itype = obj->objtype & 0xf000; inum = obj->objtype & 0x0fff; for(uint32_t i = 0; i < allcon.count; i++) { int ltype = allcon.table[i]->objtype & 0xf000; int lnum = allcon.table[i]->objtype & 0x0fff; if(ltype == itype) { if(lnum >= inum) { inum = lnum + 1; } } } obj->objtype = (itype & 0xf000) | (inum & 0x0fff); isi_contable_add(obj); isilog(L_INFO, "object: %s registered as %04x\n", obj->name, obj->objtype); return 0; }
void sysfaulthdl(int ssn) { switch(ssn) { case SIGTERM: isilog(L_CRIT, "SHUTTING DOWN ON SIGTERM!\n"); exit(4); case SIGINT: if(haltnow) { isilog(L_CRIT, "FORCED ABORT!\n"); exit(4); } haltnow = 1; isilog(L_ERR, "SIGNAL CAUGHT!\n"); break; case SIGHUP: isilog(L_WARN, "HUP RECEIVED\n"); break; case SIGPIPE: isilog(L_WARN, "SOCKET SIGNALED!\n"); break; default: isilog(L_ERR, "Unknown signal\n"); break; } }
void isi_run_sync(isi_time_t crun) { size_t i, k; int x; for(i = 0; i < allsync.count; i++) { struct isiNetSync *ns = allsync.table[i]; struct memory64x16 *mem = 0; if(!ns) continue; if(ns->ctl) { /* check cache indexes */ if((ns->ctl & NSY_OBJ) && ( !ns->target.id || !allobj.table[ns->target_index] || allobj.table[ns->target_index]->id != ns->target.id)) { ns->ctl ^= NSY_OBJ; isilog(L_DEBUG, "netsync: invalidated index\n"); } if((ns->ctl & NSY_MEM) && ( !ns->memobj.id || !allobj.table[ns->memobj_index] || allobj.table[ns->memobj_index]->id != ns->memobj.id)) { ns->ctl &= ~(NSY_MEMVALID|NSY_MEM|NSY_SYNCMEM); isilog(L_DEBUG, "netsync: invalidated index\n"); } } if((ns->ctl & NSY_MEM)) { mem = (isiram16)allobj.table[ns->memobj_index]; if(mem->info & ISI_RAMINFO_SCAN) ns->ctl |= NSY_SYNCMEM; } } for(i = 0; i < allsync.count; i++) { struct isiNetSync *ns = allsync.table[i]; struct memory64x16 *mem = 0; struct isiInfo *dev = 0; if(!ns) continue; if(!isi_time_lt(&ns->nrun, &crun)) continue; switch(ns->synctype) { /* update indexes */ case ISIN_SYNC_MEM: case ISIN_SYNC_MEMDEV: if(!(ns->ctl & NSY_MEM)) { x = isi_find_obj_index(&ns->memobj); if(x < 0) break; ns->memobj_index = x; ns->ctl |= NSY_MEM; isilog(L_DEBUG, "netsync: adding mem index %x\n", ns->ctl); } if((ns->ctl & NSY_MEM)) { mem = (isiram16)allobj.table[ns->memobj_index]; if(mem->info & ISI_RAMINFO_SCAN) mem->info ^= ISI_RAMINFO_SCAN; } if(mem && !(ns->ctl & NSY_MEMVALID)) { uint32_t mask = 0xffff; uint32_t addr; uint32_t alen; int ex, z; uint32_t idx; for(ex = ns->extents; ex--; ) { addr = ns->base[ex]; alen = ns->len[ex]; for(z = 0; z < alen; z++) { idx = (addr+z) & mask; if(idx > 0x10000) { isilog(L_ERR, "sync: over clear\n"); } mem->ctl[idx] &= 0xffff0000; mem->ctl[idx] |= (ISI_RAMCTL_DELTA|ISI_RAMCTL_SYNC) | ((~mem->ram[idx]) & 0xffff); } } mem->info |= ISI_RAMINFO_SCAN; ns->ctl |= NSY_MEMVALID; } if(ns->synctype != ISIN_SYNC_MEMDEV) break; case ISIN_SYNC_DEVR: case ISIN_SYNC_DEVV: case ISIN_SYNC_DEVRV: if(!(ns->ctl & NSY_OBJ)) { x = isi_find_obj_index(&ns->target); if(x < 0) break; ns->target_index = x; ns->ctl |= NSY_OBJ; isilog(L_DEBUG, "netsync: adding dev index %x\n", ns->ctl); } if((ns->ctl & NSY_OBJ)) dev = (struct isiInfo *)allobj.table[ns->target_index]; break; } switch(ns->synctype) { case ISIN_SYNC_MEM: case ISIN_SYNC_MEMDEV: if((ns->ctl & NSY_MEMVALID) && (ns->ctl & NSY_SYNCMEM)) { uint32_t mask = 0xffff; uint32_t addr; uint32_t alen; uint32_t idx; int ex, z; uint32_t sta = 0; uint32_t sln = 0; uint32_t ndln = 0; int fsync = 1; for(ex = ns->extents; ex--; ) { addr = ns->base[ex]; alen = ns->len[ex]; sta = 0; sln = 0; ndln = 0; *(uint32_t*)(allsync.out+4) = mem->id.id; uint8_t *wlo = allsync.out+8; uint16_t *mw = (uint16_t*)(wlo); uint8_t *wlimit = allsync.out+1294; for(z = 0; z < alen; z++) { idx = (addr+z) & mask; if(sln) { sln+=2; *mw = mem->ram[idx] & 0xffff; mw++; } if(((mem->ram[idx] & 0xffff) ^ (mem->ctl[idx] & 0xffff))) { if(!sln) { sta = idx << 1; sln = 2; mw = (uint16_t*)(wlo+6); *mw = mem->ram[idx] & 0xffff; mw++; } ndln = 0; mem->ctl[idx] &= 0xfffe0000; mem->ctl[idx] |= (mem->ram[idx] & 0xffffu); } else { if(sln) ndln+=2; } if(((uint8_t*)mw) >= wlimit || ndln > 12 || sln >= 1200) { wlo[0] = (uint8_t)(sta); wlo[1] = (uint8_t)(sta>>8); wlo[2] = (uint8_t)(sta>>16); wlo[3] = (uint8_t)(sta>>24); wlo[4] = (uint8_t)(sln); wlo[5] = (uint8_t)(sln >> 8); wlo = (uint8_t*)mw; ndln = sln = sta = 0; if(((uint8_t*)mw) >= wlimit) { fsync = 0; break; } } } if(sln) { wlo[0] = (uint8_t)(sta); wlo[1] = (uint8_t)(sta>>8); wlo[2] = (uint8_t)(sta>>16); wlo[3] = (uint8_t)(sta>>24); wlo[4] = (uint8_t)(sln); wlo[5] = (uint8_t)(sln >> 8); } if((uint8_t*)mw > allsync.out + 8) { *(uint32_t*)(allsync.out) = ISIMSG(SYNCMEM32, 0, ((uint8_t*)mw - (allsync.out + 4))); for(k = 0; k < allses.count; k++) { struct isiSession *ses; ses = allses.table[k]; if(!ses) continue; session_write_msgex(ses, allsync.out); } } } if(fsync) { ns->ctl &= ~NSY_SYNCMEM; } } case ISIN_SYNC_DEVR: case ISIN_SYNC_DEVV: case ISIN_SYNC_DEVRV: if((ns->ctl & NSY_OBJ) && !(ns->ctl & NSY_SYNCOBJ)) { ns->ctl |= NSY_SYNCOBJ; struct isiReflection const *rfl; if(dev->rvproto) { rfl = dev->rvproto; *(uint32_t*)(allsync.out+4) = dev->id.id; if(rfl->length > 1300) { isilog(L_ERR, "sync: over write rv\n"); } memcpy(allsync.out+8, dev->rvstate, rfl->length); *(uint32_t*)(allsync.out) = ISIMSG(SYNCRVS, 0, 4+(rfl->length)); for(k = 0; k < allses.count; k++) { struct isiSession *ses; ses = allses.table[k]; if(!ses) continue; session_write_msgex(ses, allsync.out); } } if(dev->svproto) { rfl = dev->svproto; *(uint32_t*)(allsync.out+4) = dev->id.id; if(rfl->length > 1300) { isilog(L_ERR, "sync: over write sv\n"); } memcpy(allsync.out+8, dev->svstate, rfl->length); *(uint32_t*)(allsync.out) = ISIMSG(SYNCSVS, 0, 4+(rfl->length)); for(k = 0; k < allses.count; k++) { struct isiSession *ses; ses = allses.table[k]; if(!ses) continue; session_write_msgex(ses, allsync.out); } } } break; }
int main(int argc, char**argv, char**envp) { uint32_t cux; uintptr_t gccq = 0; uintptr_t lucycles = 0; uintptr_t lucpus = 0; struct stats sts = {0, }; int paddlimit = 0; int premlimit = 0; isi_init_contable(); isi_register_objects(); isi_objtable_init(); isi_init_sestable(); isi_inittable(&alldev); isi_inittable(&allcpu); isi_synctable_init(); int i; uint32_t k; if( argc > 1 ) { i = parse_args(argc, argv); if(i) return i; } else { fprintf(stderr, gsc_usage, argv[0], argv[0]); return 0; } if(endf) { unsigned char * mflip; uint32_t rsize; loadbinfile(endf, 1, &mflip, &rsize); savebinfile(endf, 0, mflip, rsize); return 0; } struct sigaction hnler; hnler.sa_handler = sysfaulthdl; hnler.sa_flags = 0; if(redisaddr) { redis_make_session_lu(redisaddr); } if(!rqrun && !flagsvr) { fprintf(stderr, "At least -r or -s must be specified.\n"); return 0; } if(flagsvr) { if(!rqrun) enter_service(); makeserver(listenportnumber); } if(rqrun) { make_interactive(); isi_addcpu(); } sigaction(SIGINT, &hnler, NULL); sigaction(SIGTERM, &hnler, NULL); sigaction(SIGHUP, &hnler, NULL); sigaction(SIGPIPE, &hnler, NULL); fetchtime(<UTime); lucycles = 0; // how many cycles ran (debugging) cux = 0; // CPU index - currently never changes if(rqrun && allcpu.count && ((struct isiCPUInfo*)allcpu.table[cux])->ctl & ISICTL_DEBUG) { showdiag_dcpu(allcpu.table[cux], 1); } while(!haltnow) { struct isiCPUInfo * ccpu; struct isiInfo * ccpi; struct timespec CRun; ccpu = (struct isiCPUInfo*)(ccpi = allcpu.table[cux]); fetchtime(&CRun); if(!allcpu.count) { struct timespec stime = {0, 10000}; nanosleep(&stime, NULL); } else { int ccq = 0; int tcc = numberofcpus * 2; if(tcc < 20) tcc = 20; while(ccq < tcc && isi_time_lt(&ccpi->nrun, &CRun)) { sts.quanta++; ccpi->c->RunCycles(ccpi, CRun); //TODO some hardware may need to work at the same time lucycles += ccpu->cycl; if(rqrun && (ccpu->ctl & ISICTL_TRACE) && (ccpu->cycl)) { showdiag_dcpu(ccpi, 1); } ccpu->cycl = 0; fetchtime(&CRun); ccq++; } if(ccq >= tcc) gccq++; sts.cpusched++; fetchtime(&CRun); if(ccpi->updev.t && ccpi->updev.t->c->RunCycles) { ccpi->updev.t->c->RunCycles(ccpi->updev.t, CRun); } } fetchtime(&CRun); isi_run_sync(CRun); fetchtime(&CRun); if(CRun.tv_sec > LTUTime.tv_sec) { // roughly one second between status output if(rqrun && !flagdbg) { // interactive diag double clkdelta; float clkrate; if(allcpu.count) showdiag_dcpu(allcpu.table[0], 0); clkdelta = ((double)(CRun.tv_sec - LTUTime.tv_sec)) + (((double)CRun.tv_nsec) * 0.000000001); clkdelta-=(((double)LTUTime.tv_nsec) * 0.000000001); if(!lucpus) lucpus = 1; clkrate = ((((double)lucycles) * clkdelta) * 0.001) / numberofcpus; fprintf(stderr, "DC: %.4f sec, %d at % 9.3f kHz (% 8ld) [Q:% 8d, S:% 8d, SC:% 8d]\r", clkdelta, numberofcpus, clkrate, gccq, sts.quanta, sts.cpusched, sts.cpusched / numberofcpus ); if(allcpu.count) showdiag_up(4); } fetchtime(<UTime); if(gccq >= sts.cpusched / numberofcpus ) { if(numberofcpus > softcpumin) { numberofcpus--; if(rqrun) fprintf(stderr, "TODO: Offline a CPU\n"); premlimit--; paddlimit = 0; } } else { if(numberofcpus < softcpumax) { //fetchtime(&allcpus[numberofcpus].nrun); //isi_addtime(&allcpus[numberofcpus].nrun, quantum); numberofcpus++; if(rqrun) fprintf(stderr, "TODO: Online a CPU\n"); } } lucycles = 0; lucpus = 0; gccq = 0; memset(&sts, 0, sizeof(struct stats)); if(premlimit < 20) premlimit+=10; if(paddlimit < 20) paddlimit+=2; for(k = 0; k < allses.count; k++) { struct isiSession *ses = allses.table[k]; if(ses->LTick) ses->LTick(ses, CRun); } } if(allses.pcount != allses.count) { if(allses.ptable) { free(allses.ptable); allses.ptable = 0; } allses.pcount = allses.count; allses.ptable = (struct pollfd*)isi_alloc(sizeof(struct pollfd) * allses.pcount); if(!allses.ptable) { isilogerr("malloc poll table fails!"); } i = 0; for(k = 0; k < allses.count; k++) { allses.ptable[i].fd = allses.table[k]->sfd; allses.ptable[i].events = POLLIN; i++; } } if(allses.ptable) { i = poll(allses.ptable, allses.pcount, 0); } else { i = 0; } for(k = 0; k < allses.count; k++) { struct isiSession *ses = allses.table[k]; if(ses && ses->STick && (ses->cmdqstart != ses->cmdqend)) ses->STick(ses, CRun); } if(i > 0) { for(k = 0; k < allses.pcount; k++) { if(!allses.ptable[k].revents) continue; struct isiSession *ses = allses.table[k]; const char *etxt = 0; /* Here be dragons */ switch(allses.ptable[k].revents) { case POLLERR: etxt = "poll: FD error\n"; goto sessionerror; case POLLHUP: etxt = "poll: FD hangup\n"; goto sessionerror; case POLLNVAL: etxt = "poll: FD invalid\n"; goto sessionerror; default: if(allses.ptable[k].revents & POLLIN) { if(ses->sfd == allses.ptable[k].fd) { if(ses->Recv(ses, CRun)) goto sessionerror; } else { isilog(L_ERR, "netses: session ID error\n"); } } } continue; sessionerror: if(etxt) isilog(L_ERR, etxt); if(ses->sfd == allses.ptable[k].fd) { isi_delete_ses(ses); k = allses.pcount; } } } if(!flagdbg) { cux++; if(!(cux < allcpu.count)) { cux = 0; } } else { numberofcpus = 1; cux = 0; } if(haltnow) { break; } } if(flagsvr) { isilog(L_WARN, "closing connections\n"); while(allses.count) { isi_delete_ses(allses.table[0]); } } while(allobj.count) { isi_delete_object(allobj.table[0]); } if(rqrun) printf("\n\n\n\n"); return 0; }
static int parse_args(int argc, char**argv) { int i, k; for(i = 1; i < argc; i++) { switch(argv[i][0]) { case '-': for(k = 1; k > 0 && argv[i][k] > 31; k++) { switch(argv[i][k]) { case 'T': rqrun = 2; break; case 'r': rqrun = 1; break; case 'v': verblevel++; break; case 'l': isi_scan_dir(); break; case 'F': usefs = 1; break; case 'd': k = -1; if(i+1<argc) { diskf = strdup(argv[++i]); usefs = 1; } break; case 'p': k = -1; if(i+1 < argc) { listenportnumber = atoi(argv[i+1]); if(listenportnumber < 1 || listenportnumber > 65535) { isilog(L_CRIT, "Invalid port number %d\n", listenportnumber); return 1; } i++; } break; case 'e': loadendian = 2; break; case 'E': k = -1; if(i+1<argc) { endf = strdup(argv[++i]); } break; case 's': flagsvr = 1; break; case 'D': flagdbg = 1; break; case 'R': k = -1; if(i+1<argc) { redisaddr = strdup(argv[++i]); } break; case 'B': k = -1; if(i+1<argc) { binf = strdup(argv[++i]); } break; } } break; default: isilog(L_ERR, "\"%s\" Ignored\n", argv[i]); break; } } return 0; }