Пример #1
0
static inline void dedicated_idle_sleep(unsigned int cpu)
{
	struct paca_struct *ppaca = &paca[cpu ^ 1];

	/* Only sleep if the other thread is not idle */
	if (!(ppaca->lppaca.idle)) {
		local_irq_disable();

		/*
		 * We are about to sleep the thread and so wont be polling any
		 * more.
		 */
		clear_thread_flag(TIF_POLLING_NRFLAG);

		/*
		 * SMT dynamic mode. Cede will result in this thread going
		 * dormant, if the partner thread is still doing work.  Thread
		 * wakes up if partner goes idle, an interrupt is presented, or
		 * a prod occurs.  Returning from the cede enables external
		 * interrupts.
		 */
		if (!need_resched())
			cede_processor();
		else
			local_irq_enable();
	} else {
		/*
		 * Give the HV an opportunity at the processor, since we are
		 * not doing any work.
		 */
		poll_pending();
	}
}
Пример #2
0
int dedicated_idle(void)
{
	long oldval;
	struct paca_struct *lpaca = get_paca(), *ppaca;
	unsigned long start_snooze;
	unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
	unsigned int cpu = smp_processor_id();

	ppaca = &paca[cpu ^ 1];

	while (1) {
		/*
		 * Indicate to the HV that we are idle. Now would be
		 * a good time to find other work to dispatch.
		 */
		lpaca->lppaca.xIdle = 1;

		oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
		if (!oldval) {
			set_thread_flag(TIF_POLLING_NRFLAG);
			start_snooze = __get_tb() +
				*smt_snooze_delay * tb_ticks_per_usec;
			while (!need_resched() && !cpu_is_offline(cpu)) {
				/*
				 * Go into low thread priority and possibly
				 * low power mode.
				 */
				HMT_low();
				HMT_very_low();

				if (*smt_snooze_delay == 0 ||
				    __get_tb() < start_snooze)
					continue;

				HMT_medium();

				if (!(ppaca->lppaca.xIdle)) {
					local_irq_disable();

					/*
					 * We are about to sleep the thread
					 * and so wont be polling any
					 * more.
					 */
					clear_thread_flag(TIF_POLLING_NRFLAG);

					/*
					 * SMT dynamic mode. Cede will result
					 * in this thread going dormant, if the
					 * partner thread is still doing work.
					 * Thread wakes up if partner goes idle,
					 * an interrupt is presented, or a prod
					 * occurs.  Returning from the cede
					 * enables external interrupts.
					 */
					if (!need_resched())
						cede_processor();
					else
						local_irq_enable();
				} else {
					/*
					 * Give the HV an opportunity at the
					 * processor, since we are not doing
					 * any work.
					 */
					poll_pending();
				}
			}

			clear_thread_flag(TIF_POLLING_NRFLAG);
		} else {
			set_need_resched();
		}

		HMT_medium();
		lpaca->lppaca.xIdle = 0;
		schedule();
		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
			cpu_die();
	}
	return 0;
}