NetBSD-Bugs archive

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

kern/41598: [USB][usb.c][usb_task_thread]when the function tsleep() be called, this may cause the system disable the interrupt a long time in some system.



>Number:         41598
>Category:       kern
>Synopsis:       [USB][usb.c][usb_task_thread]when the function tsleep() be 
>called, this may cause the system disable the interrupt a long time in some 
>system.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Jun 15 13:40:00 +0000 2009
>Originator:     zhenhua,lin
>Release:        no
>Organization:
no
>Environment:
In private system, with the USB stack from NetBSD.
>Description:
at the function usb_task_thread() in the usb.c.

We call this statement "s = splusb();", will disable the (USB)interrupt system. 
The statement "task = TAILQ_FIRST(&taskq->tasks);", obtains the variable 
"task"'s value, this value has two cases:
1) NULL. Then the system will call the "tsleep", let the system in the disable 
(USB) interrupt context;
2) !NULL.  This will deal the task. Then get the next task again, deal the task 
iteratively. Everything is OK. But, At finally, it will turn to the first case 
also.


so, It may be a bug in some system, isn't it?


If this is bug, then, the same at the function usbd_transfer()
>How-To-Repeat:
see above.
>Fix:
can we fix like this: (not verify yet)
======================================
void
usb_task_thread(void *arg)
{
        struct usb_task *task;
        struct usb_taskq *taskq;
        int s;

        taskq = arg;
        DPRINTF(("usb_task_thread: start taskq %s\n", taskq->name));

        s = splusb();
        for (;;) {
                task = TAILQ_FIRST(&taskq->tasks);
                if (task == NULL) {
+                       splx(s);
                        tsleep(&taskq->tasks, PWAIT, "usbtsk", 0);
                        task = TAILQ_FIRST(&taskq->tasks);
                }
                DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task));
                if (task != NULL) {
                        TAILQ_REMOVE(&taskq->tasks, task, next);
                        task->queue = -1;
                        splx(s);
                        task->fun(task->arg);
                        s = splusb();
                }
        }
}



Home | Main Index | Thread Index | Old Index