atomic的相關操作定義都在include/asm/atomic.h中,各個平台有不同的實現方法,比如在x86平台上,CPU提供了在指令執行期間對總線加鎖的手段。CPU芯片上有一條引線#HLOCK pin,如果匯編語言的程序中在一條指令前面加上前綴"LOCK",經過匯編以後的機器代碼就使CPU在執行這條指令的時候把#HLOCK pin的電位拉低,持續到這條指令結束時放開,從而把總線鎖住,這樣同一總線上別的CPU就暫時不能通過總線訪問內存了,保證了這條指令在多處理器環境中的原子性。
在uclinux目前對atomic的實現中,有這樣一個注釋:
/*
* Atomic operations that C can't guarantee us. Useful for
* resource counting etc..
*
* Generally we do not concern about SMP BFIN systems, so we don't have
* to deal with that.
*
* Tony Kou ([email protected]) Lineo Inc. 2001
*/
也就是它並不考慮SMP的情況,我希望對此進行適當的修改。但是在bf561中,它並沒有提供類似x86這樣鎖定總線的功能,它有的僅僅是一個TESTSET的指令,而無法在硬件上提供其它的鎖定機制,因此我們需要為其添加一個類似於spinlock這樣的鎖。
查了下linux-2.6.19的內核代碼,在asm-sparc/atomic.h中有一個類似的作法:
/* We do the bulk of the actual work out of line in two common
* routines in assembler, see arch/sparc/lib/atomic.S for the
* "fun" details.
*
* For SMP the trick is you embed the spin lock byte within
* the word, use the low byte so signedness is easily retained
* via a quick arithmetic shift. It looks like this:
*
* ----------------------------------------
* | signed 24-bit counter value | lock | atomic_t
* ----------------------------------------
* 31 8 7 0
*/
為省事,干脆單獨在atomic_t的結構體中加上一個spinlock:
typedef struct {
int counter;
testset_t lock;
} atomic_t;
相應的操作函數也作一下修改,如:
#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
static inline int atomic_sub_return(int i, atomic_t * v)
{
int __temp = 0;
long flags;
adi_acquire_lock(&v->lock);
local_irq_save(flags);
v->counter -= i;
__temp = v->counter;
local_irq_restore(flags);
adi_release_lock(&v->lock);
return __temp;
}
以後再考慮一下性能問題。
uclinux-2008R1-RC8(bf561)到VDSP5的移植(62)
uclinux-2008R1-RC8(bf561)到VDSP5的移植(60):current_text_addr
uclinux-2008R1-RC8(bf561)到VDSP5的移植(58)
uclinux-2008R1-RC8(bf561)到VDSP5的移植(57)
uclinux-2008R1-RC8(bf561)到VDSP5的移植(56):__grab_cache_page
uclinux-2008R1-RC8(bf561)到VDSP5的移植(46):raw_rwlock_t