*参照元 [#l26071d1] #backlinks *説明 [#q888ff6e] -パス: [[linux-2.6.33/arch/x86/include/asm/atomic_32.h]] -アトミック値から指定した値を加算し、加算後の値を返す。 -- **引数 [#x0b8e60a] -int i --加算する値 -atomic_t *v --加算対象のアトミック値 --[[linux-2.6.33/atomic_t]] **返り値 [#n37146b4] -int --加算後の v の値 **参考 [#w74de1f6] *実装 [#d3cbd5c6] /** * atomic_add_return - add integer and return * @v: pointer of type atomic_t * @i: integer value to add * * Atomically adds @i to @v and returns @i + @v */ static inline int atomic_add_return(int i, atomic_t *v) { int __i; #ifdef CONFIG_M386 -386 プロセッサ向けバイナリを作る場合 --[[linux-2.6.33/CONFIG_M386]] unsigned long flags; if (unlikely(boot_cpu_data.x86 <= 3)) goto no_xadd; -プロセッサファミリが 3以下(386 以前のプロセッサ)の場合は、 xadd 命令がサポートされていない。 --[[linux-2.6.33/unlikely()]] --[[linux-2.6.33/boot_cpu_data(global)]] #endif /* Modern 486+ processor */ __i = i; -加算する値を保存しておく。 asm volatile(LOCK_PREFIX "xaddl %0, %1" : "+r" (i), "+m" (v->counter) : : "memory"); -xaddl: xadd 命令(Exchange and Add)の 32ビット版である。 ロックプリフィクスと組み合わせるとアトミックな加算が実行できる。 --[[linux-2.6.33/LOCK_PREFIX]] -v->counter と i を交換して、合計を v->counter にロードする。 return i + __i; -i は加算する前の v->counter の値が入っている。 --なお、この return にいたる前に、 別の誰かが v->counter を更新する可能性があるため、 return v->counter; と書くことはできない。 #ifdef CONFIG_M386 no_xadd: /* Legacy 386 processor */ local_irq_save(flags); - --[[linux-2.6.33/local_irq_save()]] __i = atomic_read(v); - --[[linux-2.6.33/atomic_read()]] atomic_set(v, i + __i); - --[[linux-2.6.33/atomic_set()]] local_irq_restore(flags); - --[[linux-2.6.33/local_irq_restore()]] return i + __i; #endif } *コメント [#ybc8c3f0]