Aracılığıyla paylaş


Kesme Kodunu Eşitleme

Aşağıdaki faktörler, çok işlemcili sistemlerde donanım kesintilerini işleyen sürücü kodunu karmaşıklaştırır:

  • Bir cihaz her kesinti gerçekleştiğinde, cihazın bir sonraki kesintisinde üzerine yazılabilmesi nedeniyle geçici olan, kesintiye özgü bilgiler sağlar.

  • Cihazlar, nispeten yüksek IRQL'lerde kesintiye uğrar ve kesme hizmet rutinleri (ISR), diğer sürücü kodlarının yürütülmesini kesintiye uğratabilir.

  • DIRQL kesmeleri için ISR, sürücü tarafından sağlanan bir döndürme kilidini tutarken DIRQL'de çalıştırılmalıdır, böylece ISR geçici bilgileri kaydederken ek kesmeleri önleyebilir. DIRQL, mevcut işlemcinin kesintiye uğramasını önler ve döndürme kilidi, başka bir işlemcinin kesintiye uğramasını önler.

  • ISR yürütülürken cihaz kesintiye uğrayamadığından ISR hızlı bir şekilde çalıştırılmalıdır. Uzun ISR yürütme süreleri sistemi yavaşlatabilir veya veri kaybına neden olabilir.

  • IsR ve ertelenen yordam çağrısı (DPC) yordamının genellikle ISR'nin cihazın geçici verilerini depoladığı bir depolama alanına erişmesi gerekir. Bu yordamların depolama alanına aynı anda erişmemesi için birbirleriyle senkronize olması gerekir.

