ÏÈ¿´½ø³Ì¼äµÄ»¥³â¡£ÔÚlinuxÄÚºËÖÐÖ÷Ҫͨ¹ýsemaphore»úÖƺÍspin_lock»úÖÆʵÏÖ¡£Ö÷ÒªµÄÇø±ðÊÇÔÚsemaphore»úÖÆÖУ¬½ø²»ÁËÁÙ½çÇøʱ»á½øÐнø³ÌµÄÇл»£¬¶øspin_lock¸ÕÖ´ÐÐæµÈ£¨ÔÚSMPÖУ©¡£ÏÈ¿´ÄÚºËÖеÄsemaphore»úÖÆ¡£Ç°ÌáÊǶÔÒýÓüÆÊýcountÔö¼õµÄÔ×ÓÐÔ²Ù×÷¡£ÄÚºËÓÃatomic_tµÄÊý¾Ý½á¹¹ºÍÔÚËüÉÏÃæµÄһϵÁвÙ×÷Èçatomic_add()¡¢atomic_sub()µÈµÈʵÏÖ¡££¨¶¨ÒåÔÚatomic.hÖУ©semaphone»úÖÆÖ÷Ҫͨ¹ýup()ºÍdown()Á½¸ö²Ù×÷ʵÏÖ¡£semaphoneµÄ½á¹¹Îª:
struct semaphore
{
atomic_t count;
int sleepers;
wait_queue_head_t wait;
};
ÏàÓ¦µÄdown()º¯ÊýΪ:
static inline void down(struct semaphore*sem)
{
/* 1 */sem->count--; //ΪÔ×Ó²Ù×÷
if(sem->count<0)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
tsk->state = TASK_UNINTERRUPTIBLE;
add_wait_queue_exclusive(&sem->wait, &wait);
spin_lock_irq(&semaphore_lock);
/* 2 */ sem->sleepers++;
for (;;) {
int sleepers = sem->sleepers;
/*
* Add "everybody else" into it. They aren't
* playing, because we own the spinlock.
*/
/* 3 */ if (!atomic_add_negative(sleepers - 1, &sem->count)) {
/* 4 */ sem->sleepers = 0; //Õâʱsem->count=0
break;
}
/* 4 */ sem->sleepers = 1; /* us - see -1 above */ // Õâʱsem
->count
=-1
spin_unlock_irq(&semaphore_lock);
schedule();
tsk->state = TASK_UNINTERRUPTIBLE;
spin_lock_irq(&semaphore_lock);
}
spin_unlock_irq(&semaphore_lock);
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
wake_up(&sem->wait);
}
}
ÏàÓ¦µÄup()º¯ÊýΪ:
void up(struct semaphore*sem)
{
sem->count++; //ΪÔ×Ó²Ù×÷
if(sem->count<=0)
{
//»½Ðѵȴý¶ÓÁÐÖеÄÒ»¸ö·ûºÏÌõ¼þµÄ½ø³Ì£¨ÒòΪÿ¸ö½ø³Ì¶¼¼ÓÁËTASK_EXCLUSIVE±êÖ¾£©
¡£
};
feng201310 ÓÚ 2014-05-19 14:46:08·¢±í:
¶ÁÁË£¬Ð»ÁË
h497916507 ÓÚ 2013-08-01 13:38:28·¢±í:
mark
js001sdx ÓÚ 2009-09-29 10:10:58·¢±í:
¶ÁÁË£¬Ð»ÁË
augustnov ÓÚ 2006-11-16 09:32:15·¢±í:
¿ÉÒÔ¿´³ö£¬ËüºÍsemaphore»úÖƽâ¾öµÄ¶¼ÊÇÁ½¸ö½ø³ÌµÄ»¥³âÎÊÌ⣬¶¼ÊÇÈÃÒ»¸ö½ø³ÌÍ˳öÁÙ½çÇøºóÁíÒ»¸ö½ø³Ì²Å½øÈëµÄ·½·¨£¬²»¹ýsempahore»úÖÆʵÐеÄÊÇÈýø³ÌÔÝʱÈóöCPU£¬½øÈëµÈ´ý¶ÓÁеȴýµÄ²ßÂÔ£¬¶øspin_lockʵÐеÄÈ´ÊÇÈ´½ø³ÌÔÚԵؿÕת£¬µÈ×ÅÁíÒ»¸ö½ø³Ì½áÊøµÄ²ßÂÔ¡£
ϱ߿¼ÂÇÖж϶ÔÁÙ½çÇøµÄÓ°Ïì¡£Òª»¥³âµÄ»¹Óнø³ÌºÍÖжϷþÎñ³ÌÐòÖ®¼ä¡£µ±Ò»¸ö½ø³ÌÔÚÖ´ÐÐÒ»¸öÁÙ½çÇøµÄ´úÂëʱ£¬¿ÉÄÜ·¢ÉúÖжϣ¬¶øÖжϺ¯Êý¿ÉÄܾͻáµ÷ÓÃÕâ¸öÁÙ½çÇøµÄ´úÂ룬²»ÈÃËü½øÈëµÄ»°¾Í»á²úÉúËÀËø¡£Õâʱһ¸öÓÐЧµÄ·½·¨¾ÍÊǹØÖжÏÁË¡£
#define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ;
cli":
"=g" (x): /* no input */ :"memory")
#define local_irq_restore(x) __asm__ __volatile__("pushl %0 ; popfl": /*
no
output */ :"g" (x):"memory")
#define local_irq_disable() __asm__ __volatile__("cli": : :"memory")
#define local_irq_enable() __asm__ __volatile__("sti": : :"memory")
#define cpu_bh_disable(cpu) do { local_bh_count(cpu)++; barrier(); } while (0)
#define cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--; } while (0)
#define local_bh_disable() cpu_bh_disable(smp_processor_id())
#define local_bh_enable() cpu_bh_enable(smp_processor_id())
¶ÔÓÚUPÀ´Ëµ£¬ÉÏÃæÒѾÊÇ×ã¹»ÁË£¬²»¹ý¶ÔÓÚSMPÀ´Ëµ£¬»¹Òª·ÀÖ¹À´×ÔÆäËücpuµÄÓ°Ï죬Õâʱ½â¾öµÄ·½·¨¾Í¿ÉÒÔ°ÑÉÏÃæµÄspin_lock»úÖÆÒ²×ۺϽøÀ´ÁË¡£
#define spin_lock_irqsave(lock, flags) do {
local_irq_save(flags); sp
in_lock(lock); } while (0)
#define spin_lock_irq(lock) do { local_irq_disable();
spin_lock(lo
ck); } while (0)
#define spin_lock_bh(lock) do { local_bh_disable();
spin_lock(loc
k); } while (0)
#define spin_unlock_irqrestore(lock, flags) do { spin_unlock(lock); local_i
rq_restore(flags); } while (0)
#define spin_unlock_irq(lock) do { spin_unlock(lock);
local_irq_enable();
} while (0)
#define spin_unlock_bh(lock) do { spin_unlock(lock);
local_bh_enable();
} while (0)
Ç°Ãæ˵¹ý£¬¶ÔÓÚUPÀ´Ëµ£¬spin_lock£¨£©Êǿյģ¬ËùÒÔÒÔÉϵĶ¨Òå¾ÍÒ»ÆðÊÊÓÃÓÚUP ºÍSMPµÄÇéÐÎÁË¡£
read_lock_irqsave(lock, flags) , read_lock_irq(lock),
read_lock_bh(lock) ºÍ
write_lock_irqsave(lock, flags) , write_lock_irq(lock),
write_lock_bh(lock
)
¾ÍÊÇspin_lockµÄÒ»¸öССµÄ±äÐͶø¼ºÁË¡£
augustnov ÓÚ 2006-11-16 09:31:56·¢±í:
µ±È»£¬»¹ÓÐÁíÒ»ÖÖÇé¿ö£¬¾ÍÊÇup()²Ù×÷ºÍdown()²Ù×÷Êǽ»*³öÏֵģ¬Ò»°ãµÄ¹æÂɾÍÊÇ£¬Èç¹û½ø³ÌÔÚÁÙ½çÇøÆÚ¼äÓÖÓнø³Ì£¨ÎÞÂÛÊÇÄĸö½ø³Ì£¬ÐÂÀ´µÄ»¹ÊǸձ»»½ÐѵÄÄǸö£©½øÈë˯Ãߣ¬¾Í»áÁîcountµÄÖµ´Ó0±äΪ-1£¬´Ó¶ø½ø³ÌÔÚ´ÓÁÙ½çÇø³öÀ´Ö´ÐÐup()Àï¾Í±ØÐëÖ´ÐÐÒ»´Îwake_up()£¬ÒÔÈ·±£ËùÓеĽø³Ì¶¼Äܱ»»½ÐÑ£¬ÒòΪ¶à»½ÐѼ¸¸öÊÇû¹ØϵµÄ¡£Èç¹û½ø³ÌÔÚÁÙ½çÇøÆÚ¼äûÓбðµÄ½ø³Ì½øÈë˯Ãߣ¬Ôò´ÓÁÙ½çÇø³öÀ´Ö´ÐÐup()ʱ¾ÍÓò»×ÅÈ¥Ö´ÐÐwake_up()ÁË£¨µ±È»£¬Ö´ÐÐÁËҲûʲôӰÏ죬²»¹ý¶àÓà°ÕÁË£©¡£¶øΪʲôҪ°Ñwake_up()ºÍcount++·Ö¿ªÄØ£¬¿ÉÒÔ´ÓÉÏÃæµÄup1¿´³öÀ´£¬ÀýÈ磬½ø³Ì2µÚÒ»´ÎµÃµ½»ú»áÔËÐÐʱ£¬±¾À´Õâʱ»½ÐÑËüµÄ½ø³Ì»¹Ã»Ö´ÐÐup()µÄ£¬µ«ÓпÉÄÜÆäËü½ø³ÌÖ´ÐÐÁËup()ÁË£¬ËùÒÔÕæÓпÉÄܻᷢÏÖcount==1µÄÇé¿ö£¬ÕâʱËü¾ÍÕæµÄ²»ÓÃ˯¾õÁË£¬Áîcount=sleepers=0£¬¾Í¿ÉÒÔ½Ó×ÅÍùÏÂÖ´ÐÐÁË¡£»¹¿É¿´³öÒ»µã£¬Ò»°ãµÄ£¬( count ,sleepers)µÄÖµµÄÈ¡Öµ·¶Î§Îª(n ,0)[n>0] ºÍ(0 ,0)ºÍ (1 ,-1)¡£Ï±߿´¿´spin_lock»úÖÆ¡£
Spin_lock²ÉÓõķ½Ê½ÊÇÈÃÒ»¸ö½ø³ÌÔËÐУ¬ÁíÍâµÄ½ø³ÌæµÈ´ý£¬ÓÉÓÚÔÚÖ»ÓÐÒ»¸öcpuµÄ»úÆ÷(UP)ÉÏ΢¹ÛÉÏÖ»ÓÐÒ»¸ö½ø³ÌÔÚÔËÐС£ËùÒÔÔÚUPÖУ¬spin_lockºÍspin_unlock¾Í¶¼ÊÇ¿ÕµÄÁË¡£ÔÚSMPÖУ¬spin_lock()ºÍspin_unlock()¶¨ÒåÈçÏ£º
typedef struct {
volatile unsigned int lock;
} spinlock_t;
static inline void spin_lock(spinlock_t *lock)
{
__asm__ __volatile__(
"\n1:\t"
"lock ; decb %0\n\t"
"js 2f\n" //lock->lock< 0 ,jmp 2 forward
".section .text.lock,\"ax\"\n"
"2:\t"
"cmpb $0,%0\n\t" //wait lock->lock==1
"rep;nop\n\t"
"jle 2b\n\t"
"jmp 1b\n"
".previous"
:"=m" (lock->lock) : : "memory");
}
static inline void spin_unlock(spinlock_t *lock)
{
__asm__ __volatile__(
"movb $1,%0"
:"=m" (lock->lock) : : "memory"); //lock->lock=1
}
Ò»°ãÊÇÈç´ËʹÓÃ:
#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED;
spin_lock_(&xxx_lock)
...
critical section
...
spin_unlock (&xxx_lock)
augustnov ÓÚ 2006-11-16 09:31:36·¢±í:
¼ÙÉ迪ʼʱ£¬count=1;sleepers=0¡£µ±½ø³ÌAÖ´ÐÐdown()ʱ£¬ÒýÓüÆÊýcount--£¬Èç¹ûÕâʱËüµÄÖµ´óÓÚµÈÓÚ0£¬Ôò´Ódown()ÖÐÖ±½Ó·µ»Ø¡£Èç¹ûcountÉÙÓÚ0£¬ÔòAµÄstate¸ÄΪTASK_INTERRUPTIBLEºó½øÈëÕâ¸öÐźÅÁ¿µÄµÈ´ý¶ÓÁÐÖУ¬Í¬Ê±Ê¹sleepers++;È»ºóÖØмÆËãcount=sleepers - 1 + count,ÈôÕâʱÒýÓüÆÊýÈÔСÓÚ0£¨Ò»°ãÇé¿öÏÂӦΪ-1£¬ÒòΪcount = - sleepers,²»¹ýÔÚSMP½á¹¹ÖУ¬ÆÚ¼ä±ðµÄ½ø³Ì¿ÉÄÜÖ´ÐÐÁËup()ºÍdown()´Ó¶øʹµÃÒýÓüÆÊýµÄÖµ¿ÉÄܱ仯£©£¬ÔòÖ´Ðнø³ÌÇл»¡£
µ±½ø³ÌAÓÖ»ñµÃ»ú»áÔËÐÐʱ£¬ËüÏÈÖ´ÐÐwake_up(&sem->wait)²Ù×÷£¬»½Ðѵȴý¶ÓÁÐÀïµÄÒ»¸ö½ø³Ì£¬½Ó×ÅËü½øÈëÁÙ½çÇø£¬´ÓÁÙ½çÇø³öÀ´Ê±Ö´ÐÐup()²Ù×÷£¬Ê¹sem->count++,£¨Èç¹û½ø³ÌAÊÇ´Ódown()ÖÐÖ±½Ó·µ»Ø£¬ÒòΪÕâʱµÈ´ý¶ÓÁÐÒ»¶¨Îª¿Õ£¬ËùÒÔËü²»ÓÃÖ´ÐÐwake_up()²Ù×÷£¬Ö±½Ó½øÈëÁÙ½çÇø£¬ÔÚ´ÓÁÙ½çÇø³öÀ´Ê±Ò»ÑùÖ´ÐÐup()²Ù×÷£¬Ê¹ sem->count++£©¡£ÕâʱÈç¹ûcountµÄֵСÓÚµÈÓÚ0£¬Õâ±íÃ÷ÔÚËüÔÚÁÙ½çÇøÆÚ¼äÓÖÓÐÒ»¸ö½ø³Ì£¨¿ÉÄܾÍÊÇËü½øÈëÁÙ½çÇøʱ»½ÐѵÄÄǸö½ø³Ì£©½øÈë˯ÃßÁË£¬ÔòÖ´ÐÐwake_up()²Ù×÷£¬·´Ö®£¬Èç¹ûcountµÄÖµÒѾ´óÓÚ0£¬Õâ±íÃ÷ÔÚËüÔÚÁÙ½çÇøÆÚ¼äûÓбðµÄ½ø³Ì£¨°üÀ¨ÔÚËü½øÈëÁÙ½çÇøʱ±»Ëü»½ÐѹýµÄÄǸö½ø³Ì£©½øÈë˯Ãߣ¬ÄÇôËü¾Í¿ÉÒÔÖ±½Ó·µ»ØÁË¡£
´Ó±»»½ÐѵÄÄǸö½ø³Ì¿´¿´£¬Èç¹ûÔÚ»½ÐÑËüµÄ½ø³ÌûִÐÐup()֮ǰËü¾ÍµÃµ½ÁËÔËÐлú»á£¬ÕâʱËüÓÖÖØмÆËãcount=sleepers - 1 + count=-1£»´Ó¶øsleepers±»¸³Öµ1£»ÕâʱËüÓÖ±ØÐë½øÐе÷¶ÈÈóöÔËÐеĻú»á¸ø±ðµÄ½ø³Ì£¬×Ô¼ºÈ¥Ë¯Ãß¡£ÕâÕýÊÇ·¢ÉúÔÚ»½ÐÑËüµÄ½ø³ÌÔÚÁÙ½çÇøʱÔËÐеÄʱºò¡£Èç¹ûÊÇÔÚ»½ÐÑËüµÄ½ø³ÌÖ´ÐÐÁËup()²Ù×÷ºóËü²ÅµÃµ½ÁËÔËÐлú»á£¬¶øÇÒÔÚ»½ÐÑËüµÄ½ø³ÌÔÚÁÙ½çÇøÆÚ¼äʱû±ðµÄ½ø³ÌÖ´ÐÐdown()£¬ÔòcountµÄÖµÔÚ½ø³ÌÖ´ÐÐup()֮ǰÒÀȻΪ0£¬ÕâʱÔÚup()ÀïÃæ¾Í²»±ØÒªÔÙÖ´ÐÐwake_up()º¯ÊýÁË¡£¿ÉÒÔͨ¹ýÒ»¸öÀý×ÓÀ´ËµÃ÷¾ßÌåµÄʵÏÖ¡£É迪ʼsem->count=sem->sleepers=0¡£Ò²¾ÍÊÇÓÐËøµ«Î޵ȴý¶ÓÁÐ £¨Ò»¸ö½ø³ÌÒѾÔÚÔËÐÐÖУ©¡£ÏȺó·Ö±ð½øÐÐ3¸ödown()²Ù×÷£¬ºÍ3¸öup()²Ù×÷£¬ÈçÏ£ºÎªÁ˲ûÊö·½±ã£¬Ö»±£ÁôÁËһЩ»á¸Ä±äsleepersºÍcountÖµµÄ²½Ö裬²¢ÇÒ×ñÑ´Ó×óµ½ÓÒÒÀ´Î½øÐеÄÔÔò¡£
down1:
count(0->-1),sleepers(0->1),sleepers-1+count(-1),count(-1),sleepers(1),µ÷¶È
down2:
count(-1->-2),sleepers(1->2),sleepers-1+count(-1),count(-1),sleepers(1),µ÷¶È
down3:
count(-1->-2),sleepers(1->2),sleepers-1+count(-1),count(-1),sleepers(1),µ÷¶È
up1:
count(-1->0),»½ÐÑÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ1£©,£¨½ø³Ì1µÃµ½»ú»áÔËÐУ©
sleepers-1+count(0),count(0),sleepers(0),break,
»½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ2£©£¬£¨½ø³Ì2µÃµ½»ú»áÔËÐУ©
sleepers-1+count(-1),count(-1),sleepers(1),
µ÷¶È£¨Ã»´ïµ½Ìõ¼þ£¬ÓÖµÃ˯¾õ£©Ò²¿ÉÄÜÊÇÕâÑùµÄ£º
up1`:
count(-1->0),»½ÐÑÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ1£©,£¨½ø³Ì1µÃµ½»ú»áÔËÐУ©
sleepers-1+count(0),count(0),sleepers(0),break,
»½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ2£©£¬½ø³Ì2ÔÚÒÔºó²ÅµÃµ½»ú»áÔËÐУ©
up2:
count(-1->0),£¨ÒòΪcount<=0£©»½ÐÑÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ2£©,½ø³Ì2µÃµ½»ú»áÔËÐУ©
sleepers-+count(0) , count(0) , sleepers(0) ,break,
»½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ3£©£¬½ø³Ì3µÃµ½»ú»áÔËÐУ©
sleepers-1+count(-1),count(-1),sleepers(1),
µ÷¶È£¨Ã»´ïµ½Ìõ¼þ£¬ÓÖµÃ˯¾õ£©¶ÔÓ¦ÉÏÃæµÄ1`£º
up2`:
count(0->1),£¨ÒòΪcount>0,ËùÒÔÖ±½Ó·µ»Ø£©½ø³Ì2µÃµ½»ú»áÔËÐУ©
sleepers-1+count(0),count(0),sleepers(0),break,
»½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¬£¨ÉèΪ3£©
up3:
count(-1->0),£¨ÒòΪcount<=0£©»½ÐÑÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ3£©,½ø³Ì3µÃµ½»ú»áÔËÐУ©
sleepers-1+count(0),count(0),sleepers(0),break,
»½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¨Õâʱ¶ÓÁÐÀïû½ø³ÌÁË£©
½ø³Ì3ÔËÐнáÊø£¬Ö´ÐÐup(), ʹcount =1 ,Õâʱ±ä³ÉûËø״̬ £©
¶ÔÓ¦ÉϱߵÄ2`£º
up3`:
count(0->1),£¨ÒòΪcount>0,ËùÒÔÖ±½Ó·µ»Ø£©½ø³Ì3µÃµ½»ú»áÔËÐУ©
sleepers-1+count(0),count(0),sleepers(0),break,
»½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¨Õâʱ¶ÓÁÐÀïû½ø³ÌÁË£©
½ø³Ì3ÔËÐнáÊø£¬Ö´ÐÐup(), ʹcount =1 ,Õâʱ±ä³ÉûËø״̬ £©