免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1580 | 回复: 0
打印 上一主题 下一主题

l4中 mutex 实现的流程及代码分析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-22 08:51 |只看该作者 |倒序浏览

    只有多任务系统才需要mutex,这点应该不用解释,在l4系统中实现mutex 的本质
就是让无法获得mutex的任务,通过调度交出当前运行权,交由其他任务继续运行,
当获得mutex的任务在释放mutex时,如果发现有对metex的lock请求,也同样交出运行权,

  然后前面无法获得mutex的任务或将继续运行,重新进行lock mutex测试,然后继续上面的流程,

获得就继续运行,没有获得就交出运行权

先看下mutex的结构:

 

  1. struct mutex {
  2.     L4_Word_t fHolder;
  3.     L4_Word_t fNeeded;
  4.     L4_Word_t fCount;
  5.     };

 

具体的流程图如下:

上图中如果 mutex lock  不成功,调用thread_swith切换到fHolder所保存的 ,已经成功mutex lock的
的thread
 
实现代码:
  1. stmdb sp!, {r4, r5, lr} /* r4 and r5 are local variables,
  2. lr needed when we do the syscall */
  3. /* r4 -- saved lock address */
  4. ldr r4, [r0]
  5. /* Here we load the utcb address */
  6. mov r3, #0xff000000
  7. /* r5 -- saved UTCB address ,liunote see arch\arm\libs\l4\include\vregs.h */
  8. ldr r5, [r3, #0xff0]        /* uctb => 0xff000ff0 */
  9. /* From here r4 and r5 are safe, the thread_switch
  10. syscall will not trash these registers */
  11. /* r0 is tmp */
  12. /* First we set the point at which we want to
  13. be restarted in case of preemption */
  14. adr r0, preempt_handler
  15. str r0, [r5, #__L4_TCR_PREEMPT_CALLBACK_IP*4] /* preempt_callback_ip */
  16. /* And then we enable the preemption callback to
  17. occur */
  18. mov r0, #32
  19. strb r0, [r5, #TCR_PREEMPT_FLAGS] /* arch\arm\libs\l4\include\vregs.h __L4_TCR_PREEMPT_FLAGS 's last byte !!! */
  20. LABEL(preempt_handler) /* If preempt we restart here */
  21. /* r0 is lock holder */
  22. ldr r0, [r4]
  23. /* r1 is me (real tid is in the user-defined handle)*/
  24. ldr r1, [r5, #__L4_TCR_USER_DEFINED_HANDLE*4]
  25. /* test if lock holder is == 0 */
  26. cmp r0, #0 /* mutex-> fHolder 为0,表示没有被占*/
  27. beq grab_lock /* liunote , get lock ok !!! */
  28. /* or if lock holder is me */
  29. cmp r0, r1
  30. beq exit_path /* We already have the lock so we jump forward to
  31. the part where we turn off preemption and return */
  32. /* we couldn't get the lock so we fall through to here */
  33. /* r0 holds lock holder, will be argument to the system call */
  34. /* r1 is temp */
  35. /* Load syscall ptr */ /* liunote : r0 is lock holder (mutex-> fHolder), 然后L4_ThreadSwitch 切换到lock holer 去了 */
  36. ldr ip, =L4_ThreadSwitch
  37. mov r1, #1
  38. str r1, [r4, #4] /* Let current lock holder know there is contention liunote [r4,#4] ==> mutex -> fNeeded =1 ,让目前holder 住的thread 知道有其他mutex 请求
  39. so that it knows to yield at the end of its timeslice , 这样时间片到了要放弃,或者unlock muxtex时主动放弃*/
  40. /* Load branch address */
  41. ldr ip, [ip]
  42. stmdb sp!, {r4-r11}
  43. mov lr, pc
  44. /* do the system call */
  45. mov pc, ip
  46. ldmia sp!, {r4-r11}
  47. /* After syscall return to preempt_handler */ /* 没有lock 住的thread 到这里thread switch , 然后会切回来继续执行lock !!! */
  48. b preempt_handler
  49. LABEL(grab_lock)
  50. /* The lock is free -- we try to grab it before being preempted */
  51. /* r0 is tmp */
  52. mov r0, #0
  53. str r0, [r4, #4] /* If we get this far, then noone of a higher priority than liunote [r4,#4] ==> mutex -> fNeeded =0
  54. us wants the lock, so we can unset the yield needed flag */
  55. /* Now we store ourself as the lock handler, this is transaction complete, although
  56. we still might be preempted right here, in which case we validaly have the lock
  57. and the preempt handler will go through sucessfully */
  58. str r1, [r4] /* mutex-> fHolder = thread user define handler (__L4_TCR_USER_DEFINED_HANDLE) !!! */
  59. strb r0, [r5, #TCR_PREEMPT_FLAGS] /* liunote 设置utcb的__L4_TCR_PREEMPT_FLAGS 最后1byte 为0 */
  60. ldmia sp!, {r4, r5, pc} /* RETURN POINT */
  61. LABEL(exit_path)
  62. /* Exit path that occurs if we were preempted, before returning --
  63. same as above, however we need to zero, r0 first */
  64. mov r0, #0
  65. strb r0, [r5, #TCR_PREEMPT_FLAGS]
  66. ldmia sp!, {r4, r5, pc} /* RETURN POINT */

 

mutex unlock 的实现很简单:

 

  1. struct mutex *mtx = (struct mutex *) *mutex;
  2.     mtx->fHolder = 0;

  3.     if (mtx->fNeeded) {
  4.     mtx->fNeeded = 0;
  5.     L4_ThreadSwitch(L4_nilthread); /*
  6.     }

 

关于L4_ThreadSwitch 切到nil thread,表示放弃运行,交由系统调度

 

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP