|
|
1.1 ! root 1: /* ! 2: * coh.386/sys2.c ! 3: * ! 4: * Filesystem related system calls. ! 5: * ! 6: * Revised: Mon Jul 12 08:56:23 1993 CDT ! 7: */ ! 8: ! 9: #include <kernel/_sleep.h> ! 10: #include <sys/coherent.h> ! 11: #include <sys/errno.h> ! 12: #include <fcntl.h> ! 13: #include <sys/fd.h> ! 14: #include <sys/ino.h> ! 15: #include <sys/inode.h> ! 16: #include <sys/mount.h> ! 17: #include <sys/sched.h> ! 18: #include <sys/stat.h> ! 19: #include <sys/file.h> ! 20: ! 21: /* ! 22: * Determine accessibility of the given file. ! 23: */ ! 24: ! 25: uaccess(np, mode) ! 26: char *np; ! 27: register int mode; ! 28: { ! 29: register INODE *ip; ! 30: register int r; ! 31: IO io; ! 32: struct direct dir; ! 33: ! 34: schizo (); ! 35: ! 36: io.io_seg = IOUSR; ! 37: r = ftoi (np, 'r', & io, & dir); ! 38: ! 39: schizo (); ! 40: ! 41: if (r) ! 42: return; ! 43: ip = u.u_cdiri; ! 44: if (! iaccess (ip, mode)) ! 45: u.u_error = EACCES; ! 46: idetach (ip); ! 47: return 0; ! 48: } ! 49: ! 50: /* ! 51: * Schizo - swap real and effective id's. ! 52: */ ! 53: schizo() ! 54: { ! 55: register int t; ! 56: ! 57: t = u.u_uid; ! 58: u.u_uid = u.u_ruid; ! 59: u.u_ruid = t; ! 60: t = u.u_gid; ! 61: u.u_gid = u.u_rgid; ! 62: u.u_rgid = t; ! 63: } ! 64: ! 65: /* ! 66: * Turn accounting on or off. ! 67: */ ! 68: uacct(np) ! 69: register char *np; ! 70: { ! 71: if (super () == 0) ! 72: return; ! 73: ! 74: if (np == NULL) { ! 75: if (acctip == NULL) { ! 76: u.u_error = EINVAL; ! 77: return; ! 78: } ! 79: ! 80: ldetach (acctip); ! 81: acctip = NULL; ! 82: } else { ! 83: INODE * ip; ! 84: IO io; ! 85: struct direct dir; ! 86: ! 87: if (acctip != NULL) { ! 88: u.u_error = EINVAL; ! 89: return; ! 90: } ! 91: ! 92: io.io_seg = IOUSR; ! 93: if (ftoi (np, 'r', & io, & dir)) ! 94: return; ! 95: ! 96: ip = u.u_cdiri; ! 97: if ((ip->i_mode & IFMT) != IFREG) { ! 98: u.u_error = EINVAL; ! 99: idetach (ip); ! 100: return; ! 101: } ! 102: iunlock (ip); ! 103: acctip = ip; ! 104: } ! 105: return 0; ! 106: } ! 107: ! 108: /* ! 109: * Set current directory. ! 110: */ ! 111: uchdir(np) ! 112: char *np; ! 113: { ! 114: setcdir (np, & u.u_cdir); ! 115: return 0; ! 116: } ! 117: ! 118: /* ! 119: * Given a directory name and a pointer to a working directory pointer, ! 120: * Save the inode associated with the directory name in the working ! 121: * directory pointer and release the old one. This is used to change ! 122: * working and root directories. ! 123: */ ! 124: setcdir(np, ipp) ! 125: char *np; ! 126: register INODE **ipp; ! 127: { ! 128: register INODE *ip; ! 129: IO io; ! 130: struct direct dir; ! 131: ! 132: io.io_seg = IOUSR; ! 133: if (ftoi (np, 'r', & io, & dir)) ! 134: return; ! 135: ! 136: ip = u.u_cdiri; ! 137: if ((ip->i_mode & IFMT) != IFDIR) { ! 138: u.u_error = ENOTDIR; ! 139: idetach (ip); ! 140: return; ! 141: } ! 142: if (iaccess (ip, IPE) == 0) { ! 143: u.u_error = EACCES; ! 144: idetach (ip); ! 145: return; ! 146: } ! 147: iunlock (ip); ! 148: ldetach (* ipp); ! 149: * ipp = ip; ! 150: } ! 151: ! 152: /* ! 153: * Change the mode of a file. ! 154: */ ! 155: uchmod(np, mode) ! 156: char *np; ! 157: { ! 158: register INODE *ip; ! 159: IO io; ! 160: struct direct dir; ! 161: ! 162: io.io_seg = IOUSR; ! 163: if (ftoi (np, 'r', & io, & dir)) ! 164: return; ! 165: ! 166: ip = u.u_cdiri; ! 167: if (owner (ip->i_uid)) { ! 168: if (u.u_uid) ! 169: mode &= ~ ISVTXT; ! 170: ip->i_mode &= IFMT; ! 171: ip->i_mode |= mode & ~ IFMT; ! 172: icrt (ip); /* chmod - ctime */ ! 173: } ! 174: idetach (ip); ! 175: return 0; ! 176: } ! 177: ! 178: /* ! 179: * Change owner and group of a file. ! 180: */ ! 181: uchown(np, uid, gid) ! 182: char *np; ! 183: { ! 184: register INODE *ip; ! 185: IO io; ! 186: struct direct dir; ! 187: ! 188: io.io_seg = IOUSR; ! 189: if (ftoi (np, 'r', & io, & dir)) ! 190: return; ! 191: ! 192: ip = u.u_cdiri; ! 193: if (super ()) { ! 194: ip->i_mode &= ~ (ISUID | ISGID); /* clear any setuid/setgid */ ! 195: ip->i_uid = uid; ! 196: ip->i_gid = gid; ! 197: icrt (ip); /* chown - ctime */ ! 198: } ! 199: idetach (ip); ! 200: return 0; ! 201: } ! 202: ! 203: /* ! 204: * Set root directory. ! 205: */ ! 206: uchroot(np) ! 207: register char *np; ! 208: { ! 209: if (super ()) ! 210: setcdir (np, & u.u_rdir); ! 211: return 0; ! 212: } ! 213: ! 214: /* ! 215: * Close the given file descriptor. ! 216: */ ! 217: uclose(fd) ! 218: { ! 219: fdclose (fd); ! 220: return 0; ! 221: } ! 222: ! 223: /* ! 224: * Create a file with the given mode. ! 225: */ ! 226: ucreat(np, mode) ! 227: char *np; ! 228: register int mode; ! 229: { ! 230: return uopen (np, O_WRONLY | O_CREAT | O_TRUNC, mode); ! 231: } ! 232: ! 233: /* ! 234: * Duplicate a file descriptor. ! 235: */ ! 236: udup(ofd) ! 237: { ! 238: return fddup (ofd, 0); ! 239: } ! 240: ! 241: /* ! 242: * Given a file descriptor, return a status structure. ! 243: */ ! 244: ufstat(fd, stp) ! 245: struct stat *stp; ! 246: { ! 247: register INODE *ip; ! 248: register FD *fdp; ! 249: struct stat stat; ! 250: ! 251: if ((fdp = fdget (fd)) == NULL) ! 252: return; ! 253: ! 254: ip = fdp->f_ip; ! 255: istat (ip, & stat); ! 256: ! 257: if (kucopy (& stat, stp, sizeof (stat)) != sizeof (stat)) { ! 258: u.u_error = EFAULT; ! 259: return -1; ! 260: } ! 261: return 0; ! 262: } ! 263: ! 264: /* ! 265: * File control. ! 266: */ ! 267: ! 268: ufcntl (fd, cmd, arg) ! 269: unsigned fd; ! 270: unsigned cmd; ! 271: unsigned arg; ! 272: { ! 273: register FD * fdp; ! 274: struct flock sfl; ! 275: ! 276: T_VLAD(2, printf("fcntl(%d,%x,%x) ", fd, cmd, arg)); ! 277: ! 278: /* ! 279: * Validate file descriptor. ! 280: */ ! 281: ! 282: if ((fdp = fdget (fd)) == NULL) { ! 283: u.u_error = EBADF; ! 284: return; ! 285: } ! 286: ! 287: switch (cmd) { ! 288: ! 289: case F_DUPFD: ! 290: /* ! 291: * Validate base file descriptor. ! 292: */ ! 293: if (arg >= NOFILE) { ! 294: u.u_error = EINVAL; ! 295: return; ! 296: } ! 297: ! 298: /* ! 299: * Search for next available file descriptor. ! 300: */ ! 301: ! 302: return fddup (fd, arg); ! 303: ! 304: case F_SETFL: ! 305: fdp->f_flag &= ~ (IPNDLY | IPAPPEND | IPNONBLOCK); ! 306: if (arg & O_NDELAY) ! 307: fdp->f_flag |= IPNDLY; ! 308: if (arg & O_APPEND) ! 309: fdp->f_flag |= IPAPPEND; ! 310: if (arg & O_NONBLOCK) ! 311: fdp->f_flag |= IPNONBLOCK; ! 312: ! 313: /* ! 314: * Originally, this call returned the previous flag values, ! 315: * as permitted by the various standards. However, many ! 316: * programs incorrectly check for "== 0" as the return ! 317: * condition from this function rather than "!= -1" as they ! 318: * should. ! 319: */ ! 320: return 0; ! 321: ! 322: case F_GETFL: ! 323: switch (fdp->f_flag & (IPR | IPW)) { ! 324: case IPR: arg = O_RDONLY; break; ! 325: case IPW: arg = O_WRONLY; break; ! 326: default: arg = O_RDWR; break; ! 327: } ! 328: ! 329: if ((fdp->f_flag & IPNDLY) != 0) ! 330: arg |= O_NDELAY; ! 331: ! 332: if ((fdp->f_flag & IPAPPEND) != 0) ! 333: arg |= O_APPEND; ! 334: ! 335: if ((fdp->f_flag & IPNONBLOCK) != 0) ! 336: arg |= O_NONBLOCK; ! 337: ! 338: return arg; ! 339: ! 340: case F_GETLK: ! 341: case F_SETLK: ! 342: case F_SETLKW: ! 343: if (ukcopy ((struct flock *) arg, & sfl, ! 344: sizeof (struct flock)) != sizeof (struct flock)) { ! 345: u.u_error = EFAULT; ! 346: return -1; ! 347: } ! 348: if (rlock (fdp, cmd, & sfl)) ! 349: return -1; ! 350: if (cmd == F_GETLK && ! 351: kucopy (& sfl, (struct flock *) arg, ! 352: sizeof (struct flock)) != sizeof (struct flock)) { ! 353: u.u_error = EFAULT; ! 354: return -1; ! 355: } ! 356: return 0; ! 357: ! 358: case F_GETFD: ! 359: return fdgetflags (fd); ! 360: ! 361: case F_SETFD: ! 362: return fdsetflags (fd, arg); ! 363: ! 364: default: ! 365: T_VLAD (0x02, printf ("'fcntl - unknown cmd=%d arg=0x0%x' ", ! 366: cmd, arg)); ! 367: u.u_error = EINVAL; ! 368: } ! 369: } ! 370: ! 371: /* ! 372: * Device control information. ! 373: */ ! 374: ! 375: int ! 376: uioctl (fd, cmd, argp, regsetp) ! 377: unsigned fd; ! 378: unsigned cmd; ! 379: __VOID__ * argp; ! 380: gregset_t * regsetp; ! 381: { ! 382: register FD *fdp; ! 383: register INODE *ip; ! 384: register int mode; ! 385: ! 386: ! 387: T_PIGGY (0x8, printf ("uioctl(%d, 0x%x, 0x%x)", fd, cmd, argp)); ! 388: ! 389: if ((fdp = fdget (fd)) == NULL) ! 390: return; ! 391: ip = fdp->f_ip; ! 392: mode = ip->i_mode & IFMT; ! 393: if (mode != IFCHR && mode != IFBLK) { ! 394: u.u_error = ENOTTY; ! 395: return; ! 396: } ! 397: dioctl (ip->i_a.i_rdev, cmd, argp, fdp->f_flag, regsetp); ! 398: return 0; ! 399: } ! 400: ! 401: /* ! 402: * Create a link, `np2' to the already existing file `np1'. ! 403: */ ! 404: ! 405: ulink (np1, np2) ! 406: char *np1; ! 407: char *np2; ! 408: { ! 409: return do_link (np1, np2, IOUSR); ! 410: } ! 411: ! 412: ! 413: /* ! 414: * Internal version of link (), used by ulink () and umkdir (). ! 415: */ ! 416: ! 417: int ! 418: do_link (path1, path2, space) ! 419: char * path1; ! 420: char * path2; ! 421: int space; ! 422: { ! 423: register INODE *ip1; ! 424: IO io; ! 425: struct direct dir; ! 426: ! 427: io.io_seg = space; ! 428: if (ftoi (path1, 'r', & io, & dir)) ! 429: return; ! 430: ! 431: ip1 = u.u_cdiri; ! 432: if ((ip1->i_mode & IFMT) == IFDIR && super () == 0) { ! 433: idetach (ip1); ! 434: return; ! 435: } ! 436: ! 437: iunlock (ip1); ! 438: ! 439: io.io_seg = space; ! 440: if (ftoi (path2, 'c', & io, & dir)) { ! 441: ldetach (ip1); ! 442: return; ! 443: } ! 444: ! 445: if (u.u_cdiri != NULL) { ! 446: u.u_error = EEXIST; ! 447: idetach (u.u_cdiri); ! 448: ldetach (ip1); ! 449: return; ! 450: } ! 451: ! 452: if (ip1->i_dev != u.u_pdiri->i_dev) { ! 453: u.u_error = EXDEV; ! 454: idetach (u.u_pdiri); ! 455: ldetach (ip1); ! 456: return; ! 457: } ! 458: ! 459: if (iaccess (u.u_pdiri, IPW) == 0) { ! 460: idetach (u.u_pdiri); ! 461: ldetach (ip1); ! 462: return; ! 463: } ! 464: ! 465: idirent (ip1->i_ino, & io, & dir); ! 466: idetach (u.u_pdiri); ! 467: ilock (ip1); ! 468: ! 469: /* ! 470: * idirent() can fail during iwrite. In this case we should not ! 471: * increase link count. ! 472: * As result of this old bug, 286 mkdir utility destroys file ! 473: * system when runs out of free blocks. ! 474: */ ! 475: ! 476: if (! u.u_error) ! 477: ip1->i_nlink ++; ! 478: ! 479: icrt (ip1); /* link - ctime */ ! 480: idetach (ip1); ! 481: return 0; ! 482: } ! 483: ! 484: ! 485: /* ! 486: * Seek on the given file descriptor. ! 487: */ ! 488: ! 489: off_t ! 490: ulseek(fd, off, w) ! 491: register off_t off; ! 492: { ! 493: register FD *fdp; ! 494: register INODE *ip; ! 495: ! 496: if ((fdp = fdget (fd)) == NULL) ! 497: return; ! 498: ip = fdp->f_ip; ! 499: if ((ip->i_mode & IFMT) == IFPIPE) { ! 500: u.u_error = ESPIPE; ! 501: return; ! 502: } ! 503: switch (w) { ! 504: case 0: ! 505: break; ! 506: ! 507: case 1: ! 508: off += fdp->f_seek; ! 509: break; ! 510: ! 511: case 2: ! 512: off += ip->i_size; ! 513: break; ! 514: ! 515: default: ! 516: u.u_error = EINVAL; ! 517: return; ! 518: } ! 519: ! 520: if (off < 0) { ! 521: u.u_error = EINVAL; ! 522: return; ! 523: } ! 524: ! 525: fdp->f_seek = off; ! 526: return off; ! 527: } ! 528: ! 529: /* ! 530: * Create a special file. ! 531: */ ! 532: umknod(np, mode, rdev) ! 533: char *np; ! 534: dev_t rdev; ! 535: { ! 536: register INODE *ip; ! 537: register int type; ! 538: IO io; ! 539: struct direct dir; ! 540: ! 541: type = mode & IFMT; ! 542: if (type != IFPIPE && super () == 0) ! 543: return; ! 544: if (type != IFBLK && type != IFCHR) ! 545: rdev = 0; ! 546: ! 547: io.io_seg = IOUSR; ! 548: if (ftoi (np, 'c', & io, & dir)) ! 549: return; ! 550: ! 551: if ((ip = u.u_cdiri) != NULL) { ! 552: u.u_error = EEXIST; ! 553: idetach (ip); ! 554: return; ! 555: } ! 556: ! 557: if ((ip = imake (mode, rdev, & io, & dir)) != NULL) ! 558: idetach (ip); ! 559: ! 560: return 0; ! 561: } ! 562: ! 563: /* ! 564: * Mount the device `sp' on the pathname `np'. The flag, `f', ! 565: * indicates that the device is to be mounted read only. ! 566: */ ! 567: umount(sp, np, f) ! 568: char *sp; ! 569: char *np; ! 570: { ! 571: register INODE *ip; ! 572: register MOUNT *mp; ! 573: register dev_t rdev; ! 574: register int mode; ! 575: IO io; ! 576: struct direct dir; ! 577: ! 578: io.io_seg = IOUSR; ! 579: if (ftoi (sp, 'r', & io, & dir)) ! 580: return; ! 581: ! 582: ip = u.u_cdiri; ! 583: if (iaccess (ip, IPR | IPW) == 0) ! 584: goto err; ! 585: ! 586: mode = ip->i_mode; ! 587: rdev = ip->i_a.i_rdev; ! 588: if ((mode & IFMT) != IFBLK) { ! 589: u.u_error = ENOTBLK; ! 590: goto err; ! 591: } ! 592: ! 593: idetach(ip); ! 594: ! 595: io.io_seg = IOUSR; ! 596: if (ftoi (np, 'r', & io, & dir)) ! 597: return; ! 598: ! 599: ip = u.u_cdiri; ! 600: ! 601: if (iaccess (ip, IPR) == 0) ! 602: goto err; ! 603: ! 604: if ((ip->i_mode & IFMT) != IFDIR) { ! 605: u.u_error = ENOTDIR; ! 606: goto err; ! 607: } ! 608: ! 609: /* Check for current directory, open, or mount directory */ ! 610: ! 611: if (ip->i_refc > 1 || ip->i_ino == ROOTIN) { ! 612: u.u_error = EBUSY; ! 613: goto err; ! 614: } ! 615: for (mp = mountp ; mp != NULL ; mp = mp->m_next) { ! 616: if (mp->m_dev == rdev) { ! 617: u.u_error = EBUSY; ! 618: goto err; ! 619: } ! 620: } ! 621: ! 622: if ((mp = fsmount (rdev, f)) == NULL) ! 623: goto err; ! 624: mp->m_ip = ip; ! 625: ip->i_flag |= IFMNT; ! 626: ip->i_refc ++; ! 627: err: ! 628: idetach (ip); ! 629: return 0; ! 630: } ! 631: ! 632: /* ! 633: * Poll devices for input/output events. ! 634: */ ! 635: int ! 636: upoll(pollfds, npoll, msec) ! 637: struct pollfd * pollfds; ! 638: unsigned long npoll; ! 639: int msec; ! 640: { ! 641: register struct pollfd * pollp; /* current poll pointer */ ! 642: register FD * fdp; /* current file descriptor ptr */ ! 643: auto int fd; /* current file descriptor */ ! 644: auto int rev; /* last event report received */ ! 645: auto int nev; /* number non-zero event reports */ ! 646: auto int i; ! 647: char * cp; ! 648: int ret = -1; ! 649: ! 650: /* ! 651: * Validate number of polls. ! 652: */ ! 653: if ((npoll < 0) || (npoll > NOFILE)) { ! 654: u.u_error = EINVAL; ! 655: goto poll_done; ! 656: } ! 657: ! 658: /* ! 659: * If there are any fd's to poll ! 660: * validate address of polling information. ! 661: * npoll of 0 is legal, allows user a short delay. ! 662: */ ! 663: if (npoll) ! 664: if ((pollfds == NULL) ! 665: || !useracc(pollfds, npoll*sizeof(struct pollfd), 1)) { ! 666: u.u_error = EFAULT; ! 667: goto poll_done; ! 668: } ! 669: ! 670: for (;;) { ! 671: /* ! 672: * Service each poll in turn. ! 673: */ ! 674: for (nev=0, i=npoll, pollp = pollfds; i > 0; --i, pollp++) { ! 675: ! 676: /* ! 677: * Fetch file descriptor. ! 678: */ ! 679: fd = getuwd(&pollp->fd); ! 680: ! 681: /* ! 682: * Ignore negative file descriptors. ! 683: */ ! 684: if (fd < 0) { ! 685: rev = 0; ! 686: goto remember; ! 687: } ! 688: ! 689: #if 1 ! 690: /* ! 691: * Ignore file descriptors that are too large. ! 692: */ ! 693: if (fd >= NOFILE) { ! 694: rev = 0; ! 695: goto remember; ! 696: } ! 697: #else ! 698: /* For now, msg polling is deleted. */ ! 699: /* ! 700: * Poll message queue. ! 701: */ ! 702: if (fd >= NOFILE) { ! 703: rev = msgpoll(fd, getusd(&pollp->events), msec); ! 704: goto remember; ! 705: } ! 706: #endif ! 707: ! 708: /* ! 709: * Validate file descriptor. ! 710: */ ! 711: if ((fdp = fdget (fd)) == NULL) { ! 712: rev = POLLNVAL; ! 713: goto remember; ! 714: } ! 715: ! 716: switch ( fdp->f_ip->i_mode & IFMT ) { ! 717: case IFCHR: ! 718: rev = dpoll(fdp->f_ip->i_a.i_rdev, ! 719: getusd(&pollp->events)&0xffff, msec); ! 720: break; ! 721: case IFPIPE: ! 722: rev = ppoll(fdp->f_ip, ! 723: getusd(&pollp->events)&0xffff, msec); ! 724: break; ! 725: default: ! 726: printf("polling illegal dev: fd=%d mode=%x\n", ! 727: fd, fdp->f_ip->i_mode); ! 728: rev = POLLNVAL; ! 729: break; ! 730: } ! 731: ! 732: /* ! 733: * Remember reponses. ! 734: */ ! 735: remember: ! 736: cp = (char *)(&pollp->revents); ! 737: putusd(cp, rev); ! 738: ! 739: /* ! 740: * Record number of non-zero responses. ! 741: */ ! 742: if (rev) ! 743: nev++; ! 744: } ! 745: ! 746: /* ! 747: * Non-blocking poll or poll response received. ! 748: */ ! 749: if ( (nev != 0) || (msec == 0) ) { ! 750: pollexit(); ! 751: ret = nev; ! 752: goto poll_done; ! 753: } ! 754: ! 755: /* ! 756: * Schedule wakeup timer if positive delay interval given ! 757: * and the timer is not currently set. ! 758: */ ! 759: if ( (msec > 0) && (cprocp->p_polltim.t_func == NULL) ) { ! 760: /* ! 761: * Convert milliseconds to clock ticks. ! 762: */ ! 763: msec += (1000 / HZ) - 1; ! 764: msec /= (1000 / HZ); ! 765: timeout(&cprocp->p_polltim, msec, ! 766: wakeup, &cprocp->p_polls); ! 767: } ! 768: ! 769: /* ! 770: * Wake for polled event, poll timeout, or signal. ! 771: */ ! 772: ! 773: { ! 774: __sleep_t sleep; ! 775: ! 776: sleep = x_sleep (& cprocp->p_polls, pritty, ! 777: slpriSigCatch, "poll"); ! 778: ! 779: /* ! 780: * Terminate event monitoring. ! 781: */ ! 782: ! 783: pollexit(); ! 784: ! 785: /* ! 786: * Signal woke us up. ! 787: */ ! 788: ! 789: if (sleep == PROCESS_SIGNALLED) { ! 790: u.u_error = EINTR; ! 791: goto poll_done; ! 792: } ! 793: } ! 794: ! 795: /* ! 796: * We were woken up by timeout wakeup. ! 797: */ ! 798: if ( (msec > 0) && (cprocp->p_polltim.t_lbolt <= lbolt) ) { ! 799: ret = 0; ! 800: goto poll_done; ! 801: } ! 802: } ! 803: ! 804: poll_done: ! 805: /* ! 806: * Cancel timeout ! 807: */ ! 808: if ( (msec > 0) && (cprocp->p_polltim.t_func != NULL) ) ! 809: timeout(&cprocp->p_polltim, 0, NULL, NULL); ! 810: ! 811: return ret; ! 812: } ! 813: ! 814: /* ! 815: * Suspend execution for a short interval. ! 816: * ! 817: * Return the number of milliseconds actually slept. ! 818: * Shares use of cprocp->p_polltim with upoll(). ! 819: */ ! 820: int ! 821: unap(msec) ! 822: int msec; ! 823: { ! 824: int ret, lbolt0; ! 825: int ticksToWait, ticksWaited; ! 826: ! 827: if (msec <= 0) ! 828: return 0; ! 829: ! 830: /* ! 831: * Convert milliseconds to clock ticks. ! 832: * ! 833: * Wait for at least the specified number of milliseconds. ! 834: * For 100 Hz clock, if nap is for 11 msec, timeout is for 2 ticks. ! 835: */ ! 836: ticksToWait = ((msec * HZ) + 999) / 1000; ! 837: timeout (& cprocp->p_polltim, ticksToWait, wakeup, & cprocp->p_polls); ! 838: ! 839: /* ! 840: * Wake for timeout or signal. ! 841: */ ! 842: lbolt0 = lbolt; ! 843: if (x_sleep (& cprocp->p_polls, pritty, slpriSigCatch, ! 844: "nap") == PROCESS_SIGNALLED) { ! 845: /* ! 846: * Signal woke us up. ! 847: */ ! 848: u.u_error = EINTR; ! 849: goto napDone; ! 850: } else { ! 851: /* ! 852: * We were awakened by a timeout. ! 853: * Return number of milliseconds actually waited. ! 854: */ ! 855: ticksWaited = lbolt - lbolt0; ! 856: if (ticksWaited >= 0) ! 857: ret = (ticksWaited * 1000) / HZ; ! 858: else ! 859: ret = 0; ! 860: goto napDone; ! 861: } ! 862: ! 863: napDone: ! 864: /* ! 865: * Cancel timeout ! 866: */ ! 867: timeout (& cprocp->p_polltim, 0, NULL, NULL); ! 868: ! 869: return ret; ! 870: } ! 871:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.