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