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

📄 time.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	else {		/* This is only for the case where the user is setting the time		 * way back to a time such that the boot time would have been		 * before 1970 ... eg. we booted ten days ago, and we are setting		 * the time to Jan 5, 1970 */		do_gtod.varp->stamp_xsec = new_xsec;		do_gtod.tb_orig_stamp = tb_last_stamp;	}	write_unlock_irqrestore(&xtime_lock, flags);}/* * This function is a copy of the architecture independent function * but which calls do_settimeofday rather than setting the xtime * fields itself.  This way, the fields which are used for  * do_settimeofday get updated too. */long ppc64_sys32_stime(int* tptr){	int value;	struct timeval myTimeval;	if (!capable(CAP_SYS_TIME))		return -EPERM;	if (get_user(value, tptr))		return -EFAULT;	myTimeval.tv_sec = value;	myTimeval.tv_usec = 0;	do_settimeofday(&myTimeval);	return 0;}/* * This function is a copy of the architecture independent function * but which calls do_settimeofday rather than setting the xtime * fields itself.  This way, the fields which are used for  * do_settimeofday get updated too. */long ppc64_sys_stime(long* tptr){	long value;	struct timeval myTimeval;	if (!capable(CAP_SYS_TIME))		return -EPERM;	if (get_user(value, tptr))		return -EFAULT;	myTimeval.tv_sec = value;	myTimeval.tv_usec = 0;	do_settimeofday(&myTimeval);	return 0;}void __init time_init(void){	/* This function is only called on the boot processor */	unsigned long flags;	struct rtc_time tm;	ppc_md.calibrate_decr();	if ( ! piranha_simulator ) {		ppc_md.get_boot_time(&tm);	}	write_lock_irqsave(&xtime_lock, flags);	xtime.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,			      tm.tm_hour, tm.tm_min, tm.tm_sec);	tb_last_stamp = get_tb();	do_gtod.tb_orig_stamp = tb_last_stamp;	do_gtod.varp = &do_gtod.vars[0];	do_gtod.var_idx = 0;	do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;	do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;	do_gtod.varp->tb_to_xs = tb_to_xs;	do_gtod.tb_to_us = tb_to_us;	xtime_sync_interval = tb_ticks_per_sec - (tb_ticks_per_sec/8);	next_xtime_sync_tb = tb_last_stamp + xtime_sync_interval;	time_freq = 0;	xtime.tv_usec = 0;	last_rtc_update = xtime.tv_sec;	write_unlock_irqrestore(&xtime_lock, flags);#ifdef CONFIG_PPC_ISERIES	/* HACK HACK This allows the iSeries profiling to use /proc/profile */	prof_shift = 0;#endif	/* Not exact, but the timer interrupt takes care of this */	set_dec(tb_ticks_per_jiffy);}/*  * After adjtimex is called, adjust the conversion of tb ticks * to microseconds to keep do_gettimeofday synchronized  * with ntpd. * Use the time_adjust, time_freq and time_offset computed by adjtimex to  * adjust the frequency.*//* #define DEBUG_PPC_ADJTIMEX 1 */void ppc_adjtimex(void){	unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec, new_tb_to_xs, new_xsec, new_stamp_xsec;	unsigned long tb_ticks_per_sec_delta;	long delta_freq, ltemp;	struct div_result divres; 	unsigned long flags;	struct gettimeofday_vars * temp_varp;	unsigned temp_idx;	long singleshot_ppm = 0;	/* Compute parts per million frequency adjustment to accomplish the time adjustment	   implied by time_offset to be applied over the elapsed time indicated by time_constant.	   Use SHIFT_USEC to get it into the same units as time_freq. */	if ( time_offset < 0 ) {		ltemp = -time_offset;		ltemp <<= SHIFT_USEC - SHIFT_UPDATE;		ltemp >>= SHIFT_KG + time_constant;		ltemp = -ltemp;	}	else {		ltemp = time_offset;		ltemp <<= SHIFT_USEC - SHIFT_UPDATE;		ltemp >>= SHIFT_KG + time_constant;	}		/* If there is a single shot time adjustment in progress */	if ( time_adjust ) {#ifdef DEBUG_PPC_ADJTIMEX		printk("ppc_adjtimex: ");		if ( adjusting_time == 0 )			printk("starting ");		printk("single shot time_adjust = %ld\n", time_adjust);#endif				adjusting_time = 1;				/* Compute parts per million frequency adjustment to match time_adjust */		singleshot_ppm = tickadj * HZ;			/* The adjustment should be tickadj*HZ to match the code in linux/kernel/timer.c, but		   experiments show that this is too large. 3/4 of tickadj*HZ seems about right */		singleshot_ppm -= singleshot_ppm / 4;		/* Use SHIFT_USEC to get it into the same units as time_freq */			singleshot_ppm <<= SHIFT_USEC;		if ( time_adjust < 0 )			singleshot_ppm = -singleshot_ppm;	}	else {#ifdef DEBUG_PPC_ADJTIMEX		if ( adjusting_time )			printk("ppc_adjtimex: ending single shot time_adjust\n");#endif		adjusting_time = 0;	}		/* Add up all of the frequency adjustments */	delta_freq = time_freq + ltemp + singleshot_ppm;		/* Compute a new value for tb_ticks_per_sec based on the frequency adjustment */	den = 1000000 * (1 << (SHIFT_USEC - 8));	if ( delta_freq < 0 ) {		tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( (-delta_freq) >> (SHIFT_USEC - 8))) / den;		new_tb_ticks_per_sec = tb_ticks_per_sec + tb_ticks_per_sec_delta;	}	else {		tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( delta_freq >> (SHIFT_USEC - 8))) / den;		new_tb_ticks_per_sec = tb_ticks_per_sec - tb_ticks_per_sec_delta;	}	#ifdef DEBUG_PPC_ADJTIMEX	printk("ppc_adjtimex: ltemp = %ld, time_freq = %ld, singleshot_ppm = %ld\n", ltemp, time_freq, singleshot_ppm);	printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld  new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec);#endif					/* Compute a new value of tb_to_xs (used to convert tb to microseconds and a new value of 	   stamp_xsec which is the time (in 1/2^20 second units) corresponding to tb_orig_stamp.  This 	   new value of stamp_xsec compensates for the change in frequency (implied by the new tb_to_xs)	   which guarantees that the current time remains the same */ 	tb_ticks = get_tb() - do_gtod.tb_orig_stamp;	div128_by_32( 1024*1024, 0, new_tb_ticks_per_sec, &divres );	new_tb_to_xs = divres.result_low;	new_xsec = mulhdu( tb_ticks, new_tb_to_xs );	write_lock_irqsave( &xtime_lock, flags );	old_xsec = mulhdu( tb_ticks, do_gtod.varp->tb_to_xs );	new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec;	/* There are two copies of tb_to_xs and stamp_xsec so that no lock is needed to access and use these	   values in do_gettimeofday.  We alternate the copies and as long as a reasonable time elapses between	   changes, there will never be inconsistent values.  ntpd has a minimum of one minute between updates */	if (do_gtod.var_idx == 0) {		temp_varp = &do_gtod.vars[1];		temp_idx  = 1;	}	else {		temp_varp = &do_gtod.vars[0];		temp_idx  = 0;	}	temp_varp->tb_to_xs = new_tb_to_xs;	temp_varp->stamp_xsec = new_stamp_xsec;	mb();	do_gtod.varp = temp_varp;	do_gtod.var_idx = temp_idx;	write_unlock_irqrestore( &xtime_lock, flags );}#define TICK_SIZE tick#define FEBRUARY	2#define	STARTOFTIME	1970#define SECDAY		86400L#define SECYR		(SECDAY * 365)#define	leapyear(year)		((year) % 4 == 0)#define	days_in_year(a) 	(leapyear(a) ? 366 : 365)#define	days_in_month(a) 	(month_days[(a) - 1])static int month_days[12] = {	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};/* * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) */void GregorianDay(struct rtc_time * tm){	int leapsToDate;	int lastYear;	int day;	int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };	lastYear=tm->tm_year-1;	/*	 * Number of leap corrections to apply up to end of last year	 */	leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;	/*	 * This year is a leap year if it is divisible by 4 except when it is	 * divisible by 100 unless it is divisible by 400	 *	 * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be	 */	if((tm->tm_year%4==0) &&	   ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&	   (tm->tm_mon>2))	{		/*		 * We are past Feb. 29 in a leap year		 */		day=1;	}	else	{		day=0;	}	day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] +		   tm->tm_mday;	tm->tm_wday=day%7;}void to_tm(int tim, struct rtc_time * tm){	register int    i;	register long   hms, day;	day = tim / SECDAY;	hms = tim % SECDAY;	/* Hours, minutes, seconds are easy */	tm->tm_hour = hms / 3600;	tm->tm_min = (hms % 3600) / 60;	tm->tm_sec = (hms % 3600) % 60;	/* Number of years in days */	for (i = STARTOFTIME; day >= days_in_year(i); i++)		day -= days_in_year(i);	tm->tm_year = i;	/* Number of months in days left */	if (leapyear(tm->tm_year))		days_in_month(FEBRUARY) = 29;	for (i = 1; day >= days_in_month(i); i++)		day -= days_in_month(i);	days_in_month(FEBRUARY) = 28;	tm->tm_mon = i;	/* Days are what is left over (+1) from all that. */	tm->tm_mday = day + 1;	/*	 * Determine the day of week	 */	GregorianDay(tm);}/* Auxiliary function to compute scaling factors *//* Actually the choice of a timebase running at 1/4 the of the bus * frequency giving resolution of a few tens of nanoseconds is quite nice. * It makes this computation very precise (27-28 bits typically) which * is optimistic considering the stability of most processor clock * oscillators and the precision with which the timebase frequency * is measured but does not harm. */unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) {        unsigned mlt=0, tmp, err;        /* No concern for performance, it's done once: use a stupid         * but safe and compact method to find the multiplier.         */          for (tmp = 1U<<31; tmp != 0; tmp >>= 1) {                if (mulhwu(inscale, mlt|tmp) < outscale) mlt|=tmp;        }          /* We might still be off by 1 for the best approximation.         * A side effect of this is that if outscale is too large         * the returned value will be zero.         * Many corner cases have been checked and seem to work,         * some might have been forgotten in the test however.         */          err = inscale*(mlt+1);        if (err <= inscale/2) mlt++;        return mlt;  }/* * Divide a 128-bit dividend by a 32-bit divisor, leaving a 128 bit * result. */void div128_by_32( unsigned long dividend_high, unsigned long dividend_low,		   unsigned divisor, struct div_result *dr ){	unsigned long a,b,c,d, w,x,y,z, ra,rb,rc;	a = dividend_high >> 32;	b = dividend_high & 0xffffffff;	c = dividend_low >> 32;	d = dividend_low & 0xffffffff;	w = a/divisor;	ra = (a - (w * divisor)) << 32;	x = (ra + b)/divisor;	rb = ((ra + b) - (x * divisor)) << 32;	y = (rb + c)/divisor;	rc = ((rb + b) - (y * divisor)) << 32;	z = (rc + d)/divisor;	dr->result_high = (w << 32) + x;	dr->result_low  = (y << 32) + z;}

⌨️ 快捷键说明

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