main.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. #include "all.h"
  2. #include "mem.h"
  3. #include "io.h"
  4. #include "ureg.h"
  5. #include "9p1.h"
  6. Rendez dawnrend;
  7. void
  8. machinit(void)
  9. {
  10. int n;
  11. n = m->machno;
  12. memset(m, 0, sizeof(Mach));
  13. m->machno = n;
  14. m->mmask = 1<<m->machno;
  15. m->lights = 0;
  16. active.exiting = 0;
  17. active.machs = 1;
  18. }
  19. static
  20. void
  21. confinit(void)
  22. {
  23. conf.nmach = 1;
  24. conf.nproc = 40;
  25. conf.mem = meminit();
  26. conf.sparemem = conf.mem/12; /* 8% spare for chk etc */
  27. conf.nalarm = 200;
  28. conf.nuid = 1000;
  29. conf.nserve = 15;
  30. conf.nfile = 30000;
  31. conf.nlgmsg = 100;
  32. conf.nsmmsg = 500;
  33. /*
  34. * if you have trouble with IDE DMA or RWM (multi-sector transfers),
  35. * perhaps due to old hardware, set idedma to zero in localconfinit().
  36. */
  37. conf.idedma = 1;
  38. localconfinit();
  39. conf.nwpath = conf.nfile*8;
  40. conf.nauth = conf.nfile/10;
  41. conf.gidspace = conf.nuid*3;
  42. cons.flags = 0;
  43. }
  44. /*
  45. * compute BUFSIZE*(NDBLOCK+INDPERBUF+INDPERBUF⁲+INDPERBUF⁳+INDPERBUF⁴)
  46. * while watching for overflow; in that case, return 0.
  47. */
  48. static uvlong
  49. adduvlongov(uvlong a, uvlong b)
  50. {
  51. uvlong r = a + b;
  52. return (r < a || r < b)? 0: r;
  53. }
  54. static uvlong
  55. muluvlongov(uvlong a, uvlong b)
  56. {
  57. uvlong r = a * b;
  58. return (r < a || r < b)? 0: r;
  59. }
  60. static uvlong
  61. maxsize(void)
  62. {
  63. int i;
  64. uvlong max = NDBLOCK, ind = 1;
  65. for (i = 0; i < NIBLOCK; i++) {
  66. ind = muluvlongov(ind, INDPERBUF); /* power of INDPERBUF */
  67. if (ind == 0)
  68. return 0;
  69. max = adduvlongov(max, ind);
  70. if (max == 0)
  71. return 0;
  72. }
  73. return muluvlongov(max, BUFSIZE);
  74. }
  75. enum {
  76. INDPERBUF⁲ = ((Off)INDPERBUF *INDPERBUF),
  77. INDPERBUF⁴ = ((Off)INDPERBUF⁲*INDPERBUF⁲),
  78. };
  79. static void
  80. printsizes(void)
  81. {
  82. uvlong max = maxsize();
  83. print("\tblock size = %d; ", RBUFSIZE);
  84. if (max == 0)
  85. print("max file size exceeds 2⁶⁴ bytes\n");
  86. else {
  87. uvlong offlim = 1ULL << (sizeof(Off)*8 - 1);
  88. if (max >= offlim)
  89. max = offlim - 1;
  90. print("max file size = %,llud\n", (Wideoff)max);
  91. }
  92. print("\tINDPERBUF = %d, INDPERBUF^4 = %,lld, ", INDPERBUF,
  93. (Wideoff)INDPERBUF⁴);
  94. print("CEPERBK = %d\n", CEPERBK);
  95. print("\tsizeofs: Dentry = %d, Cache = %d\n",
  96. sizeof(Dentry), sizeof(Cache));
  97. }
  98. void
  99. main(void)
  100. {
  101. int i;
  102. echo = 1;
  103. predawn = 1;
  104. formatinit();
  105. machinit();
  106. vecinit();
  107. confinit();
  108. lockinit();
  109. printinit();
  110. procinit();
  111. clockinit();
  112. print("\nPlan 9 %d-bit file server with %d-deep indir blks%s\n",
  113. sizeof(Off)*8 - 1, NIBLOCK,
  114. (conf.idedma? " and IDE DMA+RWM": ""));
  115. printsizes();
  116. alarminit();
  117. mainlock.wr.name = "mainr";
  118. mainlock.rd.name = "mainw";
  119. reflock.name = "ref";
  120. qlock(&reflock);
  121. qunlock(&reflock);
  122. serveq = newqueue(1000);
  123. raheadq = newqueue(1000);
  124. mbinit();
  125. sntpinit();
  126. otherinit();
  127. files = ialloc(conf.nfile * sizeof(*files), 0);
  128. for(i=0; i<conf.nfile; i++) {
  129. qlock(&files[i]);
  130. files[i].name = "file";
  131. qunlock(&files[i]);
  132. }
  133. wpaths = ialloc(conf.nwpath * sizeof(*wpaths), 0);
  134. uid = ialloc(conf.nuid * sizeof(*uid), 0);
  135. gidspace = ialloc(conf.gidspace * sizeof(*gidspace), 0);
  136. authinit();
  137. print("iobufinit\n");
  138. iobufinit();
  139. arginit();
  140. userinit(touser, 0, "ini");
  141. predawn = 0;
  142. wakeup(&dawnrend);
  143. launchinit();
  144. schedinit();
  145. }
  146. /*
  147. * read ahead processes.
  148. * read message from q and then
  149. * read the device.
  150. */
  151. int
  152. rbcmp(void *va, void *vb)
  153. {
  154. Rabuf *ra, *rb;
  155. ra = *(Rabuf**)va;
  156. rb = *(Rabuf**)vb;
  157. if(rb == 0)
  158. return 1;
  159. if(ra == 0)
  160. return -1;
  161. if(ra->dev > rb->dev)
  162. return 1;
  163. if(ra->dev < rb->dev)
  164. return -1;
  165. if(ra->addr > rb->addr)
  166. return 1;
  167. if(ra->addr < rb->addr)
  168. return -1;
  169. return 0;
  170. }
  171. void
  172. rahead(void)
  173. {
  174. Rabuf *rb[50];
  175. Iobuf *p;
  176. int i, n;
  177. for (;;) {
  178. rb[0] = recv(raheadq, 0);
  179. for(n=1; n<nelem(rb); n++) {
  180. if(raheadq->count <= 0)
  181. break;
  182. rb[n] = recv(raheadq, 0);
  183. }
  184. qsort(rb, n, sizeof(rb[0]), rbcmp);
  185. for(i=0; i<n; i++) {
  186. if(rb[i] == 0)
  187. continue;
  188. p = getbuf(rb[i]->dev, rb[i]->addr, Bread);
  189. if(p)
  190. putbuf(p);
  191. lock(&rabuflock);
  192. rb[i]->link = rabuffree;
  193. rabuffree = rb[i];
  194. unlock(&rabuflock);
  195. }
  196. }
  197. }
  198. /*
  199. * main filesystem server loop.
  200. * entered by many processes.
  201. * they wait for message buffers and
  202. * then process them.
  203. */
  204. void
  205. serve(void)
  206. {
  207. int i;
  208. Chan *cp;
  209. Msgbuf *mb;
  210. for (;;) {
  211. qlock(&reflock);
  212. mb = recv(serveq, 0);
  213. cp = mb->chan;
  214. rlock(&cp->reflock);
  215. qunlock(&reflock);
  216. rlock(&mainlock);
  217. if(cp->protocol == nil){
  218. /* do we recognise the protocol in this packet? */
  219. for(i = 0; fsprotocol[i] != nil; i++)
  220. if(fsprotocol[i](mb) != 0) {
  221. cp->protocol = fsprotocol[i];
  222. break;
  223. }
  224. if(cp->protocol == nil){
  225. print("no protocol for message\n");
  226. for(i = 0; i < 12; i++)
  227. print(" %2.2uX", mb->data[i]);
  228. print("\n");
  229. }
  230. }
  231. else
  232. cp->protocol(mb);
  233. mbfree(mb);
  234. runlock(&mainlock);
  235. runlock(&cp->reflock);
  236. }
  237. }
  238. void
  239. init0(void)
  240. {
  241. m->proc = u;
  242. u->state = Running;
  243. u->mach = m;
  244. spllo();
  245. (*u->start)();
  246. }
  247. void*
  248. getarg(void)
  249. {
  250. return u->arg;
  251. }
  252. enum {
  253. Keydelay = 5*60, /* seconds to wait for key press */
  254. };
  255. void
  256. exit(void)
  257. {
  258. long timeleft;
  259. u = 0;
  260. lock(&active);
  261. active.machs &= ~(1<<m->machno);
  262. active.exiting = 1;
  263. unlock(&active);
  264. if(!predawn)
  265. spllo();
  266. print("cpu %d exiting\n", m->machno);
  267. while(active.machs)
  268. delay(1);
  269. print("halted at %T.\n", time());
  270. print("press the Enter key to reboot sooner than %d mins.\n",
  271. Keydelay/60);
  272. delay(500); /* time to drain print q */
  273. splhi();
  274. /* reboot after delay (for debugging) or at newline */
  275. for (timeleft = Keydelay; timeleft > 0; timeleft--)
  276. if (rawchar(1) == '\n')
  277. break;
  278. spllo();
  279. delay(500); /* time to drain echo q */
  280. print("rebooting...\n");
  281. delay(500); /* time to drain print q */
  282. splhi();
  283. consreset();
  284. firmware();
  285. }
  286. /*
  287. * 1 sec timer
  288. * process+alarm+rendez+rwlock
  289. */
  290. static Rendez sec;
  291. static
  292. void
  293. callsec(Alarm *a, void *arg)
  294. {
  295. User *u = arg;
  296. cancel(a);
  297. wakeup(&u->tsleep);
  298. }
  299. void
  300. waitsec(int msec)
  301. {
  302. alarm(msec, callsec, u);
  303. sleep(&u->tsleep, no, 0);
  304. }
  305. #define DUMPTIME 5 /* 5 am */
  306. #define WEEKMASK 0 /* every day (1=sun, 2=mon, 4=tue, etc.) */
  307. /*
  308. * calculate the next dump time.
  309. * minimum delay is 100 minutes.
  310. */
  311. Timet
  312. nextdump(Timet t)
  313. {
  314. Timet nddate = nextime(t+MINUTE(100), DUMPTIME, WEEKMASK);
  315. if(!conf.nodump)
  316. print("next dump at %T\n", nddate);
  317. return nddate;
  318. }
  319. /*
  320. * process to copy dump blocks from
  321. * cache to worm. it runs flat out when
  322. * it gets work, but only looks for
  323. * work every 10 seconds.
  324. */
  325. void
  326. wormcopy(void)
  327. {
  328. int f, dorecalc = 1;
  329. Timet dt, t = 0, nddate = 0, ntoytime = 0;
  330. Filsys *fs;
  331. for (;;) {
  332. if (dorecalc) {
  333. dorecalc = 0;
  334. t = time();
  335. nddate = nextdump(t); /* chatters */
  336. ntoytime = time();
  337. }
  338. dt = time() - t;
  339. if(dt < 0 || dt > MINUTE(100)) {
  340. if(dt < 0)
  341. print("time went back\n");
  342. else
  343. print("time jumped ahead\n");
  344. dorecalc = 1;
  345. continue;
  346. }
  347. t += dt;
  348. f = 0;
  349. if(t > ntoytime) {
  350. dt = time() - rtctime();
  351. if(dt < 0)
  352. dt = -dt;
  353. if(dt > 10)
  354. print("rtc time more than 10 seconds out\n");
  355. else if(dt > 1)
  356. settime(rtctime());
  357. ntoytime = time() + HOUR(1);
  358. } else if(/* !f && */ t > nddate) { /* !f is always true here */
  359. if(!conf.nodump) {
  360. print("automatic dump %T\n", t);
  361. for(fs=filsys; fs->name; fs++)
  362. if(fs->dev->type == Devcw)
  363. cfsdump(fs);
  364. }
  365. dorecalc = 1;
  366. } else {
  367. rlock(&mainlock);
  368. for(fs=filsys; fs->name; fs++)
  369. if(fs->dev->type == Devcw)
  370. f |= dumpblock(fs->dev);
  371. runlock(&mainlock);
  372. if(0 && f == 0)
  373. f = 0; /* f = dowcp(); */
  374. if(!f)
  375. waitsec(10000);
  376. wormprobe();
  377. }
  378. }
  379. }
  380. /*
  381. * process to synch blocks
  382. * it puts out a block/cache-line every second
  383. * it waits 10 seconds if caught up.
  384. * in both cases, it takes about 10 seconds
  385. * to get up-to-date.
  386. */
  387. void
  388. synccopy(void)
  389. {
  390. int f;
  391. for (;;) {
  392. rlock(&mainlock);
  393. f = syncblock();
  394. runlock(&mainlock);
  395. if(!f)
  396. waitsec(10000);
  397. else
  398. waitsec(1000);
  399. /* pokewcp(); */
  400. }
  401. }