Basic time functions and fix time system call

This commit is contained in:
Ali Mashtizadeh 2014-12-30 17:54:42 -08:00
parent 79a55fc518
commit 266dfcc857
6 changed files with 332 additions and 8 deletions

View File

@ -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);
}
}

View File

@ -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__ */

View File

@ -12,6 +12,7 @@ src_common = [
"file.c",
"string.c",
"syscall.c",
"time.c",
"printf.c",
"posix/mman.c",
]

View File

@ -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
View 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;
}

View File

@ -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;