On 02/10, Denys Vlasenko wrote: > > # define HEAD_MASK (TICKET_SLOWPATH_FLAG-1) > > ... > unlock_again: > > val = xadd((&lock->ticket.head_tail, TICKET_LOCK_INC); > if (unlikely(!(val & HEAD_MASK))) { > /* overflow. we inadvertently incremented the tail word. > * tail's lsb is TICKET_SLOWPATH_FLAG. > * Increment inverted this bit, fix it up. > * (inc _may_ have messed up tail counter too, > * will deal with it after kick.) > */ > val ^= TICKET_SLOWPATH_FLAG; > } > > if (unlikely(val & TICKET_SLOWPATH_FLAG)) { > ...kick the waiting task... > > val -= TICKET_SLOWPATH_FLAG; > if (unlikely(!(val & HEAD_MASK))) { > /* overflow. we inadvertently incremented tail word, *and* > * TICKET_SLOWPATH_FLAG was set, increment overflowed > * that bit too and incremented tail counter. > * This means we (inadvertently) taking the lock again! > * Oh well. Take it, and unlock it again... > */ > while (1) { > if (READ_ONCE(lock->tickets.head) != TICKET_TAIL(val)) > cpu_relax(); > } > goto unlock_again; > } > > > Granted, this looks ugly.
complicated ;) But "Take it, and unlock it again" simply can't work, this can deadlock. Note that unlock() can be called after successful try_lock(). And other problems with lock-ordering, like lock(X); lock(Y); unlock(X); Oleg. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/