|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Mach Operating System
24: * Copyright (c) 1987 Carnegie-Mellon University
25: * All rights reserved. The CMU software License Agreement specifies
26: * the terms and conditions for use and redistribution.
27: */
28:
29: #include <sys/param.h>
30: #include <sys/systm.h>
31: #include <sys/proc.h>
32: #include <sys/user.h>
33: #include <sys/file.h>
34: #include <sys/vnode.h>
35: #include <sys/kernel.h>
36: #include <sys/buf.h>
37:
38: #include <machine/spl.h>
39:
40: #include <kern/queue.h>
41: #include <sys/lock.h>
42: #include <kern/thread.h>
43: #include <kern/ast.h>
44:
45: #include <kern/cpu_number.h>
46: #include <vm/vm_kern.h>
47:
48: #include <kern/task.h>
49: #include <mach/time_value.h>
50:
51: _sleep_continue()
52: {
53: register struct proc *p;
54: register thread_t thread = current_thread();
55: thread_act_t th_act;
56: struct uthread * ut;
57: int sig, catch;
58: int error = 0;
59:
60: th_act = current_act();
61: ut = get_bsdthread_info(th_act);
62: catch = ut->uu_pri & PCATCH;
63: p = current_proc();
64:
65: #if FIXME /* [ */
66: thread->wait_mesg = NULL;
67: #endif /* FIXME ] */
68: switch (get_thread_waitresult(thread)) {
69: case THREAD_TIMED_OUT:
70: error = EWOULDBLOCK;
71: break;
72: case THREAD_AWAKENED:
73: /*
74: * Posix implies any signal should be delivered
75: * first, regardless of whether awakened due
76: * to receiving event.
77: */
78: if (!catch)
79: break;
80: /* else fall through */
81: case THREAD_INTERRUPTED:
82: if (catch) {
83: unix_master();
84: if (thread_should_abort(current_thread())) {
85: error = EINTR;
86: } else if (SHOULDissignal(p,ut)) {
87: if (sig = CURSIG(p)) {
88: if (p->p_sigacts->ps_sigintr & sigmask(sig))
89: error = EINTR;
90: else
91: error = ERESTART;
92: }
93: if (thread_should_abort(current_thread())) {
94: error = EINTR;
95: }
96: }
97: unix_release();
98: }
99: break;
100: }
101:
102: if ((error == EINTR) || (error == ERESTART)) {
103: thread_apc_set(th_act, bsd_ast);
104: }
105: if (ut->uu_timo)
106: thread_cancel_timer();
107:
108: thread_set_funneled(TRUE);
109: unix_syscall_return((*ut->uu_continuation)(error));
110: }
111:
112: /*
113: * Give up the processor till a wakeup occurs
114: * on chan, at which time the process
115: * enters the scheduling queue at priority pri.
116: * The most important effect of pri is that when
117: * pri<=PZERO a signal cannot disturb the sleep;
118: * if pri>PZERO signals will be processed.
119: * If pri&PCATCH is set, signals will cause sleep
120: * to return 1, rather than longjmp.
121: * Callers of this routine must be prepared for
122: * premature return, and check that the reason for
123: * sleeping has gone away.
124: */
125:
126: #if FIXME
127: static __inline__
128: #endif
129: int
130: _sleep(chan, pri, wmsg, timo, continuation)
131: caddr_t chan;
132: int pri;
133: char *wmsg;
134: int timo;
135: int (*continuation)();
136: {
137: register struct proc *p;
138: register thread_t thread = current_thread();
139: thread_act_t th_act;
140: struct uthread * ut;
141: int sig, catch = pri & PCATCH;
142: int error = 0;
143: spl_t s;
144:
145: s = splhigh();
146:
147: th_act = current_act();
148: ut = get_bsdthread_info(th_act);
149:
150: p = current_proc();
151: #if KTRACE
152: if (KTRPOINT(p, KTR_CSW))
153: ktrcsw(p->p_tracep, 1, 0);
154: #endif
155: p->p_priority = pri & PRIMASK;
156:
157: if (chan)
158: assert_wait(chan, (catch ? THREAD_ABORTSAFE : THREAD_UNINT));
159:
160: if (timo)
161: thread_set_timer(timo, NSEC_PER_SEC / hz);
162: /*
163: * We start our timeout
164: * before calling CURSIG, as we could stop there, and a wakeup
165: * or a SIGCONT (or both) could occur while we were stopped.
166: * A SIGCONT would cause us to be marked as SSLEEP
167: * without resuming us, thus we must be ready for sleep
168: * when CURSIG is called. If the wakeup happens while we're
169: * stopped, p->p_wchan will be 0 upon return from CURSIG.
170: */
171: if (catch) {
172: unix_master();
173: if (SHOULDissignal(p,ut)) {
174: if (sig = CURSIG(p)) {
175: clear_wait(thread, THREAD_INTERRUPTED, TRUE);
176: if (p->p_sigacts->ps_sigintr & sigmask(sig))
177: error = EINTR;
178: else
179: error = ERESTART;
180: unix_release();
181: goto out;
182: }
183: }
184: if (thread_should_abort(current_thread())) {
185: clear_wait(thread, THREAD_INTERRUPTED, TRUE);
186: error = EINTR;
187: unix_release();
188: goto out;
189: }
190: if (get_thread_waitevent(thread) == 0) { /*already happened */
191: unix_release();
192: goto out;
193: }
194: unix_release();
195: }
196:
197: #if FIXME /* [ */
198: thread->wait_mesg = wmsg;
199: #endif /* FIXME ] */
200: (void) spl0();
201: p->p_stats->p_ru.ru_nvcsw++;
202:
203: if (continuation != (int (*)()) 0 ) {
204: ut->uu_continuation = continuation;
205: ut->uu_pri = pri;
206: ut->uu_timo = timo;
207: thread_block(_sleep_continue);
208: /* NOTREACHED */
209: }
210:
211: thread_block(0);
212:
213: #if FIXME /* [ */
214: thread->wait_mesg = NULL;
215: #endif /* FIXME ] */
216: switch (get_thread_waitresult(thread)) {
217: case THREAD_TIMED_OUT:
218: error = EWOULDBLOCK;
219: break;
220: case THREAD_AWAKENED:
221: /*
222: * Posix implies any signal should be delivered
223: * first, regardless of whether awakened due
224: * to receiving event.
225: */
226: if (!catch)
227: break;
228: /* else fall through */
229: case THREAD_INTERRUPTED:
230: if (catch) {
231: unix_master();
232: if (thread_should_abort(current_thread())) {
233: error = EINTR;
234: } else if (SHOULDissignal(p,ut)) {
235: if (sig = CURSIG(p)) {
236: if (p->p_sigacts->ps_sigintr & sigmask(sig))
237: error = EINTR;
238: else
239: error = ERESTART;
240: }
241: if (thread_should_abort(current_thread())) {
242: error = EINTR;
243: }
244: }
245: unix_release();
246: }
247: break;
248: }
249: out:
250: if ((error == EINTR) || (error == ERESTART)) {
251: thread_apc_set(th_act, bsd_ast);
252: }
253: if (timo)
254: thread_cancel_timer();
255: (void) splx(s);
256: return (error);
257: }
258:
259: int sleep(chan, pri)
260: void *chan;
261: int pri;
262: {
263:
264: return (_sleep((caddr_t)chan, pri, (char *)NULL, 0, (void (*)())0 ));
265:
266: }
267:
268: int tsleep(chan, pri, wmsg, timo)
269: void *chan;
270: int pri;
271: char * wmsg;
272: int timo;
273: {
274: return(_sleep((caddr_t)chan, pri, wmsg, timo, (void (*)())0 ));
275: }
276:
277: int tsleep0(chan, pri, wmsg, timo, continuation)
278: void *chan;
279: int pri;
280: char * wmsg;
281: int timo;
282: int (*continuation)();
283: {
284: return(_sleep((caddr_t)chan, pri, wmsg, timo, continuation));
285: }
286:
287: /*
288: * Wake up all processes sleeping on chan.
289: */
290: void
291: wakeup(chan)
292: register void *chan;
293: {
294: int s;
295:
296: s = splhigh();
297: thread_wakeup_prim((caddr_t)chan,FALSE, THREAD_AWAKENED,0);
298: splx(s);
299: }
300:
301: /*
302: * Wake up the first process sleeping on chan.
303: *
304: * Be very sure that the first process is really
305: * the right one to wakeup.
306: */
307: wakeup_one(chan)
308: register caddr_t chan;
309: {
310: int s;
311:
312: s = splhigh();
313: thread_wakeup_prim((caddr_t)chan,FALSE, THREAD_AWAKENED);
314: splx(s);
315: }
316:
317: /*
318: * Compute the priority of a process when running in user mode.
319: * Arrange to reschedule if the resulting priority is better
320: * than that of the current process.
321: */
322: void
323: resetpriority(p)
324: register struct proc *p;
325: {
326: int newpri;
327: #if FIXME
328: if (p->p_nice < 0)
329: newpri = BASEPRI_USER +
330: (p->p_nice * (MAXPRI_USER - BASEPRI_USER)) / PRIO_MIN;
331: else
332: newpri = BASEPRI_USER -
333: (p->p_nice * BASEPRI_USER) / PRIO_MAX;
334:
335: (void)task_priority(p->task, newpri, TRUE);
336: #endif /* FIXME */
337: }
338:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.