Basic time functions and fix time system call
This commit is contained in:
parent
79a55fc518
commit
266dfcc857
@ -2,6 +2,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
// Castor Only
|
||||
#include <syscall.h>
|
||||
@ -34,6 +35,7 @@ Cmd_Help(int argc, const char *argv[])
|
||||
printf("exit Exit shell\n");
|
||||
printf("help Display the list of commands\n");
|
||||
printf("ls List files in a directory\n");
|
||||
printf("date Print current date and time\n");
|
||||
printf("bkpt Trigger a kernel breakpoint\n");
|
||||
}
|
||||
|
||||
@ -110,6 +112,13 @@ Cmd_Cat(int argc, const char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cmd_Date(int argc, const char *argv[])
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
fputs(ctime(&t), stdout);
|
||||
}
|
||||
|
||||
void
|
||||
Cmd_Hexdump(int argc, const char *argv[])
|
||||
{
|
||||
@ -146,21 +155,23 @@ DispatchCommand(char *buf)
|
||||
|
||||
// execute command
|
||||
if (strcmp(argv[0], "help") == 0) {
|
||||
Cmd_Help(argc, (const char **)argv);
|
||||
Cmd_Help(argc, (const char **)argv);
|
||||
} else if (strcmp(argv[0], "bkpt") == 0) {
|
||||
asm volatile("int3");
|
||||
} else if (strcmp(argv[0], "cat") == 0) {
|
||||
Cmd_Cat(argc, (const char **)argv);
|
||||
Cmd_Cat(argc, (const char **)argv);
|
||||
} else if (strcmp(argv[0], "date") == 0) {
|
||||
Cmd_Date(argc, (const char **)argv);
|
||||
} else if (strcmp(argv[0], "echo") == 0) {
|
||||
Cmd_Echo(argc, (const char **)argv);
|
||||
Cmd_Echo(argc, (const char **)argv);
|
||||
} else if (strcmp(argv[0], "exit") == 0) {
|
||||
exit(0);
|
||||
exit(0);
|
||||
} else if (strcmp(argv[0], "ls") == 0) {
|
||||
Cmd_List(argc, (const char **)argv);
|
||||
Cmd_List(argc, (const char **)argv);
|
||||
} else if (strcmp(argv[0], "#") == 0) {
|
||||
// Ignore comments
|
||||
} else if (buf[0] != '\0') {
|
||||
printf("Unknown command '%s'\n", buf);
|
||||
printf("Unknown command '%s'\n", buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,5 +2,47 @@
|
||||
#ifndef __TIME_H__
|
||||
#define __TIME_H__
|
||||
|
||||
typedef uint64_t time_t;
|
||||
typedef uint64_t suseconds_t;
|
||||
|
||||
struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
};
|
||||
|
||||
struct timeval
|
||||
{
|
||||
time_t tv_sec;
|
||||
suseconds_t tv_usec;
|
||||
};
|
||||
|
||||
struct timezone {
|
||||
int tz_minuteswest;
|
||||
int tz_dsttime;
|
||||
};
|
||||
|
||||
time_t time(time_t *t);
|
||||
char *asctime_r(const struct tm *tm, char *buf);
|
||||
char *asctime(const struct tm *tm);
|
||||
char *ctime_r(const time_t *timep, char *buf);
|
||||
char *ctime(const time_t *timep);
|
||||
struct tm *gmtime(const time_t *timep);
|
||||
struct tm *gmtime_r(const time_t *timep, struct tm *result);
|
||||
struct tm *localtime(const time_t *timep);
|
||||
struct tm *localtime_r(const time_t *timep, struct tm *result);
|
||||
time_t mktime(struct tm *tm);
|
||||
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
|
||||
// XXX: Not implemented
|
||||
int settimeofday(const struct timeval *tv, const struct timezone *tz);
|
||||
|
||||
#endif /* __TIME_H__ */
|
||||
|
||||
|
@ -12,6 +12,7 @@ src_common = [
|
||||
"file.c",
|
||||
"string.c",
|
||||
"syscall.c",
|
||||
"time.c",
|
||||
"printf.c",
|
||||
"posix/mman.c",
|
||||
]
|
||||
|
@ -234,3 +234,57 @@ int fprintf(FILE *stream, const char *fmt, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct StrState {
|
||||
char *buf;
|
||||
char *cur;
|
||||
size_t maxlen;
|
||||
} StrState;
|
||||
|
||||
static void strputc(int c, void *handle)
|
||||
{
|
||||
StrState *state = (StrState *)handle;
|
||||
|
||||
if ((state->maxlen != -1) &&
|
||||
(state->cur - state->buf >= state->maxlen)) {
|
||||
state->cur[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
state->cur[0] = c;
|
||||
state->cur++;
|
||||
}
|
||||
|
||||
int sprintf(char *str, const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
StrState state;
|
||||
|
||||
state.buf = str;
|
||||
state.cur = str;
|
||||
state.maxlen = -1;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = kvprintf(fmt, strputc, &state, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int snprintf(char *str, size_t n, const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
StrState state;
|
||||
|
||||
state.buf = str;
|
||||
state.cur = str;
|
||||
state.maxlen = n;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = kvprintf(fmt, strputc, &state, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
214
lib/libc/time.c
Normal file
214
lib/libc/time.c
Normal file
@ -0,0 +1,214 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <syscall.h>
|
||||
|
||||
#define TZ_OFFSET_SECS 0
|
||||
|
||||
static const char *dayOfWeek[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static const char *months[12] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
time_t
|
||||
time(time_t *t)
|
||||
{
|
||||
uint64_t nsec = SystemTime();
|
||||
time_t sec = nsec / 1000000000;
|
||||
|
||||
printf("%ld\n", nsec);
|
||||
|
||||
if (t)
|
||||
*t = sec;
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
int
|
||||
gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
uint64_t nsec = SystemTime();
|
||||
|
||||
tv->tv_sec = nsec / 1000000000;
|
||||
tv->tv_usec = (nsec % 1000000000) / 1000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
settimeofday(const struct timeval *tv, const struct timezone *tz)
|
||||
{
|
||||
// set errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *
|
||||
asctime_r(const struct tm *tm, char *buf)
|
||||
{
|
||||
// assert(tm->tm_wday < 7);
|
||||
// assert(tm->tm_mon < 12);
|
||||
|
||||
snprintf(buf, 26, "%s %s %2d %2d:%02d:%02d %4d\n",
|
||||
dayOfWeek[tm->tm_wday], months[tm->tm_mon],
|
||||
tm->tm_mday, tm->tm_hour, tm->tm_min,
|
||||
tm->tm_sec, tm->tm_year + 1900);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
asctime(const struct tm *tm)
|
||||
{
|
||||
static char buf[26];
|
||||
return asctime_r(tm, buf);
|
||||
}
|
||||
|
||||
char *
|
||||
ctime_r(const time_t *timep, char *buf)
|
||||
{
|
||||
struct tm tm;
|
||||
return asctime_r(localtime_r(timep, &tm), buf);
|
||||
}
|
||||
|
||||
char *
|
||||
ctime(const time_t *timep)
|
||||
{
|
||||
return asctime(localtime(timep));
|
||||
}
|
||||
|
||||
static bool
|
||||
Time_IsLeapYear(uint64_t year)
|
||||
{
|
||||
if ((year % 4) != 0)
|
||||
return false;
|
||||
if ((year % 100) != 0)
|
||||
return true;
|
||||
if ((year % 400) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
Time_DaysInMonth(uint64_t year, uint64_t month)
|
||||
{
|
||||
static const uint64_t days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
if ((month == 2) && Time_IsLeapYear(year))
|
||||
return 29;
|
||||
else
|
||||
return days[month];
|
||||
}
|
||||
|
||||
|
||||
struct tm *
|
||||
gmtime_r(const time_t *timep, struct tm *tm)
|
||||
{
|
||||
uint64_t secs, mins, hours;
|
||||
uint64_t days;
|
||||
uint64_t y, m;
|
||||
|
||||
// Compute seconds
|
||||
secs = *timep % (60 * 60 * 24);
|
||||
days = *timep / (60 * 60 * 24);
|
||||
mins = secs / 60;
|
||||
secs = secs % 60;
|
||||
|
||||
// Compute minutes
|
||||
hours = mins / 60;
|
||||
mins = mins % 60;
|
||||
|
||||
// Compute hours
|
||||
hours = hours % 24;
|
||||
|
||||
tm->tm_sec = secs;
|
||||
tm->tm_min = mins;
|
||||
tm->tm_hour = hours;
|
||||
|
||||
tm->tm_wday = (days + 3) % 7;
|
||||
|
||||
for (y = 1970; ; y++) {
|
||||
uint64_t daysOfYear;
|
||||
if (Time_IsLeapYear(y)) {
|
||||
daysOfYear = 366;
|
||||
} else {
|
||||
daysOfYear = 365;
|
||||
}
|
||||
|
||||
if (days < daysOfYear) {
|
||||
tm->tm_yday = days;
|
||||
tm->tm_year = y - 1900;
|
||||
break;
|
||||
}
|
||||
days -= daysOfYear;
|
||||
}
|
||||
|
||||
for (m = 0; ; m++) {
|
||||
uint64_t daysOfMonth = Time_DaysInMonth(tm->tm_year + 1900, m);
|
||||
|
||||
if (days < daysOfMonth) {
|
||||
tm->tm_mday = days;
|
||||
tm->tm_mon = m;
|
||||
break;
|
||||
}
|
||||
days -= daysOfMonth;
|
||||
}
|
||||
|
||||
return tm;
|
||||
}
|
||||
|
||||
struct tm *
|
||||
gmtime(const time_t *timep)
|
||||
{
|
||||
static struct tm tm;
|
||||
return gmtime_r(timep, &tm);
|
||||
}
|
||||
|
||||
struct tm *
|
||||
localtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
time_t t = *timep - TZ_OFFSET_SECS;
|
||||
return gmtime_r(&t, result);
|
||||
}
|
||||
|
||||
struct tm *
|
||||
localtime(const time_t *timep)
|
||||
{
|
||||
static struct tm tm;
|
||||
return localtime_r(timep, &tm);
|
||||
}
|
||||
|
||||
time_t
|
||||
mktime(struct tm *tm)
|
||||
{
|
||||
uint64_t days = 0;
|
||||
uint64_t secs = 0;
|
||||
uint64_t y, m;
|
||||
|
||||
// Convert to UNIX epoch
|
||||
for (y = 70; y < tm->tm_year; y++) {
|
||||
if (Time_IsLeapYear(y))
|
||||
days += 366;
|
||||
else
|
||||
days += 365;
|
||||
}
|
||||
|
||||
uint64_t yday = 0;
|
||||
for (m = 0; m < tm->tm_mon; m++) {
|
||||
yday += Time_DaysInMonth(tm->tm_year + 1900, m);
|
||||
}
|
||||
yday += tm->tm_mday;
|
||||
days += yday;
|
||||
|
||||
secs = 24 * days + tm->tm_hour;
|
||||
secs = secs * 60 + tm->tm_min;
|
||||
secs = secs * 60 + tm->tm_sec;
|
||||
|
||||
secs += TZ_OFFSET_SECS;
|
||||
|
||||
return secs;
|
||||
}
|
||||
|
@ -204,9 +204,11 @@ KTime_GetEpochNS()
|
||||
Spinlock_Lock(&ktimeLock);
|
||||
tscDiff = Time_GetTSC() - ktimeLastTSC;
|
||||
if (ticksPerSecondStable)
|
||||
epoch = ktimeLastEpoch + tscDiff / (ticksPerSecondStable / 1000000);
|
||||
epoch = ktimeLastEpoch * 1000000000
|
||||
+ tscDiff * 1000000000 / ticksPerSecondStable;
|
||||
else
|
||||
epoch = ktimeLastEpoch + tscDiff / (ticksPerSecond / 1000000);
|
||||
epoch = ktimeLastEpoch * 1000000000
|
||||
+ tscDiff * 1000000000 / ticksPerSecond;
|
||||
Spinlock_Unlock(&ktimeLock);
|
||||
|
||||
return epoch;
|
||||
|
Loading…
Reference in New Issue
Block a user