cli()/sti()移除指南

cli()/sti()移除指南

UniProcessor:UP 單處理器
MultiProcessor:MP 多處理器
#### cli()/sti() removal guide, started by Ingo Molnar [email protected]

[原文:linux-2.6.22/Documentation/cli-sti-removal.txt]
CN Translated by [email protected]
Version 1.0

as of 2.5.28, five popular macros have been removed on SMP, and are being phased out on UP:
cli(), sti(), save_flags(flags), save_flags_cli(flags), restore_flags(flags), until now it was possible to protect driver code against interrupt handlers via a cli(), but from now on other, more lightweight methods have to be used for synchronization, such as spinlocks or semaphores.
針對2.5.28內核,五個常用的宏在SMP系統上已經被刪除,在UP系統上也正逐漸刪除:cli(), sti(), save_flags(flags), save_flags_cli(flags), restore_flags(flags)在這以前,主要通過cli()保護驅動代碼不受中斷處理程序的干擾,現在有更輕量級的方法用作同步如自旋鎖,信號量。

for example, driver code that used to do something like:
例如,如下的驅動代碼在SMP系統上是正確的:

    struct driver_data;

    irq_handler (...)
    {
        ....
        driver_data.finish = 1;
        driver_data.new_work = 0;
        ....
    }

    ...

    ioctl_func (...)
    {
        ...
        cli();
        ...
        driver_data.finish = 0;
        driver_data.new_work = 2;
        ...
        sti();
        ...
    }

was SMP-correct because the cli() function ensured that no interrupt handler (amongst them the above irq_handler()) function would execute while the cli()-ed section is executing.
因爲cli()函數保證當cli()-ed的區域在執行的時候,沒有一箇中斷處理函數可以執行。

but from now on a more direct method of locking has to be used:
但是從現在開始,可以使用一種更直接的鎖。

    spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
    struct driver_data;

    irq_handler (...)
    {
        unsigned long flags;
        ....
        spin_lock_irqsave(&driver_lock, flags);
        ....
        driver_data.finish = 1;
        driver_data.new_work = 0;
        ....
        spin_unlock_irqrestore(&driver_lock, flags);
        ....
    }

    ...

    ioctl_func (...)
    {
        ...
        spin_lock_irq(&driver_lock);
        ...
        driver_data.finish = 0;
        driver_data.new_work = 2;
        ...
        spin_unlock_irq(&driver_lock);
        ...
    }

the above code has a number of advantages:

- the locking relation is easier to understand - actual lock usage
  pinpoints the critical sections. cli() usage is too opaque.
  Easier to understand means it's easier to debug.

- it's faster, because spinlocks are faster to acquire than the
  potentially heavily-used IRQ lock. Furthermore, your driver does
  not have to wait eg. for a big heavy SCSI interrupt to finish,
  because the driver_lock spinlock is only used by your driver.
  cli() on the other hand was used by many drivers, and extended
  the critical section to the whole IRQ handler function - creating
  serious lock contention.
上面的代碼有許多好處:
-容易理解鎖的關係-鎖的使用突出了臨界區域。cli()的使用顯得比較難懂。容易理解意味着方便調試。

-速度較快,因爲獲得自旋鎖比大量使用的IRQ鎖要快。而且驅動代碼沒有必要等待中斷結束(如一個耗時的SCSI中斷),因爲只有你的驅動使用driver_lock自旋鎖。另一方面很多驅動都會使用cli(),使得臨界區域擴展到整個IRQ中斷處理函數-這樣就創建了嚴重的鎖競爭。
to make the transition easier, we've still kept the cli(), sti(), save_flags(), save_flags_cli() and restore_flags() macros defined on UP systems - but their usage will be phased out until 2.6 is
released.
爲了方便過渡,仍然在UP系統上保留了宏定義cli(), sti(), save_flags(), save_flags_cli() and restore_flags(),但是2.6 的release會刪除它們的使用。

drivers that want to disable local interrupts (interrupts on the current CPU), can use the following five macros:
驅動如果想禁止本地中斷(在當前CPU上的中斷),可以使用下面的五個宏:

  local_irq_disable(), local_irq_enable(), local_save_flags(flags), local_irq_save(flags), local_irq_restore(flags)

but beware, their meaning and semantics are much simpler, far from that of the old cli(), sti(), save_flags(flags) and restore_flags(flags) SMP meaning:
同舊的宏cli(), sti(), save_flags(flags) and restore_flags(flags)相比,它們的意義和語義相對簡單,

    local_irq_disable()       => turn local IRQs off

    local_irq_enable()        => turn local IRQs on

    local_save_flags(flags)   => save the current IRQ state into flags. The
                                 state can be on or off. (on some
                                 architectures there's even more bits in it.)

    local_irq_save(flags)     => save the current IRQ state into flags and
                                 disable interrupts.

    local_irq_restore(flags)  => restore the IRQ state from flags.

(local_irq_save can save both irqs on and irqs off state, and local_irq_restore can restore into both irqs on and irqs off state.)

another related change is that synchronize_irq() now takes a parameter: synchronize_irq(irq). This change too has the purpose of making SMP synchronization more lightweight - this way you can wait for your own interrupt handler to finish, no need to wait for other IRQ sources.
另外一個相關的變化是函數synchronize_irq()現在需要一個參數:synchronize_irq(irq)。這個變化的目的使得SMP同步更快了-通過這種方式,就可以只等待自己的中斷處理函數,沒有必要等待其他的IRQ資源。

why were these changes done? The main reason was the architectural burden of maintaining the cli()/sti() interface - it became a real problem. The new interrupt system is much more streamlined, easier to understand, debug, and it's also a bit faster - the same happened to it that will happen to cli()/sti() using drivers once they convert to spinlocks :-)
爲什麼做這些變化?主要的原因是維護接口cli()/sti()對應的系統架構負擔-成爲了一個真正的問題。新的中斷系統更加流水線化,容易理解,調試,也更快了-一旦驅動代碼由cli()/sti()轉換成自旋鎖,也會發生同樣的事情:-)。

 

 

摘自:http://wg206.spaces.live.com/blog/cns!F96F35563934F232!569.entry

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章