#include "typesdef.h" #include "errno.h" #include "list.h" #include "osal/sleep.h" #include "osal/irq.h" #ifdef CSKY_OS #include "csi_kernel.h" #include #include #define OS_MS_PERIOD_TICK (1000/OS_SYSTICK_HZ) extern uint32_t g_cpuloading; extern uint64_t g_sys_tick_count; static uint64 sys_time_base_ns = 0; static uint64 sys_time_real_ns = 0; uint64 os_jiffies(void) { return (g_sys_tick_count); } uint32 os_cpuloading(void) { return g_cpuloading; } uint32 os_seconds(void) { return krhino_curr_nanosec()/1000000000; } uint64 os_mseconds(void) { return krhino_curr_nanosec()/1000000; } uint64 os_useconds(void) { return krhino_curr_nanosec()/1000; } void os_systime(struct timespec *tm) { uint64 diff_ns = krhino_curr_nanosec() - sys_time_base_ns; tm->tv_sec = (sys_time_real_ns + diff_ns) / NANOSECONDS_PER_SECOND; tm->tv_nsec = (sys_time_real_ns + diff_ns) % NANOSECONDS_PER_SECOND; } #ifdef __NEWLIB__ int gettimeofday(struct timeval *ptimeval, void *ptimezone) #else int gettimeofday(struct timeval *ptimeval, struct timezone *ptimezone) #endif { uint64 diff_ns = krhino_curr_nanosec() - sys_time_base_ns; ptimeval->tv_sec = (sys_time_real_ns + diff_ns) / NANOSECONDS_PER_SECOND; ptimeval->tv_usec = ((sys_time_real_ns + diff_ns) % NANOSECONDS_PER_SECOND) / 1000; //加时区 //ptimeval->tv_sec += (8*3600); //东八区 return 0; } int settimeofday(const struct timeval *tv, const struct timezone *tz) { uint32 f = disable_irq(); sys_time_base_ns = krhino_curr_nanosec(); sys_time_real_ns = (uint64)tv->tv_sec * NANOSECONDS_PER_SECOND + (uint64)tv->tv_usec * 1000UL; enable_irq(f); return 0; } time_t time(time_t *t) { time_t v; uint64 diff_ns = krhino_curr_nanosec() - sys_time_base_ns; v = (sys_time_real_ns + diff_ns) / NANOSECONDS_PER_SECOND; if (t) *t = v; return v; } int clock_gettime(uint32 clk_id, struct timespec *tp) { if(tp){ uint64 ns = krhino_curr_nanosec(); tp->tv_sec = ns / NANOSECONDS_PER_SECOND; tp->tv_nsec = ns % NANOSECONDS_PER_SECOND; } return 0; } int32 timespec_validate(const struct timespec *time) { int32 ret = 0; if (time != NULL) { /* Verify 0 <= tv_nsec < 1000000000. */ if ((time->tv_nsec >= 0) && (time->tv_nsec < NANOSECONDS_PER_SECOND)) { ret = 1; } } return ret; } int32 timespec_cmp(const struct timespec *x, const struct timespec *y) { int32 ret = 0; /* Check parameters */ if ((x == NULL) && (y == NULL)) { ret = 0; } else if (y == NULL) { ret = 1; } else if (x == NULL) { ret = -1; } else if (x->tv_sec > y->tv_sec) { ret = 1; } else if (x->tv_sec < y->tv_sec) { ret = -1; } else { /* seconds are equal compare nano seconds */ if (x->tv_nsec > y->tv_nsec) { ret = 1; } else if (x->tv_nsec < y->tv_nsec) { ret = -1; } else { ret = 0; } } return ret; } int32 timespec_to_ticks(const struct timespec *time, uint64 *result) { int32 ret = 0; uint64 llTotalTicks = 0; long lNanoseconds = 0; /* Check parameters. */ if ((time == NULL) || (result == NULL)) { ret = -EINVAL; } else if ((ret == 0) && (timespec_validate(time) == FALSE)) { ret = -EINVAL; } else { /* Convert timespec.tv_sec to ticks. */ llTotalTicks = (uint64) OS_SYSTICK_HZ * (time->tv_sec); /* Convert timespec.tv_nsec to ticks. This value does not have to be checked * for overflow because a valid timespec has 0 <= tv_nsec < 1000000000 and * NANOSECONDS_PER_TICK > 1. */ lNanoseconds = time->tv_nsec / (long) NANOSECONDS_PER_TICK + /* Whole nanoseconds. */ (long)(time->tv_nsec % (long) NANOSECONDS_PER_TICK != 0); /* Add 1 to round up if needed. */ /* Add the nanoseconds to the total ticks. */ llTotalTicks += (uint64) lNanoseconds; /* Write result. */ *result = (uint64) llTotalTicks; } return ret; } void nanosec_to_timespec(int64 llSource, struct timespec *time) { long lCarrySec = 0; /* Convert to timespec. */ time->tv_sec = (time_t)(llSource / NANOSECONDS_PER_SECOND); time->tv_nsec = (long)(llSource % NANOSECONDS_PER_SECOND); /* Subtract from tv_sec if tv_nsec < 0. */ if (time->tv_nsec < 0L) { /* Compute the number of seconds to carry. */ lCarrySec = (time->tv_nsec / (long) NANOSECONDS_PER_SECOND) + 1L; time->tv_sec -= (time_t)(lCarrySec); time->tv_nsec += lCarrySec * (long) NANOSECONDS_PER_SECOND; } } int32 timespec_add(const struct timespec *x, const struct timespec *y, struct timespec *result) { int64 llPartialSec = 0; int32 ret = 0; /* Check parameters. */ if ((result == NULL) || (x == NULL) || (y == NULL)) { return -1; } /* Perform addition. */ result->tv_nsec = x->tv_nsec + y->tv_nsec; /* check for overflow in case nsec value was invalid */ if (result->tv_nsec < 0) { ret = 1; } else { llPartialSec = (result->tv_nsec) / NANOSECONDS_PER_SECOND; result->tv_nsec = (result->tv_nsec) % NANOSECONDS_PER_SECOND; result->tv_sec = x->tv_sec + y->tv_sec + llPartialSec; /* check for overflow */ if (result->tv_sec < 0) { ret = 1; } } return ret; } int32 timespec_add_nanosec(const struct timespec *x, int64 llNanoseconds, struct timespec *result) { int64 llTotalNSec = 0; int32 ret = 0; /* Check parameters. */ if ((result == NULL) || (x == NULL)) { return -1; } /* add nano seconds */ llTotalNSec = x->tv_nsec + llNanoseconds; /* check for nano seconds overflow */ if (llTotalNSec < 0) { ret = 1; } else { result->tv_nsec = llTotalNSec % NANOSECONDS_PER_SECOND; result->tv_sec = x->tv_sec + (llTotalNSec / NANOSECONDS_PER_SECOND); /* check for seconds overflow */ if (result->tv_sec < 0) { ret = 1; } } return ret; } int32 timespec_sub(const struct timespec *x, const struct timespec *y, struct timespec *result) { int32 cmp_ret = 0; int32 ret = 0; /* Check parameters. */ if ((result == NULL) || (x == NULL) || (y == NULL)) { return -1; } cmp_ret = timespec_cmp(x, y); /* if x < y then result would be negative, return 1 */ if (cmp_ret == -1) { ret = 1; } else if (cmp_ret == 0) { /* if times are the same return zero */ result->tv_sec = 0; result->tv_nsec = 0; } else { /* If x > y Perform subtraction. */ result->tv_sec = x->tv_sec - y->tv_sec; result->tv_nsec = x->tv_nsec - y->tv_nsec; /* check if nano seconds value needs to borrow */ if (result->tv_nsec < 0) { /* Based on comparison, tv_sec > 0 */ result->tv_sec--; result->tv_nsec += (long) NANOSECONDS_PER_SECOND; } /* if nano second is negative after borrow, it is an overflow error */ if (result->tv_nsec < 0) { ret = -1; } } return ret; } int32 timespec_detal_ticks(const struct timespec *abstime, const struct timespec *curtime, uint64 *result) { int32 ret = 0; struct timespec diff = { 0 }; if(abstime == NULL || curtime == NULL || result == NULL){ return -EINVAL; } ret = timespec_sub(abstime, curtime, &diff); if (ret == 1) { /* abstime was in the past. */ ret = -ETIMEDOUT; } else if (ret == -1) { /* error */ ret = -EINVAL; } /* Convert the time difference to ticks. */ if (ret == 0) { ret = timespec_to_ticks(&diff, result); } return ret; } uint64 os_jiffies_to_msecs(uint64 jiff) { return ((jiff)*OS_MS_PERIOD_TICK); } uint64 os_msecs_to_jiffies(uint64 msec) { return ((msec)/OS_MS_PERIOD_TICK); } #endif