Bu faktörlerin tümü nedeniyle, kesmeleri işleyen sürücü kodu yazarken aşağıdaki kuralları kullanmanız gerekir:

  • Yalnızca EvtInterruptIsr geri çağırma işlevi, kesme bilgileri içeren cihaz kayıtları gibi değişken kesme verilerine erişir.

    EvtInterruptIsr geri çağırma işlevi, geçici verileri, sürücünün EvtInterruptDpc, EvtInterruptWorkItem veya birden fazla EvtDpcFunc geri çağırma işlevinin erişebileceği sürücü tanımlı kesme veri arabelleğine taşımalıdır.

    Sürücünüz, kesme nesneleri için EvtInterruptDpc veya EvtInterruptWorkItem geri çağırma işlevleri sağlıyorsa, kesme verilerini depolamak için en iyi yer kesme nesnesinin bağlam alanıdır. Kesme nesnesinin geri çağırma işlevleri, aldıkları nesne tutamacını kullanarak nesnenin bağlam alanına erişebilir.

    Sürücünüz her #B4 #A5 EvtInterruptIsr #A6 #C7 callback fonksiyonu için birden çok #B0 #A1 EvtDpcFunc #A2 #C3 callback fonksiyonu sağlıyorsa, kesme verilerini her DPC nesnesinin bağlam alanında saklayabilirsiniz.

  • Kesme veri arabelleğine erişen tüm sürücü kodları, yalnızca bir işlem veriye erişebileceği şekilde eşzamanlı hale getirilmelidir.

    DIRQL kesme nesneleri için EvtInterruptIsr geri çağırma fonksiyonu, kesme nesnesinin sürücü tarafından sağlanan dönüş kilidini tutarken IRQL = DIRQL seviyesinde bu veri arabelleğine erişir. Bu nedenle, arabelleğe erişen tüm rutinler, spin kilidini tutarken DIRQL'de de çalışmalıdır. (Genellikle kesmenin EvtInterruptDpc veya EvtDpcFunc geri çağırma işlevi, arabelleğe erişmesi gereken tek diğer yordamdır.)

    EvtInterruptIsr geri çağırma fonksiyonu hariç, kesme veri arabelleğine erişim sağlayan tüm rutinlerin aşağıdakilerden birini yapması gerekir:

    • Kesme veri arabelleğine erişen bir `EvtInterruptSynchronize` geri çağırma işlevini planlamak için `WdfInterruptSynchronize` çağırın.
    • WdfInterruptAcquireLock ve WdfInterruptReleaseLock çağrıları arasına kesme veri arabelleğine erişen kodu yerleştirin.

    Bu tekniklerin her ikisi de EvtInterruptDpc veya EvtDpcFunc işlevinin kesmenin spin kilidini tutarken DIRQL'deki kesme verilerine erişmesini sağlar. DIRQL, mevcut işlemcinin kesintiye uğramasını önler ve spin kilidi başka bir işlemcinin kesintiye uğramasını önler.

    Cihazınız birden çok kesme vektörlerini veya iletilerini destekliyorsa ve sürücünüzün bu kesmeleri işlemesini eşitlemek istiyorsanız, birden çok DIRQL kesme nesnesine tek bir döndürme kilidi atayabilirsiniz. Çerçeve, kesme kümesinin en yüksek DIRQL değerini belirler ve senkronize kodun kümedeki kesme vektörleri veya iletileri tarafından kesintiye uğramaması için her zaman bu DIRQL'de spin kilidini alır.

    Pasif düzey kesme nesneleri için çatı, IRQL = PASSIVE_LEVEL'de sürücünün EvtInterruptIsr geri çağırma işlevini çağırmadan önce pasif düzey kesme kilidini alır. Sonuç olarak, arabelleğe erişen tüm yordamların kesme kilidini edinmesi veya arabellek erişimini dahili olarak eşitlemesi gerekir. Genellikle, kesmenin EvtInterruptWorkItem geri çağırma işlevi, arabelleğe erişen tek başka yordamdır. Bir EvtInterruptWorkItem geri çağırma işlevinden kesme kilidini alma hakkında bilgi için bu sayfanın Açıklamalar bölümüne bakın.

    Ayrıca, birden çok pasif düzey kesme nesnesine tek bir bekleme kilidi atayarak sürücünüzün birden çok kesme vektörünün işlenmesini eşitleyebilirsiniz.

  • DIRQL kesmelerini işleyen bazı kodlarınızın IRQL = PASSIVE_LEVEL'da çalışması gerekiyorsa, EvtInterruptDpc veya EvtDpcFunc geri çağırma işlevi, kodun EvtWorkItem geri çağırma işlevleri olarak çalışmasını sağlamak için bir veya daha fazla iş öğesi oluşturabilir.

    Alternatif olarak, KMDF 1.11 ve sonraki sürümlerinde sürücü, WdfInterruptQueueWorkItemForIsr çağrısını yaparak bir kesme iş öğesi isteyebilir. (Bir sürücünün EvtInterruptIsr geri çağırım işlevinin WdfInterruptQueueWorkItemForIsr veya WdfInterruptQueueDpcForIsr işlevlerini çağırabileceğini, ancak her ikisini birden çağıramayacağını hatırlayın.)

  • Bir sürücünün EvtInterruptDpc ve EvtDpcFunc geri çağırma fonksiyonlarını birbiriyle ve bir cihazla ilişkili diğer geri çağırma fonksiyonlarıyla eşitlemek önemliyse, sürücünüz AutomaticSerialization üyesini kesme talebinin WDF_INTERRUPT_CONFIG yapısında ve DPC nesnesinin WDF_DPC_CONFIG yapısında TRUE olarak ayarlayabilirsiniz. Alternatif olarak, sürücü çerçeve döndürme kilitleri kullanabilir. (AutomaticSerialization üyesinin DOĞRU olarak ayarlanması, bir EvtInterruptIsr geri çağırma işlevini diğer geri çağırma işlevleriyle senkronize etmez. Bu konuda daha önce açıklandığı gibi, bir EvtInterruptIsr geri çağırma işlevini senkronize etmek için WdfInterruptSynchronize veya WdfInterruptAcquireLock kullanın.)

Sürücü yordamlarını eşitleme hakkında daha fazla bilgi için bkz. Framework-Based Sürücüleri için Eşitleme Teknikleri.