sysproc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #include <a.out.h>
  8. int shargs(char*, int, char**);
  9. Ref sysr1ref;
  10. long
  11. sysr1(ulong *arg)
  12. {
  13. long a;
  14. a = *arg;
  15. if(a > 0)
  16. return incref(&sysr1ref);
  17. if(a < 0)
  18. return decref(&sysr1ref);
  19. return sysr1ref.ref;
  20. /*
  21. extern int chandebug;
  22. extern void dumpmount(void);
  23. print("[%s %s %lud] r1 = %lud\n", up->user, up->text, up->pid, arg[0]);
  24. chandebug=!chandebug;
  25. if(chandebug)
  26. dumpmount();
  27. return 0;
  28. */
  29. }
  30. long
  31. sysrfork(ulong *arg)
  32. {
  33. Proc *p;
  34. int n, i;
  35. Fgrp *ofg;
  36. Pgrp *opg;
  37. Rgrp *org;
  38. Egrp *oeg;
  39. ulong pid, flag;
  40. Mach *wm;
  41. flag = arg[0];
  42. /* Check flags before we commit */
  43. if((flag & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
  44. error(Ebadarg);
  45. if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG))
  46. error(Ebadarg);
  47. if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG))
  48. error(Ebadarg);
  49. if((flag&RFPROC) == 0) {
  50. if(flag & (RFMEM|RFNOWAIT))
  51. error(Ebadarg);
  52. if(flag & (RFFDG|RFCFDG)) {
  53. ofg = up->fgrp;
  54. if(flag & RFFDG)
  55. up->fgrp = dupfgrp(ofg);
  56. else
  57. up->fgrp = dupfgrp(nil);
  58. closefgrp(ofg);
  59. }
  60. if(flag & (RFNAMEG|RFCNAMEG)) {
  61. opg = up->pgrp;
  62. up->pgrp = newpgrp();
  63. if(flag & RFNAMEG)
  64. pgrpcpy(up->pgrp, opg);
  65. /* inherit noattach */
  66. up->pgrp->noattach = opg->noattach;
  67. closepgrp(opg);
  68. }
  69. if(flag & RFNOMNT)
  70. up->pgrp->noattach = 1;
  71. if(flag & RFREND) {
  72. org = up->rgrp;
  73. up->rgrp = newrgrp();
  74. closergrp(org);
  75. }
  76. if(flag & (RFENVG|RFCENVG)) {
  77. oeg = up->egrp;
  78. up->egrp = smalloc(sizeof(Egrp));
  79. up->egrp->ref = 1;
  80. if(flag & RFENVG)
  81. envcpy(up->egrp, oeg);
  82. closeegrp(oeg);
  83. }
  84. if(flag & RFNOTEG)
  85. up->noteid = incref(&noteidalloc);
  86. return 0;
  87. }
  88. p = newproc();
  89. p->fpsave = up->fpsave;
  90. p->scallnr = up->scallnr;
  91. p->s = up->s;
  92. p->nerrlab = 0;
  93. p->slash = up->slash;
  94. p->dot = up->dot;
  95. incref(p->dot);
  96. memmove(p->note, up->note, sizeof(p->note));
  97. p->privatemem = up->privatemem;
  98. p->noswap = up->noswap;
  99. p->nnote = up->nnote;
  100. p->notified = 0;
  101. p->lastnote = up->lastnote;
  102. p->notify = up->notify;
  103. p->ureg = up->ureg;
  104. p->dbgreg = 0;
  105. /* Make a new set of memory segments */
  106. n = flag & RFMEM;
  107. qlock(&p->seglock);
  108. if(waserror()){
  109. qunlock(&p->seglock);
  110. nexterror();
  111. }
  112. for(i = 0; i < NSEG; i++)
  113. if(up->seg[i])
  114. p->seg[i] = dupseg(up->seg, i, n);
  115. qunlock(&p->seglock);
  116. poperror();
  117. /* File descriptors */
  118. if(flag & (RFFDG|RFCFDG)) {
  119. if(flag & RFFDG)
  120. p->fgrp = dupfgrp(up->fgrp);
  121. else
  122. p->fgrp = dupfgrp(nil);
  123. }
  124. else {
  125. p->fgrp = up->fgrp;
  126. incref(p->fgrp);
  127. }
  128. /* Process groups */
  129. if(flag & (RFNAMEG|RFCNAMEG)) {
  130. p->pgrp = newpgrp();
  131. if(flag & RFNAMEG)
  132. pgrpcpy(p->pgrp, up->pgrp);
  133. /* inherit noattach */
  134. p->pgrp->noattach = up->pgrp->noattach;
  135. }
  136. else {
  137. p->pgrp = up->pgrp;
  138. incref(p->pgrp);
  139. }
  140. if(flag & RFNOMNT)
  141. up->pgrp->noattach = 1;
  142. if(flag & RFREND)
  143. p->rgrp = newrgrp();
  144. else {
  145. incref(up->rgrp);
  146. p->rgrp = up->rgrp;
  147. }
  148. /* Environment group */
  149. if(flag & (RFENVG|RFCENVG)) {
  150. p->egrp = smalloc(sizeof(Egrp));
  151. p->egrp->ref = 1;
  152. if(flag & RFENVG)
  153. envcpy(p->egrp, up->egrp);
  154. }
  155. else {
  156. p->egrp = up->egrp;
  157. incref(p->egrp);
  158. }
  159. p->hang = up->hang;
  160. p->procmode = up->procmode;
  161. /* Craft a return frame which will cause the child to pop out of
  162. * the scheduler in user mode with the return register zero
  163. */
  164. forkchild(p, up->dbgreg);
  165. p->parent = up;
  166. p->parentpid = up->pid;
  167. if(flag&RFNOWAIT)
  168. p->parentpid = 0;
  169. else {
  170. lock(&up->exl);
  171. up->nchild++;
  172. unlock(&up->exl);
  173. }
  174. if((flag&RFNOTEG) == 0)
  175. p->noteid = up->noteid;
  176. p->fpstate = up->fpstate;
  177. pid = p->pid;
  178. memset(p->time, 0, sizeof(p->time));
  179. p->time[TReal] = MACHP(0)->ticks;
  180. kstrdup(&p->text, up->text);
  181. kstrdup(&p->user, up->user);
  182. /*
  183. * since the bss/data segments are now shareable,
  184. * any mmu info about this process is now stale
  185. * (i.e. has bad properties) and has to be discarded.
  186. */
  187. flushmmu();
  188. p->basepri = up->basepri;
  189. p->priority = up->basepri;
  190. p->fixedpri = up->fixedpri;
  191. p->mp = up->mp;
  192. wm = up->wired;
  193. if(wm)
  194. procwired(p, wm->machno);
  195. ready(p);
  196. sched();
  197. return pid;
  198. }
  199. static ulong
  200. l2be(long l)
  201. {
  202. uchar *cp;
  203. cp = (uchar*)&l;
  204. return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
  205. }
  206. long
  207. sysexec(ulong *arg)
  208. {
  209. Segment *s, *ts;
  210. ulong t, d, b;
  211. int i;
  212. Chan *tc;
  213. char **argv, **argp;
  214. char *a, *charp, *args, *file;
  215. char *progarg[sizeof(Exec)/2+1], *elem, progelem[64];
  216. ulong ssize, spage, nargs, nbytes, n, bssend;
  217. int indir;
  218. Exec exec;
  219. char line[sizeof(Exec)];
  220. Fgrp *f;
  221. Image *img;
  222. ulong magic, text, entry, data, bss;
  223. validaddr(arg[0], 1, 0);
  224. file = (char*)arg[0];
  225. indir = 0;
  226. elem = nil;
  227. if(waserror()){
  228. free(elem);
  229. nexterror();
  230. }
  231. for(;;){
  232. tc = namec(file, Aopen, OEXEC, 0);
  233. if(waserror()){
  234. cclose(tc);
  235. nexterror();
  236. }
  237. if(!indir)
  238. kstrdup(&elem, up->genbuf);
  239. n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
  240. if(n < 2)
  241. error(Ebadexec);
  242. magic = l2be(exec.magic);
  243. text = l2be(exec.text);
  244. entry = l2be(exec.entry);
  245. if(n==sizeof(Exec) && (magic == AOUT_MAGIC)){
  246. if((text&KZERO) == KZERO
  247. || entry < UTZERO+sizeof(Exec)
  248. || entry >= UTZERO+sizeof(Exec)+text)
  249. error(Ebadexec);
  250. break; /* for binary */
  251. }
  252. /*
  253. * Process #! /bin/sh args ...
  254. */
  255. memmove(line, &exec, sizeof(Exec));
  256. if(indir || line[0]!='#' || line[1]!='!')
  257. error(Ebadexec);
  258. n = shargs(line, n, progarg);
  259. if(n == 0)
  260. error(Ebadexec);
  261. indir = 1;
  262. /*
  263. * First arg becomes complete file name
  264. */
  265. progarg[n++] = file;
  266. progarg[n] = 0;
  267. validaddr(arg[1], BY2WD, 1);
  268. arg[1] += BY2WD;
  269. file = progarg[0];
  270. if(strlen(elem) >= sizeof progelem)
  271. error(Ebadexec);
  272. strcpy(progelem, elem);
  273. progarg[0] = progelem;
  274. poperror();
  275. cclose(tc);
  276. }
  277. data = l2be(exec.data);
  278. bss = l2be(exec.bss);
  279. t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1);
  280. d = (t + data + (BY2PG-1)) & ~(BY2PG-1);
  281. bssend = t + data + bss;
  282. b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
  283. if(((t|d|b) & KZERO) == KZERO)
  284. error(Ebadexec);
  285. /*
  286. * Args: pass 1: count
  287. */
  288. nbytes = BY2WD; /* hole for profiling clock at top of stack */
  289. nargs = 0;
  290. if(indir){
  291. argp = progarg;
  292. while(*argp){
  293. a = *argp++;
  294. nbytes += strlen(a) + 1;
  295. nargs++;
  296. }
  297. }
  298. evenaddr(arg[1]);
  299. argp = (char**)arg[1];
  300. validaddr((ulong)argp, BY2WD, 0);
  301. while(*argp){
  302. a = *argp++;
  303. if(((ulong)argp&(BY2PG-1)) < BY2WD)
  304. validaddr((ulong)argp, BY2WD, 0);
  305. validaddr((ulong)a, 1, 0);
  306. nbytes += (vmemchr(a, 0, 0x7FFFFFFF) - a) + 1;
  307. nargs++;
  308. }
  309. ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1));
  310. /*
  311. * 8-byte align SP for those (e.g. sparc) that need it.
  312. * execregs() will subtract another 4 bytes for argc.
  313. */
  314. if((ssize+4) & 7)
  315. ssize += 4;
  316. spage = (ssize+(BY2PG-1)) >> PGSHIFT;
  317. /*
  318. * Build the stack segment, putting it in kernel virtual for the moment
  319. */
  320. if(spage > TSTKSIZ)
  321. error(Enovmem);
  322. qlock(&up->seglock);
  323. if(waserror()){
  324. qunlock(&up->seglock);
  325. nexterror();
  326. }
  327. up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  328. /*
  329. * Args: pass 2: assemble; the pages will be faulted in
  330. */
  331. argv = (char**)(TSTKTOP - ssize);
  332. charp = (char*)(TSTKTOP - nbytes);
  333. args = charp;
  334. if(indir)
  335. argp = progarg;
  336. else
  337. argp = (char**)arg[1];
  338. for(i=0; i<nargs; i++){
  339. if(indir && *argp==0) {
  340. indir = 0;
  341. argp = (char**)arg[1];
  342. }
  343. *argv++ = charp + (USTKTOP-TSTKTOP);
  344. n = strlen(*argp) + 1;
  345. memmove(charp, *argp++, n);
  346. charp += n;
  347. }
  348. free(up->text);
  349. up->text = elem;
  350. elem = nil; /* so waserror() won't free elem */
  351. USED(elem);
  352. /* copy args; easiest from new process's stack */
  353. n = charp - args;
  354. if(n > 128) /* don't waste too much space on huge arg lists */
  355. n = 128;
  356. a = up->args;
  357. up->args = nil;
  358. free(a);
  359. up->args = smalloc(n);
  360. memmove(up->args, args, n);
  361. if(n>0 && up->args[n-1]!='\0'){
  362. /* make sure last arg is NUL-terminated */
  363. /* put NUL at UTF-8 character boundary */
  364. for(i=n-1; i>0; --i)
  365. if(fullrune(up->args+i, n-i))
  366. break;
  367. up->args[i] = 0;
  368. n = i+1;
  369. }
  370. up->nargs = n;
  371. /*
  372. * Committed.
  373. * Free old memory.
  374. * Special segments are maintained across exec
  375. */
  376. for(i = SSEG; i <= BSEG; i++) {
  377. putseg(up->seg[i]);
  378. /* prevent a second free if we have an error */
  379. up->seg[i] = 0;
  380. }
  381. for(i = BSEG+1; i < NSEG; i++) {
  382. s = up->seg[i];
  383. if(s != 0 && (s->type&SG_CEXEC)) {
  384. putseg(s);
  385. up->seg[i] = 0;
  386. }
  387. }
  388. /*
  389. * Close on exec
  390. */
  391. f = up->fgrp;
  392. for(i=0; i<=f->maxfd; i++)
  393. fdclose(i, CCEXEC);
  394. /* Text. Shared. Attaches to cache image if possible */
  395. /* attachimage returns a locked cache image */
  396. img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT);
  397. ts = img->s;
  398. up->seg[TSEG] = ts;
  399. ts->flushme = 1;
  400. ts->fstart = 0;
  401. ts->flen = sizeof(Exec)+text;
  402. unlock(img);
  403. /* Data. Shared. */
  404. s = newseg(SG_DATA, t, (d-t)>>PGSHIFT);
  405. up->seg[DSEG] = s;
  406. /* Attached by hand */
  407. incref(img);
  408. s->image = img;
  409. s->fstart = ts->fstart+ts->flen;
  410. s->flen = data;
  411. /* BSS. Zero fill on demand */
  412. up->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT);
  413. /*
  414. * Move the stack
  415. */
  416. s = up->seg[ESEG];
  417. up->seg[ESEG] = 0;
  418. up->seg[SSEG] = s;
  419. qunlock(&up->seglock);
  420. poperror(); /* seglock */
  421. poperror(); /* elem */
  422. s->base = USTKTOP-USTKSIZE;
  423. s->top = USTKTOP;
  424. relocateseg(s, USTKTOP-TSTKTOP);
  425. /*
  426. * '/' processes are higher priority (hack to make /ip more responsive).
  427. */
  428. if(devtab[tc->type]->dc == L'/')
  429. up->basepri = PriRoot;
  430. up->priority = up->basepri;
  431. poperror();
  432. cclose(tc);
  433. /*
  434. * At this point, the mmu contains info about the old address
  435. * space and needs to be flushed
  436. */
  437. flushmmu();
  438. qlock(&up->debug);
  439. up->nnote = 0;
  440. up->notify = 0;
  441. up->notified = 0;
  442. up->privatemem = 0;
  443. procsetup(up);
  444. qunlock(&up->debug);
  445. if(up->hang)
  446. up->procctl = Proc_stopme;
  447. return execregs(entry, ssize, nargs);
  448. }
  449. int
  450. shargs(char *s, int n, char **ap)
  451. {
  452. int i;
  453. s += 2;
  454. n -= 2; /* skip #! */
  455. for(i=0; s[i]!='\n'; i++)
  456. if(i == n-1)
  457. return 0;
  458. s[i] = 0;
  459. *ap = 0;
  460. i = 0;
  461. for(;;) {
  462. while(*s==' ' || *s=='\t')
  463. s++;
  464. if(*s == 0)
  465. break;
  466. i++;
  467. *ap++ = s;
  468. *ap = 0;
  469. while(*s && *s!=' ' && *s!='\t')
  470. s++;
  471. if(*s == 0)
  472. break;
  473. else
  474. *s++ = 0;
  475. }
  476. return i;
  477. }
  478. int
  479. return0(void*)
  480. {
  481. return 0;
  482. }
  483. long
  484. syssleep(ulong *arg)
  485. {
  486. int n;
  487. n = arg[0];
  488. if(n <= 0) {
  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. /* Check we are not detaching the current stack segment */
  677. if((ulong)arg >= s->base && (ulong)arg < s->top) {
  678. qunlock(&s->lk);
  679. error(Ebadarg);
  680. }
  681. up->seg[i] = 0;
  682. qunlock(&s->lk);
  683. putseg(s);
  684. qunlock(&up->seglock);
  685. poperror();
  686. /* Ensure we flush any entries from the lost segment */
  687. flushmmu();
  688. return 0;
  689. }
  690. long
  691. syssegfree(ulong *arg)
  692. {
  693. Segment *s;
  694. ulong from, to;
  695. from = arg[0];
  696. s = seg(up, from, 1);
  697. if(s == nil)
  698. error(Ebadarg);
  699. to = (from + arg[1]) & ~(BY2PG-1);
  700. from = PGROUND(from);
  701. if(to > s->top) {
  702. qunlock(&s->lk);
  703. error(Ebadarg);
  704. }
  705. mfreeseg(s, from, (to - from) / BY2PG);
  706. qunlock(&s->lk);
  707. flushmmu();
  708. return 0;
  709. }
  710. /* For binary compatibility */
  711. long
  712. sysbrk_(ulong *arg)
  713. {
  714. return ibrk(arg[0], BSEG);
  715. }
  716. long
  717. sysrendezvous(ulong *arg)
  718. {
  719. ulong tag;
  720. ulong val;
  721. Proc *p, **l;
  722. tag = arg[0];
  723. l = &REND(up->rgrp, tag);
  724. up->rendval = ~0UL;
  725. lock(up->rgrp);
  726. for(p = *l; p; p = p->rendhash) {
  727. if(p->rendtag == tag) {
  728. *l = p->rendhash;
  729. val = p->rendval;
  730. p->rendval = arg[1];
  731. while(p->mach != 0)
  732. ;
  733. ready(p);
  734. unlock(up->rgrp);
  735. return val;
  736. }
  737. l = &p->rendhash;
  738. }
  739. /* Going to sleep here */
  740. up->rendtag = tag;
  741. up->rendval = arg[1];
  742. up->rendhash = *l;
  743. *l = up;
  744. up->state = Rendezvous;
  745. unlock(up->rgrp);
  746. if (edf->isedf(up))
  747. edf->edfblock(up);
  748. sched();
  749. return up->rendval;
  750. }