Пример #1
0
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;
		}
Пример #2
0
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(&LTUTime);
	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(&LTUTime);
			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;
}