sysproc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. #include "u.h"
  2. #include "tos.h"
  3. #include "../port/lib.h"
  4. #include "mem.h"
  5. #include "dat.h"
  6. #include "fns.h"
  7. #include "../port/error.h"
  8. #include "edf.h"
  9. #include <a.out.h>
  10. int shargs(char*, int, char**);
  11. extern void checkpages(void);
  12. long
  13. sysr1(ulong*)
  14. {
  15. extern int chandebug;
  16. chandebug = !chandebug;
  17. checkpages();
  18. return 0;
  19. }
  20. long
  21. sysrfork(ulong *arg)
  22. {
  23. Proc *p;
  24. int n, i;
  25. Fgrp *ofg;
  26. Pgrp *opg;
  27. Rgrp *org;
  28. Egrp *oeg;
  29. ulong pid, flag;
  30. Mach *wm;
  31. flag = arg[0];
  32. /* Check flags before we commit */
  33. if((flag & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
  34. error(Ebadarg);
  35. if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG))
  36. error(Ebadarg);
  37. if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG))
  38. error(Ebadarg);
  39. if((flag&RFPROC) == 0) {
  40. if(flag & (RFMEM|RFNOWAIT))
  41. error(Ebadarg);
  42. if(flag & (RFFDG|RFCFDG)) {
  43. ofg = up->fgrp;
  44. if(flag & RFFDG)
  45. up->fgrp = dupfgrp(ofg);
  46. else
  47. up->fgrp = dupfgrp(nil);
  48. closefgrp(ofg);
  49. }
  50. if(flag & (RFNAMEG|RFCNAMEG)) {
  51. opg = up->pgrp;
  52. up->pgrp = newpgrp();
  53. if(flag & RFNAMEG)
  54. pgrpcpy(up->pgrp, opg);
  55. /* inherit noattach */
  56. up->pgrp->noattach = opg->noattach;
  57. closepgrp(opg);
  58. }
  59. if(flag & RFNOMNT)
  60. up->pgrp->noattach = 1;
  61. if(flag & RFREND) {
  62. org = up->rgrp;
  63. up->rgrp = newrgrp();
  64. closergrp(org);
  65. }
  66. if(flag & (RFENVG|RFCENVG)) {
  67. oeg = up->egrp;
  68. up->egrp = smalloc(sizeof(Egrp));
  69. up->egrp->ref = 1;
  70. if(flag & RFENVG)
  71. envcpy(up->egrp, oeg);
  72. closeegrp(oeg);
  73. }
  74. if(flag & RFNOTEG)
  75. up->noteid = incref(&noteidalloc);
  76. return 0;
  77. }
  78. p = newproc();
  79. p->fpsave = up->fpsave;
  80. p->scallnr = up->scallnr;
  81. p->s = up->s;
  82. p->nerrlab = 0;
  83. p->slash = up->slash;
  84. p->dot = up->dot;
  85. incref(p->dot);
  86. memmove(p->note, up->note, sizeof(p->note));
  87. p->privatemem = up->privatemem;
  88. p->noswap = up->noswap;
  89. p->nnote = up->nnote;
  90. p->notified = 0;
  91. p->lastnote = up->lastnote;
  92. p->notify = up->notify;
  93. p->ureg = up->ureg;
  94. p->dbgreg = 0;
  95. /* Make a new set of memory segments */
  96. n = flag & RFMEM;
  97. qlock(&p->seglock);
  98. if(waserror()){
  99. qunlock(&p->seglock);
  100. nexterror();
  101. }
  102. for(i = 0; i < NSEG; i++)
  103. if(up->seg[i])
  104. p->seg[i] = dupseg(up->seg, i, n);
  105. qunlock(&p->seglock);
  106. poperror();
  107. /* File descriptors */
  108. if(flag & (RFFDG|RFCFDG)) {
  109. if(flag & RFFDG)
  110. p->fgrp = dupfgrp(up->fgrp);
  111. else
  112. p->fgrp = dupfgrp(nil);
  113. }
  114. else {
  115. p->fgrp = up->fgrp;
  116. incref(p->fgrp);
  117. }
  118. /* Process groups */
  119. if(flag & (RFNAMEG|RFCNAMEG)) {
  120. p->pgrp = newpgrp();
  121. if(flag & RFNAMEG)
  122. pgrpcpy(p->pgrp, up->pgrp);
  123. /* inherit noattach */
  124. p->pgrp->noattach = up->pgrp->noattach;
  125. }
  126. else {
  127. p->pgrp = up->pgrp;
  128. incref(p->pgrp);
  129. }
  130. if(flag & RFNOMNT)
  131. up->pgrp->noattach = 1;
  132. if(flag & RFREND)
  133. p->rgrp = newrgrp();
  134. else {
  135. incref(up->rgrp);
  136. p->rgrp = up->rgrp;
  137. }
  138. /* Environment group */
  139. if(flag & (RFENVG|RFCENVG)) {
  140. p->egrp = smalloc(sizeof(Egrp));
  141. p->egrp->ref = 1;
  142. if(flag & RFENVG)
  143. envcpy(p->egrp, up->egrp);
  144. }
  145. else {
  146. p->egrp = up->egrp;
  147. incref(p->egrp);
  148. }
  149. p->hang = up->hang;
  150. p->procmode = up->procmode;
  151. /* Craft a return frame which will cause the child to pop out of
  152. * the scheduler in user mode with the return register zero
  153. */
  154. forkchild(p, up->dbgreg);
  155. p->parent = up;
  156. p->parentpid = up->pid;
  157. if(flag&RFNOWAIT)
  158. p->parentpid = 0;
  159. else {
  160. lock(&up->exl);
  161. up->nchild++;
  162. unlock(&up->exl);
  163. }
  164. if((flag&RFNOTEG) == 0)
  165. p->noteid = up->noteid;
  166. p->fpstate = up->fpstate;
  167. pid = p->pid;
  168. memset(p->time, 0, sizeof(p->time));
  169. p->time[TReal] = MACHP(0)->ticks;
  170. kstrdup(&p->text, up->text);
  171. kstrdup(&p->user, up->user);
  172. /*
  173. * since the bss/data segments are now shareable,
  174. * any mmu info about this process is now stale
  175. * (i.e. has bad properties) and has to be discarded.
  176. */
  177. flushmmu();
  178. p->basepri = up->basepri;
  179. p->priority = up->basepri;
  180. p->fixedpri = up->fixedpri;
  181. p->mp = up->mp;
  182. wm = up->wired;
  183. if(wm)
  184. procwired(p, wm->machno);
  185. ready(p);
  186. sched();
  187. return pid;
  188. }
  189. static ulong
  190. l2be(long l)
  191. {
  192. uchar *cp;
  193. cp = (uchar*)&l;
  194. return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
  195. }
  196. long
  197. sysexec(ulong *arg)
  198. {
  199. Segment *s, *ts;
  200. ulong t, d, b;
  201. int i;
  202. Chan *tc;
  203. char **argv, **argp;
  204. char *a, *charp, *args, *file;
  205. char *progarg[sizeof(Exec)/2+1], *elem, progelem[64];
  206. ulong ssize, spage, nargs, nbytes, n, bssend;
  207. int indir;
  208. Exec exec;
  209. char line[sizeof(Exec)];
  210. Fgrp *f;
  211. Image *img;
  212. ulong magic, text, entry, data, bss;
  213. Tos *tos;
  214. validaddr(arg[0], 1, 0);
  215. file = (char*)arg[0];
  216. indir = 0;
  217. elem = nil;
  218. if(waserror()){
  219. free(elem);
  220. nexterror();
  221. }
  222. for(;;){
  223. tc = namec(file, Aopen, OEXEC, 0);
  224. if(waserror()){
  225. cclose(tc);
  226. nexterror();
  227. }
  228. if(!indir)
  229. kstrdup(&elem, up->genbuf);
  230. n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
  231. if(n < 2)
  232. error(Ebadexec);
  233. magic = l2be(exec.magic);
  234. text = l2be(exec.text);
  235. entry = l2be(exec.entry);
  236. if(n==sizeof(Exec) && (magic == AOUT_MAGIC)){
  237. if((text&KZERO) == KZERO
  238. || entry < UTZERO+sizeof(Exec)
  239. || entry >= UTZERO+sizeof(Exec)+text)
  240. error(Ebadexec);
  241. break; /* for binary */
  242. }
  243. /*
  244. * Process #! /bin/sh args ...
  245. */
  246. memmove(line, &exec, sizeof(Exec));
  247. if(indir || line[0]!='#' || line[1]!='!')
  248. error(Ebadexec);
  249. n = shargs(line, n, progarg);
  250. if(n == 0)
  251. error(Ebadexec);
  252. indir = 1;
  253. /*
  254. * First arg becomes complete file name
  255. */
  256. progarg[n++] = file;
  257. progarg[n] = 0;
  258. validaddr(arg[1], BY2WD, 1);
  259. arg[1] += BY2WD;
  260. file = progarg[0];
  261. if(strlen(elem) >= sizeof progelem)
  262. error(Ebadexec);
  263. strcpy(progelem, elem);
  264. progarg[0] = progelem;
  265. poperror();
  266. cclose(tc);
  267. }
  268. data = l2be(exec.data);
  269. bss = l2be(exec.bss);
  270. t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1);
  271. d = (t + data + (BY2PG-1)) & ~(BY2PG-1);
  272. bssend = t + data + bss;
  273. b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
  274. if(((t|d|b) & KZERO) == KZERO)
  275. error(Ebadexec);
  276. /*
  277. * Args: pass 1: count
  278. */
  279. nbytes = sizeof(Tos); /* hole for profiling clock at top of stack (and more) */
  280. nargs = 0;
  281. if(indir){
  282. argp = progarg;
  283. while(*argp){
  284. a = *argp++;
  285. nbytes += strlen(a) + 1;
  286. nargs++;
  287. }
  288. }
  289. evenaddr(arg[1]);
  290. argp = (char**)arg[1];
  291. validaddr((ulong)argp, BY2WD, 0);
  292. while(*argp){
  293. a = *argp++;
  294. if(((ulong)argp&(BY2PG-1)) < BY2WD)
  295. validaddr((ulong)argp, BY2WD, 0);
  296. validaddr((ulong)a, 1, 0);
  297. nbytes += (vmemchr(a, 0, 0x7FFFFFFF) - a) + 1;
  298. nargs++;
  299. }
  300. ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1));
  301. /*
  302. * 8-byte align SP for those (e.g. sparc) that need it.
  303. * execregs() will subtract another 4 bytes for argc.
  304. */
  305. if((ssize+4) & 7)
  306. ssize += 4;
  307. spage = (ssize+(BY2PG-1)) >> PGSHIFT;
  308. /*
  309. * Build the stack segment, putting it in kernel virtual for the moment
  310. */
  311. if(spage > TSTKSIZ)
  312. error(Enovmem);
  313. qlock(&up->seglock);
  314. if(waserror()){
  315. qunlock(&up->seglock);
  316. nexterror();
  317. }
  318. up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  319. /*
  320. * Args: pass 2: assemble; the pages will be faulted in
  321. */
  322. tos = (Tos*)(TSTKTOP - sizeof(Tos));
  323. tos->cyclefreq = m->cyclefreq;
  324. cycles((uvlong*)&tos->pcycles);
  325. tos->pcycles = -tos->pcycles;
  326. tos->kcycles = tos->pcycles;
  327. tos->clock = 0;
  328. argv = (char**)(TSTKTOP - ssize);
  329. charp = (char*)(TSTKTOP - nbytes);
  330. args = charp;
  331. if(indir)
  332. argp = progarg;
  333. else
  334. argp = (char**)arg[1];
  335. for(i=0; i<nargs; i++){
  336. if(indir && *argp==0) {
  337. indir = 0;
  338. argp = (char**)arg[1];
  339. }
  340. *argv++ = charp + (USTKTOP-TSTKTOP);
  341. n = strlen(*argp) + 1;
  342. memmove(charp, *argp++, n);
  343. charp += n;
  344. }
  345. free(up->text);
  346. up->text = elem;
  347. elem = nil; /* so waserror() won't free elem */
  348. USED(elem);
  349. /* copy args; easiest from new process's stack */
  350. n = charp - args;
  351. if(n > 128) /* don't waste too much space on huge arg lists */
  352. n = 128;
  353. a = up->args;
  354. up->args = nil;
  355. free(a);
  356. up->args = smalloc(n);
  357. memmove(up->args, args, n);
  358. if(n>0 && up->args[n-1]!='\0'){
  359. /* make sure last arg is NUL-terminated */
  360. /* put NUL at UTF-8 character boundary */
  361. for(i=n-1; i>0; --i)
  362. if(fullrune(up->args+i, n-i))
  363. break;
  364. up->args[i] = 0;
  365. n = i+1;
  366. }
  367. up->nargs = n;
  368. /*
  369. * Committed.
  370. * Free old memory.
  371. * Special segments are maintained across exec
  372. */
  373. for(i = SSEG; i <= BSEG; i++) {
  374. putseg(up->seg[i]);
  375. /* prevent a second free if we have an error */
  376. up->seg[i] = 0;
  377. }
  378. for(i = BSEG+1; i < NSEG; i++) {
  379. s = up->seg[i];
  380. if(s != 0 && (s->type&SG_CEXEC)) {
  381. putseg(s);
  382. up->seg[i] = 0;
  383. }
  384. }
  385. /*
  386. * Close on exec
  387. */
  388. f = up->fgrp;
  389. for(i=0; i<=f->maxfd; i++)
  390. fdclose(i, CCEXEC);
  391. /* Text. Shared. Attaches to cache image if possible */
  392. /* attachimage returns a locked cache image */
  393. img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT);
  394. ts = img->s;
  395. up->seg[TSEG] = ts;
  396. ts->flushme = 1;
  397. ts->fstart = 0;
  398. ts->flen = sizeof(Exec)+text;
  399. unlock(img);
  400. /* Data. Shared. */
  401. s = newseg(SG_DATA, t, (d-t)>>PGSHIFT);
  402. up->seg[DSEG] = s;
  403. /* Attached by hand */
  404. incref(img);
  405. s->image = img;
  406. s->fstart = ts->fstart+ts->flen;
  407. s->flen = data;
  408. /* BSS. Zero fill on demand */
  409. up->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT);
  410. /*
  411. * Move the stack
  412. */
  413. s = up->seg[ESEG];
  414. up->seg[ESEG] = 0;
  415. up->seg[SSEG] = s;
  416. qunlock(&up->seglock);
  417. poperror(); /* seglock */
  418. poperror(); /* elem */
  419. s->base = USTKTOP-USTKSIZE;
  420. s->top = USTKTOP;
  421. relocateseg(s, USTKTOP-TSTKTOP);
  422. /*
  423. * '/' processes are higher priority (hack to make /ip more responsive).
  424. */
  425. if(devtab[tc->type]->dc == L'/')
  426. up->basepri = PriRoot;
  427. up->priority = up->basepri;
  428. poperror();
  429. cclose(tc);
  430. /*
  431. * At this point, the mmu contains info about the old address
  432. * space and needs to be flushed
  433. */
  434. flushmmu();
  435. qlock(&up->debug);
  436. up->nnote = 0;
  437. up->notify = 0;
  438. up->notified = 0;
  439. up->privatemem = 0;
  440. procsetup(up);
  441. qunlock(&up->debug);
  442. if(up->hang)
  443. up->procctl = Proc_stopme;
  444. return execregs(entry, ssize, nargs);
  445. }
  446. int
  447. shargs(char *s, int n, char **ap)
  448. {
  449. int i;
  450. s += 2;
  451. n -= 2; /* skip #! */
  452. for(i=0; s[i]!='\n'; i++)
  453. if(i == n-1)
  454. return 0;
  455. s[i] = 0;
  456. *ap = 0;
  457. i = 0;
  458. for(;;) {
  459. while(*s==' ' || *s=='\t')
  460. s++;
  461. if(*s == 0)
  462. break;
  463. i++;
  464. *ap++ = s;
  465. *ap = 0;
  466. while(*s && *s!=' ' && *s!='\t')
  467. s++;
  468. if(*s == 0)
  469. break;
  470. else
  471. *s++ = 0;
  472. }
  473. return i;
  474. }
  475. int
  476. return0(void*)
  477. {
  478. return 0;
  479. }
  480. long
  481. syssleep(ulong *arg)
  482. {
  483. int n;
  484. n = arg[0];
  485. if(n <= 0) {
  486. if (up->edf && (up->edf->flags & Admitted))
  487. edfyield();
  488. else
  489. yield();
  490. return 0;
  491. }
  492. if(n < TK2MS(1))
  493. n = TK2MS(1);
  494. tsleep(&up->sleep, return0, 0, n);
  495. return 0;
  496. }
  497. long
  498. sysalarm(ulong *arg)
  499. {
  500. return procalarm(arg[0]);
  501. }
  502. long
  503. sysexits(ulong *arg)
  504. {
  505. char *status;
  506. char *inval = "invalid exit string";
  507. char buf[ERRMAX];
  508. status = (char*)arg[0];
  509. if(status){
  510. if(waserror())
  511. status = inval;
  512. else{
  513. validaddr((ulong)status, 1, 0);
  514. if(vmemchr(status, 0, ERRMAX) == 0){
  515. memmove(buf, status, ERRMAX);
  516. buf[ERRMAX-1] = 0;
  517. status = buf;
  518. }
  519. }
  520. poperror();
  521. }
  522. pexit(status, 1);
  523. return 0; /* not reached */
  524. }
  525. long
  526. sys_wait(ulong *arg)
  527. {
  528. int pid;
  529. Waitmsg w;
  530. OWaitmsg *ow;
  531. if(arg[0] == 0)
  532. return pwait(nil);
  533. validaddr(arg[0], sizeof(OWaitmsg), 1);
  534. evenaddr(arg[0]);
  535. pid = pwait(&w);
  536. if(pid >= 0){
  537. ow = (OWaitmsg*)arg[0];
  538. readnum(0, ow->pid, NUMSIZE, w.pid, NUMSIZE);
  539. readnum(0, ow->time+TUser*NUMSIZE, NUMSIZE, w.time[TUser], NUMSIZE);
  540. readnum(0, ow->time+TSys*NUMSIZE, NUMSIZE, w.time[TSys], NUMSIZE);
  541. readnum(0, ow->time+TReal*NUMSIZE, NUMSIZE, w.time[TReal], NUMSIZE);
  542. strncpy(ow->msg, w.msg, sizeof(ow->msg));
  543. ow->msg[sizeof(ow->msg)-1] = '\0';
  544. }
  545. return pid;
  546. }
  547. long
  548. sysawait(ulong *arg)
  549. {
  550. int i;
  551. int pid;
  552. Waitmsg w;
  553. ulong n;
  554. n = arg[1];
  555. validaddr(arg[0], n, 1);
  556. pid = pwait(&w);
  557. if(pid < 0)
  558. return -1;
  559. i = snprint((char*)arg[0], n, "%d %lud %lud %lud %q",
  560. w.pid,
  561. w.time[TUser], w.time[TSys], w.time[TReal],
  562. w.msg);
  563. return i;
  564. }
  565. long
  566. sysdeath(ulong*)
  567. {
  568. pprint("deprecated system call\n");
  569. pexit("Suicide", 0);
  570. return 0; /* not reached */
  571. }
  572. void
  573. werrstr(char *fmt, ...)
  574. {
  575. va_list va;
  576. if(up == nil)
  577. return;
  578. va_start(va, fmt);
  579. vseprint(up->syserrstr, up->syserrstr+ERRMAX, fmt, va);
  580. va_end(va);
  581. }
  582. static long
  583. generrstr(char *buf, uint nbuf)
  584. {
  585. char tmp[ERRMAX];
  586. if(nbuf == 0)
  587. error(Ebadarg);
  588. validaddr((ulong)buf, nbuf, 1);
  589. if(nbuf > sizeof tmp)
  590. nbuf = sizeof tmp;
  591. memmove(tmp, buf, nbuf);
  592. /* make sure it's NUL-terminated */
  593. tmp[nbuf-1] = '\0';
  594. memmove(buf, up->syserrstr, nbuf);
  595. buf[nbuf-1] = '\0';
  596. memmove(up->syserrstr, tmp, nbuf);
  597. return 0;
  598. }
  599. long
  600. syserrstr(ulong *arg)
  601. {
  602. return generrstr((char*)arg[0], arg[1]);
  603. }
  604. /* compatibility for old binaries */
  605. long
  606. sys_errstr(ulong *arg)
  607. {
  608. return generrstr((char*)arg[0], 64);
  609. }
  610. long
  611. sysnotify(ulong *arg)
  612. {
  613. if(arg[0] != 0)
  614. validaddr(arg[0], sizeof(ulong), 0);
  615. up->notify = (int(*)(void*, char*))(arg[0]);
  616. return 0;
  617. }
  618. long
  619. sysnoted(ulong *arg)
  620. {
  621. if(arg[0]!=NRSTR && !up->notified)
  622. error(Egreg);
  623. return 0;
  624. }
  625. long
  626. syssegbrk(ulong *arg)
  627. {
  628. int i;
  629. ulong addr;
  630. Segment *s;
  631. addr = arg[0];
  632. for(i = 0; i < NSEG; i++) {
  633. s = up->seg[i];
  634. if(s == 0 || addr < s->base || addr >= s->top)
  635. continue;
  636. switch(s->type&SG_TYPE) {
  637. case SG_TEXT:
  638. case SG_DATA:
  639. case SG_STACK:
  640. error(Ebadarg);
  641. default:
  642. return ibrk(arg[1], i);
  643. }
  644. }
  645. error(Ebadarg);
  646. return 0; /* not reached */
  647. }
  648. long
  649. syssegattach(ulong *arg)
  650. {
  651. return segattach(up, arg[0], (char*)arg[1], arg[2], arg[3]);
  652. }
  653. long
  654. syssegdetach(ulong *arg)
  655. {
  656. int i;
  657. ulong addr;
  658. Segment *s;
  659. qlock(&up->seglock);
  660. if(waserror()){
  661. qunlock(&up->seglock);
  662. nexterror();
  663. }
  664. s = 0;
  665. addr = arg[0];
  666. for(i = 0; i < NSEG; i++)
  667. if(s = up->seg[i]) {
  668. qlock(&s->lk);
  669. if((addr >= s->base && addr < s->top) ||
  670. (s->top == s->base && addr == s->base))
  671. goto found;
  672. qunlock(&s->lk);
  673. }
  674. error(Ebadarg);
  675. found:
  676. /*
  677. * Check we are not detaching the initial stack segment.
  678. */
  679. if(s == up->seg[SSEG]){
  680. qunlock(&s->lk);
  681. error(Ebadarg);
  682. }
  683. up->seg[i] = 0;
  684. qunlock(&s->lk);
  685. putseg(s);
  686. qunlock(&up->seglock);
  687. poperror();
  688. /* Ensure we flush any entries from the lost segment */
  689. flushmmu();
  690. return 0;
  691. }
  692. long
  693. syssegfree(ulong *arg)
  694. {
  695. Segment *s;
  696. ulong from, to;
  697. from = arg[0];
  698. s = seg(up, from, 1);
  699. if(s == nil)
  700. error(Ebadarg);
  701. to = (from + arg[1]) & ~(BY2PG-1);
  702. from = PGROUND(from);
  703. if(to > s->top) {
  704. qunlock(&s->lk);
  705. error(Ebadarg);
  706. }
  707. mfreeseg(s, from, (to - from) / BY2PG);
  708. qunlock(&s->lk);
  709. flushmmu();
  710. return 0;
  711. }
  712. /* For binary compatibility */
  713. long
  714. sysbrk_(ulong *arg)
  715. {
  716. return ibrk(arg[0], BSEG);
  717. }
  718. long
  719. sysrendezvous(ulong *arg)
  720. {
  721. ulong tag;
  722. ulong val;
  723. Proc *p, **l;
  724. tag = arg[0];
  725. l = &REND(up->rgrp, tag);
  726. up->rendval = ~0UL;
  727. lock(up->rgrp);
  728. for(p = *l; p; p = p->rendhash) {
  729. if(p->rendtag == tag) {
  730. *l = p->rendhash;
  731. val = p->rendval;
  732. p->rendval = arg[1];
  733. while(p->mach != 0)
  734. ;
  735. ready(p);
  736. unlock(up->rgrp);
  737. return val;
  738. }
  739. l = &p->rendhash;
  740. }
  741. /* Going to sleep here */
  742. up->rendtag = tag;
  743. up->rendval = arg[1];
  744. up->rendhash = *l;
  745. *l = up;
  746. up->state = Rendezvous;
  747. unlock(up->rgrp);
  748. sched();
  749. return up->rendval;
  750. }