Skip to content

Commit

Permalink
syscall: implement more syscalls
Browse files Browse the repository at this point in the history
  • Loading branch information
mosmeh committed Sep 6, 2024
1 parent 420ef66 commit 5c2e7cb
Show file tree
Hide file tree
Showing 8 changed files with 277 additions and 40 deletions.
10 changes: 10 additions & 0 deletions kernel/api/dirent.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <stdint.h>

#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
Expand All @@ -18,3 +20,11 @@ struct linux_dirent {
// char pad; // Zero padding byte
// char d_type; // File type
};

struct linux_dirent64 {
uint64_t d_ino;
int64_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
};
33 changes: 33 additions & 0 deletions kernel/api/sys/stat.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,36 @@ struct linux_stat {
unsigned long __unused4;
unsigned long __unused5;
};

struct linux_stat64 {
unsigned long long st_dev;
unsigned char __pad0[4];

unsigned long __st_ino;

unsigned int st_mode;
unsigned int st_nlink;

unsigned long st_uid;
unsigned long st_gid;

unsigned long long st_rdev;
unsigned char __pad3[4];

long long st_size;
unsigned long st_blksize;

/* Number 512-byte blocks allocated. */
unsigned long long st_blocks;

unsigned long st_atime;
unsigned long st_atime_nsec;

unsigned long st_mtime;
unsigned int st_mtime_nsec;

unsigned long st_ctime;
unsigned long st_ctime_nsec;

unsigned long long st_ino;
};
6 changes: 6 additions & 0 deletions kernel/api/sys/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,20 @@
#define SYS_getpgid 132
#define SYS_getdents 141
#define SYS_sched_yield 158
#define SYS_nanosleep 162
#define SYS_poll 168
#define SYS_getcwd 183
#define SYS_mmap2 192
#define SYS_stat64 195
#define SYS_lstat64 196
#define SYS_getdents64 220
#define SYS_gettid 224
#define SYS_set_thread_area 243
#define SYS_get_thread_area 244
#define SYS_exit_group 252
#define SYS_set_tid_address 258
#define SYS_clock_gettime 265
#define SYS_clock_nanosleep 267
#define SYS_socket 359
#define SYS_bind 361
#define SYS_connect 362
Expand Down
7 changes: 7 additions & 0 deletions kernel/api/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ struct timespec {
time_t tv_sec;
long long tv_nsec;
};

typedef int32_t time32_t;

struct timespec32 {
time32_t tv_sec;
int32_t tv_nsec;
};
82 changes: 70 additions & 12 deletions kernel/syscall/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ int sys_clock_gettime(clockid_t clk_id, struct timespec* user_tp) {
return 0;
}

int sys_clock_gettime32(clockid_t clk_id, struct timespec32* user_tp) {
struct timespec tp;
int rc = time_now(clk_id, &tp);
if (IS_ERR(rc))
return rc;
struct timespec32 tp32 = {
.tv_sec = tp.tv_sec,
.tv_nsec = tp.tv_nsec,
};
if (copy_to_user(user_tp, &tp32, sizeof(struct timespec32)))
return -EINVAL;
return 0;
}

struct sleep_blocker {
clockid_t clock_id;
struct timespec deadline;
Expand All @@ -28,13 +42,9 @@ static bool unblock_sleep(const struct sleep_blocker* blocker) {
return timespec_compare(&now, &blocker->deadline) >= 0;
}

int sys_clock_nanosleep(clockid_t clockid, int flags,
const struct timespec* user_request,
struct timespec* user_remain) {
struct timespec request;
if (copy_from_user(&request, user_request, sizeof(struct timespec)))
return -EFAULT;

static int clock_nanosleep(clockid_t clockid, int flags,
const struct timespec* request,
struct timespec* remain) {
struct timespec deadline = {0};
// Call time_now regardless of the flags to validate the clockid
int rc = time_now(clockid, &deadline);
Expand All @@ -43,10 +53,10 @@ int sys_clock_nanosleep(clockid_t clockid, int flags,

switch (flags) {
case 0:
timespec_add(&deadline, &request);
timespec_add(&deadline, request);
break;
case TIMER_ABSTIME:
deadline = request;
deadline = *request;
break;
default:
return -EINVAL;
Expand All @@ -56,15 +66,63 @@ int sys_clock_nanosleep(clockid_t clockid, int flags,
rc = sched_block((unblock_fn)unblock_sleep, &blocker, 0);
if (IS_ERR(rc))
return rc;
if (user_remain && flags != TIMER_ABSTIME) {
struct timespec remain = deadline;
if (remain && flags != TIMER_ABSTIME) {
*remain = deadline;
struct timespec now;
rc = time_now(clockid, &now);
if (IS_ERR(rc))
return rc;
timespec_saturating_sub(&remain, &now);
timespec_saturating_sub(remain, &now);
}
return 0;
}

int sys_clock_nanosleep(clockid_t clockid, int flags,
const struct timespec* user_request,
struct timespec* user_remain) {
struct timespec request;
if (copy_from_user(&request, user_request, sizeof(struct timespec)))
return -EFAULT;
struct timespec remain = {0};
int rc =
clock_nanosleep(clockid, flags, &request, user_remain ? &remain : NULL);
if (IS_ERR(rc))
return rc;
if (user_remain) {
if (copy_to_user(user_remain, &remain, sizeof(struct timespec)))
return -EFAULT;
}
return 0;
}

int sys_clock_nanosleep_time32(clockid_t clockid, int flags,
const struct timespec32* user_request,
struct timespec32* user_remain) {
struct timespec32 request32;
if (copy_from_user(&request32, user_request, sizeof(struct timespec32)))
return -EFAULT;
struct timespec request = {
.tv_sec = request32.tv_sec,
.tv_nsec = request32.tv_nsec,
};
struct timespec remain = {0};
int rc =
clock_nanosleep(clockid, flags, &request, user_remain ? &remain : NULL);
if (IS_ERR(rc))
return rc;
if (user_remain) {
struct timespec32 rem = {
.tv_sec = remain.tv_sec,
.tv_nsec = remain.tv_nsec,
};
if (copy_to_user(user_remain, &rem, sizeof(struct timespec32)))
return -EFAULT;
}
return 0;
}

int sys_nanosleep_time32(const struct timespec32* user_duration,
struct timespec32* user_rem) {
return sys_clock_nanosleep_time32(CLOCK_MONOTONIC, 0, user_duration,
user_rem);
}
Loading

0 comments on commit 5c2e7cb

Please sign in to comment.