diff --git a/arch/x86/kernel/timer.c b/arch/x86/kernel/timer.c index b66646ba..617d47d9 100644 --- a/arch/x86/kernel/timer.c +++ b/arch/x86/kernel/timer.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,19 @@ uint64_t get_clock_tick(void) return timer_ticks; } +int sys_times(struct tms* buffer, clock_t* clock) +{ + if (BUILTIN_EXPECT(!buffer, 0)) + return -EINVAL; + if (BUILTIN_EXPECT(!clock, 0)) + return -EINVAL; + + memset(buffer, 0x00, sizeof(struct tms)); + *clock = buffer->tms_utime = (clock_t) ((timer_ticks - per_core(current_task)->start_tick) * CLOCKS_PER_SEC / TIMER_FREQ); + + return 0; +} + /* * Handles the timer. In this case, it's very simple: We * increment the 'timer_ticks' variable every time the diff --git a/include/metalsvm/syscall.h b/include/metalsvm/syscall.h index 97785247..b47fc284 100644 --- a/include/metalsvm/syscall.h +++ b/include/metalsvm/syscall.h @@ -49,6 +49,7 @@ extern "C" { #define __NR_fork 12 #define __NR_wait 13 #define __NR_execve 14 +#define __NR_times 15 #ifdef __cplusplus } diff --git a/include/metalsvm/tasks_types.h b/include/metalsvm/tasks_types.h index 58f65cf2..e607dc3c 100644 --- a/include/metalsvm/tasks_types.h +++ b/include/metalsvm/tasks_types.h @@ -72,6 +72,8 @@ typedef struct task { vma_t* vma_list; /// Additional status flags. For instance, to signalize the using of the FPU uint32_t flags; + /// starting time/tick of the task + uint64_t start_tick; /// Start address of the heap uint32_t start_heap; /// End address of the heap diff --git a/include/metalsvm/time.h b/include/metalsvm/time.h index 4c2cdf51..702207b9 100644 --- a/include/metalsvm/time.h +++ b/include/metalsvm/time.h @@ -30,6 +30,26 @@ extern "C" { #endif +typedef uint32_t clock_t; + +struct tms { + clock_t tms_utime; + clock_t tms_stime; + clock_t tms_cutime; + clock_t tms_cstime; +}; + +#ifndef CLOCKS_PER_SEC +// newlib's default value +#define CLOCKS_PER_SEC 1000 +#endif + +/** @brief Determines the time in CLK_TCK's + * + * System call, which returns the value of time in CLK_TCK's + */ +int sys_times(struct tms*, clock_t* clock); + /** @brief Initialize Timer interrupts * * This procedure installs IRQ handlers for timer interrupts diff --git a/kernel/syscall.c b/kernel/syscall.c index 95a39fc6..d3ed8a41 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -23,6 +23,7 @@ #include #include #include +#include static int sys_write(int fildes, const char *buf, size_t len) { @@ -105,7 +106,7 @@ int syscall_handler(uint32_t sys_nr, ...) break; case __NR_wait: { int32_t* status = va_arg(vl, int32_t*); - + ret = wait(status); break; } @@ -117,6 +118,13 @@ int syscall_handler(uint32_t sys_nr, ...) ret = sys_execve(name, argv, env); break; } + case __NR_times: { + struct tms* buffer = va_arg(vl, struct tms*); + clock_t* clock = va_arg(vl, clock_t*); + + ret = sys_times(buffer, clock); + break; + } default: kputs("invalid system call\n"); ret = -ENOSYS; diff --git a/kernel/tasks.c b/kernel/tasks.c index ae699687..26774de7 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,7 @@ DEFINE_PER_CORE(task_t*, current_task, NULL); * A task's id will be its position in this array. */ static task_t task_table[MAX_TASKS] = {[0 ... MAX_TASKS-1] = {0, TASK_INVALID, ATOMIC_INIT(0), \ - SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0}}; + SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}}; static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT; /** @brief helper function for the assembly code to determine the current task @@ -193,6 +194,7 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg) task_table[i].flags = TASK_DEFAULT_FLAGS; task_table[i].start_heap = 0; task_table[i].end_heap = 0; + task_table[i].start_tick = get_clock_tick(); task_table[i].status = TASK_READY; break; } @@ -256,6 +258,7 @@ int sys_fork(void) task_table[i].outbox[per_core(current_task)->id] = &per_core(current_task)->inbox; task_table[i].flags = per_core(current_task)->flags; memcpy(&(task_table[i].fpu), &(per_core(current_task)->fpu), sizeof(union fpu_state)); + task_table[i].start_tick = get_clock_tick(); task_table[i].start_heap = 0; task_table[i].end_heap = 0; diff --git a/kernel/tests.c b/kernel/tests.c index 08f3d45f..fd1c200f 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -113,8 +113,8 @@ int test_init(void) //create_kernel_task(NULL, producer, NULL); //create_kernel_task(NULL, consumer, NULL); //create_user_task(NULL, "/bin/hello", argv); - create_user_task(NULL, "/bin/tests", argv); - //create_user_task(NULL, "/bin/jacobi", argv); + //create_user_task(NULL, "/bin/tests", argv); + create_user_task(NULL, "/bin/jacobi", argv); return 0; } diff --git a/newlib/examples/jacobi.c b/newlib/examples/jacobi.c index 6c0e7a20..f4804aa3 100644 --- a/newlib/examples/jacobi.c +++ b/newlib/examples/jacobi.c @@ -96,7 +96,7 @@ int main(int argc, char **argv) double** A=0; double* X; double* X_old, xi; - double start,stop; + clock_t start, end; if (generate_empty_matrix(&A,MATRIX_SIZE) < 0) { @@ -126,7 +126,7 @@ int main(int argc, char **argv) iter_start = 0; iter_end = MATRIX_SIZE; - //start = RCCE_wtime(); + start = clock(); while(1) { @@ -158,7 +158,7 @@ int main(int argc, char **argv) } } - //stop = RCCE_wtime(); + end = clock(); if (MATRIX_SIZE < 16) { printf("Print the solution...\n"); @@ -187,7 +187,7 @@ int main(int argc, char **argv) printf("\nmatrix size: %d x %d\n", MATRIX_SIZE, MATRIX_SIZE); printf("number of iterations: %d\n", iterations); - //printf("calculation time: %f s\n", stop-start); + printf("calculation time: %f s\n", (float) (end-start) / (float) CLOCKS_PER_SEC); free((void*) X_old); free((void*) X); diff --git a/newlib/src/libgloss/metalsvm/syscall.h b/newlib/src/libgloss/metalsvm/syscall.h index 5390a27b..6d137508 100644 --- a/newlib/src/libgloss/metalsvm/syscall.h +++ b/newlib/src/libgloss/metalsvm/syscall.h @@ -38,6 +38,7 @@ extern "C" { #define __NR_fork 12 #define __NR_wait 13 #define __NR_execve 14 +#define __NR_times 15 #define _STR(token) #token #define _SYSCALLSTR(x) "int $" _STR(x) " " diff --git a/newlib/src/libgloss/metalsvm/times.c b/newlib/src/libgloss/metalsvm/times.c index ed7baa16..5c4ebcd7 100644 --- a/newlib/src/libgloss/metalsvm/times.c +++ b/newlib/src/libgloss/metalsvm/times.c @@ -24,14 +24,20 @@ #include #undef errno extern int errno; -#include "warning.h" +#include "syscall.h" clock_t _DEFUN (_times, (buf), struct tms *buf) { - errno = ENOSYS; - return -1; -} + clock_t clock = 0; + int ret; -stub_warning(_times) + ret = SYSCALL2(__NR_times, buf, &clock); + if (ret < 0) { + errno = -ret; + return (clock_t) -1; + } + + return clock; +}