idle.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:3k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Idle daemon for PowerPC.  Idle daemon will handle any action
  3.  * that needs to be taken when the system becomes idle.
  4.  *
  5.  * Written by Cort Dougan (cort@cs.nmt.edu)
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License
  9.  * as published by the Free Software Foundation; either version
  10.  * 2 of the License, or (at your option) any later version.
  11.  */
  12. #include <linux/config.h>
  13. #include <linux/errno.h>
  14. #include <linux/sched.h>
  15. #include <linux/kernel.h>
  16. #include <linux/mm.h>
  17. #include <linux/smp.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/stddef.h>
  20. #include <linux/unistd.h>
  21. #include <linux/ptrace.h>
  22. #include <linux/slab.h>
  23. #include <asm/pgtable.h>
  24. #include <asm/uaccess.h>
  25. #include <asm/system.h>
  26. #include <asm/io.h>
  27. #include <asm/processor.h>
  28. #include <asm/mmu.h>
  29. #include <asm/cache.h>
  30. #include <asm/time.h>
  31. #include <asm/iSeries/LparData.h>
  32. #include <asm/iSeries/HvCall.h>
  33. #include <asm/iSeries/ItLpQueue.h>
  34. unsigned long maxYieldTime = 0;
  35. unsigned long minYieldTime = 0xffffffffffffffffUL;
  36. #ifdef CONFIG_PPC_ISERIES
  37. static void yield_shared_processor(void)
  38. {
  39. struct paca_struct *lpaca = get_paca();
  40. unsigned long tb;
  41. unsigned long yieldTime;
  42. HvCall_setEnabledInterrupts( HvCall_MaskIPI |
  43.      HvCall_MaskLpEvent |
  44.      HvCall_MaskLpProd |
  45.      HvCall_MaskTimeout );
  46. tb = get_tb();
  47. /* Compute future tb value when yield should expire */
  48. HvCall_yieldProcessor( HvCall_YieldTimed, tb+tb_ticks_per_jiffy );
  49. yieldTime = get_tb() - tb;
  50. if ( yieldTime > maxYieldTime )
  51. maxYieldTime = yieldTime;
  52. if ( yieldTime < minYieldTime )
  53. minYieldTime = yieldTime;
  54. /* The decrementer stops during the yield.  Force a fake decrementer
  55.  * here and let the timer_interrupt code sort out the actual time.
  56.  */
  57. lpaca->xLpPaca.xIntDword.xFields.xDecrInt = 1;
  58. process_iSeries_events();
  59. }
  60. #endif /* CONFIG_PPC_ISERIES */
  61. int idled(void)
  62. {
  63. struct paca_struct *lpaca;
  64. long oldval;
  65. #ifdef CONFIG_PPC_ISERIES
  66. unsigned long CTRL;
  67. #endif
  68. /* endless loop with no priority at all */
  69. current->nice = 20;
  70. current->counter = -100;
  71. #ifdef CONFIG_PPC_ISERIES
  72. /* ensure iSeries run light will be out when idle */
  73. current->thread.flags &= ~PPC_FLAG_RUN_LIGHT;
  74. CTRL = mfspr(CTRLF);
  75. CTRL &= ~RUNLATCH;
  76. mtspr(CTRLT, CTRL);
  77. #endif
  78. init_idle();
  79. lpaca = get_paca();
  80. for (;;) {
  81. #ifdef CONFIG_PPC_ISERIES
  82. if ( lpaca->xLpPaca.xSharedProc ) {
  83. if ( ItLpQueue_isLpIntPending( lpaca->lpQueuePtr ) )
  84. process_iSeries_events();
  85. if ( !current->need_resched )
  86. yield_shared_processor();
  87. }
  88. else 
  89. #endif
  90. {
  91. /* Avoid an IPI by setting need_resched */
  92. oldval = xchg(&current->need_resched, -1);
  93. if (!oldval) {
  94. while(current->need_resched == -1) {
  95. #ifdef CONFIG_PPC_ISERIES
  96. HMT_medium();
  97. if ( ItLpQueue_isLpIntPending( lpaca->lpQueuePtr ) )
  98. process_iSeries_events();
  99. #endif
  100. HMT_low();
  101. }
  102. }
  103. }
  104. HMT_medium();
  105. if (current->need_resched) {
  106. schedule();
  107. check_pgt_cache();
  108. }
  109. }
  110. return 0;
  111. }
  112. /*
  113.  * SMP entry into the idle task - calls the same thing as the
  114.  * non-smp versions. -- Cort
  115.  */
  116. int cpu_idle(void)
  117. {
  118. idled();
  119. return 0; 
  120. }