sleepq problem

2012-12-05 Thread Alexandr Matveev
Hello,

I'm writing a storage controller driver for 9.0-RELEASE-p4 and i'm using
sleepq at initialization to sleep until command is processed by controller:

struct command {
...
uint8_tdone;
};

void send_command_and_wait(struct command *cmd)
{
command-done = 0;

send_command(cmd);

for (;;) {
sleepq_lock(command-done);
if (command-done)
break;
sleepq_add(command-done, NULL, wait for completion,
SLEEPQ_SLEEP, 0);
sleepq_wait(command-done, 0);
}
sleepq_release(command-done);
}

Interrupt handler calls special function when command is processed:

void command_finish(struct command *cmd)
{
sleepq_lock(command-done);
command-done = 1;
sleepq_signal(command-done, SLEEPQ_SLEEP, 0, 0);
sleepq_release(command-done);
}

This code panics very often with following messages:

Sleeping thread (tid 100248, pid 1859) owns a non-sleepable lock
sched_switch() at sched_switch+0xf1
mi_switch() at mi_switch+0x170
sleepq_wait() at sleepq_wait+0x44
send_command_and_wait() at send_command_with_retry+0x77
...
panic: sleeping thread
cpuid = 1
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2a
kdb_backtrace() at kdb_backtrace+0x37
panic() at panic+0x187
propagate_priority() at propagate_priority+0x161
turnstile_wait() at turnstile_wait+0x1b8
_mtx_lock_sleep() at _mtx_lock_sleep+0xb0
_mtx_lock_flags() at _mtx_lock_flags+0x96
softclock() at softclock+0x25e
intr_event_execute_handlers() at intr_event_execute_handlers+0x66
ithread_loop() at ithread_loop+0x96
fork_exit() at fork_exit+0x11d
fork_trampoline() at fork_trampoline+0xe
--- trap 0, rip = 0, rsp = 0xff80002fad00, rbp = 0 ---

Where tid 100248 is my driver thread which is sleeping  waiting for command
completion:
db show thread 100248
Thread 100243 at 0xfe0146aa98c0:
 proc (pid 1859): 0xfe02a6815488
 name: kldload
 stack: 0xff8464bf2000-0xff8464bf5fff
 flags: 0x4  pflags: 0
 state: INHIBITED: {SLEEPING}
 wmesg: wait for completion  wchan: 0xff8464c1e244
 priority: 127
 container lock: sleepq chain (0x81101af8)

But I can't understand what goes wrong. Sleepq chain lock is owned by
the other thread:
db show lock 0x81101af8
 class: spin mutex
 name: sleepq chain
 flags: {SPIN, RECURSE}
 state: {OWNED}
 owner: 0xfe0008377000 (tid 100019, pid 12, swi4: clock)

Unfortunately, I can't find any examples of using sleepq in drivers.
What am I missing or don't understand?

-- 
Alexandr Matveev

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


Re: sleepq problem

2012-12-05 Thread Andriy Gapon
on 05/12/2012 17:55 Alexandr Matveev said the following:
 Hello,
 
 I'm writing a storage controller driver for 9.0-RELEASE-p4 and i'm using
 sleepq at initialization to sleep until command is processed by controller:
 
 struct command {
 ...
 uint8_tdone;
 };
 
 void send_command_and_wait(struct command *cmd)
 {
 command-done = 0;
 
 send_command(cmd);
 
 for (;;) {
 sleepq_lock(command-done);
 if (command-done)
 break;
 sleepq_add(command-done, NULL, wait for completion,
 SLEEPQ_SLEEP, 0);
 sleepq_wait(command-done, 0);
 }
 sleepq_release(command-done);
 }
 
 Interrupt handler calls special function when command is processed:
 
 void command_finish(struct command *cmd)
 {
 sleepq_lock(command-done);
 command-done = 1;
 sleepq_signal(command-done, SLEEPQ_SLEEP, 0, 0);
 sleepq_release(command-done);
 }
 
 This code panics very often with following messages:
 
 Sleeping thread (tid 100248, pid 1859) owns a non-sleepable lock
 sched_switch() at sched_switch+0xf1
 mi_switch() at mi_switch+0x170
 sleepq_wait() at sleepq_wait+0x44
 send_command_and_wait() at send_command_with_retry+0x77
 ...
 panic: sleeping thread
 cpuid = 1
 KDB: stack backtrace:
 db_trace_self_wrapper() at db_trace_self_wrapper+0x2a
 kdb_backtrace() at kdb_backtrace+0x37
 panic() at panic+0x187
 propagate_priority() at propagate_priority+0x161
 turnstile_wait() at turnstile_wait+0x1b8
 _mtx_lock_sleep() at _mtx_lock_sleep+0xb0
 _mtx_lock_flags() at _mtx_lock_flags+0x96
 softclock() at softclock+0x25e
 intr_event_execute_handlers() at intr_event_execute_handlers+0x66
 ithread_loop() at ithread_loop+0x96
 fork_exit() at fork_exit+0x11d
 fork_trampoline() at fork_trampoline+0xe
 --- trap 0, rip = 0, rsp = 0xff80002fad00, rbp = 0 ---
 
 Where tid 100248 is my driver thread which is sleeping  waiting for command
 completion:
 db show thread 100248
 Thread 100243 at 0xfe0146aa98c0:
  proc (pid 1859): 0xfe02a6815488
  name: kldload
  stack: 0xff8464bf2000-0xff8464bf5fff
  flags: 0x4  pflags: 0
  state: INHIBITED: {SLEEPING}
  wmesg: wait for completion  wchan: 0xff8464c1e244
  priority: 127
  container lock: sleepq chain (0x81101af8)
 
 But I can't understand what goes wrong. Sleepq chain lock is owned by
 the other thread:
 db show lock 0x81101af8
  class: spin mutex
  name: sleepq chain
  flags: {SPIN, RECURSE}
  state: {OWNED}
  owner: 0xfe0008377000 (tid 100019, pid 12, swi4: clock)
 
 Unfortunately, I can't find any examples of using sleepq in drivers.
 What am I missing or don't understand?
 
You should not use sleepq, it's too low level.
See locking(9) and follow references from there.

-- 
Andriy Gapon
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org