200 likes | 405 Views
Concurrency and Race Conditions. 報告者 : 彭敏君 ANT 實驗室 2011/03/24. outline. 5.0. 引言 5.1. scull 缺陷 5.2. Concurrency and Its Management 5.3. Semaphores and Mutex 5.4. Completions 機制 5.5. Spinlocks 5.6. 鎖定 機制的使用 準則 5.7. 鎖定機制外的選擇. 引言. Scull 存在缺陷的原因 早期 Linux 不支援 SMP
E N D
Concurrency and RaceConditions 報告者:彭敏君 ANT實驗室 2011/03/24
outline 5.0. 引言 5.1.scull 缺陷 5.2. Concurrency and Its Management 5.3. Semaphores and Mutex 5.4. Completions 機制 5.5. Spinlocks 5.6. 鎖定機制的使用準則 5.7. 鎖定機制外的選擇
引言 • Scull 存在缺陷的原因 • 早期Linux 不支援SMP • 只有在hardware interrupt會發生concurrency
Scull • 以下是Scull 中的一段程式碼 • if (!dptr->data[s_pos]) { dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL); if (!dptr->data[s_pos]) gotoout; } • 假設有兩個process (A and B) 都執行到 if (!dptr->data[s_pos]) 則?
Concurrency and Its Managemen Linux 自2.6版本後加入了可插隊 目前的系統大多都是SMP架構 熱插拔
Semaphores and Mutex <linux/semaphore.h> void sema_init(struct semaphore *sem, intval); DECLARE_MUTEX(name); //1 DECLARE_MUTEX_LOCKED(name); //0 void init_MUTEX(struct semaphore *sem); void init_MUTEX_LOCKED(struct semaphore *sem);
Semaphores and Mutex Down up void down(struct semaphore *sem); intdown_interruptible(struct semaphore *sem); intdown_trylock(struct semaphore *sem); void up(struct semaphore *sem);
Semaphores and Mutex 複習一下Scull_dev的結構 structscull_dev { structscull_qset *data; /* Pointer to first quantum set */ intquantum; /* the current quantum size */ intqset; /* the current array size */ unsigned long size; /* amount of data stored here */ unsigned intaccess_key; /* used by sculluid and scullpriv */ structsemaphore sem; /* mutual exclusion semaphore */ structcdevcdev; /* Char device structure */ };
Semaphores and Mutex Scull 初始化 for (i = 0; i < scull_nr_devs; i++) { scull_devices[i].quantum = scull_quantum; scull_devices[i].qset = scull_qset; sema_init(&scull_devices[i].sem, 1); scull_setup_cdev(&scull_devices[i], i); }
Semaphores and Mutex <linux/rwsem.h> Reader void init_rwsem(structrw_semaphore *sem); void down_write(structrw_semaphore *sem); intdown_write_trylock(structrw_semaphore *sem); void up_write(structrw_semaphore *sem); void downgrade_write(structrw_semaphore *sem);
Semaphores and Mutex Writer void down_write(structrw_semaphore *sem); intdown_write_trylock(structrw_semaphore *sem); void up_write(structrw_semaphore *sem); void downgrade_write(structrw_semaphore *sem);
Completions <linux/completion.h> 等候完成 完成通知 DECLARE_COMPLETION(my_completion); void wait_for_completion(struct completion *c); void complete(struct completion *c); void complete_all(struct completion *c);
Completions Read Write ssize_tcomplete_read (struct file *filp, char __user *buf, size_t count, loff_t *pos){ printk(KERN_DEBUG "process %i (%s) going to sleep\n",current->pid, current->comm); wait_for_completion(&comp); printk(KERN_DEBUG "awoken %i (%s)\n", current->pid, current->comm); ] return 0; /* EOF */ } ssize_tcomplete_write (struct file *filp, const char __user *buf, size_t count, loff_t *pos) { printk(KERN_DEBUG "process %i (%s) awakening the readers...\n", current->pid, current->comm); complete(&comp); return count; /* succeed, to avoid retrial */ }
Spinlocks • <linux/spinlock.h> • spinlock_tmy_lock = SPIN_LOCK_UNLOCKED; • void spin_lock_init(spinlock_t *lock); • Lock • void spin_lock(spinlock_t *lock); • unLock • void spin_unlock(spinlock_t *lock);
Spinlocks • Lock • void spin_lock(spinlock_t *lock); • void spin_lock_irqsave(spinlock_t *lock, unsigned long flags); • void spin_lock_irq(spinlock_t *lock); • void spin_lock_bh(spinlock_t *lock) • unLock • void spin_unlock(spinlock_t *lock); • void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags); • void spin_unlock_irq(spinlock_t *lock); • void spin_unlock_bh(spinlock_t *lock);
Spinlocks • tryLock • intspin_trylock(spinlock_t *lock); • intspin_trylock_bh(spinlock_t *lock);
Spinlocks • Read • void read_lock(rwlock_t *lock); • void read_lock_irqsave(rwlock_t *lock, unsigned long flags); • void read_lock_irq(rwlock_t *lock); • void read_lock_bh(rwlock_t *lock); • void read_unlock(rwlock_t *lock); • void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags); • void read_unlock_irq(rwlock_t *lock); • void read_unlock_bh(rwlock_t *lock);
Spinlocks • Write • void write_lock(rwlock_t *lock); • void write_lock_irqsave(rwlock_t *lock, unsigned long flags); • void write_lock_irq(rwlock_t *lock); • void write_lock_bh(rwlock_t *lock); • intwrite_trylock(rwlock_t *lock); • void write_unlock(rwlock_t *lock); • void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags); • void write_unlock_irq(rwlock_t *lock); • void write_unlock_bh(rwlock_t *lock);
鎖定機制的使用準則 規則明確 不同時鎖定多個資源 規劃時仔細考慮鎖定的區間
鎖定機制外的選擇 無所演算法 連動運算 位元運算 Ready-Copy-Upate (RCU)