|
|
1.1 ! root 1: /* ! 2: * Code for various kinds of delays. Most of this is nonportable and ! 3: * requires various enhancements to the operating system, so it won't ! 4: * work on all systems. It is included in curses to provide a portable ! 5: * interface, and so curses itself can use it for function keys. ! 6: */ ! 7: ! 8: /* @(#) naps.c: 1.1 10/15/83 (1.10 3/6/83) */ ! 9: ! 10: #include "curses.ext" ! 11: #include <signal.h> ! 12: ! 13: #define NAPINTERVAL 100 ! 14: #define HZ 60 ! 15: ! 16: /* From early specs - this may change by 4.2BSD */ ! 17: struct _timeval { ! 18: long tv_sec; ! 19: long tv_usec; ! 20: }; ! 21: ! 22: /* ! 23: * Delay the output for ms milliseconds. ! 24: * Note that this is NOT the same as a high resolution sleep. It will ! 25: * cause a delay in the output but will not necessarily suspend the ! 26: * processor. For applications needing to sleep for 1/10th second, ! 27: * this is not a usable substitute. It causes a pause in the displayed ! 28: * output, for example, for the eye wink in snake. It is disrecommended ! 29: * for "delay" to be much more than 1/2 second, especially at high ! 30: * baud rates, because of all the characters it will output. Note ! 31: * that due to system delays, the actual pause could be even more. ! 32: * Some games won't work decently with this routine. ! 33: */ ! 34: delay_output(ms) ! 35: int ms; ! 36: { ! 37: extern int _outchar(); /* it's in putp.c */ ! 38: ! 39: return _delay(ms*10, _outchar); ! 40: } ! 41: ! 42: /* ! 43: * napms. Sleep for ms milliseconds. We don't expect a particularly good ! 44: * resolution - 60ths of a second is normal, 10ths might even be good enough, ! 45: * but the rest of the program thinks in ms because the unit of resolution ! 46: * varies from system to system. (In some countries, it's 50ths, for example.) ! 47: * ! 48: * Here are some reasonable ways to get a good nap. ! 49: * ! 50: * (1) Use the select system call in Berkeley 4.2BSD. ! 51: * ! 52: * (2) Use the 1/10th second resolution wait in the UNIX 3.0 tty driver. ! 53: * It turns out this is hard to do - you need a tty line that is ! 54: * always unused that you have read permission on to sleep on. ! 55: * ! 56: * (3) Install the ft (fast timer) device in your kernel. ! 57: * This is a psuedo-device to which an ioctl will wait n ticks ! 58: * and then send you an alarm. ! 59: * ! 60: * (4) Install the nap system call in your kernel. ! 61: * This system call does a timeout for the requested number of ticks. ! 62: * ! 63: * (5) Write a routine that busy waits checking the time with ftime. ! 64: * Ftime is not present on USG systems, and since this busy waits, ! 65: * it will drag down response on your system. But it works. ! 66: */ ! 67: #ifdef TIOCREMOTE ! 68: /* on 4.2BSD, use select */ ! 69: napms(ms) ! 70: int ms; ! 71: { ! 72: struct _timeval t; ! 73: ! 74: /* ! 75: * If your 4.2BSD select still rounds up to the next higher second, ! 76: * you should remove this code and install the ft driver. ! 77: * This routine was written under the assumption that the problem ! 78: * would be corrected by 4.2BSD. ! 79: */ ! 80: t.sec = ms/1000; ! 81: t.usec = 1000 * (ms % 1000); ! 82: select(0, 0, 0, 0, &t); ! 83: return OK; ! 84: } ! 85: #else ! 86: /* ! 87: * Pause for ms milliseconds. Convert to ticks and wait that long. ! 88: * Call nap, which is either defined below or a system call. ! 89: */ ! 90: napms(ms) ! 91: int ms; ! 92: { ! 93: int ticks; ! 94: int rv; ! 95: ! 96: ticks = ms / (1000 / HZ); ! 97: if (ticks <= 0) ! 98: ticks = 1; ! 99: rv = nap(ticks); /* call either the code below or nap system call */ ! 100: return rv; ! 101: } ! 102: #endif ! 103: ! 104: #ifdef FTIOCSET ! 105: #define HASNAP ! 106: /* ! 107: * The following code is adapted from the sleep code in libc. ! 108: * It uses the "fast timer" device posted to USENET in Feb 1982. ! 109: * nap is like sleep but the units are ticks (e.g. 1/60ths of ! 110: * seconds in the USA). ! 111: */ ! 112: #include <setjmp.h> ! 113: static jmp_buf jmp; ! 114: static int ftfd; ! 115: ! 116: /* don't call nap directly, you should call napms instead */ ! 117: static int ! 118: nap(n) ! 119: unsigned n; ! 120: { ! 121: int napx(); ! 122: unsigned altime; ! 123: int (*alsig)() = SIG_DFL; ! 124: char *ftname; ! 125: struct requestbuf { ! 126: short time; ! 127: short signo; ! 128: } rb; ! 129: ! 130: if (n==0) ! 131: return OK; ! 132: if (ftfd <= 0) { ! 133: ftname = "/dev/ft0"; ! 134: while (ftfd <= 0 && ftname[7] <= '~') { ! 135: ftfd = open(ftname, 0); ! 136: if (ftfd <= 0) ! 137: ftname[7] ++; ! 138: } ! 139: } ! 140: if (ftfd <= 0) { /* Couldn't open a /dev/ft? */ ! 141: sleepnap(n); ! 142: return ERR; ! 143: } ! 144: altime = alarm(1000); /* time to maneuver */ ! 145: if (setjmp(jmp)) { ! 146: signal(SIGALRM, alsig); ! 147: alarm(altime); ! 148: return OK; ! 149: } ! 150: if (altime) { ! 151: if (altime > n) ! 152: altime -= n; ! 153: else { ! 154: n = altime; ! 155: altime = 1; ! 156: } ! 157: } ! 158: alsig = signal(SIGALRM, napx); ! 159: rb.time = n; ! 160: rb.signo = SIGALRM; ! 161: ioctl(ftfd, FTIOCSET, &rb); ! 162: for(;;) ! 163: pause(); ! 164: /*NOTREACHED*/ ! 165: } ! 166: ! 167: static ! 168: napx() ! 169: { ! 170: longjmp(jmp, 1); ! 171: } ! 172: #endif ! 173: ! 174: #ifdef USG ! 175: #ifndef HASNAP ! 176: #define HASNAP ! 177: #define IDLETTY "/dev/idletty" ! 178: /* ! 179: * Do it with the timer in the tty driver. Resolution is only 1/10th ! 180: * of a second. Problem is, if the user types something while we're ! 181: * sleeping, we wake up immediately, and have no way to tell how long ! 182: * we should sleep again. So we're sneaky and use a tty which we are ! 183: * pretty sure nobody is using. ! 184: * ! 185: * Note that we should be able to do this by setting VMIN to 100 and VTIME ! 186: * to the proper number of ticks. But due to a bug in the USG tty driver ! 187: * (this bug was still there in 5.0) this hangs until VMIN chars are typed ! 188: * no matter how much time elapses. ! 189: * ! 190: * This requires some care. If you choose a tty that is a dialup or ! 191: * which otherwise can show carrier, it will hang and you won't get ! 192: * any response from the keyboard. You can use /dev/tty if you have ! 193: * no such tty, but response will feel funny as described above. ! 194: * To find a suitable tty, try "stty > /dev/ttyxx" for various ttyxx's ! 195: * that look unused. If it hangs, you can't use it. You might try ! 196: * connecting a cable to your port that raises carrier to keep it from hanging. ! 197: * ! 198: * To use this feature on USG, you must ! 199: * ln /dev/ttyxx /dev/idletty, ! 200: * where /dev/ttyxx is one of your tty lines that is never used but ! 201: * won't hang on open. Otherwise we always return ERR. ! 202: * ! 203: * THIS USG CODE IS UNSUPPORTED AND ON A USE-AT-YOUR-OWN-RISK BASIS. ! 204: */ ! 205: static int ! 206: nap(ticks) ! 207: int ticks; ! 208: { ! 209: struct termio t, ot; ! 210: static int ttyfd; ! 211: int n, tenths; ! 212: char c; ! 213: ! 214: if (ttyfd == 0) ! 215: ttyfd = open(IDLETTY, 2); ! 216: if (ttyfd < 0) { ! 217: sleepnap(ticks); ! 218: return ERR; ! 219: } ! 220: tenths = (ticks+(HZ/10)/2) / (HZ/10); /* Round to nearest 10th second */ ! 221: ioctl(ttyfd, TCGETA, &t); ! 222: ot = t; ! 223: t.c_lflag &= ~ICANON; ! 224: t.c_cc[VMIN] = 0; ! 225: t.c_cc[VTIME] = tenths; ! 226: ioctl(ttyfd, TCSETAW, &t); ! 227: n = read(ttyfd, &c, 1); ! 228: ioctl(ttyfd, TCSETAW, &ot); ! 229: /* ! 230: * Now we potentially have a character in c that somebody's going ! 231: * to want. We just hope and pray they use getch, because there ! 232: * is no reasonable way to push it back onto the tty. ! 233: */ ! 234: if (n > 0) { ! 235: for (n=0; SP->input_queue[n] >= 0; n++) ! 236: ; ! 237: SP->input_queue[n++] = c; ! 238: SP->input_queue[n++] = -1; ! 239: } ! 240: return OK; ! 241: } ! 242: #endif ! 243: #endif ! 244: ! 245: /* If you have some other externally supplied nap(), add -DHASNAP to cflags */ ! 246: #ifndef HASNAP ! 247: static int ! 248: nap(ms) ! 249: int ms; ! 250: { ! 251: sleep((ms+999)/1000); ! 252: return ERR; ! 253: } ! 254: #endif ! 255: ! 256: /* ! 257: * Nothing better around, so we have to simulate nap with sleep. ! 258: */ ! 259: static ! 260: sleepnap(ticks) ! 261: { ! 262: sleep((ticks+(HZ-1))/HZ); ! 263: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.