pintos (3) --Priority Inversion
来源:互联网 发布:淘宝买家大尺度晒图 编辑:程序博客网 时间:2024/05/18 03:35
解决lock上优先级反转的问题
- 优先级反转的问题使用优先级捐赠来解决,当当前线程想要获得低优先级线程拥有的锁时,将低优先级线程的优先级设为当前线程的优先级,当低优先级线程释放锁的时候恢复其原始优先级。
- 整个过程分两个部分:捐赠和恢复。
- 其中的问题有:链式捐赠,多重捐赠,捐赠对信号量的影响。
优先级捐赠分两步:
- 如果要获取的锁已被获取,且拥有者的优先级低于当前线程,则设置其优先级为当前线程优先级。此时存在捐赠链的情况。
- 在释放锁的时候,恢复初始优先级。此时存在被多个锁捐赠的情况。
在struct thread中:
为了恢复基础优先级,我们将其保存: int base_priority; /* Base priority. */
为了解决被多锁捐赠的情况,我们保存当前线程获取到的所有锁: struct list lock_list; /* Acquired locks.*/
为了解决链式捐赠的问题,我们增加指向被当前线程捐赠优先级的线程指针: struct thread *donate_to; /* Donate priority to this thread.*/
同时在init_thread()中初始化它们。
为了维护lock_list,我们修改struct lock,增加list_elem:
/* Lock. */struct lock { struct thread *holder; /* Thread holding lock (for debugging). */ struct semaphore semaphore; /* Binary semaphore controlling access. */ struct list_elem elem; /* List element.*/ };
对1的实现在lock_acquire()函数中:
voidlock_acquire (struct lock *lock){ ASSERT (lock != NULL); ASSERT (!intr_context ()); ASSERT (!lock_held_by_current_thread (lock)); /* If lock is held and the holder's priority below current thread, * set it's priority equal current thread.*/ struct thread *t = thread_current(); if(!thread_mlfqs && lock->holder != NULL && t->priority > lock->holder->priority){ t->donate_to = lock->holder; /* Donate chain. */ while(t->donate_to != NULL){ t->donate_to->priority = t->priority; t = t->donate_to; } } sema_down (&lock->semaphore); lock->holder = thread_current (); list_push_back(&thread_current()->lock_list, &lock->elem);}
如果要捐赠的线程同时也捐赠给其他线程优先级,则链式的捐赠下去。
若成功获取该锁,则将该锁加入到当前线程的lock_list中。
注:thread_mlfqs为多级反馈调度的指示变量,当前可看作false。
lock_try_acquire()则只需要维护lock_list:
boollock_try_acquire (struct lock *lock){ bool success; ASSERT (lock != NULL); ASSERT (!lock_held_by_current_thread (lock)); success = sema_try_down (&lock->semaphore); if (success){ lock->holder = thread_current (); list_push_back(&thread_current()->lock_list, &lock->elem); } return success;}
对2的实现在lock_release()函数中:
voidlock_release (struct lock *lock) { ASSERT (lock != NULL); ASSERT (lock_held_by_current_thread (lock)); /* * */ struct thread *t = thread_current(); struct list_elem *e; int max_priority = t->base_priority; /* Iterator all locks.*/ for (e = list_begin (&t->lock_list); e != list_end (&t->lock_list); e = list_next (e)){ struct lock *l = list_entry(e, struct lock, elem); if(l == lock){ /* This lock will be release, * so we should get the max priority from other locks.*/ continue; } struct list *waiters = &l->semaphore.waiters; /* Iterator this lock's waiters.*/ if(list_size(waiters) != 0){ int p = list_entry(list_front(waiters), struct thread, elem)->priority; if(p > max_priority){ max_priority = p; } } } /* Release this lock from lock_list.*/ list_remove(&lock->elem); /* Clear donate_to.*/ if(!list_empty(&lock->semaphore.waiters)) list_entry(list_front(&lock->semaphore.waiters), struct thread, elem)->donate_to = NULL; lock->holder = NULL; if(!thread_mlfqs){ t->priority = max_priority; } sema_up (&lock->semaphore);}
首先将要释放的lock从lock_list中排除掉
- 如果lock_list仍不为空,说明当前线程仍被其他lock的等待线程捐赠优先级,故从其中找出优先级最高的线程,将其优先级设为当前线程优先级
- 如果lock_list为空,则直接恢复base_priority。
最后,将要释放的lock从当前线程的lock_list中删除,以及设置捐赠线程的donate_to为NULL。
设置优先级的时候,如果当前线程优先级被捐赠,则只设置base_priority:
voidthread_set_priority (int new_priority) { enum intr_level old_level = intr_disable (); struct thread *t = thread_current(); if(t->priority == t->base_priority){ /* Not been donated.*/ t->priority = new_priority; }else if(new_priority > t->priority){ t->priority = new_priority; } t->base_priority = new_priority; thread_yield(); intr_set_level (old_level);}
还存在的一个问题是,我们之前维护sema waiters list 为按优先级排列,当waiters中的线程优先级被捐赠之后,sema_up()就不能保证唤醒的是优先级最高的线程了,所以我们在唤醒前,要将waiters list重新排序:
voidsema_up (struct semaphore *sema) { enum intr_level old_level; ASSERT (sema != NULL); old_level = intr_disable (); /* The thread's priority may be donated, so we need sort it.*/ list_sort(&sema->waiters, priority_less, NULL); if (!list_empty (&sema->waiters)) thread_unblock (list_entry (list_pop_front (&sema->waiters), struct thread, elem)); sema->value++; intr_set_level (old_level); thread_yield();}
通过所有priority-donate-*
- pintos (3) --Priority Inversion
- pintos (2) --Priority Scheduling
- priority inversion
- Priority Inversion:优先级反转
- Priority Inversion - 优先级翻转
- 优先级倒置(Priority inversion)
- 说说优先级倒置(Priority inversion)
- [JAVA学习笔记-72]关于Priority Inversion
- Priority
- pintos安装
- Pintos安装
- inversion
- Inversion
- Inversion
- 【pintos学习笔记】(1)pintos配置
- Pintos的一点笔记
- qemu运行pintos
- pintos线程转换机制
- python 过滤xml非法字符 :not well-formed (invalid token)错误处理
- 自然语言处理(五 文本相似度)
- canvas(图像)
- 科技文档,报告等书写规格
- Android从上往下滑动或从下往上滑动结束Activity
- pintos (3) --Priority Inversion
- 【C#编程最佳实践 五】项目与代码流程实践
- 购物车可增加减少数量可添加
- SPSS考前突击
- 关于Hbase的一些优化
- 深入理解c语言指针-第五章
- 初学者---Android Fragment之间数据传递的三种方式
- SpringCloud Eureda入门案例
- Syncios Data Transfer(IOS数据传输工具)官方中文版V1.6.2下载 | SynciOS Data Transfer破解版