⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Date       Who Description * ---------- --- -------------------------------------------------------- * *==========================================================================*/void smp_invalidate_interrupt(void){	int cpu_id = smp_processor_id();	unsigned long *mmc = &flush_mm->context[cpu_id];	if (!cpu_isset(cpu_id, flush_cpumask))		return;	if (flush_va == FLUSH_ALL) {		*mmc = NO_CONTEXT;		if (flush_mm == current->active_mm)			activate_context(flush_mm);		else			cpu_clear(cpu_id, flush_mm->cpu_vm_mask);	} else {		unsigned long va = flush_va;		if (*mmc != NO_CONTEXT) {			va &= PAGE_MASK;			va |= (*mmc & MMU_CONTEXT_ASID_MASK);			__flush_tlb_page(va);		}	}	cpu_clear(cpu_id, flush_cpumask);}/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*//* Stop CPU request Routins                                                 *//*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*//*==========================================================================* * Name:         smp_send_stop * * Description:  This routine requests stop all CPUs. *               1.Request other CPU to execute 'stop_this_cpu()'. * * Born on Date: 2002.02.05 * * Arguments:    NONE * * Returns:      void (cannot fail) * * Modification log: * Date       Who Description * ---------- --- -------------------------------------------------------- * *==========================================================================*/void smp_send_stop(void){	smp_call_function(stop_this_cpu, NULL, 1, 0);}/*==========================================================================* * Name:         stop_this_cpu * * Description:  This routine halt CPU. * * Born on Date: 2002.02.05 * * Arguments:    NONE * * Returns:      void (cannot fail) * * Modification log: * Date       Who Description * ---------- --- -------------------------------------------------------- * *==========================================================================*/static void stop_this_cpu(void *dummy){	int cpu_id = smp_processor_id();	/*	 * Remove this CPU:	 */	cpu_clear(cpu_id, cpu_online_map);	/*	 * PSW IE = 1;	 * IMASK = 0;	 * goto SLEEP	 */	local_irq_disable();	outl(0, M32R_ICU_IMASK_PORTL);	inl(M32R_ICU_IMASK_PORTL);	/* dummy read */	local_irq_enable();	for ( ; ; );}/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*//* Call function Routins                                                     *//*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*//*==========================================================================* * Name:         smp_call_function * * Description:  This routine sends a 'CALL_FUNCTION_IPI' to all other CPUs *               in the system. * * Born on Date: 2002.02.05 * * Arguments:    *func - The function to run. This must be fast and *                       non-blocking. *               *info - An arbitrary pointer to pass to the function. *               nonatomic - currently unused. *               wait - If true, wait (atomically) until function has *                      completed on other CPUs. * * Returns:      0 on success, else a negative status code. Does not return *               until remote CPUs are nearly ready to execute <<func>> or *               are or have executed. * * Cautions:     You must not call this function with disabled interrupts or *               from a hardware interrupt handler, you may call it from a *               bottom half handler. * * Modification log: * Date       Who Description * ---------- --- -------------------------------------------------------- * *==========================================================================*/int smp_call_function(void (*func) (void *info), void *info, int nonatomic,	int wait){	struct call_data_struct data;	int cpus;#ifdef DEBUG_SMP	unsigned long flags;	__save_flags(flags);	if (!(flags & 0x0040))	/* Interrupt Disable NONONO */		BUG();#endif /* DEBUG_SMP */	/* Holding any lock stops cpus from going down. */	spin_lock(&call_lock);	cpus = num_online_cpus() - 1;	if (!cpus) {		spin_unlock(&call_lock);		return 0;	}	/* Can deadlock when called with interrupts disabled */	WARN_ON(irqs_disabled());	data.func = func;	data.info = info;	atomic_set(&data.started, 0);	data.wait = wait;	if (wait)		atomic_set(&data.finished, 0);	call_data = &data;	mb();	/* Send a message to all other CPUs and wait for them to respond */	send_IPI_allbutself(CALL_FUNCTION_IPI, 0);	/* Wait for response */	while (atomic_read(&data.started) != cpus)		barrier();	if (wait)		while (atomic_read(&data.finished) != cpus)			barrier();	spin_unlock(&call_lock);	return 0;}/*==========================================================================* * Name:         smp_call_function_interrupt * * Description:  This routine executes on CPU which received *               'CALL_FUNCTION_IPI'. * * Born on Date: 2002.02.05 * * Arguments:    NONE * * Returns:      void (cannot fail) * * Modification log: * Date       Who Description * ---------- --- -------------------------------------------------------- * *==========================================================================*/void smp_call_function_interrupt(void){	void (*func) (void *info) = call_data->func;	void *info = call_data->info;	int wait = call_data->wait;	/*	 * Notify initiating CPU that I've grabbed the data and am	 * about to execute the function	 */	mb();	atomic_inc(&call_data->started);	/*	 * At this point the info structure may be out of scope unless wait==1	 */	irq_enter();	(*func)(info);	irq_exit();	if (wait) {		mb();		atomic_inc(&call_data->finished);	}}/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*//* Timer Routins                                                             *//*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*//*==========================================================================* * Name:         smp_send_timer * * Description:  This routine sends a 'LOCAL_TIMER_IPI' to all other CPUs *               in the system. * * Born on Date: 2002.02.05 * * Arguments:    NONE * * Returns:      void (cannot fail) * * Modification log: * Date       Who Description * ---------- --- -------------------------------------------------------- * *==========================================================================*/void smp_send_timer(void){	send_IPI_allbutself(LOCAL_TIMER_IPI, 1);}/*==========================================================================* * Name:         smp_send_timer * * Description:  This routine executes on CPU which received *               'LOCAL_TIMER_IPI'. * * Born on Date: 2002.02.05 * * Arguments:    *regs - a pointer to the saved regster info * * Returns:      void (cannot fail) * * Modification log: * Date       Who Description * ---------- --- -------------------------------------------------------- * *==========================================================================*/void smp_ipi_timer_interrupt(struct pt_regs *regs){	irq_enter();	smp_local_timer_interrupt(regs);	irq_exit();}/*==========================================================================* * Name:         smp_local_timer_interrupt * * Description:  Local timer interrupt handler. It does both profiling and *               process statistics/rescheduling. *               We do profiling in every local tick, statistics/rescheduling *               happen only every 'profiling multiplier' ticks. The default *               multiplier is 1 and it can be changed by writing the new *               multiplier value into /proc/profile. * * Born on Date: 2002.02.05 * * Arguments:    *regs - a pointer to the saved regster info * * Returns:      void (cannot fail) * * Original:     arch/i386/kernel/apic.c * * Modification log: * Date       Who Description * ---------- --- -------------------------------------------------------- * 2003-06-24 hy  use per_cpu structure. *==========================================================================*/void smp_local_timer_interrupt(struct pt_regs *regs){	int user = user_mode(regs);	int cpu_id = smp_processor_id();	/*	 * The profiling function is SMP safe. (nothing can mess	 * around with "current", and the profiling counters are	 * updated with atomic operations). This is especially	 * useful with a profiling multiplier != 1	 */	profile_tick(CPU_PROFILING, regs);	if (--per_cpu(prof_counter, cpu_id) <= 0) {		/*		 * The multiplier may have changed since the last time we got		 * to this point as a result of the user writing to		 * /proc/profile. In this case we need to adjust the APIC		 * timer accordingly.		 *		 * Interrupts are already masked off at this point.		 */		per_cpu(prof_counter, cpu_id)			= per_cpu(prof_multiplier, cpu_id);		if (per_cpu(prof_counter, cpu_id)			!= per_cpu(prof_old_multiplier, cpu_id))		{			per_cpu(prof_old_multiplier, cpu_id)				= per_cpu(prof_counter, cpu_id);		}		update_process_times(user);	}}/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*//* Send IPI Routins                                                          *//*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*//*==========================================================================* * Name:         send_IPI_allbutself * * Description:  This routine sends a IPI to all other CPUs in the system. * * Born on Date: 2002.02.05 * * Arguments:    ipi_num - Number of IPI *               try -  0 : Send IPI certainly. *                     !0 : The following IPI is not sended when Target CPU *                          has not received the before IPI. * * Returns:      void (cannot fail) * * Modification log: * Date       Who Description * ---------- --- -------------------------------------------------------- * *==========================================================================*/void send_IPI_allbutself(int ipi_num, int try){	cpumask_t cpumask;	cpumask = cpu_online_map;	cpu_clear(smp_processor_id(), cpumask);	send_IPI_mask(cpumask, ipi_num, try);}/*==========================================================================* * Name:         send_IPI_mask * * Description:  This routine sends a IPI to CPUs in the system. * * Born on Date: 2002.02.05 * * Arguments:    cpu_mask - Bitmap of target CPUs logical ID *               ipi_num - Number of IPI *               try -  0 : Send IPI certainly. *                     !0 : The following IPI is not sended when Target CPU *                          has not received the before IPI. * * Returns:      void (cannot fail) * * Modification log: * Date       Who Description * ---------- --- -------------------------------------------------------- * *==========================================================================*/static void send_IPI_mask(cpumask_t cpumask, int ipi_num, int try){	cpumask_t physid_mask, tmp;	int cpu_id, phys_id;	int num_cpus = num_online_cpus();	if (num_cpus <= 1)	/* NO MP */		return;	cpus_and(tmp, cpumask, cpu_online_map);	BUG_ON(!cpus_equal(cpumask, tmp));	physid_mask = CPU_MASK_NONE;	for_each_cpu_mask(cpu_id, cpumask){		if ((phys_id = cpu_to_physid(cpu_id)) != -1)			cpu_set(phys_id, physid_mask);	}	send_IPI_mask_phys(physid_mask, ipi_num, try);}/*==========================================================================* * Name:         send_IPI_mask_phys * * Description:  This routine sends a IPI to other CPUs in the system. * * Born on Date: 2002.02.05 * * Arguments:    cpu_mask - Bitmap of target CPUs physical ID *               ipi_num - Number of IPI *               try -  0 : Send IPI certainly. *                     !0 : The following IPI is not sended when Target CPU *                          has not received the before IPI. * * Returns:      IPICRi regster value. * * Modification log: * Date       Who Description * ---------- --- -------------------------------------------------------- * *==========================================================================*/unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num,	int try){	spinlock_t *ipilock;	volatile unsigned long *ipicr_addr;	unsigned long ipicr_val;	unsigned long my_physid_mask;	unsigned long mask = cpus_addr(physid_mask)[0];	if (mask & ~physids_coerce(phys_cpu_present_map))		BUG();	if (ipi_num >= NR_IPIS)		BUG();	mask <<= IPI_SHIFT;	ipilock = &ipi_lock[ipi_num];	ipicr_addr = (volatile unsigned long *)(M32R_ICU_IPICR_ADDR		+ (ipi_num << 2));	my_physid_mask = ~(1 << smp_processor_id());	/*	 * lock ipi_lock[i]	 * check IPICRi == 0	 * write IPICRi (send IPIi)	 * unlock ipi_lock[i]	 */	spin_lock(ipilock);	__asm__ __volatile__ (		";; CHECK IPICRi == 0		\n\t"		".fillinsn			\n"		"1:				\n\t"		"ld	%0, @%1			\n\t"		"and	%0, %4			\n\t"		"beqz	%0, 2f			\n\t"		"bnez	%3, 3f			\n\t"		"bra	1b			\n\t"		";; WRITE IPICRi (send IPIi)	\n\t"		".fillinsn			\n"		"2:				\n\t"		"st	%2, @%1			\n\t"		".fillinsn			\n"		"3:				\n\t"		: "=&r"(ipicr_val)		: "r"(ipicr_addr), "r"(mask), "r"(try), "r"(my_physid_mask)		: "memory"	);	spin_unlock(ipilock);	return ipicr_val;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -