• Peter Hurley's avatar
    Bluetooth: Fix nested sleeps · dfb2fae7
    Peter Hurley authored
    l2cap/rfcomm/sco_sock_accept() are wait loops which may acquire
    sleeping locks. Since both wait loops and sleeping locks use
    task_struct.state to sleep and wake, the nested sleeping locks
    destroy the wait loop state.
    
    Use the newly-minted wait_woken() and DEFINE_WAIT_FUNC() for the
    wait loop. DEFINE_WAIT_FUNC() allows an alternate wake function
    to be specified; in this case, the predefined scheduler function,
    woken_wake_function(). This wait construct ensures wakeups will
    not be missed without requiring the wait loop to set the
    task state before condition evaluation. How this works:
    
     CPU 0                            |  CPU 1
                                      |
                                      | is <condition> set?
                                      | no
    set <condition>                   |
                                      |
    wake_up_interruptible             |
      woken_wake_function             |
        set WQ_FLAG_WOKEN             |
        try_to_wake_up                |
                                      | wait_woken
                                      |   set TASK_INTERRUPTIBLE
                                      |   WQ_FLAG_WOKEN? yes
                                      |   set TASK_RUNNING
                                      |
                                      | - loop -
    				  |
    				  | is <condition> set?
                                      | yes - exit wait loop
    
    Fixes "do not call blocking ops when !TASK_RUNNING" warnings
    in l2cap_sock_accept(), rfcomm_sock_accept() and sco_sock_accept().
    Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
    Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
    dfb2fae7
l2cap_sock.c 35.1 KB