• M
    V4L/DVB (7714): pvrusb2: Fix hang on module removal · 18ecbb47
    Mike Isely 提交于
    The pvrusb2 driver was getting had by this scenario:
    
    1. Task A calls kthread_stop() for task B.
    2. Before exiting, then Task B calls kthread_stop() for task C.
    
    The problem is, kthread_stop() wants to allocate an internal resource
    to itself (i.e. acquire a lock), which won't be released until
    kthread_stop() returns.  But kthread_stop() won't return until task B
    is dead.  But task B won't die until it finishes its call to
    kthread_stop() for task C, and that will block waiting on the resource
    already allocated inside task A.  Deadlock.
    
    With the pvrusb2 driver, task A is the caller to pvr_exit(), task B is
    the control thread run inside of pvrusb2-context.c, and task C is any
    worker thread run inside of pvrusb2-hdw.c.
    
    This problem got introduced by the previous threading setup change,
    which was itself an attempt to fix a module tear-down race (which it
    actually did fix).  The lesson here is that a task being waited on as
    part of a kthread_stop() simply cannot be allow to also issue a
    kthread_stop() - or we make sure not to issue the enclosing
    kthread_stop() until we know that the inner kthread_stop() has
    completed first.  The solution for the pvrusb2 driver is some hackish
    code which changes the main control thread tear down into a two step
    process.  This then makes it possible to delay issuing the
    kthread_stop() on the control thread until after we know that
    everything has been torn down first.  (And yes, we really need that
    kthread_stop() because it's the only way to safely guarantee that a
    module-referencing kernel thread has safely returned back out of the
    module before we finally remove the module.)
    Signed-off-by: NMike Isely <isely@pobox.com>
    Signed-off-by: NMauro Carvalho Chehab <mchehab@infradead.org>
    18ecbb47
pvrusb2-context.c 8.7 KB