smp.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 727 行 · 第 1/2 页

C
727
字号
	/*  Send a message to all other CPUs and wait for them to respond  */	send_IPI_allbutself(IPI_CALL_FUNC);	/*  Wait for response  */	timeout = jiffies + HZ;	while ( (atomic_read (&data.unstarted_count) > 0) &&		time_before (jiffies, timeout) )		barrier ();	/* We either got one or timed out. Release the lock */	mb();	smp_call_function_data = NULL;	if (atomic_read (&data.unstarted_count) > 0) {		printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d)\n",		      smp_processor_id());		return -ETIMEDOUT;	}	while (wait && atomic_read (&data.unfinished_count) > 0)			barrier ();	return 0;}EXPORT_SYMBOL(smp_call_function);/* * Flush all other CPU's tlb and then mine.  Do this with on_each_cpu() * as we want to ensure all TLB's flushed before proceeding. */extern void flush_tlb_all_local(void);voidsmp_flush_tlb_all(void){	on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);}void smp_do_timer(struct pt_regs *regs){	int cpu = smp_processor_id();	struct cpuinfo_parisc *data = &cpu_data[cpu];        if (!--data->prof_counter) {		data->prof_counter = data->prof_multiplier;		update_process_times(user_mode(regs));	}}/* * Called by secondaries to update state and initialize CPU registers. */static void __initsmp_cpu_init(int cpunum){	extern int init_per_cpu(int);  /* arch/parisc/kernel/setup.c */	extern void init_IRQ(void);    /* arch/parisc/kernel/irq.c */	/* Set modes and Enable floating point coprocessor */	(void) init_per_cpu(cpunum);	disable_sr_hashing();	mb();	/* Well, support 2.4 linux scheme as well. */	if (cpu_test_and_set(cpunum, cpu_online_map))	{		extern void machine_halt(void); /* arch/parisc.../process.c */		printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum);		machine_halt();	}  	/* Initialise the idle task for this CPU */	atomic_inc(&init_mm.mm_count);	current->active_mm = &init_mm;	if(current->mm)		BUG();	enter_lazy_tlb(&init_mm, current);	init_IRQ();   /* make sure no IRQ's are enabled or pending */}/* * Slaves start using C here. Indirectly called from smp_slave_stext. * Do what start_kernel() and main() do for boot strap processor (aka monarch) */void __init smp_callin(void){	extern void cpu_idle(void);	/* arch/parisc/kernel/process.c */	int slave_id = cpu_now_booting;#if 0	void *istack;#endif	smp_cpu_init(slave_id);#if 0	/* NOT WORKING YET - see entry.S */	istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER);	if (istack == NULL) {	    printk(KERN_CRIT "Failed to allocate interrupt stack for cpu %d\n",slave_id);	    BUG();	}	mtctl(istack,31);#endif	flush_cache_all_local(); /* start with known state */	flush_tlb_all_local();	local_irq_enable();  /* Interrupts have been off until now */	cpu_idle();      /* Wait for timer to schedule some work */	/* NOTREACHED */	panic("smp_callin() AAAAaaaaahhhh....\n");}/* * Bring one cpu online. */int __init smp_boot_one_cpu(int cpuid){	struct task_struct *idle;	long timeout;	/* 	 * Create an idle task for this CPU.  Note the address wed* 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 . . .	 */	idle = fork_idle(cpuid);	if (IS_ERR(idle))		panic("SMP: fork failed for CPU:%d", cpuid);	idle->thread_info->cpu = cpuid;	/* Let _start know what logical CPU we're booting	** (offset into init_tasks[],cpu_data[])	*/	cpu_now_booting = cpuid;	/* 	** boot strap code needs to know the task address since	** it also contains the process stack.	*/	smp_init_current_idle_task = idle ;	mb();	printk("Releasing cpu %d now, hpa=%lx\n", cpuid, cpu_data[cpuid].hpa);	/*	** This gets PDC to release the CPU from a very tight loop.	**	** From the PA-RISC 2.0 Firmware Architecture Reference Specification:	** "The MEM_RENDEZ vector specifies the location of OS_RENDEZ which 	** is executed after receiving the rendezvous signal (an interrupt to 	** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the 	** contents of memory are valid."	*/	__raw_writel(IRQ_OFFSET(TIMER_IRQ), cpu_data[cpuid].hpa);	mb();	/* 	 * OK, wait a bit for that CPU to finish staggering about. 	 * Slave will set a bit when it reaches smp_cpu_init().	 * Once the "monarch CPU" sees the bit change, it can move on.	 */	for (timeout = 0; timeout < 10000; timeout++) {		if(cpu_online(cpuid)) {			/* Which implies Slave has started up */			cpu_now_booting = 0;			smp_init_current_idle_task = NULL;			goto alive ;		}		udelay(100);		barrier();	}	put_task_struct(idle);	idle = NULL;	printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid);	return -1;alive:	/* Remember the Slave data */#if (kDEBUG>=100)	printk(KERN_DEBUG "SMP: CPU:%d came alive after %ld _us\n",		cpuid, timeout * 100);#endif /* kDEBUG */#ifdef ENTRY_SYS_CPUS	cpu_data[cpuid].state = STATE_RUNNING;#endif	return 0;}void __devinit smp_prepare_boot_cpu(void){	int bootstrap_processor=cpu_data[0].cpuid;	/* CPU ID of BSP */#ifdef ENTRY_SYS_CPUS	cpu_data[0].state = STATE_RUNNING;#endif	/* Setup BSP mappings */	printk("SMP: bootstrap CPU ID is %d\n",bootstrap_processor);	cpu_set(bootstrap_processor, cpu_online_map);	cpu_set(bootstrap_processor, cpu_present_map);	cache_decay_ticks = HZ/100;	/* FIXME very rough.  */}/*** inventory.c:do_inventory() hasn't yet been run and thus we** don't 'discover' the additional CPU's until later.*/void __init smp_prepare_cpus(unsigned int max_cpus){	cpus_clear(cpu_present_map);	cpu_set(0, cpu_present_map);	parisc_max_cpus = max_cpus;	if (!max_cpus)		printk(KERN_INFO "SMP mode deactivated.\n");}void smp_cpus_done(unsigned int cpu_max){	return;}int __devinit __cpu_up(unsigned int cpu){	if (cpu != 0 && cpu < parisc_max_cpus)		smp_boot_one_cpu(cpu);	return cpu_online(cpu) ? 0 : -ENOSYS;}#ifdef ENTRY_SYS_CPUS/* Code goes along with:**    entry.s:        ENTRY_NAME(sys_cpus)   / * 215, for cpu stat * /*/int sys_cpus(int argc, char **argv){	int i,j=0;	extern int current_pid(int cpu);	if( argc > 2 ) {		printk("sys_cpus:Only one argument supported\n");		return (-1);	}	if ( argc == 1 ){	#ifdef DUMP_MORE_STATE		for(i=0; i<NR_CPUS; i++) {			int cpus_per_line = 4;			if(cpu_online(i)) {				if (j++ % cpus_per_line)					printk(" %3d",i);				else					printk("\n %3d",i);			}		}		printk("\n"); #else	    	printk("\n 0\n"); #endif	} else if((argc==2) && !(strcmp(argv[1],"-l"))) {		printk("\nCPUSTATE  TASK CPUNUM CPUID HARDCPU(HPA)\n");#ifdef DUMP_MORE_STATE		for(i=0;i<NR_CPUS;i++) {			if (!cpu_online(i))				continue;			if (cpu_data[i].cpuid != NO_PROC_ID) {				switch(cpu_data[i].state) {					case STATE_RENDEZVOUS:						printk("RENDEZVS ");						break;					case STATE_RUNNING:						printk((current_pid(i)!=0) ? "RUNNING  " : "IDLING   ");						break;					case STATE_STOPPED:						printk("STOPPED  ");						break;					case STATE_HALTED:						printk("HALTED   ");						break;					default:						printk("%08x?", cpu_data[i].state);						break;				}				if(cpu_online(i)) {					printk(" %4d",current_pid(i));				}					printk(" %6d",cpu_number_map(i));				printk(" %5d",i);				printk(" 0x%lx\n",cpu_data[i].hpa);			}			}#else		printk("\n%s  %4d      0     0 --------",			(current->pid)?"RUNNING ": "IDLING  ",current->pid); #endif	} else if ((argc==2) && !(strcmp(argv[1],"-s"))) { #ifdef DUMP_MORE_STATE     		printk("\nCPUSTATE   CPUID\n");		for (i=0;i<NR_CPUS;i++) {			if (!cpu_online(i))				continue;			if (cpu_data[i].cpuid != NO_PROC_ID) {				switch(cpu_data[i].state) {					case STATE_RENDEZVOUS:						printk("RENDEZVS");break;					case STATE_RUNNING:						printk((current_pid(i)!=0) ? "RUNNING " : "IDLING");						break;					case STATE_STOPPED:						printk("STOPPED ");break;					case STATE_HALTED:						printk("HALTED  ");break;					default:				}				printk("  %5d\n",i);			}			}#else		printk("\n%s    CPU0",(current->pid==0)?"RUNNING ":"IDLING  "); #endif	} else {		printk("sys_cpus:Unknown request\n");		return (-1);	}	return 0;}#endif /* ENTRY_SYS_CPUS */#ifdef CONFIG_PROC_FSint __initsetup_profiling_timer(unsigned int multiplier){	return -EINVAL;}#endif

⌨️ 快捷键说明

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