Frage

Ich entwickle einen Patch für den Linux-Kernel. Ich habe mehrere verwenden Listen und ich habe gegen gleichzeitige Änderung auf eine protect'em Multi-Core-Maschine. Ich versuche spinlocks für dieses Ziel zu verwenden, aber es ist etwas, was ich nicht verstehen kann. Ich habe die Einträge eines sperren Liste (I Linux-Standardimplementierung von verknüpften Listen bin mit) und passieren kann, dass ein Prozess einen Syscall ruft ein Element zu entfernen, die Liste, während das gleiche Element, das da einige gesperrt ist Modifikation ist tatsächlich darauf gemacht. Wenn ich einen spinlock einfügen innerhalb des Listeneintrags, was passiert, wenn ein Prozess, es zu entfernen verwalten während jemand darauf ist spinlocking ?? Soll ich die gesamte Liste sperren? Ich bin auf der Suche nach einem Stück Code, der erklären kann, wie Griff, dies zu tun Situation.

Zum Beispiel sollte dieser Code nicht arbeiten (siehe Kommentar auf der letzten Zeile Code):

   struct lista{
    int c;
    spinlock_t lock;
    struct list_head;
}

spinlock_t list_lock;
struct lista lista;


//INSERT
struct lista* cursor;
struct lista* new = (struct lista*) kmalloc(sizeof(struct lista),GFP_KERNEL);

/*do something*/
spin_lock(&list_lock);     //Lock on the whole list
list_for_each_entry(cursor,&lista.list,list){
    if (cursor->c == something ){
        ...
        spin_unlock(&list_lock)  //unlock
        spin_lock(&cursor->lock) // Lock on list entry
        list_add(&new->list, &lista.list);
        spin_unlock(&cursor->lock)  // unlock of the list entry
        ...
    }
}


//REMOVAL
struct lista* cursor;

spin_lock(&list_lock);  
list_for_each_entry(cursor,&lista.list,list){
    if (cursor->c == something ){
        ...
        spin_unlock(&list_lock)  //unlock
        spin_lock(&cursor->lock) // Lock on list entry
        list_del(&cursor.list,&lista.list);
        spin_unlock(&cursor->lock)  // unlock of the list entry
        kfree(cursor);  //WHEN THE ENTRY IS FREED SOMEONE COULD HAVE TAKEN THE LOCK SINCE IT IS UNLOCKED
        ...
    }
}

Können Sie mir helfen ??

War es hilfreich?

Lösung

nicht loslassen list_lock, bis Sie das Element fertig sind zu entfernen.

Sie könnten mit dem etwas umständlich Verfahren von Ende:

  1. Acquire Liste Sperre (dies wird andere eingehende Threads blockieren)
  2. Acquire Artikel Sperre, Freigabe Artikel Sperre (Dies stellt sicher, dass alle früheren Threads getan)
  3. Entfernen Artikel
  4. Freigabeliste zu sperren.

Variation:. Verwenden, um eine Leser-Schreiber-Sperre für die Liste Schloss

suchen Themen Listenelemente nehmen den Leser Sperre ändern; dies ermöglicht es, mehrere Threads auf der Liste parallel zu betreiben.

suchen Themen Listenelemente nehmen die Schreiber-Sperre zu entfernen; diese wartet für alle Leser zu verlassen und blockiert sie, bis sie losgelassen wird. In diesem Fall haben Sie noch die Liste Sperre zu halten, bis Sie das Element fertig sind entfernen,

Auf diese Weise können Sie Schritt 2 oben vermeiden. Dies könnte konzeptionell klarer erscheinen, wie Sie die sinnlos aussehende Sperre / Freigabe nicht brauchen zu erklären.

Andere Tipps

Sie sollten an Sicherheit grenzender Wahrscheinlichkeit nicht spinlocks überhaupt verwenden, es sei denn, es gibt den gleichzeitigen Zugriff von harten IRQ Kontext. Verwenden mutexes statt.

Die einfachste Option für Ihre Liste ist nur die gesamte Liste zu sperren, während Sie daran arbeiten. Mach dir keine Sorgen über pro-Artikel Schlösser, es sei denn und bis Sie feststellen, dass es auf der Liste Sperre ausreichend Anstoßes ist, dass Sie es brauchen (und in diesem Fall, werden Sie wahrscheinlich bei Verwendung RCU aussehen wollen stattdessen sowieso).

Ihre Liste Kopf braucht keinen struct lista zu sein, es sollte nur ein struct list_head sein. Beachten Sie, dass Sie halten &lista.list verwenden, das sollte nur ein list_head namens „Liste“ oder so ähnlich. Siehe zum Beispiel der Code in drivers/pci/msi.c, feststellen, dass dev->msi_list ist nur ein list_head, kein struct msi_desc.

Sie können nicht sicher die Liste Schloss fallen und greifen dann den Cursor zu sperren. Es ist möglich, dass, nachdem Sie die Liste Schloss fallen gelassen, aber bevor Sie den Cursor Sperre jemand anderes kam zu bekommen und free'd Sie den Cursor. Sie können die Sperren jonglieren, aber das ist sehr leicht zu bekommen falsch.

Sie fast auf jeden Fall mögen nur eine Sperre für die gesamte Liste und kein pro-Artikel Schlösser. Und die Liste Schloss soll ein mutex sein, wenn Sie die Liste von Interrupt-Kontext bearbeiten müssen.

Wenn u handelt nicht mit Geräten und oder den kritischen Abschnitten des Kernes, wo Spin-Lock ist ein Muss (wie es Vorkaufsrecht und Interrupt (auf Anfrage deaktiviert)), dann Y 2 Verwendung Spinlocks der un-unbedingt verschließen ur Vorkaufsrecht und Unterbrechungen. Mit Semaphore oder Mutex auch, dass auf der Liste und nicht Listenelement sieht eine bessere Lösung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top