Various refactors and end-to-end tracking of cycles

main
Sean McBride 5 years ago
parent d058f99e0f
commit 69086d012d

@ -120,7 +120,7 @@ typedef enum
#define SBOX_PREOPEN_MAGIC (707707707) // reads lol lol lol upside down
#define SOFTINT_TIMER_START_USEC (10 * 1000) // start timers 10 ms from now.
#define SOFTINT_TIMER_PERIOD_USEC (1000 * 5) // 100ms timer..
#define SOFTINT_TIMER_PERIOD_USEC (1000 * 5) // 5ms timer..
#ifdef DEBUG
#ifdef NOSTDIO

@ -1,737 +0,0 @@
#ifdef USE_SYSCALL
/* code from https://github.com/gwsystems/silverfish/blob/master/runtime/libc/libc_backing.c */
#include <runtime.h>
#include <sandbox.h>
#include <sys/types.h>
#include <sys/socket.h>
// What should we tell the child program its UID and GID are?
#define UID 0xFF
#define GID 0xFE
// Elf auxilary vector values (see google for what those are)
#define AT_NULL 0
#define AT_IGNORE 1
#define AT_EXECFD 2
#define AT_PHDR 3
#define AT_PHENT 4
#define AT_PHNUM 5
#define AT_PAGESZ 6
#define AT_BASE 7
#define AT_FLAGS 8
#define AT_ENTRY 9
#define AT_NOTELF 10
#define AT_UID 11
#define AT_EUID 12
#define AT_GID 13
#define AT_EGID 14
#define AT_CLKTCK 17
#define AT_SECURE 23
#define AT_BASE_PLATFORM 24
#define AT_RANDOM 25
// offset = a WASM ptr to memory the runtime can use
void
stub_init(i32 offset)
{
// What program name will we put in the auxiliary vectors
char *program_name = sandbox_current()->mod->name;
// Copy the program name into WASM accessible memory
i32 program_name_offset = offset;
strcpy(get_memory_ptr_for_runtime(offset, sizeof(program_name)), program_name);
offset += sizeof(program_name);
// The construction of this is:
// evn1, env2, ..., NULL, auxv_n1, auxv_1, auxv_n2, auxv_2 ..., NULL
i32 env_vec[] = {
// Env variables would live here, but we don't supply any
0,
// We supply only the bare minimum AUX vectors
AT_PAGESZ,
WASM_PAGE_SIZE,
AT_UID,
UID,
AT_EUID,
UID,
AT_GID,
GID,
AT_EGID,
GID,
AT_SECURE,
0,
AT_RANDOM,
(i32)rand(), // It's pretty stupid to use rand here, but w/e
0,
};
i32 env_vec_offset = offset;
memcpy(get_memory_ptr_for_runtime(env_vec_offset, sizeof(env_vec)), env_vec, sizeof(env_vec));
module_libc_init(sandbox_current()->mod, env_vec_offset, program_name_offset);
}
// Emulated syscall implementations
// We define our own syscall numbers, because WASM uses x86_64 values even on systems that are not x86_64
#define SYS_READ 0
u32
wasm_read(i32 filedes, i32 buf_offset, i32 nbyte)
{
char *buf = get_memory_ptr_void(buf_offset, nbyte);
i32 res = (i32)read(filedes, buf, nbyte);
if (res == -1) return -errno;
return res;
}
#define SYS_WRITE 1
i32
wasm_write(i32 fd, i32 buf_offset, i32 buf_size)
{
char *buf = get_memory_ptr_void(buf_offset, buf_size);
i32 res = (i32)write(fd, buf, buf_size);
if (res == -1) return -errno;
return res;
}
#define WO_RDONLY 00
#define WO_WRONLY 01
#define WO_RDWR 02
#define WO_CREAT 0100
#define WO_EXCL 0200
#define WO_NOCTTY 0400
#define WO_TRUNC 01000
#define WO_APPEND 02000
#define WO_NONBLOCK 04000
#define WO_DSYNC 010000
#define WO_SYNC 04010000
#define WO_RSYNC 04010000
#define WO_DIRECTORY 0200000
#define WO_NOFOLLOW 0400000
#define WO_CLOEXEC 02000000
#define SYS_OPEN 2
i32
wasm_open(i32 path_off, i32 flags, i32 mode)
{
char *path = get_memory_string(path_off);
i32 modified_flags = 0;
if (flags & WO_RDONLY) {
modified_flags |= O_RDONLY;
flags ^= WO_RDONLY;
}
if (flags & WO_WRONLY) {
modified_flags |= O_WRONLY;
flags ^= WO_WRONLY;
}
if (flags & WO_RDWR) {
modified_flags |= O_RDWR;
flags ^= WO_RDWR;
}
if (flags & WO_APPEND) {
modified_flags |= O_APPEND;
flags ^= WO_APPEND;
}
if (flags & WO_CREAT) {
modified_flags |= O_CREAT;
flags ^= WO_CREAT;
}
if (flags & WO_EXCL) {
modified_flags |= O_EXCL;
flags ^= WO_EXCL;
}
i32 res = (i32)open(path, modified_flags, mode);
if (res == -1) return -errno;
return res;
}
#define SYS_CLOSE 3
i32
wasm_close(i32 fd)
{
i32 res = (i32)close(fd);
if (res == -1) return -errno;
return res;
}
// What the wasm stat structure looks like
struct wasm_stat {
i64 st_dev;
u64 st_ino;
u32 st_nlink;
u32 st_mode;
u32 st_uid;
u32 st_gid;
u32 __pad0;
u64 st_rdev;
u64 st_size;
i32 st_blksize;
i64 st_blocks;
struct {
i32 tv_sec;
i32 tv_nsec;
} st_atim;
struct {
i32 tv_sec;
i32 tv_nsec;
} st_mtim;
struct {
i32 tv_sec;
i32 tv_nsec;
} st_ctim;
i32 __pad1[3];
};
#define SYS_STAT 4
// What the OSX stat structure looks like:
// struct stat { /* when _DARWIN_FEATURE_64_BIT_INODE is NOT defined */
// dev_t st_dev; /* device inode resides on */
// ino_t st_ino; /* inode's number */
// mode_t st_mode; /* inode protection mode */
// nlink_t st_nlink; /* number of hard links to the file */
// uid_t st_uid; /* user-id of owner */
// gid_t st_gid; /* group-id of owner */
// dev_t st_rdev; /* device type, for special file inode */
// struct timespec st_atimespec; /* time of last access */
// struct timespec st_mtimespec; /* time of last data modification */
// struct timespec st_ctimespec; /* time of last file status change */
// off_t st_size; /* file size, in bytes */
// quad_t st_blocks; /* blocks allocated for file */
// u_long st_blksize;/* optimal file sys I/O ops blocksize */
// u_long st_flags; /* user defined flags for file */
// u_long st_gen; /* file generation number */
// };
i32
wasm_stat(u32 path_str_offset, i32 stat_offset)
{
char * path = get_memory_string(path_str_offset);
struct wasm_stat *stat_ptr = get_memory_ptr_void(stat_offset, sizeof(struct wasm_stat));
struct stat stat;
i32 res = lstat(path, &stat);
if (res == -1) return -errno;
*stat_ptr = (struct wasm_stat){
.st_dev = stat.st_dev,
.st_ino = stat.st_ino,
.st_nlink = stat.st_nlink,
.st_mode = stat.st_mode,
.st_uid = stat.st_uid,
.st_gid = stat.st_gid,
.st_rdev = stat.st_rdev,
.st_size = stat.st_size,
.st_blksize = stat.st_blksize,
.st_blocks = stat.st_blocks,
};
#ifdef __APPLE__
stat_ptr->st_atim.tv_sec = stat.st_atimespec.tv_sec;
stat_ptr->st_atim.tv_nsec = stat.st_atimespec.tv_nsec;
stat_ptr->st_mtim.tv_sec = stat.st_mtimespec.tv_sec;
stat_ptr->st_mtim.tv_nsec = stat.st_mtimespec.tv_nsec;
stat_ptr->st_ctim.tv_sec = stat.st_ctimespec.tv_sec;
stat_ptr->st_ctim.tv_nsec = stat.st_ctimespec.tv_nsec;
#else
stat_ptr->st_atim.tv_sec = stat.st_atim.tv_sec;
stat_ptr->st_atim.tv_nsec = stat.st_atim.tv_nsec;
stat_ptr->st_mtim.tv_sec = stat.st_mtim.tv_sec;
stat_ptr->st_mtim.tv_nsec = stat.st_mtim.tv_nsec;
stat_ptr->st_ctim.tv_sec = stat.st_ctim.tv_sec;
stat_ptr->st_ctim.tv_nsec = stat.st_ctim.tv_nsec;
#endif
return res;
}
#define SYS_FSTAT 5
i32
wasm_fstat(i32 filedes, i32 stat_offset)
{
struct wasm_stat *stat_ptr = get_memory_ptr_void(stat_offset, sizeof(struct wasm_stat));
struct stat stat;
i32 res = fstat(filedes, &stat);
if (res == -1) return -errno;
*stat_ptr = (struct wasm_stat){
.st_dev = stat.st_dev,
.st_ino = stat.st_ino,
.st_nlink = stat.st_nlink,
.st_mode = stat.st_mode,
.st_uid = stat.st_uid,
.st_gid = stat.st_gid,
.st_rdev = stat.st_rdev,
.st_size = stat.st_size,
.st_blksize = stat.st_blksize,
.st_blocks = stat.st_blocks,
};
#ifdef __APPLE__
stat_ptr->st_atim.tv_sec = stat.st_atimespec.tv_sec;
stat_ptr->st_atim.tv_nsec = stat.st_atimespec.tv_nsec;
stat_ptr->st_mtim.tv_sec = stat.st_mtimespec.tv_sec;
stat_ptr->st_mtim.tv_nsec = stat.st_mtimespec.tv_nsec;
stat_ptr->st_ctim.tv_sec = stat.st_ctimespec.tv_sec;
stat_ptr->st_ctim.tv_nsec = stat.st_ctimespec.tv_nsec;
#else
stat_ptr->st_atim.tv_sec = stat.st_atim.tv_sec;
stat_ptr->st_atim.tv_nsec = stat.st_atim.tv_nsec;
stat_ptr->st_mtim.tv_sec = stat.st_mtim.tv_sec;
stat_ptr->st_mtim.tv_nsec = stat.st_mtim.tv_nsec;
stat_ptr->st_ctim.tv_sec = stat.st_ctim.tv_sec;
stat_ptr->st_ctim.tv_nsec = stat.st_ctim.tv_nsec;
#endif
return res;
}
#define SYS_LSTAT 6
i32
wasm_lstat(i32 path_str_offset, i32 stat_offset)
{
char * path = get_memory_string(path_str_offset);
struct wasm_stat *stat_ptr = get_memory_ptr_void(stat_offset, sizeof(struct wasm_stat));
struct stat stat;
i32 res = lstat(path, &stat);
if (res == -1) return -errno;
*stat_ptr = (struct wasm_stat){
.st_dev = stat.st_dev,
.st_ino = stat.st_ino,
.st_nlink = stat.st_nlink,
.st_mode = stat.st_mode,
.st_uid = stat.st_uid,
.st_gid = stat.st_gid,
.st_rdev = stat.st_rdev,
.st_size = stat.st_size,
.st_blksize = stat.st_blksize,
.st_blocks = stat.st_blocks,
};
#ifdef __APPLE__
stat_ptr->st_atim.tv_sec = stat.st_atimespec.tv_sec;
stat_ptr->st_atim.tv_nsec = stat.st_atimespec.tv_nsec;
stat_ptr->st_mtim.tv_sec = stat.st_mtimespec.tv_sec;
stat_ptr->st_mtim.tv_nsec = stat.st_mtimespec.tv_nsec;
stat_ptr->st_ctim.tv_sec = stat.st_ctimespec.tv_sec;
stat_ptr->st_ctim.tv_nsec = stat.st_ctimespec.tv_nsec;
#else
stat_ptr->st_atim.tv_sec = stat.st_atim.tv_sec;
stat_ptr->st_atim.tv_nsec = stat.st_atim.tv_nsec;
stat_ptr->st_mtim.tv_sec = stat.st_mtim.tv_sec;
stat_ptr->st_mtim.tv_nsec = stat.st_mtim.tv_nsec;
stat_ptr->st_ctim.tv_sec = stat.st_ctim.tv_sec;
stat_ptr->st_ctim.tv_nsec = stat.st_ctim.tv_nsec;
#endif
return res;
}
#define SYS_LSEEK 8
i32
wasm_lseek(i32 filedes, i32 file_offset, i32 whence)
{
i32 res = (i32)lseek(filedes, file_offset, whence);
if (res == -1) return -errno;
return res;
}
#define SYS_MMAP 9
u32
wasm_mmap(i32 addr, i32 len, i32 prot, i32 flags, i32 fd, i32 offset)
{
if (addr != 0) {
printf("parameter void *addr is not supported!\n");
assert(0);
}
if (fd != -1) {
printf("file mapping is not supported!\n");
assert(0);
}
assert(len % WASM_PAGE_SIZE == 0);
i32 result = sandbox_lmbound;
for (int i = 0; i < len / WASM_PAGE_SIZE; i++) { expand_memory(); }
return result;
}
#define SYS_MUNMAP 11
#define SYS_BRK 12
#define SYS_RT_SIGACTION 13
#define SYS_RT_SIGPROGMASK 14
#define SYS_IOCTL 16
i32
wasm_ioctl(i32 fd, i32 request, i32 data_offet)
{
// musl libc does some ioctls to stdout, so just allow these to silently go through
// FIXME: The above is idiotic
return 0;
}
#define SYS_READV 19
struct wasm_iovec {
i32 base_offset;
i32 len;
};
i32
wasm_readv(i32 fd, i32 iov_offset, i32 iovcnt)
{
i32 read = 0;
struct wasm_iovec *iov = get_memory_ptr_void(iov_offset, iovcnt * sizeof(struct wasm_iovec));
for (int i = 0; i < iovcnt; i++) { read += wasm_read(fd, iov[i].base_offset, iov[i].len); }
return read;
}
#define SYS_WRITEV 20
i32
wasm_writev(i32 fd, i32 iov_offset, i32 iovcnt)
{
struct wasm_iovec *iov = get_memory_ptr_void(iov_offset, iovcnt * sizeof(struct wasm_iovec));
// If we aren't on MUSL, pass writev to printf if possible
#if defined(__APPLE__) || defined(__GLIBC__)
if (fd == 1) {
int sum = 0;
for (int i = 0; i < iovcnt; i++) {
i32 len = iov[i].len;
void *ptr = get_memory_ptr_void(iov[i].base_offset, len);
printf("%.*s", len, ptr);
sum += len;
}
return sum;
}
#endif
struct iovec vecs[iovcnt];
for (int i = 0; i < iovcnt; i++) {
i32 len = iov[i].len;
void *ptr = get_memory_ptr_void(iov[i].base_offset, len);
vecs[i] = (struct iovec){ ptr, len };
}
i32 res = (i32)writev(fd, vecs, iovcnt);
if (res == -1) return -errno;
return res;
}
#define SYS_MADVISE 28
#define SYS_GETPID 39
u32
wasm_getpid()
{
return (u32)getpid();
}
#define WF_DUPFD 0
#define WF_GETFD 1
#define WF_SETFD 2
#define WF_GETFL 3
#define WF_SETFL 4
#define WF_SETOWN 8
#define WF_GETOWN 9
#define WF_SETSIG 10
#define WF_GETSIG 11
#define WF_GETLK 5
#define WF_SETLK 6
#define WF_SETLKW 7
#define SYS_FCNTL 72
u32
wasm_fcntl(u32 fd, u32 cmd, u32 arg_or_lock_ptr)
{
switch (cmd) {
case WF_SETFD:
// return fcntl(fd, F_SETFD, arg_or_lock_ptr);
return 0;
case WF_SETLK:
return 0;
default:
assert(0);
}
}
#define SYS_FSYNC 74
u32
wasm_fsync(u32 filedes)
{
u32 res = fsync(filedes);
if (res == -1) return -errno;
return 0;
}
#define SYS_GETCWD 79
u32
wasm_getcwd(u32 buf_offset, u32 buf_size)
{
char *buf = get_memory_ptr_void(buf_offset, buf_size);
char *res = getcwd(buf, buf_size);
if (!res) return 0;
return buf_offset;
}
#define SYS_UNLINK 87
u32
wasm_unlink(u32 path_str_offset)
{
char *str = get_memory_string(path_str_offset);
u32 res = unlink(str);
if (res == -1) return -errno;
return 0;
}
#define SYS_GETEUID 107
u32
wasm_geteuid()
{
return (u32)geteuid();
}
#define SYS_SET_THREAD_AREA 205
#define SYS_SET_TID_ADDRESS 218
#define SYS_GET_TIME 228
struct wasm_time_spec {
u64 sec;
u32 nanosec;
};
i32
wasm_get_time(i32 clock_id, i32 timespec_off)
{
clockid_t real_clock;
switch (clock_id) {
case 0:
real_clock = CLOCK_REALTIME;
break;
case 1:
real_clock = CLOCK_MONOTONIC;
break;
case 2:
real_clock = CLOCK_PROCESS_CPUTIME_ID;
break;
default:
assert(0);
}
struct wasm_time_spec *timespec = get_memory_ptr_void(timespec_off, sizeof(struct wasm_time_spec));
struct timespec native_timespec = { 0, 0 };
int res = clock_gettime(real_clock, &native_timespec);
if (res == -1) return -errno;
timespec->sec = native_timespec.tv_sec;
timespec->nanosec = native_timespec.tv_nsec;
return res;
}
#define SYS_EXIT_GROUP 231
i32
wasm_exit_group(i32 status)
{
exit(status);
return 0;
}
#define SYS_FCHOWN 93
i32
wasm_fchown(i32 fd, u32 owner, u32 group)
{
return fchown(fd, owner, group);
}
// networking syscalls
#define SYS_SOCKET 41
#define SYS_CONNECT 42
#define SYS_ACCEPT 43
#define SYS_BIND 49
#define SYS_LISTEN 50
i32
wasm_socket(i32 domain, i32 type, i32 protocol)
{
return socket(domain, type, protocol);
}
i32
wasm_connect(i32 sockfd, i32 sockaddr_offset, i32 addrlen)
{
return connect(sockfd, get_memory_ptr_void(sockaddr_offset, addrlen), addrlen);
}
i32
wasm_accept(i32 sockfd, i32 sockaddr_offset, i32 addrlen_offset)
{
socklen_t *addrlen = get_memory_ptr_void(addrlen_offset, sizeof(socklen_t));
return accept(sockfd, get_memory_ptr_void(sockaddr_offset, *addrlen), addrlen);
}
i32
wasm_bind(i32 sockfd, i32 sockaddr_offset, i32 addrlen)
{
return bind(sockfd, get_memory_ptr_void(sockaddr_offset, addrlen), addrlen);
}
i32
wasm_listen(i32 sockfd, i32 backlog)
{
return listen(sockfd, backlog);
}
#define SYS_SENDTO 44
#define SYS_RECVFROM 45
i32
wasm_sendto(i32 fd, i32 buff_offset, i32 len, i32 flags, i32 sockaddr_offset, i32 sockaddr_len)
{
char * buf = get_memory_ptr_void(buff_offset, len);
struct sockaddr *addr = sockaddr_len ? get_memory_ptr_void(sockaddr_offset, sockaddr_len) : NULL;
return sendto(fd, buf, len, flags, addr, sockaddr_len);
}
i32
wasm_recvfrom(i32 fd, i32 buff_offset, i32 size, i32 flags, i32 sockaddr_offset, i32 socklen_offset)
{
char * buf = get_memory_ptr_void(buff_offset, size);
socklen_t * len = get_memory_ptr_void(socklen_offset, sizeof(socklen_t));
struct sockaddr *addr = *len ? get_memory_ptr_void(sockaddr_offset, *len) : NULL;
return recvfrom(fd, buf, size, flags, addr, addr ? len : NULL);
}
i32
inner_syscall_handler(i32 n, i32 a, i32 b, i32 c, i32 d, i32 e, i32 f)
{
i32 res;
switch (n) {
case SYS_READ:
return wasm_read(a, b, c);
case SYS_WRITE:
return wasm_write(a, b, c);
case SYS_OPEN:
return wasm_open(a, b, c);
case SYS_CLOSE:
return wasm_close(a);
case SYS_STAT:
return wasm_stat(a, b);
case SYS_FSTAT:
return wasm_fstat(a, b);
case SYS_LSTAT:
return wasm_lstat(a, b);
case SYS_LSEEK:
return wasm_lseek(a, b, c);
case SYS_MMAP:
return wasm_mmap(a, b, c, d, e, f);
case SYS_MUNMAP:
return 0;
case SYS_BRK:
return 0;
case SYS_RT_SIGACTION:
return 0;
case SYS_RT_SIGPROGMASK:
return 0;
case SYS_IOCTL:
return wasm_ioctl(a, b, c);
case SYS_READV:
return wasm_readv(a, b, c);
case SYS_WRITEV:
return wasm_writev(a, b, c);
case SYS_MADVISE:
return 0;
case SYS_GETPID:
return wasm_getpid();
case SYS_FCNTL:
return wasm_fcntl(a, b, c);
case SYS_FSYNC:
return wasm_fsync(a);
case SYS_UNLINK:
return wasm_unlink(a);
case SYS_GETCWD:
return wasm_getcwd(a, b);
case SYS_GETEUID:
return wasm_geteuid();
case SYS_SET_THREAD_AREA:
return 0;
case SYS_SET_TID_ADDRESS:
return 0;
case SYS_GET_TIME:
return wasm_get_time(a, b);
case SYS_EXIT_GROUP:
return wasm_exit_group(a);
case SYS_FCHOWN:
return wasm_fchown(a, b, c);
case SYS_SOCKET:
return wasm_socket(a, b, c);
case SYS_CONNECT:
return wasm_connect(a, b, c);
case SYS_ACCEPT:
return wasm_accept(a, b, c);
case SYS_BIND:
return wasm_bind(a, b, c);
case SYS_LISTEN:
return wasm_listen(a, b);
case SYS_SENDTO:
return wasm_sendto(a, b, c, d, e, f);
case SYS_RECVFROM:
return wasm_recvfrom(a, b, c, d, e, f);
}
printf("syscall %d (%d, %d, %d, %d, %d, %d)\n", n, a, b, c, d, e, f);
assert(0);
return 0;
}
#endif

