示例#1
0
static void tasklet_hi_action(struct softirq_action *a)
{
	struct tasklet_struct *list;

	local_irq_disable();
	list = __this_cpu_read(tasklet_hi_vec.head);
	__this_cpu_write(tasklet_hi_vec.head, NULL);
	__this_cpu_write(tasklet_hi_vec.tail, &__get_cpu_var(tasklet_hi_vec).head);
	local_irq_enable();

	while (list) {
		struct tasklet_struct *t = list;

		list = list->next;

		if (tasklet_trylock(t)) {
			if (!atomic_read(&t->count)) {
#ifdef CONFIG_SEC_DEBUG_RT_THROTTLE_ACTIVE
				unsigned long long start_time, end_time;

				start_time = sec_debug_clock();
#endif
				if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
					BUG();
				sec_debug_softirq_log(9998, t->func, 7);
				t->func(t->data);
				sec_debug_softirq_log(9998, t->func, 8);
#ifdef CONFIG_SEC_DEBUG_RT_THROTTLE_ACTIVE
				end_time = sec_debug_clock();
				if (start_time + 950000000 < end_time) {
					sec_debug_aux_log(SEC_DEBUG_AUXLOG_IRQ, "TH:%llu %pf", start_time, t->func);
				}
#endif
				tasklet_unlock(t);
				continue;
			}
			tasklet_unlock(t);
		}

		local_irq_disable();
		t->next = NULL;
		*__this_cpu_read(tasklet_hi_vec.tail) = t;
		__this_cpu_write(tasklet_hi_vec.tail, &(t->next));
		__raise_softirq_irqoff(HI_SOFTIRQ);
		local_irq_enable();
	}
}
示例#2
0
asmlinkage void __do_softirq(void)
{
	struct softirq_action *h;
	__u32 pending;
	unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
	int cpu;
	unsigned long old_flags = current->flags;
	int max_restart = MAX_SOFTIRQ_RESTART;

	/*
	 * Mask out PF_MEMALLOC s current task context is borrowed for the
	 * softirq. A softirq handled such as network RX might set PF_MEMALLOC
	 * again if the socket is related to swap
	 */
	current->flags &= ~PF_MEMALLOC;

	pending = local_softirq_pending();
	account_irq_enter_time(current);

	__local_bh_disable((unsigned long)__builtin_return_address(0),
				SOFTIRQ_OFFSET);
	lockdep_softirq_enter();

	cpu = smp_processor_id();
restart:
	/* Reset the pending bitmask before enabling irqs */
	set_softirq_pending(0);

	local_irq_enable();

	h = softirq_vec;

	do {
		if (pending & 1) {
			unsigned int vec_nr = h - softirq_vec;
			int prev_count = preempt_count();
#ifdef CONFIG_SEC_DEBUG_RT_THROTTLE_ACTIVE
			unsigned long long start_time, end_time;

			start_time = sec_debug_clock();
#endif
			kstat_incr_softirqs_this_cpu(vec_nr);

			trace_softirq_entry(vec_nr);
			sec_debug_softirq_log(9999, h->action, 7);
			h->action(h);
			sec_debug_softirq_log(9999, h->action, 8);
			trace_softirq_exit(vec_nr);
#ifdef CONFIG_SEC_DEBUG_RT_THROTTLE_ACTIVE
			end_time = sec_debug_clock();
			if (start_time + 950000000 < end_time) {
				sec_debug_aux_log(SEC_DEBUG_AUXLOG_IRQ, "S:%llu %pf", start_time, h->action);
			}
#endif
			if (unlikely(prev_count != preempt_count())) {
				printk(KERN_ERR "huh, entered softirq %u %s %p"
				       "with preempt_count %08x,"
				       " exited with %08x?\n", vec_nr,
				       softirq_to_name[vec_nr], h->action,
				       prev_count, preempt_count());
				preempt_count() = prev_count;
			}

			rcu_bh_qs(cpu);
		}
		h++;
		pending >>= 1;
	} while (pending);

	local_irq_disable();

	pending = local_softirq_pending();
	if (pending) {
		if (time_before(jiffies, end) && !need_resched() &&
		    --max_restart)
			goto restart;

		wakeup_softirqd();
	}

	lockdep_softirq_exit();

	account_irq_exit_time(current);
	__local_bh_enable(SOFTIRQ_OFFSET);
	tsk_restore_flags(current, old_flags, PF_MEMALLOC);
}
irqreturn_t
handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
{
	irqreturn_t retval = IRQ_NONE;
	unsigned int flags = 0, irq = desc->irq_data.irq;

	do {
		irqreturn_t res;
#ifdef CONFIG_SEC_DEBUG_RT_THROTTLE_ACTIVE
		unsigned long long start_time, end_time;

		start_time = sec_debug_clock();
#endif
		sec_debug_irq_log(irq, (void *)action->handler, 1);
		trace_irq_handler_entry(irq, action);
		exynos_ss_irq(irq, (void *)action->handler, (int)irqs_disabled(), ESS_FLAG_IN);
		res = action->handler(irq, action->dev_id);
		exynos_ss_irq(irq, (void *)action->handler, (int)irqs_disabled(), ESS_FLAG_OUT);
		trace_irq_handler_exit(irq, action, res);
		sec_debug_irq_log(irq, (void *)action->handler, 2);
#ifdef CONFIG_SEC_DEBUG_RT_THROTTLE_ACTIVE
		end_time = sec_debug_clock();
		if (start_time + 950000000 < end_time) {
			sec_debug_aux_log(SEC_DEBUG_AUXLOG_IRQ, "I:%llu %pf", start_time, action->handler);
		}
#endif

		if (WARN_ONCE(!irqs_disabled(),"irq %u handler %pF enabled interrupts\n",
			      irq, action->handler))
			local_irq_disable();

		switch (res) {
		case IRQ_WAKE_THREAD:
			/*
			 * Catch drivers which return WAKE_THREAD but
			 * did not set up a thread function
			 */
			if (unlikely(!action->thread_fn)) {
				warn_no_thread(irq, action);
				break;
			}

			irq_wake_thread(desc, action);

			/* Fall through to add to randomness */
		case IRQ_HANDLED:
			flags |= action->flags;
			break;

		default:
			break;
		}

		retval |= res;
		action = action->next;
	} while (action);

	add_interrupt_randomness(irq, flags);

	if (!noirqdebug)
		note_interrupt(irq, desc, retval);
	return retval;
}