next up previous contents
Nächste Seite: Leistungsbewertung Aufwärts: Implementierung Vorherige Seite: sound Bibliothek   Inhalt


Fallbeispiel: Soundtreiber es1371.c

Als Testgerät wurde eine Soundblaster 128 PCI Soundkarte benutzt, die auf dem es1371 Chipsatz basiert. Der korrespondierende Linux-Treiber ist es1371.c. Ich werde an dieser Stelle auf eine Besonderheit, den Treiber betreffend, eingehen.

Diese betrifft die Synchronisation von Prozeßkontexten über Warteschlangen. Wie ich in Abschnitt 2.5.2 beschrieben habe, existieren dazu Kernfunktionen (sleep_on()) deren Aufbau in Abb. 4.4 dargestellt ist.

Abbildung 4.4: Warteschlangen-Synchronisation (durch Signale unterbrechbar)
void interruptible_sleep_on(wait_queue_head_t *q)
{
    ...

    current->state = TASK_INTERRUPTIBLE;

    wq_write_lock_irqsave(&q->lock,flags);
    __add_wait_queue(q, &wait);
    wq_write_unlock(&q->lock);

    schedule();

    wq_write_lock_irq(&q->lock);
    __remove_wait_queue(q, &wait);
    wq_write_unlock_irqrestore(&q->lock,flags);
}

Der Prozeßkontext ändert seinen Zustand in blockiert und reiht sich in die wait queue ein. Anschließend wird schedule() aufgerufen, um die Blockierung einzuleiten und auf das Ereignis, das die Warteschlange repräsentiert, zu warten. Nach dem Aufwecken entfernt sich der Kontext selbständig aus der wait queue.

Der es1371 Treiber verwendet diese Funktion aber nicht, sondern bildet das Verhalten selbständig nach (Abb. 4.5). ,,Prophylaktisch`` wird er anfangs in die Warteschlange eingereiht und am Ende der Funktion wieder entfernt. Eine Blockierung wird nur eingeleitet, wenn ein bestimmtes Ereignis nicht eingetreten ist.

Abbildung 4.5: Warteschlangen-Synchronisation in es1371.c
ssize_t es1371_read(...)
{
    DECLARE_WAITQUEUE(wait, current);
    ...
    add_wait_queue(&s->dma_adc.wait, &wait);
    while (count > 0) {
        ...
        if (cnt <= 0) {
            ...
            __set_current_state(TASK_INTERRUPTIBLE);
            schedule();
            if (signal_pending(current)) {
                ret = -ERESTARTSYS;
                break;
            }
            continue;
        }
        ...
    }
    remove_wait_queue(&s->dma_adc.wait, &wait);
    ...
}

Würde die Emulation an dieser Stelle erwarten, daß wait queue Synchronisation nur über die besprochene Schnittstelle durchgeführt wird, wäre der Treiber nicht lauffähig. Da aber im DDE die schedule() Funktion nachgebildet wird, führt auch dieser allgemeinere Fall zu einem funktionierenden Gerätetreiber.

Diese Besonderheit beweist, daß eine Emulation nur als bedingt allgemeingültig angesehen werden kann, da nicht abzusehen ist, welche Spezialsituationen eintreten können bzw. wieviel Phantasie einige Programmierer haben. Eine genaue Analyse des Kerns und stichprobenartig auch der Gerätetreiber selbst sollte diese Schwäche minimieren.


next up previous contents
Nächste Seite: Leistungsbewertung Aufwärts: Implementierung Vorherige Seite: sound Bibliothek   Inhalt
Christian Helmuth 2001-12-11