@ -19,7 +19,10 @@ u32 first_worker_processor = 0;
int worker_threads_argument[SBOX_NCORES] = { 0 }; // The worker sets its argument to -1 on error
pthread_t worker_threads[SBOX_NCORES];
static unsigned long long
/**
* @return timestamp in usec
**/
static u64
get_time()
{
struct timeval Tp;
@ -29,6 +32,10 @@ get_time()
return (Tp.tv_sec * 1000000 + Tp.tv_usec);
}
/**
* Returns instructions on use of CLI if used incorrectly
* @param cmd - The command the user entered
**/
static void
usage(char *cmd)
{
@ -36,8 +43,10 @@ usage(char *cmd)
debuglog("%s <modules_file>\n", cmd);
}
// Sets the process data segment (RLIMIT_DATA) and # file descriptors
// (RLIMIT_NOFILE) soft limit to its hard limit (see man getrlimit)
/**
* Sets the process data segment (RLIMIT_DATA) and # file descriptors
* (RLIMIT_NOFILE) soft limit to its hard limit (see man getrlimit)
**/
void set_resource_limits_to_max(){
struct rlimit resource_limit;
if (getrlimit(RLIMIT_DATA, &resource_limit) < 0) {
@ -60,6 +69,9 @@ void set_resource_limits_to_max(){
}
}
/**
* Check the number of cores and the compiler flags and allocate available cores
**/
void allocate_available_cores(){
// Find the number of processors currently online
total_online_processors = sysconf(_SC_NPROCESSORS_ONLN);
@ -80,8 +92,11 @@ void allocate_available_cores(){
first_worker_processor, MOD_REQ_CORE);
}
// If NOSTIO is defined, close stdin, stdout, stderr, and write to logfile named awesome.log. Otherwise, log to STDOUT
// NOSTIO = No Standard Input/Output?
/**
* If NOSTIO is defined, close stdin, stdout, stderr, and write to logfile named awesome.log.
* Otherwise, log to STDOUT
* NOSTIO = No Standard Input/Output?
**/
void process_nostio(){
#ifdef NOSTDIO
fclose(stdout);
@ -97,6 +112,9 @@ void process_nostio(){
#endif
}
/**
* Starts all worker threads and sleeps forever on pthread_join, which should never return
**/
void start_worker_threads(){
for (int i = 0; i < total_worker_processors; i++) {
int ret = pthread_create(&worker_threads[i], NULL, sandbox_run_func, (void *)&worker_threads_argument[i]);

@ -68,6 +68,9 @@ sandbox_pull(void)
static __thread unsigned int in_callback;
/**
* Run all outstanding events in the libuv event loop
**/
void
sandbox_io_nowait(void)
{
@ -82,10 +85,13 @@ sandbox_io_nowait(void)
// zero, so there is nothing (don't block!)
}
/**
* @param interrupt seems to be treated as boolean to indicate is_interrupt or not
* @returns A sandbox???
**/
struct sandbox *
sandbox_schedule(int interrupt)
{
struct sandbox *s = NULL;
if (ps_list_head_empty(&local_run_queue)) {
// this is in an interrupt context, don't steal work here!
if (interrupt) return NULL;
@ -95,15 +101,15 @@ sandbox_schedule(int interrupt)
}
}
s = ps_list_head_first_d(&local_run_queue, struct sandbox);
struct sandbox *sandbox = ps_list_head_first_d(&local_run_queue, struct sandbox);
assert(s->state != SANDBOX_RETURNED);
assert(sandbox->state != SANDBOX_RETURNED);
// round-robin
ps_list_rem_d(s);
ps_list_head_append_d(&local_run_queue, s);
debuglog("[%p: %s]\n", s, s->mod->name);
ps_list_rem_d(sandbox);
ps_list_head_append_d(&local_run_queue, sandbox);
debuglog("[%p: %s]\n", sandbox, sandbox->mod->name);
return s;
return sandbox;
}
/**
@ -123,6 +129,11 @@ sandbox_local_free(unsigned int number_to_free)
}
}
/**
* ???
* @return sandbox
**/
struct sandbox *
sandbox_schedule_io(void)
{
@ -138,6 +149,11 @@ sandbox_schedule_io(void)
return s;
}
/**
* ???
* @param s sandbox
**/
void
sandbox_wakeup(sandbox_t *s)
{
@ -152,6 +168,10 @@ done:
softint_enable();
}
/**
* ???
**/
void
sandbox_block(void)
{
@ -166,6 +186,10 @@ sandbox_block(void)
sandbox_switch(s);
}
/**
* ???
**/
void
sandbox_block_http(void)
{
@ -184,6 +208,10 @@ sandbox_block_http(void)
#endif
}
/**
* ???
**/
void __attribute__((noinline)) __attribute__((noreturn)) sandbox_switch_preempt(void)
{
pthread_kill(pthread_self(), SIGUSR1);
@ -192,19 +220,32 @@ void __attribute__((noinline)) __attribute__((noreturn)) sandbox_switch_preempt(
while (true)
;
}
/**
* ???
* @param s sandbox
**/
static inline void
sandbox_local_stop(struct sandbox *s)
{
ps_list_rem_d(s);
}
/**
* Adds sandbox to the completion queue
* @param sandbox
**/
void
sandbox_local_end(struct sandbox *s)
sandbox_local_end(struct sandbox *sandbox)
{
assert(ps_list_singleton_d(s));
ps_list_head_append_d(&local_completion_queue, s);
assert(ps_list_singleton_d(sandbox));
ps_list_head_append_d(&local_completion_queue, sandbox);
}
/**
* ???
* @param data - argument provided by pthread API. We set to -1 on error
**/
void *
sandbox_run_func(void *data)
{
@ -244,7 +285,9 @@ sandbox_run(sbox_request_t *sandbox_request)
sandbox_deque_push(sandbox_request);
}
// perhaps respond to request
/**
* ???
**/
void
sandbox_exit(void)
{

@ -150,6 +150,10 @@ sandbox_client_request_get(void)
return 1;
}
/**
* Sends Response Back to Client
* @return RC. -1 on Failure
**/
static inline int
sandbox_client_response_set(void)
{
@ -182,6 +186,9 @@ sandbox_client_response_set(void)
done:
assert(sndsz == curr->rr_data_len);
// Get End Timestamp
curr->total_time = rdtsc() - curr->start_time;
printf("Function returned in %lu cycles\n", curr->total_time);
#ifndef USE_HTTP_UVIO
int r = send(curr->csock, curr->req_resp_data, sndsz, 0);
@ -208,65 +215,6 @@ done:
return 0;
}
// static inline int
// sandbox_client_response_set(void)
//{
//#ifndef STANDALONE
// struct sandbox *curr = sandbox_current();
//
// int bodylen = curr->rr_data_len;
// if (bodylen > 0) {
// http_response_body_set(curr->req_resp_data, bodylen);
// char len[16] = { 0 };
// sprintf(len, "%d", bodylen);
// //content-length = body length
// char *key = curr->req_resp_data + curr->rr_data_len;
// int lenlen = strlen("content-length: "), dlen = strlen(len);
// strcpy(key, "content-length: ");
// strncat(key + lenlen, len, dlen);
// strncat(key + lenlen + dlen, "\r\n", 2);
// http_response_header_set(key, lenlen + dlen + 2);
// curr->rr_data_len += lenlen + dlen + 2;
//
// //content-type as set in the headers.
// key = curr->req_resp_data + curr->rr_data_len;
// strcpy(key, "content-type: ");
// lenlen = strlen("content-type: ");
// dlen = strlen(curr->mod->rspctype);
// if (dlen == 0) {
// int l = strlen("text/plain\r\n\r\n");
// strncat(key + lenlen, "text/plain\r\n\r\n", l);
// http_response_header_set(key, lenlen + l);
// curr->rr_data_len += lenlen + l;
// } else {
// strncat(key + lenlen, curr->mod->rspctype, dlen);
// strncat(key + lenlen + dlen, "\r\n\r\n", 4);
// http_response_header_set(key, lenlen + dlen + 4);
// curr->rr_data_len += lenlen + dlen + 4;
// }
// //TODO - other headers requested in module!
// }
//
// char *st = curr->req_resp_data + curr->rr_data_len;
// strcpy(st, "HTTP/1.1 200 OK\r\n");
// curr->rr_data_len += strlen("HTTP/1.1 200 OK\r\n");
//
// http_response_status_set(st, strlen("HTTP/1.1 200 OK\r\n"));
// int n = http_response_vector();
//#ifndef USE_HTTP_UVIO
// int r = writev(curr->csock, curr->rsi.bufs, n);
// if (r < 0) perror("writev");
//#else
// uv_write_t req = { .data = curr, };
// int r = uv_write(&req, (uv_stream_t *)&curr->cuv, curr->rsi.bufs, n, sb_write_callback);
// sandbox_block_http();
//#endif
// return 0;
//#else
// return 0;
//#endif
//}
void
sandbox_entry(void)
{

@ -13,12 +13,16 @@
#include <arch/context.h>
#include <softint.h>
__thread static volatile sig_atomic_t alarm_cnt = 0, usr1_cnt = 0;
__thread static volatile sig_atomic_t alarm_cnt = 0;
__thread static volatile sig_atomic_t usr1_cnt = 0;
__thread volatile sig_atomic_t softint_off = 0;
static const int softints[] = { SIGALRM, SIGUSR1 };
/**
* Arms the periodic timers
**/
void
softint_timer_arm(void)
{
@ -37,6 +41,9 @@ softint_timer_arm(void)
#endif
}
/**
* Disarms the periodic timers
**/
void
softint_timer_disarm(void)
{
@ -53,6 +60,10 @@ softint_timer_disarm(void)
}
}
/**
* ???
* @param u ???
**/
static inline void
softint_alarm_schedule(void *u)
{
@ -87,6 +98,12 @@ skip:
extern pthread_t worker_threads[];
/**
* ???
* @param sig Signal Type
* @param si ???
* @param u ???
**/
static inline void
softint_handler(int sig, siginfo_t *si, void *u)
{
@ -159,6 +176,9 @@ softint_handler(int sig, siginfo_t *si, void *u)
#endif
}
/**
* ???
**/
void
softint_init(void)
{

@ -11,6 +11,12 @@
#define UTIL_MOD_LINE_MAX 1024
/**
* Removes leading and trailing spaces from a string
* @param str source string
* @return string without leading or training spaces
**/
static char *
util_remove_spaces(char *str)
{
@ -26,6 +32,7 @@ util_remove_spaces(char *str)
/**
* Parses a JSON file and allocates one or more new modules
* @param filename The path of the JSON file
* @return RC 0 on Success. -1 on Error
*/
int
util_parse_modules_file_json(char *filename)
@ -162,12 +169,14 @@ util_parse_modules_file_json(char *filename)
return 0;
}
/*
/**
* TEST data file should contain:
* module_name:<arg1,arg2,arg3...>
* and if your arg has to contain a ',', woops i can't deal with that for now!
* if the first character in a line is ";", then the line is ignored!
*/
* @param filename
* @return RC 0 on Success. -1 on Error
**/
int
parse_sandbox_file_custom(char *filename)
{
@ -227,7 +236,13 @@ parse_sandbox_file_custom(char *filename)
return 0;
}
/**
* ???
* @param mod
* @param str
* @param addr
* @return sandbox
**/
struct sandbox *
util_parse_sandbox_string_json(struct module *mod, char *str, const struct sockaddr *addr)
{
@ -276,6 +291,13 @@ util_parse_sandbox_string_json(struct module *mod, char *str, const struct socka
return NULL;
}
/**
* ???
* @param mod
* @param str
* @param addr
* @return sandbox
**/
struct sandbox *
util_parse_sandbox_string_custom(struct module *mod, char *str, const struct sockaddr *addr)
{
@ -305,12 +327,13 @@ util_parse_sandbox_string_custom(struct module *mod, char *str, const struct soc
return sb;
}
/*
/**
* Each line in the file should be like:
*
* module_path:module_name:module_nargs:module_stack_size:module_max_heap_size[:moreargs::argn\n]
* if the first character in a line is ";", then the line is ignored!
*/
* @param filename
* @return RC
**/
int
util_parse_modules_file_custom(char *filename)
{

Loading…
Cancel
Save