|
|
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.