1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 2498 stevel * Common Development and Distribution License (the "License"). 6 2498 stevel * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 5891 raf 22 0 stevel /* 23 8566 Madhavan * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel #include <sys/thread.h> 28 0 stevel #include <sys/proc.h> 29 0 stevel #include <sys/debug.h> 30 0 stevel #include <sys/cmn_err.h> 31 0 stevel #include <sys/systm.h> 32 0 stevel #include <sys/sobject.h> 33 0 stevel #include <sys/sleepq.h> 34 0 stevel #include <sys/cpuvar.h> 35 0 stevel #include <sys/condvar.h> 36 0 stevel #include <sys/condvar_impl.h> 37 0 stevel #include <sys/schedctl.h> 38 0 stevel #include <sys/procfs.h> 39 0 stevel #include <sys/sdt.h> 40 8048 Madhavan #include <sys/callo.h> 41 9334 Madhavan 42 9334 Madhavan clock_t cv_timedwait_hires(kcondvar_t *, kmutex_t *, hrtime_t, hrtime_t, int); 43 0 stevel 44 0 stevel /* 45 0 stevel * CV_MAX_WAITERS is the maximum number of waiters we track; once 46 0 stevel * the number becomes higher than that, we look at the sleepq to 47 0 stevel * see whether there are *really* any waiters. 48 0 stevel */ 49 0 stevel #define CV_MAX_WAITERS 1024 /* must be power of 2 */ 50 0 stevel #define CV_WAITERS_MASK (CV_MAX_WAITERS - 1) 51 0 stevel 52 0 stevel /* 53 0 stevel * Threads don't "own" condition variables. 54 0 stevel */ 55 0 stevel /* ARGSUSED */ 56 0 stevel static kthread_t * 57 0 stevel cv_owner(void *cvp) 58 0 stevel { 59 0 stevel return (NULL); 60 0 stevel } 61 0 stevel 62 0 stevel /* 63 0 stevel * Unsleep a thread that's blocked on a condition variable. 64 0 stevel */ 65 0 stevel static void 66 0 stevel cv_unsleep(kthread_t *t) 67 0 stevel { 68 0 stevel condvar_impl_t *cvp = (condvar_impl_t *)t->t_wchan; 69 0 stevel sleepq_head_t *sqh = SQHASH(cvp); 70 0 stevel 71 0 stevel ASSERT(THREAD_LOCK_HELD(t)); 72 0 stevel 73 0 stevel if (cvp == NULL) 74 7240 rh87107 panic("cv_unsleep: thread %p not on sleepq %p", 75 7240 rh87107 (void *)t, (void *)sqh); 76 2498 stevel DTRACE_SCHED1(wakeup, kthread_t *, t); 77 0 stevel sleepq_unsleep(t); 78 0 stevel if (cvp->cv_waiters != CV_MAX_WAITERS) 79 0 stevel cvp->cv_waiters--; 80 0 stevel disp_lock_exit_high(&sqh->sq_lock); 81 0 stevel CL_SETRUN(t); 82 0 stevel } 83 0 stevel 84 0 stevel /* 85 0 stevel * Change the priority of a thread that's blocked on a condition variable. 86 0 stevel */ 87 0 stevel static void 88 0 stevel cv_change_pri(kthread_t *t, pri_t pri, pri_t *t_prip) 89 0 stevel { 90 0 stevel condvar_impl_t *cvp = (condvar_impl_t *)t->t_wchan; 91 0 stevel sleepq_t *sqp = t->t_sleepq; 92 0 stevel 93 0 stevel ASSERT(THREAD_LOCK_HELD(t)); 94 0 stevel ASSERT(&SQHASH(cvp)->sq_queue == sqp); 95 0 stevel 96 0 stevel if (cvp == NULL) 97 7240 rh87107 panic("cv_change_pri: %p not on sleep queue", (void *)t); 98 0 stevel sleepq_dequeue(t); 99 0 stevel *t_prip = pri; 100 0 stevel sleepq_insert(sqp, t); 101 0 stevel } 102 0 stevel 103 0 stevel /* 104 0 stevel * The sobj_ops vector exports a set of functions needed when a thread 105 0 stevel * is asleep on a synchronization object of this type. 106 0 stevel */ 107 0 stevel static sobj_ops_t cv_sobj_ops = { 108 0 stevel SOBJ_CV, cv_owner, cv_unsleep, cv_change_pri 109 0 stevel }; 110 0 stevel 111 0 stevel /* ARGSUSED */ 112 0 stevel void 113 0 stevel cv_init(kcondvar_t *cvp, char *name, kcv_type_t type, void *arg) 114 0 stevel { 115 0 stevel ((condvar_impl_t *)cvp)->cv_waiters = 0; 116 0 stevel } 117 0 stevel 118 0 stevel /* 119 0 stevel * cv_destroy is not currently needed, but is part of the DDI. 120 0 stevel * This is in case cv_init ever needs to allocate something for a cv. 121 0 stevel */ 122 0 stevel /* ARGSUSED */ 123 0 stevel void 124 0 stevel cv_destroy(kcondvar_t *cvp) 125 0 stevel { 126 0 stevel ASSERT((((condvar_impl_t *)cvp)->cv_waiters & CV_WAITERS_MASK) == 0); 127 0 stevel } 128 0 stevel 129 0 stevel /* 130 0 stevel * The cv_block() function blocks a thread on a condition variable 131 0 stevel * by putting it in a hashed sleep queue associated with the 132 0 stevel * synchronization object. 133 0 stevel * 134 0 stevel * Threads are taken off the hashed sleep queues via calls to 135 0 stevel * cv_signal(), cv_broadcast(), or cv_unsleep(). 136 0 stevel */ 137 0 stevel static void 138 0 stevel cv_block(condvar_impl_t *cvp) 139 0 stevel { 140 0 stevel kthread_t *t = curthread; 141 0 stevel klwp_t *lwp = ttolwp(t); 142 0 stevel sleepq_head_t *sqh; 143 0 stevel 144 0 stevel ASSERT(THREAD_LOCK_HELD(t)); 145 0 stevel ASSERT(t != CPU->cpu_idle_thread); 146 0 stevel ASSERT(CPU_ON_INTR(CPU) == 0); 147 0 stevel ASSERT(t->t_wchan0 == NULL && t->t_wchan == NULL); 148 0 stevel ASSERT(t->t_state == TS_ONPROC); 149 0 stevel 150 0 stevel t->t_schedflag &= ~TS_SIGNALLED; 151 0 stevel CL_SLEEP(t); /* assign kernel priority */ 152 0 stevel t->t_wchan = (caddr_t)cvp; 153 0 stevel t->t_sobj_ops = &cv_sobj_ops; 154 0 stevel DTRACE_SCHED(sleep); 155 0 stevel 156 0 stevel /* 157 0 stevel * The check for t_intr is to avoid doing the 158 0 stevel * account for an interrupt thread on the still-pinned 159 0 stevel * lwp's statistics. 160 0 stevel */ 161 0 stevel if (lwp != NULL && t->t_intr == NULL) { 162 0 stevel lwp->lwp_ru.nvcsw++; 163 0 stevel (void) new_mstate(t, LMS_SLEEP); 164 0 stevel } 165 0 stevel 166 0 stevel sqh = SQHASH(cvp); 167 0 stevel disp_lock_enter_high(&sqh->sq_lock); 168 0 stevel if (cvp->cv_waiters < CV_MAX_WAITERS) 169 0 stevel cvp->cv_waiters++; 170 0 stevel ASSERT(cvp->cv_waiters <= CV_MAX_WAITERS); 171 0 stevel THREAD_SLEEP(t, &sqh->sq_lock); 172 0 stevel sleepq_insert(&sqh->sq_queue, t); 173 0 stevel /* 174 0 stevel * THREAD_SLEEP() moves curthread->t_lockp to point to the 175 0 stevel * lock sqh->sq_lock. This lock is later released by the caller 176 0 stevel * when it calls thread_unlock() on curthread. 177 0 stevel */ 178 0 stevel } 179 0 stevel 180 0 stevel #define cv_block_sig(t, cvp) \ 181 0 stevel { (t)->t_flag |= T_WAKEABLE; cv_block(cvp); } 182 0 stevel 183 0 stevel /* 184 0 stevel * Block on the indicated condition variable and release the 185 0 stevel * associated kmutex while blocked. 186 0 stevel */ 187 0 stevel void 188 0 stevel cv_wait(kcondvar_t *cvp, kmutex_t *mp) 189 0 stevel { 190 0 stevel if (panicstr) 191 0 stevel return; 192 11084 Jerry ASSERT(!quiesce_active); 193 0 stevel 194 0 stevel ASSERT(curthread->t_schedflag & TS_DONT_SWAP); 195 0 stevel thread_lock(curthread); /* lock the thread */ 196 0 stevel cv_block((condvar_impl_t *)cvp); 197 0 stevel thread_unlock_nopreempt(curthread); /* unlock the waiters field */ 198 0 stevel mutex_exit(mp); 199 0 stevel swtch(); 200 0 stevel mutex_enter(mp); 201 0 stevel } 202 0 stevel 203 8048 Madhavan static void 204 8048 Madhavan cv_wakeup(void *arg) 205 8048 Madhavan { 206 8048 Madhavan kthread_t *t = arg; 207 8048 Madhavan 208 8048 Madhavan /* 209 8048 Madhavan * This mutex is acquired and released in order to make sure that 210 8048 Madhavan * the wakeup does not happen before the block itself happens. 211 8048 Madhavan */ 212 8566 Madhavan mutex_enter(&t->t_wait_mutex); 213 8566 Madhavan mutex_exit(&t->t_wait_mutex); 214 8048 Madhavan setrun(t); 215 8048 Madhavan } 216 8048 Madhavan 217 0 stevel /* 218 0 stevel * Same as cv_wait except the thread will unblock at 'tim' 219 0 stevel * (an absolute time) if it hasn't already unblocked. 220 0 stevel * 221 0 stevel * Returns the amount of time left from the original 'tim' value 222 0 stevel * when it was unblocked. 223 0 stevel */ 224 0 stevel clock_t 225 0 stevel cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t tim) 226 0 stevel { 227 9334 Madhavan hrtime_t hrtim; 228 11066 rafael clock_t now = ddi_get_lbolt(); 229 9334 Madhavan 230 11066 rafael if (tim <= now) 231 9334 Madhavan return (-1); 232 9334 Madhavan 233 11066 rafael hrtim = TICK_TO_NSEC(tim - now); 234 9334 Madhavan return (cv_timedwait_hires(cvp, mp, hrtim, nsec_per_tick, 0)); 235 11066 rafael } 236 11066 rafael 237 11066 rafael /* 238 11066 rafael * Same as cv_timedwait() except that the third argument is a relative 239 11066 rafael * timeout value, as opposed to an absolute one. There is also a fourth 240 11066 rafael * argument that specifies how accurately the timeout must be implemented. 241 11066 rafael */ 242 11066 rafael clock_t 243 11066 rafael cv_reltimedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t delta, time_res_t res) 244 11066 rafael { 245 11066 rafael hrtime_t exp; 246 11066 rafael 247 11066 rafael ASSERT(TIME_RES_VALID(res)); 248 11066 rafael 249 11066 rafael if (delta <= 0) 250 11066 rafael return (-1); 251 11066 rafael 252 11066 rafael if ((exp = TICK_TO_NSEC(delta)) < 0) 253 11066 rafael exp = CY_INFINITY; 254 11066 rafael 255 11066 rafael return (cv_timedwait_hires(cvp, mp, exp, time_res[res], 0)); 256 9334 Madhavan } 257 9334 Madhavan 258 9334 Madhavan clock_t 259 9334 Madhavan cv_timedwait_hires(kcondvar_t *cvp, kmutex_t *mp, hrtime_t tim, 260 9334 Madhavan hrtime_t res, int flag) 261 9334 Madhavan { 262 0 stevel kthread_t *t = curthread; 263 8048 Madhavan callout_id_t id; 264 0 stevel clock_t timeleft; 265 9334 Madhavan hrtime_t limit; 266 0 stevel int signalled; 267 0 stevel 268 0 stevel if (panicstr) 269 0 stevel return (-1); 270 11084 Jerry ASSERT(!quiesce_active); 271 0 stevel 272 9334 Madhavan limit = (flag & CALLOUT_FLAG_ABSOLUTE) ? gethrtime() : 0; 273 9334 Madhavan if (tim <= limit) 274 0 stevel return (-1); 275 8566 Madhavan mutex_enter(&t->t_wait_mutex); 276 9334 Madhavan id = timeout_generic(CALLOUT_REALTIME, (void (*)(void *))cv_wakeup, t, 277 9334 Madhavan tim, res, flag); 278 0 stevel thread_lock(t); /* lock the thread */ 279 0 stevel cv_block((condvar_impl_t *)cvp); 280 0 stevel thread_unlock_nopreempt(t); 281 8566 Madhavan mutex_exit(&t->t_wait_mutex); 282 0 stevel mutex_exit(mp); 283 0 stevel swtch(); 284 0 stevel signalled = (t->t_schedflag & TS_SIGNALLED); 285 0 stevel /* 286 0 stevel * Get the time left. untimeout() returns -1 if the timeout has 287 0 stevel * occured or the time remaining. If the time remaining is zero, 288 0 stevel * the timeout has occured between when we were awoken and 289 0 stevel * we called untimeout. We will treat this as if the timeout 290 0 stevel * has occured and set timeleft to -1. 291 0 stevel */ 292 8566 Madhavan timeleft = untimeout_default(id, 0); 293 0 stevel mutex_enter(mp); 294 0 stevel if (timeleft <= 0) { 295 0 stevel timeleft = -1; 296 0 stevel if (signalled) /* avoid consuming the cv_signal() */ 297 0 stevel cv_signal(cvp); 298 0 stevel } 299 0 stevel return (timeleft); 300 0 stevel } 301 0 stevel 302 0 stevel int 303 0 stevel cv_wait_sig(kcondvar_t *cvp, kmutex_t *mp) 304 0 stevel { 305 0 stevel kthread_t *t = curthread; 306 0 stevel proc_t *p = ttoproc(t); 307 0 stevel klwp_t *lwp = ttolwp(t); 308 5891 raf int cancel_pending; 309 0 stevel int rval = 1; 310 0 stevel int signalled = 0; 311 0 stevel 312 0 stevel if (panicstr) 313 0 stevel return (rval); 314 11084 Jerry ASSERT(!quiesce_active); 315 0 stevel 316 0 stevel /* 317 11173 Jonathan * Threads in system processes don't process signals. This is 318 11173 Jonathan * true both for standard threads of system processes and for 319 11173 Jonathan * interrupt threads which have borrowed their pinned thread's LWP. 320 0 stevel */ 321 11173 Jonathan if (lwp == NULL || (p->p_flag & SSYS)) { 322 0 stevel cv_wait(cvp, mp); 323 0 stevel return (rval); 324 0 stevel } 325 11173 Jonathan ASSERT(t->t_intr == NULL); 326 0 stevel 327 0 stevel ASSERT(curthread->t_schedflag & TS_DONT_SWAP); 328 5891 raf cancel_pending = schedctl_cancel_pending(); 329 0 stevel lwp->lwp_asleep = 1; 330 0 stevel lwp->lwp_sysabort = 0; 331 0 stevel thread_lock(t); 332 0 stevel cv_block_sig(t, (condvar_impl_t *)cvp); 333 0 stevel thread_unlock_nopreempt(t); 334 0 stevel mutex_exit(mp); 335 5891 raf if (ISSIG(t, JUSTLOOKING) || MUSTRETURN(p, t) || cancel_pending) 336 0 stevel setrun(t); 337 0 stevel /* ASSERT(no locks are held) */ 338 0 stevel swtch(); 339 0 stevel signalled = (t->t_schedflag & TS_SIGNALLED); 340 0 stevel t->t_flag &= ~T_WAKEABLE; 341 0 stevel mutex_enter(mp); 342 0 stevel if (ISSIG_PENDING(t, lwp, p)) { 343 0 stevel mutex_exit(mp); 344 0 stevel if (issig(FORREAL)) 345 0 stevel rval = 0; 346 0 stevel mutex_enter(mp); 347 0 stevel } 348 0 stevel if (lwp->lwp_sysabort || MUSTRETURN(p, t)) 349 0 stevel rval = 0; 350 5891 raf if (rval != 0 && cancel_pending) { 351 5891 raf schedctl_cancel_eintr(); 352 5891 raf rval = 0; 353 5891 raf } 354 0 stevel lwp->lwp_asleep = 0; 355 0 stevel lwp->lwp_sysabort = 0; 356 0 stevel if (rval == 0 && signalled) /* avoid consuming the cv_signal() */ 357 0 stevel cv_signal(cvp); 358 0 stevel return (rval); 359 0 stevel } 360 0 stevel 361 8048 Madhavan static clock_t 362 9334 Madhavan cv_timedwait_sig_hires(kcondvar_t *cvp, kmutex_t *mp, hrtime_t tim, 363 9334 Madhavan hrtime_t res, int flag) 364 0 stevel { 365 0 stevel kthread_t *t = curthread; 366 0 stevel proc_t *p = ttoproc(t); 367 0 stevel klwp_t *lwp = ttolwp(t); 368 5891 raf int cancel_pending = 0; 369 8048 Madhavan callout_id_t id; 370 0 stevel clock_t rval = 1; 371 9334 Madhavan hrtime_t limit; 372 0 stevel int signalled = 0; 373 0 stevel 374 0 stevel if (panicstr) 375 0 stevel return (rval); 376 11084 Jerry ASSERT(!quiesce_active); 377 0 stevel 378 0 stevel /* 379 11173 Jonathan * Threads in system processes don't process signals. This is 380 11173 Jonathan * true both for standard threads of system processes and for 381 11173 Jonathan * interrupt threads which have borrowed their pinned thread's LWP. 382 0 stevel */ 383 11173 Jonathan if (lwp == NULL || (p->p_flag & SSYS)) 384 9334 Madhavan return (cv_timedwait_hires(cvp, mp, tim, res, flag)); 385 11173 Jonathan ASSERT(t->t_intr == NULL); 386 0 stevel 387 0 stevel /* 388 9334 Madhavan * If tim is less than or equal to current hrtime, then the timeout 389 0 stevel * has already occured. So just check to see if there is a signal 390 0 stevel * pending. If so return 0 indicating that there is a signal pending. 391 0 stevel * Else return -1 indicating that the timeout occured. No need to 392 0 stevel * wait on anything. 393 0 stevel */ 394 9334 Madhavan limit = (flag & CALLOUT_FLAG_ABSOLUTE) ? gethrtime() : 0; 395 9334 Madhavan if (tim <= limit) { 396 0 stevel lwp->lwp_asleep = 1; 397 0 stevel lwp->lwp_sysabort = 0; 398 0 stevel rval = -1; 399 0 stevel goto out; 400 0 stevel } 401 0 stevel 402 0 stevel /* 403 0 stevel * Set the timeout and wait. 404 0 stevel */ 405 5891 raf cancel_pending = schedctl_cancel_pending(); 406 8566 Madhavan mutex_enter(&t->t_wait_mutex); 407 8048 Madhavan id = timeout_generic(CALLOUT_REALTIME, (void (*)(void *))cv_wakeup, t, 408 9334 Madhavan tim, res, flag); 409 0 stevel lwp->lwp_asleep = 1; 410 0 stevel lwp->lwp_sysabort = 0; 411 0 stevel thread_lock(t); 412 0 stevel cv_block_sig(t, (condvar_impl_t *)cvp); 413 0 stevel thread_unlock_nopreempt(t); 414 8566 Madhavan mutex_exit(&t->t_wait_mutex); 415 0 stevel mutex_exit(mp); 416 8048 Madhavan if (ISSIG(t, JUSTLOOKING) || MUSTRETURN(p, t) || cancel_pending) 417 0 stevel setrun(t); 418 0 stevel /* ASSERT(no locks are held) */ 419 0 stevel swtch(); 420 0 stevel signalled = (t->t_schedflag & TS_SIGNALLED); 421 0 stevel t->t_flag &= ~T_WAKEABLE; 422 0 stevel 423 0 stevel /* 424 0 stevel * Untimeout the thread. untimeout() returns -1 if the timeout has 425 0 stevel * occured or the time remaining. If the time remaining is zero, 426 0 stevel * the timeout has occured between when we were awoken and 427 0 stevel * we called untimeout. We will treat this as if the timeout 428 0 stevel * has occured and set rval to -1. 429 0 stevel */ 430 8566 Madhavan rval = untimeout_default(id, 0); 431 8048 Madhavan mutex_enter(mp); 432 0 stevel if (rval <= 0) 433 0 stevel rval = -1; 434 0 stevel 435 0 stevel /* 436 0 stevel * Check to see if a signal is pending. If so, regardless of whether 437 0 stevel * or not we were awoken due to the signal, the signal is now pending 438 0 stevel * and a return of 0 has the highest priority. 439 0 stevel */ 440 0 stevel out: 441 0 stevel if (ISSIG_PENDING(t, lwp, p)) { 442 0 stevel mutex_exit(mp); 443 0 stevel if (issig(FORREAL)) 444 0 stevel rval = 0; 445 0 stevel mutex_enter(mp); 446 0 stevel } 447 0 stevel if (lwp->lwp_sysabort || MUSTRETURN(p, t)) 448 0 stevel rval = 0; 449 5891 raf if (rval != 0 && cancel_pending) { 450 5891 raf schedctl_cancel_eintr(); 451 5891 raf rval = 0; 452 5891 raf } 453 0 stevel lwp->lwp_asleep = 0; 454 0 stevel lwp->lwp_sysabort = 0; 455 0 stevel if (rval <= 0 && signalled) /* avoid consuming the cv_signal() */ 456 0 stevel cv_signal(cvp); 457 0 stevel return (rval); 458 8048 Madhavan } 459 8048 Madhavan 460 8048 Madhavan /* 461 8048 Madhavan * Returns: 462 8048 Madhavan * Function result in order of precedence: 463 8048 Madhavan * 0 if a signal was received 464 8048 Madhavan * -1 if timeout occured 465 8048 Madhavan * >0 if awakened via cv_signal() or cv_broadcast(). 466 8048 Madhavan * (returns time remaining) 467 8048 Madhavan * 468 8048 Madhavan * cv_timedwait_sig() is now part of the DDI. 469 8048 Madhavan * 470 9334 Madhavan * This function is now just a wrapper for cv_timedwait_sig_hires(). 471 8048 Madhavan */ 472 8048 Madhavan clock_t 473 8048 Madhavan cv_timedwait_sig(kcondvar_t *cvp, kmutex_t *mp, clock_t tim) 474 8048 Madhavan { 475 9334 Madhavan hrtime_t hrtim; 476 9334 Madhavan 477 11066 rafael hrtim = TICK_TO_NSEC(tim - ddi_get_lbolt()); 478 9334 Madhavan return (cv_timedwait_sig_hires(cvp, mp, hrtim, nsec_per_tick, 0)); 479 11066 rafael } 480 11066 rafael 481 11066 rafael /* 482 11066 rafael * Same as cv_timedwait_sig() except that the third argument is a relative 483 11066 rafael * timeout value, as opposed to an absolute one. There is also a fourth 484 11066 rafael * argument that specifies how accurately the timeout must be implemented. 485 11066 rafael */ 486 11066 rafael clock_t 487 11066 rafael cv_reltimedwait_sig(kcondvar_t *cvp, kmutex_t *mp, clock_t delta, 488 11066 rafael time_res_t res) 489 11066 rafael { 490 11066 rafael hrtime_t exp; 491 11066 rafael 492 11066 rafael ASSERT(TIME_RES_VALID(res)); 493 11066 rafael 494 11066 rafael if ((exp = TICK_TO_NSEC(delta)) < 0) 495 11066 rafael exp = CY_INFINITY; 496 11066 rafael 497 11066 rafael return (cv_timedwait_sig_hires(cvp, mp, exp, time_res[res], 0)); 498 0 stevel } 499 0 stevel 500 0 stevel /* 501 0 stevel * Like cv_wait_sig_swap but allows the caller to indicate (with a 502 0 stevel * non-NULL sigret) that they will take care of signalling the cv 503 0 stevel * after wakeup, if necessary. This is a vile hack that should only 504 0 stevel * be used when no other option is available; almost all callers 505 0 stevel * should just use cv_wait_sig_swap (which takes care of the cv_signal 506 0 stevel * stuff automatically) instead. 507 0 stevel */ 508 0 stevel int 509 0 stevel cv_wait_sig_swap_core(kcondvar_t *cvp, kmutex_t *mp, int *sigret) 510 0 stevel { 511 0 stevel kthread_t *t = curthread; 512 0 stevel proc_t *p = ttoproc(t); 513 0 stevel klwp_t *lwp = ttolwp(t); 514 5891 raf int cancel_pending; 515 0 stevel int rval = 1; 516 0 stevel int signalled = 0; 517 0 stevel 518 0 stevel if (panicstr) 519 0 stevel return (rval); 520 0 stevel 521 0 stevel /* 522 11173 Jonathan * Threads in system processes don't process signals. This is 523 11173 Jonathan * true both for standard threads of system processes and for 524 11173 Jonathan * interrupt threads which have borrowed their pinned thread's LWP. 525 0 stevel */ 526 11173 Jonathan if (lwp == NULL || (p->p_flag & SSYS)) { 527 0 stevel cv_wait(cvp, mp); 528 0 stevel return (rval); 529 0 stevel } 530 11173 Jonathan ASSERT(t->t_intr == NULL); 531 0 stevel 532 5891 raf cancel_pending = schedctl_cancel_pending(); 533 0 stevel lwp->lwp_asleep = 1; 534 0 stevel lwp->lwp_sysabort = 0; 535 0 stevel thread_lock(t); 536 0 stevel t->t_kpri_req = 0; /* don't need kernel priority */ 537 0 stevel cv_block_sig(t, (condvar_impl_t *)cvp); 538 0 stevel /* I can be swapped now */ 539 0 stevel curthread->t_schedflag &= ~TS_DONT_SWAP; 540 0 stevel thread_unlock_nopreempt(t); 541 0 stevel mutex_exit(mp); 542 5891 raf if (ISSIG(t, JUSTLOOKING) || MUSTRETURN(p, t) || cancel_pending) 543 0 stevel setrun(t); 544 0 stevel /* ASSERT(no locks are held) */ 545 0 stevel swtch(); 546 0 stevel signalled = (t->t_schedflag & TS_SIGNALLED); 547 0 stevel t->t_flag &= ~T_WAKEABLE; 548 0 stevel /* TS_DONT_SWAP set by disp() */ 549 0 stevel ASSERT(curthread->t_schedflag & TS_DONT_SWAP); 550 0 stevel mutex_enter(mp); 551 0 stevel if (ISSIG_PENDING(t, lwp, p)) { 552 0 stevel mutex_exit(mp); 553 0 stevel if (issig(FORREAL)) 554 0 stevel rval = 0; 555 0 stevel mutex_enter(mp); 556 0 stevel } 557 0 stevel if (lwp->lwp_sysabort || MUSTRETURN(p, t)) 558 0 stevel rval = 0; 559 5891 raf if (rval != 0 && cancel_pending) { 560 5891 raf schedctl_cancel_eintr(); 561 5891 raf rval = 0; 562 5891 raf } 563 0 stevel lwp->lwp_asleep = 0; 564 0 stevel lwp->lwp_sysabort = 0; 565 0 stevel if (rval == 0) { 566 0 stevel if (sigret != NULL) 567 0 stevel *sigret = signalled; /* just tell the caller */ 568 0 stevel else if (signalled) 569 0 stevel cv_signal(cvp); /* avoid consuming the cv_signal() */ 570 0 stevel } 571 0 stevel return (rval); 572 0 stevel } 573 0 stevel 574 0 stevel /* 575 0 stevel * Same as cv_wait_sig but the thread can be swapped out while waiting. 576 0 stevel * This should only be used when we know we aren't holding any locks. 577 0 stevel */ 578 0 stevel int 579 0 stevel cv_wait_sig_swap(kcondvar_t *cvp, kmutex_t *mp) 580 0 stevel { 581 0 stevel return (cv_wait_sig_swap_core(cvp, mp, NULL)); 582 0 stevel } 583 0 stevel 584 0 stevel void 585 0 stevel cv_signal(kcondvar_t *cvp) 586 0 stevel { 587 0 stevel condvar_impl_t *cp = (condvar_impl_t *)cvp; 588 0 stevel 589 0 stevel /* make sure the cv_waiters field looks sane */ 590 0 stevel ASSERT(cp->cv_waiters <= CV_MAX_WAITERS); 591 0 stevel if (cp->cv_waiters > 0) { 592 0 stevel sleepq_head_t *sqh = SQHASH(cp); 593 0 stevel disp_lock_enter(&sqh->sq_lock); 594 0 stevel ASSERT(CPU_ON_INTR(CPU) == 0); 595 0 stevel if (cp->cv_waiters & CV_WAITERS_MASK) { 596 0 stevel kthread_t *t; 597 0 stevel cp->cv_waiters--; 598 0 stevel t = sleepq_wakeone_chan(&sqh->sq_queue, cp); 599 0 stevel /* 600 0 stevel * If cv_waiters is non-zero (and less than 601 0 stevel * CV_MAX_WAITERS) there should be a thread 602 0 stevel * in the queue. 603 0 stevel */ 604 0 stevel ASSERT(t != NULL); 605 0 stevel } else if (sleepq_wakeone_chan(&sqh->sq_queue, cp) == NULL) { 606 0 stevel cp->cv_waiters = 0; 607 0 stevel } 608 0 stevel disp_lock_exit(&sqh->sq_lock); 609 0 stevel } 610 0 stevel } 611 0 stevel 612 0 stevel void 613 0 stevel cv_broadcast(kcondvar_t *cvp) 614 0 stevel { 615 0 stevel condvar_impl_t *cp = (condvar_impl_t *)cvp; 616 0 stevel 617 0 stevel /* make sure the cv_waiters field looks sane */ 618 0 stevel ASSERT(cp->cv_waiters <= CV_MAX_WAITERS); 619 0 stevel if (cp->cv_waiters > 0) { 620 0 stevel sleepq_head_t *sqh = SQHASH(cp); 621 0 stevel disp_lock_enter(&sqh->sq_lock); 622 0 stevel ASSERT(CPU_ON_INTR(CPU) == 0); 623 0 stevel sleepq_wakeall_chan(&sqh->sq_queue, cp); 624 0 stevel cp->cv_waiters = 0; 625 0 stevel disp_lock_exit(&sqh->sq_lock); 626 0 stevel } 627 0 stevel } 628 0 stevel 629 0 stevel /* 630 0 stevel * Same as cv_wait(), but wakes up (after wakeup_time milliseconds) to check 631 0 stevel * for requests to stop, like cv_wait_sig() but without dealing with signals. 632 0 stevel * This is a horrible kludge. It is evil. It is vile. It is swill. 633 0 stevel * If your code has to call this function then your code is the same. 634 0 stevel */ 635 0 stevel void 636 0 stevel cv_wait_stop(kcondvar_t *cvp, kmutex_t *mp, int wakeup_time) 637 0 stevel { 638 0 stevel kthread_t *t = curthread; 639 0 stevel klwp_t *lwp = ttolwp(t); 640 0 stevel proc_t *p = ttoproc(t); 641 8048 Madhavan callout_id_t id; 642 0 stevel clock_t tim; 643 0 stevel 644 0 stevel if (panicstr) 645 0 stevel return; 646 0 stevel 647 0 stevel /* 648 11173 Jonathan * Threads in system processes don't process signals. This is 649 11173 Jonathan * true both for standard threads of system processes and for 650 11173 Jonathan * interrupt threads which have borrowed their pinned thread's LWP. 651 0 stevel */ 652 11173 Jonathan if (lwp == NULL || (p->p_flag & SSYS)) { 653 0 stevel cv_wait(cvp, mp); 654 0 stevel return; 655 0 stevel } 656 11173 Jonathan ASSERT(t->t_intr == NULL); 657 0 stevel 658 0 stevel /* 659 0 stevel * Wakeup in wakeup_time milliseconds, i.e., human time. 660 0 stevel */ 661 11066 rafael tim = ddi_get_lbolt() + MSEC_TO_TICK(wakeup_time); 662 8566 Madhavan mutex_enter(&t->t_wait_mutex); 663 8048 Madhavan id = realtime_timeout_default((void (*)(void *))cv_wakeup, t, 664 11066 rafael tim - ddi_get_lbolt()); 665 0 stevel thread_lock(t); /* lock the thread */ 666 0 stevel cv_block((condvar_impl_t *)cvp); 667 0 stevel thread_unlock_nopreempt(t); 668 8566 Madhavan mutex_exit(&t->t_wait_mutex); 669 0 stevel mutex_exit(mp); 670 0 stevel /* ASSERT(no locks are held); */ 671 0 stevel swtch(); 672 8566 Madhavan (void) untimeout_default(id, 0); 673 0 stevel 674 0 stevel /* 675 3930 nr123932 * Check for reasons to stop, if lwp_nostop is not true. 676 0 stevel * See issig_forreal() for explanations of the various stops. 677 0 stevel */ 678 0 stevel mutex_enter(&p->p_lock); 679 3930 nr123932 while (lwp->lwp_nostop == 0 && !(p->p_flag & SEXITLWPS)) { 680 0 stevel /* 681 0 stevel * Hold the lwp here for watchpoint manipulation. 682 0 stevel */ 683 3930 nr123932 if (t->t_proc_flag & TP_PAUSE) { 684 0 stevel stop(PR_SUSPENDED, SUSPEND_PAUSE); 685 0 stevel continue; 686 0 stevel } 687 0 stevel /* 688 0 stevel * System checkpoint. 689 0 stevel */ 690 3930 nr123932 if (t->t_proc_flag & TP_CHKPT) { 691 0 stevel stop(PR_CHECKPOINT, 0); 692 0 stevel continue; 693 0 stevel } 694 0 stevel /* 695 0 stevel * Honor fork1(), watchpoint activity (remapping a page), 696 3930 nr123932 * and lwp_suspend() requests. 697 0 stevel */ 698 3930 nr123932 if ((p->p_flag & (SHOLDFORK1|SHOLDWATCH)) || 699 3930 nr123932 (t->t_proc_flag & TP_HOLDLWP)) { 700 0 stevel stop(PR_SUSPENDED, SUSPEND_NORMAL); 701 0 stevel continue; 702 0 stevel } 703 0 stevel /* 704 0 stevel * Honor /proc requested stop. 705 0 stevel */ 706 3930 nr123932 if (t->t_proc_flag & TP_PRSTOP) { 707 0 stevel stop(PR_REQUESTED, 0); 708 0 stevel } 709 0 stevel /* 710 0 stevel * If some lwp in the process has already stopped 711 0 stevel * showing PR_JOBCONTROL, stop in sympathy with it. 712 0 stevel */ 713 3930 nr123932 if (p->p_stopsig && t != p->p_agenttp) { 714 0 stevel stop(PR_JOBCONTROL, p->p_stopsig); 715 0 stevel continue; 716 0 stevel } 717 0 stevel break; 718 0 stevel } 719 0 stevel mutex_exit(&p->p_lock); 720 0 stevel mutex_enter(mp); 721 0 stevel } 722 0 stevel 723 0 stevel /* 724 0 stevel * Like cv_timedwait_sig(), but takes an absolute hires future time 725 0 stevel * rather than a future time in clock ticks. Will not return showing 726 0 stevel * that a timeout occurred until the future time is passed. 727 0 stevel * If 'when' is a NULL pointer, no timeout will occur. 728 0 stevel * Returns: 729 8048 Madhavan * Function result in order of precedence: 730 0 stevel * 0 if a signal was received 731 0 stevel * -1 if timeout occured 732 0 stevel * >0 if awakened via cv_signal() or cv_broadcast() 733 0 stevel * or by a spurious wakeup. 734 0 stevel * (might return time remaining) 735 4123 dm120769 * As a special test, if someone abruptly resets the system time 736 4123 dm120769 * (but not through adjtime(2); drifting of the clock is allowed and 737 4123 dm120769 * expected [see timespectohz_adj()]), then we force a return of -1 738 4123 dm120769 * so the caller can return a premature timeout to the calling process 739 4123 dm120769 * so it can reevaluate the situation in light of the new system time. 740 4123 dm120769 * (The system clock has been reset if timecheck != timechanged.) 741 0 stevel */ 742 0 stevel int 743 4123 dm120769 cv_waituntil_sig(kcondvar_t *cvp, kmutex_t *mp, 744 4123 dm120769 timestruc_t *when, int timecheck) 745 0 stevel { 746 0 stevel timestruc_t now; 747 3346 vb160487 timestruc_t delta; 748 9334 Madhavan hrtime_t interval; 749 0 stevel int rval; 750 0 stevel 751 0 stevel if (when == NULL) 752 0 stevel return (cv_wait_sig_swap(cvp, mp)); 753 0 stevel 754 7982 Donghai gethrestime(&now); 755 3346 vb160487 delta = *when; 756 3346 vb160487 timespecsub(&delta, &now); 757 3346 vb160487 if (delta.tv_sec < 0 || (delta.tv_sec == 0 && delta.tv_nsec == 0)) { 758 0 stevel /* 759 0 stevel * We have already reached the absolute future time. 760 0 stevel * Call cv_timedwait_sig() just to check for signals. 761 0 stevel * We will return immediately with either 0 or -1. 762 0 stevel */ 763 9334 Madhavan rval = cv_timedwait_sig_hires(cvp, mp, 0, 1, 0); 764 0 stevel } else { 765 4123 dm120769 if (timecheck == timechanged) { 766 9334 Madhavan /* 767 9334 Madhavan * Make sure that the interval is atleast one tick. 768 9334 Madhavan * This is to prevent a user from flooding the system 769 9334 Madhavan * with very small, high resolution timers. 770 9334 Madhavan */ 771 9334 Madhavan interval = ts2hrt(&delta); 772 9334 Madhavan if (interval < nsec_per_tick) 773 9334 Madhavan interval = nsec_per_tick; 774 9334 Madhavan rval = cv_timedwait_sig_hires(cvp, mp, interval, 1, 775 8048 Madhavan CALLOUT_FLAG_HRESTIME); 776 4123 dm120769 } else { 777 4123 dm120769 /* 778 4123 dm120769 * Someone reset the system time; 779 4123 dm120769 * just force an immediate timeout. 780 4123 dm120769 */ 781 4123 dm120769 rval = -1; 782 4123 dm120769 } 783 4123 dm120769 if (rval == -1 && timecheck == timechanged) { 784 4123 dm120769 /* 785 4123 dm120769 * Even though cv_timedwait_sig() returned showing a 786 4123 dm120769 * timeout, the future time may not have passed yet. 787 4123 dm120769 * If not, change rval to indicate a normal wakeup. 788 4123 dm120769 */ 789 4123 dm120769 gethrestime(&now); 790 4123 dm120769 delta = *when; 791 4123 dm120769 timespecsub(&delta, &now); 792 4123 dm120769 if (delta.tv_sec > 0 || (delta.tv_sec == 0 && 793 4123 dm120769 delta.tv_nsec > 0)) 794 0 stevel rval = 1; 795 4123 dm120769 } 796 0 stevel } 797 0 stevel return (rval); 798 0 stevel } 799