Search code examples
linuxlistcursorkernel

list_for_each_entry reset cursor


Hi I am new in this and I trying to use list_for_each_entry to iterate over a list. It looks something like this

list_for_each_entry(pos, head, member){
    if (something == pos.x)
    //reset the loop cursor so that it starts iterating all over again
}

How do I perform the commented part without using goto? One more thing, is it safe to use break/continue inside list_for_each_entry or is there any functions available to achieve this?

Thanks.


Solution

  • Look at the definition of list_for_each_entry

    #define list_for_each_entry(pos, head, member)              \
    for (pos = list_entry((head)->next, typeof(*pos), member);  \
         &pos->member != (head);    \
         pos = list_entry(pos->member.next, typeof(*pos), member))
    

    from https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/list.h?id=refs/tags/v3.10-rc2#n418

    As you an see this is defined as a simple for loop, no black magic here, you can use continue/break.

    For your other question, I guess it depends how exactly why you're trying to do that. The simplest way would be to do:

    int iterateAgain = 0;
    list_for_each_entry(pos, head, member) {
       // (...)
       if (something == pos.x) {
           iterateAgain = 1;
           break;
        }
    }
    if (iterateAgain) {
        list_for_each_entry(pos, head, member) {
            // (...)
        }
    }
    

    But depending on your code, it might be too redundant etc. You could have a recursive function too. There are many ways of doing this.

    EDIT after your comment:

    int keepIterating;
    do {
        keepIterating = 0;
        list_for_each_entry(pos, head, member) {
           // (...)
           if (something == pos.x) {
               keepIterating = 1;
               break;
            }
        }
    } while (keepIterating);