tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

nanosecond debiting cv_timedwait



cv_timedwait can't handle sub-tick waits, which we can't do now but
when we go tickless will be handy.

It's also a pain to use in a loop with a maximum timeout -- it doesn't
tell you how many ticks passed, so you have to maintain that yourself:

	unsigned timeout = mstohz(1000);
	unsigned now, end;

	now = hardclock_ticks;
	end = now + timeout;
	while (!condition) {
		error = cv_timedwait_sig(&sc->sc_cv, &sc->sc_lock,
		    timeout);
		if (error)
			goto fail;
		now = hardclock_ticks;
		if (end < now) {
			error = EWOULDBLOCK;
			goto fail;
		}
		timeout = end - now;
	}

I propose to add the following routines to address these shortcomings:

int	cv_timedwaitns(kcondvar_t *, kmutex_t *, struct timespec *);
int	cv_timedwaitns_sig(kcondvar_t *, kmutex_t *, struct timespec *);

cv_timedwaitns(cv, lock, timeout) waits a duration at most timeout for
cv.  When it returns, it stores in timeout the remaining time, so that
you can safely write loops like:

	struct timespec timeout = { .tv_sec = 1, .tv_nsec = 0 };
	int error;

	while (!condition) {
		error = cv_timedwaitns_sig(&sc->sc_cv, &sc->sc_lock,
		    &timeout);
		if (error)
			goto fail;
	}

Objections?
int
cv_timedwaitns(kcondvar_t *cv, kmutex_t *lock, struct timespec *wait)
{
	struct timespec now, end;
	unsigned ticks;
	int error;

	getnanouptime(&now);
	timespecadd(&now, wait, &end);
	ticks = mstohz(timespec2ns(wait) / 1000000);
	error = cv_timedwait(cv, lock, ticks);
	getnanouptime(&now);
	if (timespeccmp(&now, &end, <))
		timespecsub(&end, &now, wait);
	else
		timespecclear(wait);

	return error;
}

int
cv_timedwaitns_sig(kcondvar_t *cv, kmutex_t *lock, struct timespec *wait)
{
	struct timespec now, end;
	unsigned ticks;
	int error;

	getnanouptime(&now);
	timespecadd(&now, wait, &end);
	ticks = mstohz(timespec2ns(wait) / 1000000);
	error = cv_timedwait_sig(cv, lock, ticks);
	getnanouptime(&now);
	if (timespeccmp(&now, &end, <))
		timespecsub(&end, &now, wait);
	else
		timespecclear(wait);

	return error;
}


Home | Main Index | Thread Index | Old Index