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

📄 smp.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	send_IPI_single(cpuid, IPI_CALL_FUNC);	/*  Wait for response  */	timeout = jiffies + HZ;	while ((atomic_read(&data.unstarted_count) > 0) && time_before(jiffies, timeout))		barrier();	if (atomic_read(&data.unstarted_count) > 0) {#if (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC))		goto resend;#else		smp_call_function_data = NULL;		return -ETIMEDOUT;#endif	}	if (wait)		while (atomic_read(&data.unfinished_count) > 0)			barrier();	/* unlock pointer */	smp_call_function_data = NULL;	return 0;}/* * Run a function on all other CPUs. *  <func>	The function to run. This must be fast and non-blocking. *  <info>	An arbitrary pointer to pass to the function. *  <retry>	If true, keep retrying until ready. *  <wait>	If true, wait 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. */intsmp_call_function (void (*func) (void *info), void *info, int retry, int wait){	struct smp_call_struct data;	unsigned long timeout;	int cpus = smp_num_cpus - 1;	if (cpus == 0)		return 0;		data.func = func;	data.info = info;	data.wait = wait;	atomic_set(&data.unstarted_count, cpus);	atomic_set(&data.unfinished_count, cpus);	if (pointer_lock(&smp_call_function_data, &data, retry))		return -EBUSY;	/*  Send a message to all other CPUs and wait for them to respond  */	send_IPI_allbutself(IPI_CALL_FUNC);retry:	/*  Wait for response  */	timeout = jiffies + HZ;	while ((atomic_read(&data.unstarted_count) > 0) && time_before(jiffies, timeout))		barrier();	if (atomic_read(&data.unstarted_count) > 0) {#if (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC))		int i;		for (i = 0; i < smp_num_cpus; i++) {			if (i != smp_processor_id())				platform_send_ipi(i, IPI_IRQ, IA64_IPI_DM_INT, 0);		}		goto retry;#else		smp_call_function_data = NULL;		return -ETIMEDOUT;#endif	}	if (wait)		while (atomic_read(&data.unfinished_count) > 0)			barrier();	/* unlock pointer */	smp_call_function_data = NULL;	return 0;}/* * Flush all other CPU's tlb and then mine.  Do this with smp_call_function() as we * want to ensure all TLB's flushed before proceeding. */voidsmp_flush_tlb_all(void){	smp_call_function((void (*)(void *))__flush_tlb_all, NULL, 1, 1);	__flush_tlb_all();}/* * Ideally sets up per-cpu profiling hooks.  Doesn't do much now... */static inline void __initsmp_setup_percpu_timer(int cpuid){        cpu_data[cpuid].prof_counter = 1;        cpu_data[cpuid].prof_multiplier = 1;}void smp_do_timer(struct pt_regs *regs){        int cpu = smp_processor_id();        int user = user_mode(regs);	struct cpuinfo_ia64 *data = &cpu_data[cpu];        if (--data->prof_counter <= 0) {		data->prof_counter = data->prof_multiplier;		update_process_times(user);	}}/* * AP's start using C here. */void __initsmp_callin (void) {	extern void ia64_rid_init(void);	extern void ia64_init_itm(void);	extern void ia64_cpu_local_tick(void);#ifdef CONFIG_PERFMON	extern void perfmon_init_percpu(void);#endif	int cpu = smp_processor_id();	if (test_and_set_bit(cpu, &cpu_online_map)) {		printk("CPU#%d already initialized!\n", cpu);		machine_halt();	}  	efi_map_pal_code();	cpu_init();	smp_setup_percpu_timer(cpu);	/* setup the CPU local timer tick */	ia64_init_itm();#ifdef CONFIG_PERFMON	perfmon_init_percpu();#endif	/* Disable all local interrupts */	ia64_set_lrr0(0, 1);		ia64_set_lrr1(0, 1);		local_irq_enable();		/* Interrupts have been off until now */	calibrate_delay();	my_cpu_data.loops_per_jiffy = loops_per_jiffy;	/* allow the master to continue */	set_bit(cpu, &cpu_callin_map);	/* finally, wait for the BP to finish initialization: */	while (!smp_commenced);	cpu_idle(NULL);}/* * Create the idle task for a new AP.  DO NOT use kernel_thread() because * that could end up calling schedule() in the ia64_leave_kernel exit * path in which case the new idle task could get scheduled before we * had a chance to remove it from the run-queue... */static int __init fork_by_hand(void){	/*	 * Don't care about the usp and regs settings since we'll never	 * reschedule the forked task.	 */	return do_fork(CLONE_VM|CLONE_PID, 0, 0, 0);}/* * Bring one cpu online.  Return 0 if this fails for any reason. */static int __initsmp_boot_one_cpu(int cpu){	struct task_struct *idle;	int cpu_phys_id = cpu_physical_id(cpu);	long timeout;	/* 	 * Create an idle task for this CPU.  Note that the address we	 * give to kernel_thread is irrelevant -- it's going to start	 * where OS_BOOT_RENDEVZ vector in SAL says to start.  But	 * this gets all the other task-y sort of data structures set	 * up like we wish.   We need to pull the just created idle task 	 * off the run queue and stuff it into the init_tasks[] array.  	 * Sheesh . . .	 */	if (fork_by_hand() < 0) 		panic("failed fork for CPU 0x%x", cpu_phys_id);	/*	 * We remove it from the pidhash and the runqueue	 * once we got the process:	 */	idle = init_task.prev_task;	if (!idle)		panic("No idle process for CPU 0x%x", cpu_phys_id);	init_tasks[cpu] = idle;	del_from_runqueue(idle);        unhash_process(idle);	/* Schedule the first task manually.  */	idle->processor = cpu;	idle->has_cpu = 1;	/* Let _start know what logical CPU we're booting (offset into init_tasks[] */	cpu_now_booting = cpu;	/* Kick the AP in the butt */	platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);	/* wait up to 10s for the AP to start  */	for (timeout = 0; timeout < 100000; timeout++) {		if (test_bit(cpu, &cpu_callin_map))			return 1;		udelay(100);	}	printk(KERN_ERR "SMP: Processor 0x%x is stuck.\n", cpu_phys_id);	return 0;}/* * Called by smp_init bring all the secondaries online and hold them.   * XXX: this is ACPI specific; it uses "magic" variables exported from acpi.c  *      to 'discover' the AP's.  Blech. */void __initsmp_boot_cpus(void){	int i, cpu_count = 1;	unsigned long bogosum;	/* Take care of some initial bookkeeping.  */	memset(&__cpu_physical_id, -1, sizeof(__cpu_physical_id));	memset(&ipi_op, 0, sizeof(ipi_op));	/* Setup BP mappings */	__cpu_physical_id[0] = hard_smp_processor_id();	/* on the BP, the kernel already called calibrate_delay_loop() in init/main.c */	my_cpu_data.loops_per_jiffy = loops_per_jiffy;#if 0	smp_tune_scheduling();#endif 	smp_setup_percpu_timer(0);	if (test_and_set_bit(0, &cpu_online_map)) {		printk("CPU#%d already initialized!\n", smp_processor_id());		machine_halt();	}  	init_idle();	/* Nothing to do when told not to.  */	if (max_cpus == 0) {	        printk(KERN_INFO "SMP mode deactivated.\n");		return;	}	if (max_cpus != -1) 		printk("Limiting CPUs to %d\n", max_cpus);	if (smp_boot_data.cpu_count > 1) {		printk(KERN_INFO "SMP: starting up secondaries.\n");		for (i = 0; i < smp_boot_data.cpu_count; i++) {			/* skip performance restricted and bootstrap cpu: */			if (smp_boot_data.cpu_phys_id[i] == -1			    || smp_boot_data.cpu_phys_id[i] == hard_smp_processor_id())				continue;			cpu_physical_id(cpu_count) = smp_boot_data.cpu_phys_id[i];			if (!smp_boot_one_cpu(cpu_count))				continue;	/* failed */			cpu_count++; /* Count good CPUs only... */			/* 			 * Bail if we've started as many CPUS as we've been told to.			 */			if (cpu_count == max_cpus)				break;		}	}	if (cpu_count == 1) {		printk(KERN_ERR "SMP: Bootstrap processor only.\n");	}	bogosum = 0;        for (i = 0; i < NR_CPUS; i++) {		if (cpu_online_map & (1L << i))			bogosum += cpu_data[i].loops_per_jiffy;        }	printk(KERN_INFO "SMP: Total of %d processors activated (%lu.%02lu BogoMIPS).\n",	       cpu_count, bogosum*HZ/500000, (bogosum*HZ/5000) % 100);	smp_num_cpus = cpu_count;}/*  * Called when the BP is just about to fire off init. */void __init smp_commence(void){	smp_commenced = 1;}int __initsetup_profiling_timer(unsigned int multiplier){        return -EINVAL;}/* * Assume that CPU's have been discovered by some platform-dependant * interface.  For SoftSDV/Lion, that would be ACPI. * * Setup of the IPI irq handler is done in irq.c:init_IRQ_SMP(). * * This also registers the AP OS_MC_REDVEZ address with SAL. */void __initinit_smp_config(void){	struct fptr {		unsigned long fp;		unsigned long gp;	} *ap_startup;	long sal_ret;	/* Tell SAL where to drop the AP's.  */	ap_startup = (struct fptr *) start_ap;	sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ,				       __pa(ap_startup->fp), __pa(ap_startup->gp), 0, 				       0, 0, 0);	if (sal_ret < 0) {		printk("SMP: Can't set SAL AP Boot Rendezvous: %s\n", ia64_sal_strerror(sal_ret));		printk("     Forcing UP mode\n");		max_cpus = 0;		smp_num_cpus = 1; 	}}

⌨️ 快捷键说明

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