kern_synch.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. /* $OpenBSD: kern_synch.c,v 1.121 2015/05/12 09:30:35 mikeb Exp $ */
  2. /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
  3. /*
  4. * Copyright (c) 1982, 1986, 1990, 1991, 1993
  5. * The Regents of the University of California. All rights reserved.
  6. * (c) UNIX System Laboratories, Inc.
  7. * All or some portions of this file are derived from material licensed
  8. * to the University of California by American Telephone and Telegraph
  9. * Co. or Unix System Laboratories, Inc. and are reproduced herein with
  10. * the permission of UNIX System Laboratories, Inc.
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions
  14. * are met:
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. * 3. Neither the name of the University nor the names of its contributors
  21. * may be used to endorse or promote products derived from this software
  22. * without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34. * SUCH DAMAGE.
  35. *
  36. * @(#)kern_synch.c 8.6 (Berkeley) 1/21/94
  37. */
  38. #include <sys/param.h>
  39. #include <sys/systm.h>
  40. #include <sys/proc.h>
  41. #include <sys/kernel.h>
  42. #include <sys/signalvar.h>
  43. #include <sys/resourcevar.h>
  44. #include <sys/sched.h>
  45. #include <sys/timeout.h>
  46. #include <sys/mount.h>
  47. #include <sys/syscallargs.h>
  48. #include <sys/pool.h>
  49. #include <machine/spinlock.h>
  50. #ifdef KTRACE
  51. #include <sys/ktrace.h>
  52. #endif
  53. int thrsleep(struct proc *, struct sys___thrsleep_args *);
  54. /*
  55. * We're only looking at 7 bits of the address; everything is
  56. * aligned to 4, lots of things are aligned to greater powers
  57. * of 2. Shift right by 8, i.e. drop the bottom 256 worth.
  58. */
  59. #define TABLESIZE 128
  60. #define LOOKUP(x) (((long)(x) >> 8) & (TABLESIZE - 1))
  61. TAILQ_HEAD(slpque,proc) slpque[TABLESIZE];
  62. void
  63. sleep_queue_init(void)
  64. {
  65. int i;
  66. for (i = 0; i < TABLESIZE; i++)
  67. TAILQ_INIT(&slpque[i]);
  68. }
  69. /*
  70. * During autoconfiguration or after a panic, a sleep will simply
  71. * lower the priority briefly to allow interrupts, then return.
  72. * The priority to be used (safepri) is machine-dependent, thus this
  73. * value is initialized and maintained in the machine-dependent layers.
  74. * This priority will typically be 0, or the lowest priority
  75. * that is safe for use on the interrupt stack; it can be made
  76. * higher to block network software interrupts after panics.
  77. */
  78. extern int safepri;
  79. /*
  80. * General sleep call. Suspends the current process until a wakeup is
  81. * performed on the specified identifier. The process will then be made
  82. * runnable with the specified priority. Sleeps at most timo/hz seconds
  83. * (0 means no timeout). If pri includes PCATCH flag, signals are checked
  84. * before and after sleeping, else signals are not checked. Returns 0 if
  85. * awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a
  86. * signal needs to be delivered, ERESTART is returned if the current system
  87. * call should be restarted if possible, and EINTR is returned if the system
  88. * call should be interrupted by the signal (return EINTR).
  89. */
  90. int
  91. tsleep(const volatile void *ident, int priority, const char *wmesg, int timo)
  92. {
  93. struct sleep_state sls;
  94. int error, error1;
  95. #ifdef MULTIPROCESSOR
  96. int hold_count;
  97. #endif
  98. KASSERT((priority & ~(PRIMASK | PCATCH)) == 0);
  99. #ifdef MULTIPROCESSOR
  100. KASSERT(timo || __mp_lock_held(&kernel_lock));
  101. #endif
  102. if (cold || panicstr) {
  103. int s;
  104. /*
  105. * After a panic, or during autoconfiguration,
  106. * just give interrupts a chance, then just return;
  107. * don't run any other procs or panic below,
  108. * in case this is the idle process and already asleep.
  109. */
  110. s = splhigh();
  111. splx(safepri);
  112. #ifdef MULTIPROCESSOR
  113. if (__mp_lock_held(&kernel_lock)) {
  114. hold_count = __mp_release_all(&kernel_lock);
  115. __mp_acquire_count(&kernel_lock, hold_count);
  116. }
  117. #endif
  118. splx(s);
  119. return (0);
  120. }
  121. sleep_setup(&sls, ident, priority, wmesg);
  122. sleep_setup_timeout(&sls, timo);
  123. sleep_setup_signal(&sls, priority);
  124. sleep_finish(&sls, 1);
  125. error1 = sleep_finish_timeout(&sls);
  126. error = sleep_finish_signal(&sls);
  127. /* Signal errors are higher priority than timeouts. */
  128. if (error == 0 && error1 != 0)
  129. error = error1;
  130. return (error);
  131. }
  132. /*
  133. * Same as tsleep, but if we have a mutex provided, then once we've
  134. * entered the sleep queue we drop the mutex. After sleeping we re-lock.
  135. */
  136. int
  137. msleep(const volatile void *ident, struct mutex *mtx, int priority,
  138. const char *wmesg, int timo)
  139. {
  140. struct sleep_state sls;
  141. int error, error1, spl;
  142. #ifdef MULTIPROCESSOR
  143. int hold_count;
  144. #endif
  145. KASSERT((priority & ~(PRIMASK | PCATCH | PNORELOCK)) == 0);
  146. KASSERT(mtx != NULL);
  147. if (cold || panicstr) {
  148. /*
  149. * After a panic, or during autoconfiguration,
  150. * just give interrupts a chance, then just return;
  151. * don't run any other procs or panic below,
  152. * in case this is the idle process and already asleep.
  153. */
  154. spl = MUTEX_OLDIPL(mtx);
  155. MUTEX_OLDIPL(mtx) = safepri;
  156. mtx_leave(mtx);
  157. #ifdef MULTIPROCESSOR
  158. if (__mp_lock_held(&kernel_lock)) {
  159. hold_count = __mp_release_all(&kernel_lock);
  160. __mp_acquire_count(&kernel_lock, hold_count);
  161. }
  162. #endif
  163. if ((priority & PNORELOCK) == 0) {
  164. mtx_enter(mtx);
  165. MUTEX_OLDIPL(mtx) = spl;
  166. } else
  167. splx(spl);
  168. return (0);
  169. }
  170. sleep_setup(&sls, ident, priority, wmesg);
  171. sleep_setup_timeout(&sls, timo);
  172. sleep_setup_signal(&sls, priority);
  173. /* XXX - We need to make sure that the mutex doesn't
  174. * unblock splsched. This can be made a bit more
  175. * correct when the sched_lock is a mutex.
  176. */
  177. spl = MUTEX_OLDIPL(mtx);
  178. MUTEX_OLDIPL(mtx) = splsched();
  179. mtx_leave(mtx);
  180. sleep_finish(&sls, 1);
  181. error1 = sleep_finish_timeout(&sls);
  182. error = sleep_finish_signal(&sls);
  183. if ((priority & PNORELOCK) == 0) {
  184. mtx_enter(mtx);
  185. MUTEX_OLDIPL(mtx) = spl; /* put the ipl back */
  186. } else
  187. splx(spl);
  188. /* Signal errors are higher priority than timeouts. */
  189. if (error == 0 && error1 != 0)
  190. error = error1;
  191. return (error);
  192. }
  193. void
  194. sleep_setup(struct sleep_state *sls, const volatile void *ident, int prio,
  195. const char *wmesg)
  196. {
  197. struct proc *p = curproc;
  198. #ifdef DIAGNOSTIC
  199. if (p->p_flag & P_CANTSLEEP)
  200. panic("sleep: %s failed insomnia", p->p_comm);
  201. if (ident == NULL)
  202. panic("tsleep: no ident");
  203. if (p->p_stat != SONPROC)
  204. panic("tsleep: not SONPROC");
  205. #endif
  206. #ifdef KTRACE
  207. if (KTRPOINT(p, KTR_CSW))
  208. ktrcsw(p, 1, 0);
  209. #endif
  210. sls->sls_catch = 0;
  211. sls->sls_do_sleep = 1;
  212. sls->sls_sig = 1;
  213. SCHED_LOCK(sls->sls_s);
  214. p->p_wchan = ident;
  215. p->p_wmesg = wmesg;
  216. p->p_slptime = 0;
  217. p->p_priority = prio & PRIMASK;
  218. TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], p, p_runq);
  219. }
  220. void
  221. sleep_finish(struct sleep_state *sls, int do_sleep)
  222. {
  223. struct proc *p = curproc;
  224. if (sls->sls_do_sleep && do_sleep) {
  225. p->p_stat = SSLEEP;
  226. p->p_ru.ru_nvcsw++;
  227. SCHED_ASSERT_LOCKED();
  228. mi_switch();
  229. } else if (!do_sleep) {
  230. unsleep(p);
  231. }
  232. #ifdef DIAGNOSTIC
  233. if (p->p_stat != SONPROC)
  234. panic("sleep_finish !SONPROC");
  235. #endif
  236. p->p_cpu->ci_schedstate.spc_curpriority = p->p_usrpri;
  237. SCHED_UNLOCK(sls->sls_s);
  238. /*
  239. * Even though this belongs to the signal handling part of sleep,
  240. * we need to clear it before the ktrace.
  241. */
  242. atomic_clearbits_int(&p->p_flag, P_SINTR);
  243. #ifdef KTRACE
  244. if (KTRPOINT(p, KTR_CSW))
  245. ktrcsw(p, 0, 0);
  246. #endif
  247. }
  248. void
  249. sleep_setup_timeout(struct sleep_state *sls, int timo)
  250. {
  251. if (timo)
  252. timeout_add(&curproc->p_sleep_to, timo);
  253. }
  254. int
  255. sleep_finish_timeout(struct sleep_state *sls)
  256. {
  257. struct proc *p = curproc;
  258. if (p->p_flag & P_TIMEOUT) {
  259. atomic_clearbits_int(&p->p_flag, P_TIMEOUT);
  260. return (EWOULDBLOCK);
  261. } else
  262. timeout_del(&p->p_sleep_to);
  263. return (0);
  264. }
  265. void
  266. sleep_setup_signal(struct sleep_state *sls, int prio)
  267. {
  268. struct proc *p = curproc;
  269. if ((sls->sls_catch = (prio & PCATCH)) == 0)
  270. return;
  271. /*
  272. * We put ourselves on the sleep queue and start our timeout
  273. * before calling CURSIG, as we could stop there, and a wakeup
  274. * or a SIGCONT (or both) could occur while we were stopped.
  275. * A SIGCONT would cause us to be marked as SSLEEP
  276. * without resuming us, thus we must be ready for sleep
  277. * when CURSIG is called. If the wakeup happens while we're
  278. * stopped, p->p_wchan will be 0 upon return from CURSIG.
  279. */
  280. atomic_setbits_int(&p->p_flag, P_SINTR);
  281. if (p->p_p->ps_single != NULL || (sls->sls_sig = CURSIG(p)) != 0) {
  282. if (p->p_wchan)
  283. unsleep(p);
  284. p->p_stat = SONPROC;
  285. sls->sls_do_sleep = 0;
  286. } else if (p->p_wchan == 0) {
  287. sls->sls_catch = 0;
  288. sls->sls_do_sleep = 0;
  289. }
  290. }
  291. int
  292. sleep_finish_signal(struct sleep_state *sls)
  293. {
  294. struct proc *p = curproc;
  295. int error;
  296. if (sls->sls_catch != 0) {
  297. if ((error = single_thread_check(p, 1)))
  298. return (error);
  299. if (sls->sls_sig != 0 || (sls->sls_sig = CURSIG(p)) != 0) {
  300. if (p->p_p->ps_sigacts->ps_sigintr &
  301. sigmask(sls->sls_sig))
  302. return (EINTR);
  303. return (ERESTART);
  304. }
  305. }
  306. return (0);
  307. }
  308. /*
  309. * Implement timeout for tsleep.
  310. * If process hasn't been awakened (wchan non-zero),
  311. * set timeout flag and undo the sleep. If proc
  312. * is stopped, just unsleep so it will remain stopped.
  313. */
  314. void
  315. endtsleep(void *arg)
  316. {
  317. struct proc *p = arg;
  318. int s;
  319. SCHED_LOCK(s);
  320. if (p->p_wchan) {
  321. if (p->p_stat == SSLEEP)
  322. setrunnable(p);
  323. else
  324. unsleep(p);
  325. atomic_setbits_int(&p->p_flag, P_TIMEOUT);
  326. }
  327. SCHED_UNLOCK(s);
  328. }
  329. /*
  330. * Remove a process from its wait queue
  331. */
  332. void
  333. unsleep(struct proc *p)
  334. {
  335. SCHED_ASSERT_LOCKED();
  336. if (p->p_wchan) {
  337. TAILQ_REMOVE(&slpque[LOOKUP(p->p_wchan)], p, p_runq);
  338. p->p_wchan = NULL;
  339. }
  340. }
  341. /*
  342. * Make a number of processes sleeping on the specified identifier runnable.
  343. */
  344. void
  345. wakeup_n(const volatile void *ident, int n)
  346. {
  347. struct slpque *qp;
  348. struct proc *p;
  349. struct proc *pnext;
  350. int s;
  351. SCHED_LOCK(s);
  352. qp = &slpque[LOOKUP(ident)];
  353. for (p = TAILQ_FIRST(qp); p != NULL && n != 0; p = pnext) {
  354. pnext = TAILQ_NEXT(p, p_runq);
  355. #ifdef DIAGNOSTIC
  356. if (p->p_stat != SSLEEP && p->p_stat != SSTOP)
  357. panic("wakeup: p_stat is %d", (int)p->p_stat);
  358. #endif
  359. if (p->p_wchan == ident) {
  360. --n;
  361. p->p_wchan = 0;
  362. TAILQ_REMOVE(qp, p, p_runq);
  363. if (p->p_stat == SSLEEP)
  364. setrunnable(p);
  365. }
  366. }
  367. SCHED_UNLOCK(s);
  368. }
  369. /*
  370. * Make all processes sleeping on the specified identifier runnable.
  371. */
  372. void
  373. wakeup(const volatile void *chan)
  374. {
  375. wakeup_n(chan, -1);
  376. }
  377. int
  378. sys_sched_yield(struct proc *p, void *v, register_t *retval)
  379. {
  380. yield();
  381. return (0);
  382. }
  383. int thrsleep_unlock(void *, int);
  384. int
  385. thrsleep_unlock(void *lock, int lockflags)
  386. {
  387. static _atomic_lock_t unlocked = _ATOMIC_LOCK_UNLOCKED;
  388. _atomic_lock_t *atomiclock = lock;
  389. uint32_t *ticket = lock;
  390. uint32_t ticketvalue;
  391. int error;
  392. if (!lock)
  393. return (0);
  394. if (lockflags) {
  395. if ((error = copyin(ticket, &ticketvalue, sizeof(ticketvalue))))
  396. return (error);
  397. ticketvalue++;
  398. error = copyout(&ticketvalue, ticket, sizeof(ticketvalue));
  399. } else {
  400. error = copyout(&unlocked, atomiclock, sizeof(unlocked));
  401. }
  402. return (error);
  403. }
  404. static int globalsleepaddr;
  405. int
  406. thrsleep(struct proc *p, struct sys___thrsleep_args *v)
  407. {
  408. struct sys___thrsleep_args /* {
  409. syscallarg(const volatile void *) ident;
  410. syscallarg(clockid_t) clock_id;
  411. syscallarg(const struct timespec *) tp;
  412. syscallarg(void *) lock;
  413. syscallarg(const int *) abort;
  414. } */ *uap = v;
  415. long ident = (long)SCARG(uap, ident);
  416. struct timespec *tsp = (struct timespec *)SCARG(uap, tp);
  417. void *lock = SCARG(uap, lock);
  418. long long to_ticks = 0;
  419. int abort, error;
  420. clockid_t clock_id = SCARG(uap, clock_id) & 0x7;
  421. int lockflags = SCARG(uap, clock_id) & 0x8;
  422. if (ident == 0)
  423. return (EINVAL);
  424. if (tsp != NULL) {
  425. struct timespec now;
  426. if ((error = clock_gettime(p, clock_id, &now)))
  427. return (error);
  428. #ifdef KTRACE
  429. if (KTRPOINT(p, KTR_STRUCT))
  430. ktrabstimespec(p, tsp);
  431. #endif
  432. if (timespeccmp(tsp, &now, <)) {
  433. /* already passed: still do the unlock */
  434. if ((error = thrsleep_unlock(lock, lockflags)))
  435. return (error);
  436. return (EWOULDBLOCK);
  437. }
  438. timespecsub(tsp, &now, tsp);
  439. to_ticks = (long long)hz * tsp->tv_sec +
  440. (tsp->tv_nsec + tick * 1000 - 1) / (tick * 1000) + 1;
  441. if (to_ticks > INT_MAX)
  442. to_ticks = INT_MAX;
  443. }
  444. p->p_thrslpid = ident;
  445. if ((error = thrsleep_unlock(lock, lockflags))) {
  446. goto out;
  447. }
  448. if (SCARG(uap, abort) != NULL) {
  449. if ((error = copyin(SCARG(uap, abort), &abort,
  450. sizeof(abort))) != 0)
  451. goto out;
  452. if (abort) {
  453. error = EINTR;
  454. goto out;
  455. }
  456. }
  457. if (p->p_thrslpid == 0)
  458. error = 0;
  459. else {
  460. void *sleepaddr = &p->p_thrslpid;
  461. if (ident == -1)
  462. sleepaddr = &globalsleepaddr;
  463. error = tsleep(sleepaddr, PUSER | PCATCH, "thrsleep",
  464. (int)to_ticks);
  465. }
  466. out:
  467. p->p_thrslpid = 0;
  468. if (error == ERESTART)
  469. error = EINTR;
  470. return (error);
  471. }
  472. int
  473. sys___thrsleep(struct proc *p, void *v, register_t *retval)
  474. {
  475. struct sys___thrsleep_args /* {
  476. syscallarg(const volatile void *) ident;
  477. syscallarg(clockid_t) clock_id;
  478. syscallarg(struct timespec *) tp;
  479. syscallarg(void *) lock;
  480. syscallarg(const int *) abort;
  481. } */ *uap = v;
  482. struct timespec ts;
  483. int error;
  484. if (SCARG(uap, tp) != NULL) {
  485. if ((error = copyin(SCARG(uap, tp), &ts, sizeof(ts)))) {
  486. *retval = error;
  487. return (0);
  488. }
  489. SCARG(uap, tp) = &ts;
  490. }
  491. *retval = thrsleep(p, uap);
  492. return (0);
  493. }
  494. int
  495. sys___thrwakeup(struct proc *p, void *v, register_t *retval)
  496. {
  497. struct sys___thrwakeup_args /* {
  498. syscallarg(const volatile void *) ident;
  499. syscallarg(int) n;
  500. } */ *uap = v;
  501. long ident = (long)SCARG(uap, ident);
  502. int n = SCARG(uap, n);
  503. struct proc *q;
  504. int found = 0;
  505. if (ident == 0)
  506. *retval = EINVAL;
  507. else if (ident == -1)
  508. wakeup(&globalsleepaddr);
  509. else {
  510. TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
  511. if (q->p_thrslpid == ident) {
  512. wakeup_one(&q->p_thrslpid);
  513. q->p_thrslpid = 0;
  514. if (++found == n)
  515. break;
  516. }
  517. }
  518. *retval = found ? 0 : ESRCH;
  519. }
  520. return (0);
  521. }