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

📄 rtl_time.c

📁 rtlinux3.0 的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	rtl_irqstate_t flags;	hrtime_t t;	rtl_no_interrupts(flags);	rtl_spin_lock(&lock_linuxtime);	t = gethrtime();		if (t > _i8254_clock.arch.linux_time && !rtl_global_ispending_irq(0)) {		_i8254_clock.arch.linux_time += LATCH_NS;		rtl_global_pend_irq (0);		do {			rtl_save_jiffies = jiffies;		} while (rtl_save_jiffies != jiffies);			}	rtl_spin_unlock(&lock_linuxtime);#if 0	else if (t < _i8254_clock.arch.linux_time + LATCH_NS) {		/* laptops: TSC is reset on suspend/resume */		_i8254_clock.arch.linux_time = t;	}#endif	if (!_i8254_clock.arch.istimerset) { // TODO move to the default handler		_i8254_clock.settimer (&_i8254_clock, MAX_LATCH_ONESHOT);	}	rtl_restore_interrupts(flags);}static unsigned int _8254_irq(unsigned int irq, struct pt_regs *regs){	int flags;	rtl_spin_lock_irqsave (&lock8254, flags);	if (_i8254_clock.mode == RTL_CLOCK_MODE_PERIODIC) {		if (test_and_set_bit(0, &_i8254_clock.arch.count_irqs)) {			_i8254_clock.value += _i8254_clock.resolution;		}	} else {		_i8254_clock.arch.istimerset = 0;	}	rtl_hard_enable_irq(0);	rtl_spin_unlock_irqrestore (&lock8254, flags);	_i8254_clock.handler(regs);	if (rtl_rt_system_is_idle()) {		rtl_allow_interrupts();	}	_8254_checklinuxirq();	rtl_stop_interrupts();	return 0;}static int _8254_setperiodic (clockid_t c, hrtime_t interval){	int flags;	long t;	rtl_spin_lock_irqsave (&lock8254, flags);	t = RTIME_to_8254_ticks (interval) + 1;	if (t < 10) {		t = LATCH;		rtl_printf("RTLinux 8254 periodic settimer set too low!\n");	}	if (t > LATCH) {		t = LATCH;		rtl_printf("RTLinux 8254 periodic settimer set too high!\n");	}	WRITE_COUNTER_ZERO16 (t);	_i8254_clock.value = gethrtime();	_i8254_clock.resolution = interval;	_i8254_clock.arch.istimerset = 1;	rtl_spin_unlock_irqrestore(&lock8254, flags);	return 0;}	static int _8254_setoneshot (clockid_t c, hrtime_t interval){	rtl_irqstate_t flags;	long t;	rtl_spin_lock_irqsave (&lock8254, flags);	if (interval > MAX_LATCH_ONESHOT) {		interval = MAX_LATCH_ONESHOT;	}	t = RTIME_to_8254_ticks (interval); /* - _8254_latency); */	if (t < 1) {		t = 1;	}	WRITE_COUNTER_ZERO_ONESHOT(t);	_i8254_clock.arch.istimerset = 1;	rtl_spin_unlock_irqrestore(&lock8254, flags);	return 0;}int _8254_settimermode (struct rtl_clock *c, int mode){	if (mode == _i8254_clock.mode) {		return 0;	}	if (mode == RTL_CLOCK_MODE_PERIODIC) {		outb_p(0x30, 0x43);/* 8254, channel 0, mode 0, lsb+msb */		outb_p(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */		_i8254_clock.mode = mode;		_i8254_clock.gethrtime = periodic_gethrtime;		_i8254_clock.settimer = _8254_setperiodic;		_i8254_clock.arch.count_irqs = 0;	} else if (mode == RTL_CLOCK_MODE_ONESHOT) {#ifdef CONFIG_RTL_FAST_8254		outb_p(0x10, 0x43);    /* 8254, channel 0, mode 0, lsb */#else		outb_p(0x30, 0x43);    /* 8254, channel 0, mode 0, lsb+msb */#endif		_i8254_clock.mode = mode;		_i8254_clock.gethrtime = oneshot_gethrtime;		_i8254_clock.settimer = _8254_setoneshot;		_i8254_clock.resolution = HRTICKS_PER_SEC / CLOCK_TICK_RATE;/*		{			int i;			hrtime_t begin = gethrtime();			hrtime_t end;			for (i=0; i < 100; i++) {				_i8254_clock.settimer(&_i8254_clock, MAX_LATCH_ONESHOT);			}			end = gethrtime();			_8254_latency = (int)(end - begin) / 100;			rtl_printf("8254 oneshot settimer takes %d\n", _8254_latency);		} */	} else {		return -EINVAL;	}	return 0;}extern int use_tsc;int save_use_tsc;static int _8254_init (clockid_t clock){	int flags;	rtl_no_interrupts (flags);/* #ifndef CONFIG_X86_TSC */	save_do_gettimeoffset = do_gettimeoffset;	do_gettimeoffset = do_rt_gettimeoffset;	save_use_tsc = use_tsc;	use_tsc = 0;	rtl_save_jiffies = jiffies;/* #endif */	_i8254_clock.arch.linux_time = gethrtime() + LATCH_NS;	rtl_request_global_irq(0, _8254_irq);	_8254_settimermode (clock, RTL_CLOCK_MODE_ONESHOT);	_i8254_clock.settimer (clock, HRTIME_INFINITY);	rtl_restore_interrupts (flags);	return 0;}static void _8254_uninit (clockid_t clock){	int flags;	if (clock -> mode == RTL_CLOCK_MODE_UNINITIALIZED) {		return;	}	clock->handler = RTL_CLOCK_DEFAULTS.handler;	rtl_spin_lock_irqsave (&lock8254, flags);/* #ifndef CONFIG_X88_TSC */	do_gettimeoffset = save_do_gettimeoffset;	use_tsc = save_use_tsc;/* #endif */	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */	WRITE_COUNTER_ZERO16(LATCH);	rtl_free_global_irq(0);	clock -> mode = RTL_CLOCK_MODE_UNINITIALIZED;	rtl_spin_unlock_irqrestore (&lock8254, flags);}/* sort of a constructor */int rtl_create_clock_8254(void){	_i8254_clock = RTL_CLOCK_DEFAULTS;	_i8254_clock.init = _8254_init;	_i8254_clock.uninit = _8254_uninit;	_i8254_clock.settimermode = _8254_settimermode;	return 0;}#ifdef CONFIG_X86_LOCAL_APIC/* APIC clocks */static long RTIME_to_apic_ticks(long t){	int dummy;#if HRTICKS_PER_SEC != NSECS_PER_SEC	t <<= 10;#endif	__asm__("mull %2"		:"=a" (dummy), "=d" (t)		:"g" (scaler_hrtime_to_apic), "0" (t)		);			return (t);}static inline int rtl_apic_write_initial_count (long count){	unsigned int tmp_value;	tmp_value = apic_read(APIC_TMICT);	apic_write (APIC_TMICT, count);	return 0;}static int apic_setoneshot (clockid_t apic, hrtime_t interval){	long t;	if (apic != &_apic_clock[rtl_getcpuid()]) {		rtl_printf("apic_setoneshot crosses CPUs!\n");		return -1;	}	if (interval > MAX_LATCH_ONESHOT) {		interval = MAX_LATCH_ONESHOT;	}	t = RTIME_to_apic_ticks (interval);	if (t < 1) {		t = 1;	}	rtl_apic_write_initial_count (t);	apic->arch.istimerset = 1;	return 0;}static int apic_setperiodic (clockid_t apic, hrtime_t interval){	long t;	t = RTIME_to_apic_ticks (interval);	rtl_apic_write_initial_count (t);	apic->value = gethrtime();	apic->resolution = interval;	apic->arch.istimerset = 1;	return 0;}int apic_settimermode (struct rtl_clock *apic, int mode){	unsigned long lvtt1_value;	unsigned int tmp_value;	if (apic != &_apic_clock[rtl_getcpuid()]) {		rtl_printf("apic_settimermode crosses CPUs!\n");		return -EINVAL;	}	if (mode == apic->mode) {		return 0;	}	if (mode == RTL_CLOCK_MODE_PERIODIC) {		apic -> mode = mode;		apic -> gethrtime = periodic_gethrtime;		apic -> settimer = apic_setperiodic;		tmp_value = apic_read(APIC_LVTT);		lvtt1_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;		apic_write(APIC_LVTT , lvtt1_value);	} else if (mode == RTL_CLOCK_MODE_ONESHOT) {		apic -> mode = mode;		apic -> gethrtime = oneshot_gethrtime;		apic -> settimer = apic_setoneshot;		apic -> resolution = hrtime_resolution;		tmp_value = apic_read(APIC_LVTT);		lvtt1_value = LOCAL_TIMER_VECTOR;		apic_write(APIC_LVTT , lvtt1_value);	} else {		return -EINVAL;	}	return 0;}static void apic_checklinuxirq (void){	unsigned int cpu_id = rtl_getcpuid();	clockid_t apic = &_apic_clock[cpu_id];	hrtime_t t;#ifdef __RTL_LOCALIRQS__	if ((1 << cpu_id) & rtl_reserved_cpumask) return;#endif	t = apic->gethrtime(apic);	if  (t > apic->arch.linux_time) {		rtl_local_pend_vec (LOCAL_TIMER_VECTOR,cpu_id);		apic->arch.linux_time += LATCH_NS;		if (t > apic->arch.linux_time) {			int njiffies = 0;			do {				if (++njiffies >= 2 * HZ) {					apic->arch.linux_time = t;/* 					rtl_printf("RTL: lost %d linux apic ticks on CPU %d\n", njiffies, cpu_id); */					break;				}				apic->arch.linux_time += LATCH_NS;			} while (t > apic->arch.linux_time);		}	}}static unsigned int apic_timer_irq(struct pt_regs *r){	unsigned int cpu_id = rtl_getcpuid();	clockid_t apic = &_apic_clock[cpu_id];	if (apic->mode == RTL_CLOCK_MODE_PERIODIC) {		apic->value += apic->resolution;	} else {		apic->arch.istimerset = 0;	}	apic -> handler (r);	apic_checklinuxirq();	if (!apic -> arch.istimerset) { // TODO move into the default handler		apic->settimer (apic, MAX_LATCH_ONESHOT);	}	return 0;}int volatile apic_init_flag;static unsigned int apic_init_irq(struct pt_regs *r){	unsigned int cpu_id = rtl_getcpuid();	CLOCK_APIC->settimermode (CLOCK_APIC, RTL_CLOCK_MODE_ONESHOT);	CLOCK_APIC->settimer (CLOCK_APIC, HRTIME_INFINITY);	rtl_free_local_irq (LOCAL_TIMER_VECTOR, cpu_id);	rtl_request_local_irq (LOCAL_TIMER_VECTOR, apic_timer_irq, cpu_id);	clear_bit (0, &apic_init_flag);	return 0;}/* apics are initialized to the oneshot mode by default */static int apic_clock_init (clockid_t clk){	int flags;	unsigned int cpu_id = rtl_getcpuid();	rtl_no_interrupts (flags);	clk->arch.linux_time = gethrtime() + LATCH_NS;	if (clk->arch.apic_cpu == cpu_id) {		clk->settimermode (clk, RTL_CLOCK_MODE_ONESHOT);		clk->settimer (clk, HRTIME_INFINITY);		rtl_request_local_irq (LOCAL_TIMER_VECTOR, apic_timer_irq, cpu_id);	} else {		set_bit (0, &apic_init_flag);		rtl_request_local_irq (LOCAL_TIMER_VECTOR, apic_init_irq, clk->arch.apic_cpu);		while (test_bit(0, &apic_init_flag));	}	rtl_restore_interrupts (flags);	return 0;}static void apic_uninit_handler( struct pt_regs *regs){	unsigned int cpu_id = rtl_getcpuid();	CLOCK_APIC->settimermode (CLOCK_APIC, RTL_CLOCK_MODE_PERIODIC);	CLOCK_APIC->settimer (CLOCK_APIC, LATCH_NS);	CLOCK_APIC -> mode = RTL_CLOCK_MODE_UNINITIALIZED;	rtl_unsetclockhandler (CLOCK_APIC);	rtl_free_local_irq (LOCAL_TIMER_VECTOR, cpu_id);	clear_bit (0, &apic_init_flag);}static void apic_clock_uninit (clockid_t clock){	int flags;	unsigned int cpu_id = rtl_getcpuid();	rtl_no_interrupts (flags);	if (clock -> mode == RTL_CLOCK_MODE_UNINITIALIZED) {		rtl_restore_interrupts (flags);		return;	}	if (clock->arch.apic_cpu == cpu_id) {		apic_uninit_handler(NULL);	} else {		set_bit (0, &apic_init_flag);		rtl_unsetclockhandler (clock);		rtl_setclockhandler (clock, apic_uninit_handler);		while (test_bit(0, &apic_init_flag));	}	rtl_restore_interrupts (flags);}int rtl_create_clock_apic(int cpu){	_apic_clock[cpu] = RTL_CLOCK_DEFAULTS;	_apic_clock[cpu].init = apic_clock_init;	_apic_clock[cpu].uninit = apic_clock_uninit;	_apic_clock[cpu].settimermode = apic_settimermode;	_apic_clock[cpu].arch.apic_cpu = cpu;	return 0;}#endif/* returns a pointer to the clock structure of the best controlling hw clock  * for this CPU */clockid_t rtl_getbestclock (unsigned int cpu){#ifdef CONFIG_X86_LOCAL_APIC	if (smp_found_config) {		return &_apic_clock[cpu];	} else {		return &_i8254_clock;	}#else	return &_i8254_clock;#endif}int init_module (void){	rtl_spin_lock_init (&lock8254);	rtl_spin_lock_init (&lock_linuxtime);	init_hrtime();	rtl_create_clock_8254();#ifdef CONFIG_X86_LOCAL_APIC	{	int i;			for (i = 0; i < rtl_num_cpus(); i++) {			int cpu = cpu_logical_map (i);			rtl_create_clock_apic(cpu);		}	}#endif	rtl_init_standard_clocks();	return 0;}void cleanup_module(void){	rtl_cleanup_standard_clocks();#ifdef CONFIG_X86_LOCAL_APIC	if (smp_found_config) {		int i;		for (i = 0; i < rtl_num_cpus(); i++) {			int cpu = cpu_logical_map(i);			apic_clock_uninit (&_apic_clock[cpu]);		}	}#endif	_8254_uninit(&_i8254_clock);	uninit_hrtime();}

⌨️ 快捷键说明

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