// Similar to cv_wait(), except that it returns -1 without the condition // being signaled after the timeout time has been reached. // // timeout A time, in absolute ticks since boot, when cv_timedwait() // should return. clock_t cv_timedwait(kcondvar_t * cv, kmutex_t * m, clock_t timeout) { struct timespec abstime; // All the callers of cv_timedwait calculate the timeout by adding // ticks to ddi_get_lbolt(), which is in usec. abstime.tv_sec = USEC_TO_SEC(timeout); abstime.tv_nsec = USEC_TO_NSEC(timeout - SEC_TO_USEC(abstime.tv_sec)); int error = pthread_cond_timedwait(&cv->cond, &m->mutex, &abstime); switch (error) { case 0: // Update the mutex holder since we now own the lock. m->holder = pthread_to_kthread(pthread_self()); // Return >0 on signalled wakeup. return 1; case ETIMEDOUT: // Update the mutex holder since we now own the lock. m->holder = pthread_to_kthread(pthread_self()); // Return -1 on timeout. return -1; default: // And this only happens on a programmer error. panic("pthread_cond_timedwait() failed: %s (%d)", strerror(error), error); } }
// Unlike cv_timedwait(), this timeout is relative to now. clock_t cv_timedwait_hires( kcondvar_t * cv, kmutex_t * m, hrtime_t timeout, hrtime_t resolution, int flag) { VERIFY0(flag); // We don't support flags. clock_t expiration = ddi_get_lbolt() + timeout;; if (resolution > 1) { expiration = (expiration / resolution) * resolution; } // clock_t is ticks (usec) and hrtime_t is nsec. return cv_timedwait(cv, m, USEC_TO_NSEC(expiration)); }
static ssize_t hrt_write(struct file *filp, const char __user *buff, size_t count, loff_t *f_pos) { char str[16]; ssize_t status; unsigned long usecs; if (count == 0) return 0; if (down_interruptible(&hrt.sem)) return -ERESTARTSYS; if (count > 8) count = 8; str[count] = 0; if (copy_from_user(str, buff, count)) { printk(KERN_ALERT "Error copy_from_user\n"); status = -EFAULT; goto hrt_write_done; } usecs = simple_strtoul(str, NULL, 10); if (usecs < 1 || usecs > 500000) { printk(KERN_ALERT "invalid delay %lu\n", usecs); status = -EINVAL; goto hrt_write_done; } hrt.delay = ktime_set(0, USEC_TO_NSEC(usecs)); do_toggle_test(); status = count; *f_pos += count; hrt_write_done: up(&hrt.sem); return status; }
/* * this routine serves two purposes: * 1. report progress * 2. check for deadlocks */ void *reporter(void *arg) { int status; int end = 0; struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = USEC_TO_NSEC(report_interval); tsnorm(&ts); if (duration >= 0) end = duration + time(NULL); /* sleep initially to let everything get up and running */ status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); if (status) { error("from clock_nanosleep: %s\n", strerror(status)); return NULL; } debug("reporter: starting report loop\n"); info("Press Control-C to stop test\nCurrent Inversions: \n"); for (;;) { pthread_mutex_lock(&shutdown_mtx); if (shutdown) { pthread_mutex_unlock(&shutdown_mtx); break; } pthread_mutex_unlock(&shutdown_mtx); /* wait for our reporting interval */ status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); if (status) { error("from clock_nanosleep: %s\n", strerror(status)); break; } /* check for signaled shutdown */ if (!quiet) { pthread_mutex_lock(&shutdown_mtx); if (shutdown == 0) { fputs(UP_ONE, stdout); printf("Current Inversions: %lu\n", total_inversions()); } } pthread_mutex_unlock(&shutdown_mtx); /* if we specified a duration, see if it has expired */ if (end && time(NULL) > end) { info("duration reached (%d seconds)\n", duration); set_shutdown_flag(); continue; } /* check for a pending SIGINT */ if (pending_interrupt()) { info("Keyboard Interrupt!\n"); break; } /* check watchdog stuff */ if ((watchdog_check())) { error("reporter stopping due to watchdog event\n"); set_shutdown_flag(); break; } /* clear watchdog counters */ watchdog_clear(); } debug("reporter: finished\n"); set_shutdown_flag(); return NULL; }