1: #include "ft.h"
2: #if NFT > 0
3: /*
4: * Fast Timer -- a pseudo-device that behaves like an interval timer.
5: *
6: * Note: because of exclusive open it can also be used as a lock file.
7: */
8:
9: #include "param.h"
10: #include <sys/systm.h>
11: #include <sys/tty.h>
12: #include <sys/dir.h>
13: #include <sys/user.h>
14: #include <sys/proc.h>
15: #include <sys/map.h>
16: #include <sys/conf.h>
17:
18: /*
19: * Per-minor-device state table
20: *
21: * Invariants:
22: * - device is open iff ftt_procp != 0
23: * - timeout in progress iff ftt_state != AVAILABLE
24: */
25:
26: struct fttab {
27: struct proc *ftt_procp; /* proctab entry and pid of */
28: short ftt_pid; /* controlling process. */
29: short ftt_state; /* AVAILABLE, CANCELLED, sig # */
30: } fttab[NFT];
31:
32: #define AVAILABLE (0)
33: #define CANCELLED (-1)
34:
35: #define MAXTIMEREQ (60 * hz) /* 1 minute */
36:
37: /*
38: * Open
39: *
40: * Exclusive use only
41: */
42: /*ARGSUSED*/
43: ftopen(d, flag)
44: {
45: register u_short dminor;
46: register struct fttab *ftp;
47:
48: dminor = minor(d);
49: if (dminor >= NFT) {
50: u.u_error = ENXIO;
51: return;
52: }
53: ftp = &fttab[dminor];
54: if ((ftp->ftt_procp != (struct proc *) NULL)
55: || (ftp->ftt_state != AVAILABLE)) {
56: u.u_error = EBUSY;
57: return;
58: }
59: ftp->ftt_procp = u.u_procp;
60: ftp->ftt_pid = u.u_procp->p_pid;
61: }
62:
63: /*
64: * Close
65: */
66: ftclose(d)
67: {
68: register u_short dminor;
69: register struct fttab *ftp;
70:
71: dminor = minor(d);
72: #ifdef PARANOIA
73: if (dminor >= NFT) {
74: printf("ERR: ftclose\n");
75: u.u_error = ENXIO;
76: return;
77: }
78: #endif
79: ftp = &fttab[dminor];
80: ftp->ftt_procp = (struct proc *) NULL;
81: ftp->ftt_pid = 0;
82: }
83:
84: /*
85: * Ioctl
86: *
87: * All real work is done here using
88: *
89: * FTIOCSET request a software interrupt after specified
90: * number of clock ticks
91: * FTIOCCANCEL cancel an outstanding request
92: */
93: /*ARGSUSED*/
94: ftioctl(dev, cmd, addr, flag)
95: caddr_t addr;
96: dev_t dev;
97: {
98: void fttimeout();
99: register u_short dminor;
100: register struct fttab *ftp;
101:
102: dminor = minor(dev);
103: if (dminor >= NFT) {
104: printf("ERR: ftioctl!\n");
105: u.u_error = EINVAL;
106: }
107:
108: ftp = &fttab[dminor];
109:
110: /*
111: * Make sure invoking process owns the device.
112: * This can only fail if call is from a child
113: * forked off after opening the ft device.
114: */
115: if ((u.u_procp != ftp->ftt_procp)
116: || (u.u_procp->p_pid != ftp->ftt_pid)) {
117: u.u_error = EBUSY;
118: return;
119: }
120:
121: /*
122: * Interpret command
123: */
124: switch(cmd) {
125:
126: case FTIOCSET:
127: {
128: struct {
129: u_short timereq;
130: short sigreq;
131: } request;
132:
133: /*
134: * Get request, make sure it's reasonable
135: */
136: if (copyin(addr, (caddr_t) &request, sizeof request)) {
137: u.u_error = EFAULT;
138: return;
139: }
140: if ((request.sigreq <= 0) || (request.sigreq > NSIG)
141: || (request.timereq > MAXTIMEREQ)) {
142: u.u_error = EINVAL;
143: return;
144: }
145: /*
146: * Schedule the interrupt
147: */
148: if (ftp->ftt_state != AVAILABLE) {
149: u.u_error = EBUSY;
150: return;
151: }
152: ftp->ftt_state = request.sigreq;
153: timeout(fttimeout, (caddr_t) ftp, request.timereq);
154: }
155: break;
156:
157: case FTIOCCANCEL:
158: (void) spl5();
159: if (ftp->ftt_state != AVAILABLE)
160: ftp->ftt_state = CANCELLED;
161: (void) spl0();
162: break;
163:
164: default:
165: u.u_error = ENOTTY;
166: break;
167: }
168: }
169:
170: /*
171: * Fttimeout
172: *
173: * Called by system timeout
174: *
175: * Verify that requesting process is still around
176: * Verify that request hasn't been cancelled
177: * Send the signal
178: */
179: void
180: fttimeout(ftp)
181: register struct fttab *ftp;
182: {
183: register struct proc *pp;
184: register prevstate;
185:
186: prevstate = ftp->ftt_state;
187: ftp->ftt_state = AVAILABLE;
188:
189: if ((prevstate == CANCELLED)
190: || ((pp = ftp->ftt_procp) == ((struct proc *) NULL))
191: || (pp->p_pid != ftp->ftt_pid))
192: return;
193:
194: #ifdef PARANOIA
195: if ((prevstate < 1) || (prevstate >= NSIG)) {
196: printf("ERR: fttimeout %d\n",prevstate);
197: return;
198: }
199: #endif
200: psignal(pp, prevstate);
201: }
202: #endif
Defined functions
Defined variables
fttab
defined in line
30; used 3 times
Defined struct's
fttab
defined in line
26; used 8 times
Defined macros