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

📄 smp.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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. */extern void flush_tlb_all_local(void);voidsmp_flush_tlb_all(void){	smp_call_function((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);	flush_tlb_all_local();}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 (test_and_set_bit(cpunum, (unsigned long *) (&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, cpunum);	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 */	/* Slaves wait here until Big Poppa daddy say "jump" */	mb();	/* PARANOID */	while (!smp_commenced) ;	mb();	/* PARANOID */	cpu_idle();      /* Wait for timer to schedule some work */	/* NOTREACHED */	panic("smp_callin() AAAAaaaaahhhh....\n");}/* * Create the idle task for a new Slave CPU.  DO NOT use kernel_thread() * because that could end up calling schedule(). If it did, the new idle * task could get scheduled before we had a chance to remove it from the * run-queue... */static int fork_by_hand(void){	struct pt_regs regs;  	/*	 * don't care about the regs settings since	 * we'll never reschedule the forked task.	 */	return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);}/* * Bring one cpu online. */static int smp_boot_one_cpu(int cpuid, int cpunum){	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 . . .	 */	if (fork_by_hand() < 0) 		panic("SMP: fork failed for CPU:%d", cpuid);		idle = init_task.prev_task;	if (!idle)		panic("SMP: No idle process for CPU:%d", cpuid);	task_set_cpu(idle, cpunum);	/* manually schedule idle task */	del_from_runqueue(idle);	unhash_process(idle);	init_tasks[cpunum] = idle;	/* Let _start know what logical CPU we're booting	** (offset into init_tasks[],cpu_data[])	*/	cpu_now_booting = cpunum;	/* 	** boot strap code needs to know the task address since	** it also contains the process stack.	*/	smp_init_current_idle_task = idle ;	mb();	/*	** This gets PDC to release the CPU from a very tight loop.	** See MEM_RENDEZ comments in head.S.	*/	__raw_writel(IRQ_OFFSET(TIMER_IRQ), cpu_data[cpunum].hpa);	mb();	/* 	 * OK, wait a bit for that CPU to finish staggering about. 	 * Slave will set a bit when it reaches smp_cpu_init() and then	 * wait for smp_commenced to be 1.	 * Once we see the bit change, we can move on.	 */	for (timeout = 0; timeout < 10000; timeout++) {		if(IS_LOGGED_IN(cpunum)) {			/* Which implies Slave has started up */			cpu_now_booting = 0;			smp_init_current_idle_task = NULL;			goto alive ;		}		udelay(100);		barrier();	}	init_tasks[cpunum] = NULL;	free_task_struct(idle);	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 (num %d) came alive after %ld _us\n",		cpuid,  cpunum, timeout * 100);#endif /* kDEBUG */#ifdef ENTRY_SYS_CPUS	cpu_data[cpunum].state = STATE_RUNNING;#endif	return 0;}/*** inventory.c:do_inventory() has already 'discovered' the additional CPU's.** We are ready to wrest them from PDC's control now.** Called by smp_init bring all the secondaries online and hold them.  **** o Setup of the IPI irq handler is done in irq.c.** o MEM_RENDEZ is initialzed in head.S:stext()***/void __init smp_boot_cpus(void){	int i, cpu_count = 1;	unsigned long bogosum = loops_per_jiffy; /* Count Monarch */	/* REVISIT - assumes first CPU reported by PAT PDC is BSP */	int bootstrap_processor=cpu_data[0].cpuid;	/* CPU ID of BSP */	/* Setup BSP mappings */	printk(KERN_DEBUG "SMP: bootstrap CPU ID is %d\n",bootstrap_processor);	init_task.processor = bootstrap_processor; 	current->processor = bootstrap_processor;	cpu_online_map = 1 << bootstrap_processor; /* Mark Boostrap processor as present */	current->active_mm = &init_mm;#ifdef ENTRY_SYS_CPUS	cpu_data[0].state = STATE_RUNNING;#endif	/* Nothing to do when told not to.  */	if (max_cpus == 0) {		printk(KERN_INFO "SMP mode deactivated.\n");		return;	}	if (max_cpus != -1) 		printk(KERN_INFO "Limiting CPUs to %d\n", max_cpus);	/* We found more than one CPU.... */	if (boot_cpu_data.cpu_count > 1) {		for (i = 0; i < NR_CPUS; i++) {			if (cpu_data[i].cpuid == NO_PROC_ID || 			    cpu_data[i].cpuid == bootstrap_processor)				continue;			if (smp_boot_one_cpu(cpu_data[i].cpuid, cpu_count) < 0)				continue;			bogosum += loops_per_jiffy;			cpu_count++; /* Count good CPUs only... */			/* Bail when we've started as many CPUS as told to */			if (cpu_count == max_cpus)				break;		}	}	if (cpu_count == 1) {		printk(KERN_INFO "SMP: Bootstrap processor only.\n");	}	printk(KERN_INFO "SMP: Total %d of %d processors activated "	       "(%lu.%02lu BogoMIPS noticed).\n",	       cpu_count, boot_cpu_data.cpu_count, (bogosum + 25) / 5000,	       ((bogosum + 25) / 50) % 100);	smp_num_cpus = cpu_count;#ifdef PER_CPU_IRQ_REGION	ipi_init();#endif	return;}/*  * Called from main.c by Monarch Processor. * After this, any CPU can schedule any task. */void smp_commence(void){	smp_commenced = 1;	mb();	return;}#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(IS_LOGGED_IN(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 (!IS_LOGGED_IN(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(IS_LOGGED_IN(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 (!IS_LOGGED_IN(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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -