Skip to contentSkip to conversation

interruptible_sleep_on_timeout replacement

DISCUSSION Mason 2 participants 2 messages Nov 27, 2015

lore
Share & tools
lore

Mason

author
#0 lore raw

Hello Arnd,

I have to port /ancient/ code to v4.1
The problematic line is:

  long timeout_jiffies = US_TO_JIFFIES(wait_param->timeout_microsecond);
  ...
  timeout_jiffies = interruptible_sleep_on_timeout(&(llad_context.irq_queue), timeout_jiffies);
  wait_param->timeout_microsecond = JIFFIES_TO_US(timeout_jiffies);

IIUC, the appropriate replacement is

wait_event_interruptible_timeout(wq, condition, timeout)

where wq and timeout are the original parameters?

To determine the condition... do I have to examine the corresponding wake_up_interruptible() calls? I do see several

	if (status & SOME_VAL) {
		if (!test_and_set_bit(LOG2_SOME_VAL, &(llad_context.irq_bits)))
			wake_up_interruptible(&(llad_context.irq_queue));
	}

Also I'm not sure the return value is a direct match?

Regards.

#1 lore raw
Quoted 9 lines · Mason

Hello Arnd,

I have to port /ancient/ code to v4.1
The problematic line is:

  long timeout_jiffies = US_TO_JIFFIES(wait_param->timeout_microsecond);
  ...
  timeout_jiffies = interruptible_sleep_on_timeout(&(llad_context.irq_queue), timeout_jiffies);
  wait_param->timeout_microsecond = JIFFIES_TO_US(timeout_jiffies);

Right, so it's most probably buggy (anything using *_sleep_on* is buggy almost by definition.)

Quoted 5 lines

IIUC, the appropriate replacement is

wait_event_interruptible_timeout(wq, condition, timeout)

where wq and timeout are the original parameters?

wait_event_interruptible_timeout is documented very well in include/linux/wait.h.

Quoted 7 lines

To determine the condition... do I have to examine the corresponding wake_up_interruptible() calls? I do see several

	if (status & SOME_VAL) {
		if (!test_and_set_bit(LOG2_SOME_VAL, &(llad_context.irq_bits)))
			wake_up_interruptible(&(llad_context.irq_queue));
	}

Quoting random bits of out of context code really doesn't help anyone, especially with something this complex. We really need to see the whole driver to comment properly.

Condition is, as the documentation says, is the condition to be waited for, which should evaluate to true to terminate the wait prior to the timeout.

Quoted 1 line

Also I'm not sure the return value is a direct match?

It doesn't. You're expected to know how much longer you need to wait. So, you need something like:

I think you will want something like this:

	long timeout_jiffies = US_TO_JIFFIES(wait_param->timeout_microsecond);
	long target_jiffies = jiffies + timeout_jiffies;
	long ret;
	...

	ret = wait_event_interruptible_timeout(&llad_context.irq_queue,
					       ... some condition ...
					       timeout_jiffies);

	if (ret < 0) {
		long now = jiffies;

		if (time_before_eq(now, target_jiffies))
			wait_param->timeout_microsecond =
				JIFFIES_TO_US(target_jiffies - now);
		else
			wait_param->timeout_microsecond = 0;

		return ret;
	}

	if (ret == 0) {
		timed out
	} else {
		condition was satisfied
	}

Even better, change the API so that 'timeout_microsecond' is an absolute time so you don't have accumulated errors if you're repeatedly interrupted.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.