Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393758
  • 博文数量: 53
  • 博客积分: 1910
  • 博客等级: 中尉
  • 技术积分: 1130
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-10 14:56
文章分类

全部博文(53)

文章存档

2013年(1)

2012年(17)

2011年(33)

2010年(2)

分类: 嵌入式

2011-07-26 08:47:14

    只有多任务系统才需要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,表示放弃运行,交由系统调度

 

阅读(1787) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~