Rebase and squash the FreeBSD PAL.

This commit is contained in:
woachk
2018-10-20 09:42:46 +02:00
committed by Don Porter
parent 7f5a4cc87f
commit f07dfd052f
19 changed files with 763 additions and 437 deletions
+2 -2
View File
@@ -16,8 +16,8 @@ host_target = libpal-FreeBSD.a ../../pal-gdb
defs = -DIN_PAL -DPAL_DIR="$(PAL_DIR)"
objs = $(addprefix db_,files devices pipes sockets streams memory threading \
semaphore mutex events process object main rtld misc ipc \
exception) rfork_thread
mutex events process object main rtld misc ipc \
exception2) rfork_thread
graphene_lib = .lib/graphene-lib.a
headers = $(wildcard *.h) $(wildcard ../../*.h) $(wildcard ../../../lib/*.h)
+2 -2
View File
@@ -104,12 +104,12 @@ static int open_standard_term (PAL_HANDLE * handle, const char * param,
hdl->dev.dev_type = device_type_term;
if (!(access & PAL_ACCESS_WRONLY)) {
hdl->__in.flags |= RFD(0);
hdl->hdr.flags |= RFD(0);
hdl->dev.fd_in = 0;
}
if (access & (PAL_ACCESS_WRONLY|PAL_ACCESS_RDWR)) {
hdl->__in.flags |= WFD(1);
hdl->hdr.flags |= WFD(1);
hdl->dev.fd_out = 1;
}
+19 -1
View File
@@ -78,7 +78,7 @@ int _DkEventSet (PAL_HANDLE event, int wakeup)
return IS_ERR(ret) ? PAL_ERROR_TRYAGAIN : ret;
}
int _DkEventWaitTimeout (PAL_HANDLE event, int timeout)
int _DkEventWaitTimeout (PAL_HANDLE event, uint64_t timeout)
{
int ret = 0;
if (!event->event.isnotification || !atomic_read(&event->event.signaled)) {
@@ -142,3 +142,21 @@ int _DkEventClear (PAL_HANDLE event)
atomic_set(&event->event.signaled, 0);
return 0;
}
static int event_close (PAL_HANDLE handle)
{
_DkEventSet(handle, -1);
return 0;
}
static int event_wait (PAL_HANDLE handle, uint64_t timeout)
{
return timeout == NO_TIMEOUT ? _DkEventWait(handle) :
_DkEventWaitTimeout(handle, timeout);
}
struct handle_ops event_ops = {
.close = &event_close,
.wait = &event_wait,
};
+4 -5
View File
@@ -40,6 +40,8 @@
#include <ucontext.h>
#include <errno.h>
typedef void (*PAL_UPCALL) (PAL_PTR, PAL_NUM, PAL_CONTEXT *);
int set_sighandler (int * sigs, int nsig, void * handler)
{
struct sigaction action;
@@ -327,8 +329,7 @@ static struct pal_frame * get_frame (ucontext_t * uc)
for (unsigned long ptr = rbp - sizeof(unsigned long) ;
ptr > last_rbp ; ptr -= 8) {
struct pal_frame * frame = (struct pal_frame *) ptr;
if (frame->self == frame)
if (frame->identifier == PAL_FRAME_IDENTIFIER)
return frame;
}
@@ -429,7 +430,6 @@ struct signal_ops {
};
struct signal_ops on_signals[PAL_EVENT_NUM_BOUND] = {
/* reserved */ { .signum = { 0 }, .handler = NULL },
/* DivZero */ { .signum = { SIGFPE, 0 },
.handler = _DkGenericSighandler },
/* MemFault */ { .signum = { SIGSEGV, SIGBUS, 0 },
@@ -442,7 +442,6 @@ struct signal_ops on_signals[PAL_EVENT_NUM_BOUND] = {
.handler = _DkTerminateSighandler },
/* Resume */ { .signum = { SIGCONT, 0 },
.handler = _DkGenericSighandler },
/* Failure */ { .signum = { 0 }, .handler = NULL },
};
static int _DkPersistentSighandlerSetup (int event_num)
@@ -571,7 +570,7 @@ err:
init_fail(-ret, "cannot setup signal handlers");
}
void _DkExceptionReturn (const void * event)
void _DkExceptionReturn (void * event)
{
const struct exception_event * e = (const struct exception_event *) event;
if (e->uc) {
+465
View File
@@ -0,0 +1,465 @@
/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
/* Copyright (C) 2014 Stony Brook University
This file is part of Graphene Library OS.
Graphene Library OS is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Graphene Library OS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/*
* db_signal.c
*
* This file contains APIs to set up handlers of exceptions issued by the
* host, and the methods to pass the exceptions to the upcalls.
*/
#include "pal_defs.h"
#include "pal_freebsd_defs.h"
#include "pal.h"
#include "pal_internal.h"
#include "pal_freebsd.h"
#include "pal_error.h"
#include "pal_security.h"
#include "api.h"
#include <atomic.h>
#include <sigset.h>
#include <ucontext.h>
#include <errno.h>
#if !defined(__i386__)
/* In x86_64 kernels, sigaction is required to have a user-defined
* restorer. Also, they not yet support SA_INFO. The reference:
* http://lxr.linux.no/linux+v2.6.35/arch/x86/kernel/signal.c#L448
*
* / * x86-64 should always use SA_RESTORER. * /
* if (ka->sa.sa_flags & SA_RESTORER) {
* put_user_ex(ka->sa.sa_restorer, &frame->pretcode);
* } else {
* / * could use a vstub here * /
* err |= -EFAULT;
* }
*/
void restore_rt (void) asm ("__restore_rt");
#ifndef SA_RESTORER
#define SA_RESTORER 0x04000000
#endif
#define DEFINE_RESTORE_RT(syscall) DEFINE_RESTORE_RT2(syscall)
# define DEFINE_RESTORE_RT2(syscall) \
asm ( \
" nop\n" \
".align 16\n" \
".LSTART_restore_rt:\n" \
" .type __restore_rt,@function\n" \
"__restore_rt:\n" \
" movq $" #syscall ", %rax\n" \
" syscall\n");
#endif
int set_sighandler (int * sigs, int nsig, void * handler)
{
struct sigaction action;
if (handler) {
action.sa_handler = (void (*)(int)) handler;
action.sa_flags = SA_SIGINFO;
#if !defined(__i386__)
//action.sa_flags |= SA_RESTORER;
//action.sa_restorer = restore_rt;
#endif
} else {
action.sa_handler = SIG_IGN;
}
#ifdef DEBUG
if (!linux_state.in_gdb)
#endif
action.sa_flags |= SA_NOCLDWAIT;
__sigemptyset((__sigset_t *) &action.sa_mask);
__sigaddset((__sigset_t *) &action.sa_mask, SIGCONT);
for (int i = 0 ; i < nsig ; i++) {
#if defined(__i386__)
int ret = INLINE_SYSCALL(sigaction, 3, sigs[i], &action, NULL)
#else
int ret = INLINE_SYSCALL(sigaction, 4, sigs[i], &action, NULL,
sizeof(sigset_t));
#endif
if (IS_ERR(ret))
return -PAL_ERROR_DENIED;
}
return 0;
}
typedef struct {
PAL_IDX event_num;
PAL_CONTEXT context;
ucontext_t * uc;
PAL_PTR eframe;
} PAL_EVENT;
#define SIGNAL_MASK_TIME 1000
#define save_return_point(ptr) \
asm volatile ("leaq 0(%%rip), %%rax\r\n" \
"movq %%rax, %0\r\n" \
: "=b"(ptr) :: "memory", "rax")
static int get_event_num (int signum)
{
switch(signum) {
case SIGFPE: return PAL_EVENT_DIVZERO;
case SIGSEGV: case SIGBUS: return PAL_EVENT_MEMFAULT;
case SIGILL: case SIGSYS: return PAL_EVENT_ILLEGAL;
case SIGTERM: return PAL_EVENT_QUIT;
case SIGINT: return PAL_EVENT_SUSPEND;
case SIGCONT: return PAL_EVENT_RESUME;
default: return -1;
}
}
void _DkGenericEventTrigger (PAL_IDX event_num, PAL_EVENT_HANDLER upcall,
PAL_NUM arg, struct pal_frame * frame,
ucontext_t * uc, void * eframe)
{
PAL_EVENT event;
event.event_num = event_num;
if (uc) {
event.context.r8 = uc->uc_mcontext.mc_r8;
event.context.r9 = uc->uc_mcontext.mc_r9;
event.context.r10 = uc->uc_mcontext.mc_r10;
event.context.r11 = uc->uc_mcontext.mc_r11;
event.context.r12 = uc->uc_mcontext.mc_r12;
event.context.r13 = uc->uc_mcontext.mc_r13;
event.context.r14 = uc->uc_mcontext.mc_r14;
event.context.r15 = uc->uc_mcontext.mc_r15;
event.context.rdi = uc->uc_mcontext.mc_rdi;
event.context.rsi = uc->uc_mcontext.mc_rsi;
event.context.rbp = uc->uc_mcontext.mc_rbp;
event.context.rbx = uc->uc_mcontext.mc_rbx;
event.context.rdx = uc->uc_mcontext.mc_rdx;
event.context.rax = uc->uc_mcontext.mc_rax;
event.context.rcx = uc->uc_mcontext.mc_rcx;
event.context.rsp = uc->uc_mcontext.mc_rsp;
event.context.rip = uc->uc_mcontext.mc_rip;
event.context.efl = uc->uc_mcontext.mc_flags;
event.context.err = uc->uc_mcontext.mc_err;
event.context.trapno = uc->uc_mcontext.mc_trapno;
event.context.csgsfs = 0;
event.context.oldmask = 0;
event.context.cr2 = 0;
}
if (frame) {
event.context.r15 = frame->arch.r15;
event.context.r14 = frame->arch.r14;
event.context.r13 = frame->arch.r13;
event.context.r12 = frame->arch.r12;
event.context.rdi = frame->arch.rdi;
event.context.rsi = frame->arch.rsi;
event.context.rbx = frame->arch.rbx;
/* find last frame */
event.context.rsp = frame->arch.rbp + sizeof(unsigned long) * 2;
event.context.rbp = ((unsigned long *) frame->arch.rbp)[0];
event.context.rip = ((unsigned long *) frame->arch.rbp)[1];
/* making rax = 0 to tell the caller that this PAL call failed */
event.context.rax = 0;
}
event.uc = uc;
event.eframe = eframe;
(*upcall) ((PAL_PTR) &event, arg, &event.context);
}
static bool _DkGenericSignalHandle (int event_num, siginfo_t * info,
struct pal_frame * frame,
ucontext_t * uc, void * eframe)
{
PAL_EVENT_HANDLER upcall = _DkGetExceptionHandler(event_num);
if (upcall) {
PAL_NUM arg = 0;
if (event_num == PAL_EVENT_DIVZERO ||
event_num == PAL_EVENT_MEMFAULT ||
event_num == PAL_EVENT_ILLEGAL)
arg = (PAL_NUM) (info ? info->si_addr : 0);
_DkGenericEventTrigger(event_num, upcall, arg, frame, uc, eframe);
return true;
}
return false;
}
#define ADDR_IN_PAL(addr) \
((void *) (addr) > TEXT_START && (void *) (addr) < TEXT_END)
/* This function walks the stack to find the PAL_FRAME
* that was saved upon entry to the PAL, if an exception/interrupt
* comes in during a PAL call. This is needed to support the behavior that an
* exception in the PAL has Unix-style, EAGAIN semantics.
*
* The PAL_FRAME is supposed to be in the first PAL frame, and we look for
* it by matching a special magic number, that should only appear on the stack
* once.
*
* If an exception comes in while we are not in the PAL, this PAL_FRAME won't
* exist, and it is ok to return NULL.
*/
static struct pal_frame * get_frame (ucontext_t * uc)
{
unsigned long rip = uc->uc_mcontext.mc_rip;
unsigned long rbp = uc->uc_mcontext.mc_rbp;
unsigned long last_rbp = rbp - 64;
if (!ADDR_IN_PAL(rip))
return NULL;
while (ADDR_IN_PAL(((unsigned long *) rbp)[1])) {
last_rbp = rbp;
rbp = *(unsigned long *) rbp;
}
/* search frame record in the top frame of PAL */
for (unsigned long ptr = rbp - sizeof(unsigned long) ;
ptr > last_rbp ; ptr -= 8) {
struct pal_frame * frame = (struct pal_frame *) ptr;
if (frame->identifier == PAL_FRAME_IDENTIFIER)
return frame;
}
return NULL;
}
static void return_frame (struct pal_frame * frame, int err)
{
if (err)
_DkRaiseFailure(err);
__clear_frame(frame);
arch_restore_frame(&frame->arch);
asm volatile ("xor %rax, %rax\r\n"
"leaveq\r\n"
"retq\r\n");
}
#if BLOCK_SIGFAULT == 1
static char exception_msg[24] = "--- SIGSEGV --- [ ]\n";
static volatile bool cont_exec = false;
#endif
static void _DkGenericSighandler (int signum, siginfo_t * info,
struct ucontext * uc)
{
#if BLOCK_SIGFUALT == 1
/* reseurrect this code if signal handler if giving segmentation fault */
if (signum == SIGSEGV) {
int pid = INLINE_SYSCALL(getpid, 0);
exception_msg[17] = '0' + pid / 10000;
exception_msg[18] = '0' + (pid / 1000) % 10;
exception_msg[19] = '0' + (pid / 100) % 10;
exception_msg[20] = '0' + (pid / 10) % 10;
exception_msg[21] = '0' + pid % 10;
INLINE_SYSCALL(write, 3, 1, exception_msg, 24);
while(!cont_exec);
}
#endif
struct pal_frame * frame = get_frame(uc);
void * eframe;
if (signum == SIGCONT && frame && frame->func == DkObjectsWaitAny)
return;
asm volatile ("movq %%rbp, %0" : "=r"(eframe));
if (frame && frame->func != &_DkGenericSighandler &&
signum != SIGCONT &&
signum != SIGINT &&
signum != SIGTERM) {
return_frame(frame, PAL_ERROR_BADADDR);
return;
}
int event_num = get_event_num(signum);
if (event_num == -1)
return;
_DkGenericSignalHandle(event_num, info, frame, uc, eframe);
}
static void _DkTerminateSighandler (int signum, siginfo_t * info,
struct ucontext * uc)
{
struct pal_frame * frame = get_frame(uc);
void * eframe;
asm volatile ("movq %%rbp, %0" : "=r"(eframe));
int event_num = get_event_num(signum);
if (event_num == -1)
return;
if (!_DkGenericSignalHandle(event_num, NULL, frame, uc, eframe))
_DkThreadExit();
}
static void _DkPipeSighandler (int signum, siginfo_t * info,
struct ucontext * uc)
{
return;
}
void _DkRaiseFailure (int error)
{
PAL_EVENT_HANDLER upcall = _DkGetExceptionHandler(PAL_EVENT_FAILURE);
if (!upcall)
return;
PAL_EVENT event;
event.event_num = PAL_EVENT_FAILURE;
event.uc = NULL;
event.eframe = NULL;
(*upcall) ((PAL_PTR) &event, error, NULL);
}
struct signal_ops {
int signum[3];
void (*handler) (int signum, siginfo_t * info, ucontext_t * uc);
};
struct signal_ops on_signals[] = {
[PAL_EVENT_DIVZERO] = { .signum = { SIGFPE, 0 },
.handler = _DkGenericSighandler },
[PAL_EVENT_MEMFAULT] = { .signum = { SIGSEGV, SIGBUS, 0 },
.handler = _DkGenericSighandler },
[PAL_EVENT_ILLEGAL] = { .signum = { SIGILL, SIGSYS, 0 },
.handler = _DkGenericSighandler },
[PAL_EVENT_QUIT] = { .signum = { SIGTERM, 0, 0 },
.handler = _DkTerminateSighandler },
[PAL_EVENT_SUSPEND] = { .signum = { SIGINT, 0 },
.handler = _DkTerminateSighandler },
[PAL_EVENT_RESUME] = { .signum = { SIGCONT, 0 },
.handler = _DkGenericSighandler },
};
static int _DkPersistentSighandlerSetup (int event_num)
{
int nsigs, * sigs = on_signals[event_num].signum;
for (nsigs = 0 ; sigs[nsigs] ; nsigs++);
int ret = set_sighandler(sigs, nsigs, on_signals[event_num].handler);
if (ret < 0)
return ret;
return 0;
}
void signal_setup (void)
{
int ret, sig = SIGCHLD;
#ifdef DEBUG
if (!linux_state.in_gdb)
#endif
set_sighandler(&sig, 1, NULL);
sig = SIGPIPE;
if ((ret = set_sighandler(&sig, 1, &_DkPipeSighandler)) < 0)
goto err;
int events[] = {
PAL_EVENT_DIVZERO,
PAL_EVENT_MEMFAULT,
PAL_EVENT_ILLEGAL,
PAL_EVENT_QUIT,
PAL_EVENT_SUSPEND,
PAL_EVENT_RESUME,
};
for (int e = 0 ; e < sizeof(events) / sizeof(events[0]) ; e++)
if ((ret = _DkPersistentSighandlerSetup(events[e])) < 0)
goto err;
return;
err:
init_fail(-ret, "cannot setup signal handlers");
}
void _DkExceptionReturn (void * event)
{
PAL_EVENT * e = event;
if (e->eframe) {
struct pal_frame * frame = (struct pal_frame *) e->eframe;
int err = 0;
switch (e->event_num) {
case PAL_EVENT_MEMFAULT:
err = PAL_ERROR_BADADDR;
break;
case PAL_EVENT_QUIT:
case PAL_EVENT_SUSPEND:
case PAL_EVENT_RESUME:
err = PAL_ERROR_INTERRUPTED;
break;
}
if (err)
_DkRaiseFailure(err);
__clear_frame(frame);
}
if (e->uc) {
/* copy the context back to ucontext */
e->uc->uc_mcontext.mc_r8 = e->context.r8;
e->uc->uc_mcontext.mc_r9 = e->context.r9;
e->uc->uc_mcontext.mc_r10 = e->context.r10;
e->uc->uc_mcontext.mc_r11 = e->context.r11;
e->uc->uc_mcontext.mc_r12 = e->context.r12;
e->uc->uc_mcontext.mc_r13 = e->context.r13;
e->uc->uc_mcontext.mc_r14 = e->context.r14;
e->uc->uc_mcontext.mc_r15 = e->context.r15;
e->uc->uc_mcontext.mc_rdi = e->context.rdi;
e->uc->uc_mcontext.mc_rsi = e->context.rsi;
e->uc->uc_mcontext.mc_rbp = e->context.rbp;
e->uc->uc_mcontext.mc_rbx = e->context.rbx;
e->uc->uc_mcontext.mc_rdx = e->context.rdx;
e->uc->uc_mcontext.mc_rax = e->context.rax;
e->uc->uc_mcontext.mc_rcx = e->context.rcx;
e->uc->uc_mcontext.mc_rsp = e->context.rsp;
e->uc->uc_mcontext.mc_rip = e->context.rip;
e->uc->uc_mcontext.mc_flags = e->context.efl;
e->uc->uc_mcontext.mc_err = e->context.err;
e->uc->uc_mcontext.mc_trapno = e->context.trapno;
/* return to the frame of exception handler */
asm volatile ("movq %0, %%rbp\r\n"
"leaveq\r\n"
"retq\r\n" :: "r"(e->eframe) : "memory");
}
}
+4 -4
View File
@@ -58,7 +58,7 @@ static int file_open (PAL_HANDLE * handle, const char * type, const char * uri,
int len = strlen(uri);
PAL_HANDLE hdl = malloc(HANDLE_SIZE(file) + len + 1);
SET_HANDLE_TYPE(hdl, file);
hdl->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
hdl->hdr.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
hdl->file.fd = ret;
hdl->file.offset = 0;
hdl->file.append = 0;
@@ -243,7 +243,7 @@ static int file_attrquery (const char * type, const char * uri,
static int file_attrquerybyhdl (PAL_HANDLE handle,
PAL_STREAM_ATTR * attr)
{
int fd = handle->__in.fds[0];
int fd = handle->hdr.fds[0];
struct stat stat_buf;
int ret = INLINE_SYSCALL(fstat, 2, fd, &stat_buf);
@@ -258,7 +258,7 @@ static int file_attrquerybyhdl (PAL_HANDLE handle,
static int file_attrsetbyhdl (PAL_HANDLE handle,
PAL_STREAM_ATTR * attr)
{
int fd = handle->__in.fds[0], ret;
int fd = handle->hdr.fds[0], ret;
ret = INLINE_SYSCALL(fchmod, 2, fd, attr->share_flags);
if (IS_ERR(ret))
@@ -341,7 +341,7 @@ static int dir_open (PAL_HANDLE * handle, const char * type, const char * uri,
int len = strlen(uri);
PAL_HANDLE hdl = malloc(HANDLE_SIZE(dir) + len + 1);
SET_HANDLE_TYPE(hdl, dir);
hdl->__in.flags |= RFD(0);
hdl->hdr.flags |= RFD(0);
hdl->dir.fd = ret;
char * path = (void *) hdl + HANDLE_SIZE(dir);
memcpy(path, uri, len + 1);
+9 -59
View File
@@ -186,57 +186,6 @@ PAL_NUM _DkGetHostId (void)
return 0;
}
int create_domain_dir (void)
{
int ret = 0;
const char * path;
ret = INLINE_SYSCALL(mkdir, 2, (path = GRAPHENE_PIPEDIR), 0777);
if (IS_ERR(ret) && ERRNO(ret) != EEXIST) {
if (ERRNO(ret) == ENOENT) {
ret = INLINE_SYSCALL(mkdir, 2, (path = GRAPHENE_TEMPDIR), 0777);
if (!IS_ERR(ret)) {
INLINE_SYSCALL(chmod, 2, GRAPHENE_TEMPDIR, 0777);
ret = INLINE_SYSCALL(mkdir, 2, (path = GRAPHENE_PIPEDIR), 0777);
}
}
if (IS_ERR(ret)) {
printf("Cannot create directory %s, please check permission\n",
path);
return -PAL_ERROR_DENIED;
}
}
if (!IS_ERR(ret))
INLINE_SYSCALL(chmod, 2, GRAPHENE_PIPEDIR, 0777);
char * pipedir = __alloca(sizeof(GRAPHENE_PIPEDIR) + 10);
unsigned int id;
do {
if (!getrand(&id, sizeof(unsigned int))) {
printf("Unable to generate random numbers\n");
return -PAL_ERROR_DENIED;
}
snprintf(pipedir, sizeof(GRAPHENE_PIPEDIR) + 10,
GRAPHENE_PIPEDIR "/%08x", id);
ret = INLINE_SYSCALL(mkdir, 2, pipedir, 0700);
if (IS_ERR(ret) && ERRNO(ret) != -EEXIST) {
printf("Cannot create directory %s, please fix permission\n",
pipedir);
return -PAL_ERROR_DENIED;
}
} while (IS_ERR(ret));
pal_sec.domain_id = id;
return 0;
}
#include "dynamic_link.h"
void setup_pal_map (struct link_map * map);
@@ -271,6 +220,9 @@ void pal_bsd_main (void * args)
bsd_state.pid = INLINE_SYSCALL(getpid, 0);
bsd_state.uid = uid;
bsd_state.gid = gid;
if (!bsd_state.parent_pid)
bsd_state.parent_pid = bsd_state.pid;
PAL_HANDLE first_thread = malloc(HANDLE_SIZE(thread));
SET_HANDLE_TYPE(first_thread, thread);
@@ -288,7 +240,7 @@ void pal_bsd_main (void * args)
int len = strlen(argv[0]);
PAL_HANDLE file = malloc(HANDLE_SIZE(file) + len + 1);
SET_HANDLE_TYPE(file, file);
file->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
file->hdr.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
file->file.fd = fd;
char * path = (void *) file + HANDLE_SIZE(file);
get_norm_path(argv[0], path, 0, len + 1);
@@ -302,17 +254,15 @@ void pal_bsd_main (void * args)
manifest = file;
done_init:
/* Create domain directory for pipes */
if(!pal_sec.domain_id){
if ((ret = create_domain_dir()) < 0)
init_fail(-ret, "cannot create pipe directory");
if (!parent && !exec && !manifest) {
printf("USAGE: %s [executable|manifest] args ...\n", pal_name);
_DkProcessExit(0);
return;
}
signal_setup();
/* jump to main function */
pal_main(pal_sec.domain_id, (void *) pal_map.l_addr,
pal_name, argc, argv, envp, parent, first_thread, exec, manifest);
pal_main(bsd_state.parent_pid, manifest, exec, NULL, parent, first_thread, argv, envp);
}
/* the following code is borrowed from CPUID */
+3 -3
View File
@@ -40,7 +40,7 @@ bool _DkCheckMemoryMappable (const void * addr, int size)
{
return (addr <= DATA_END && addr + size >= TEXT_START);
}
int _DkVirtualMemoryAlloc (void ** paddr, int size, int alloc_type,
int _DkVirtualMemoryAlloc (void ** paddr, uint64_t size, int alloc_type,
int prot)
{
void * addr = *paddr, * mem = addr;
@@ -59,14 +59,14 @@ int _DkVirtualMemoryAlloc (void ** paddr, int size, int alloc_type,
return 0;
}
int _DkVirtualMemoryFree (void * addr, int size)
int _DkVirtualMemoryFree (void * addr, uint64_t size)
{
int ret = INLINE_SYSCALL(munmap, 2, addr, size);
return IS_ERR(ret) ? unix_to_pal_error(ERRNO(ret)) : 0;
}
int _DkVirtualMemoryProtect (void * addr, int size, int prot)
int _DkVirtualMemoryProtect (void * addr, uint64_t size, int prot)
{
int ret = INLINE_SYSCALL(mprotect, 3, addr, size, HOST_PROT(prot));
+8 -1
View File
@@ -200,7 +200,7 @@ static int init_randgen (void)
return 0;
}
void getrand (void * buffer, size_t size)
int getrand (void * buffer, size_t size)
{
unsigned long val;
size_t bytes = 0;
@@ -228,4 +228,11 @@ void getrand (void * buffer, size_t size)
_DkInternalLock(&lock);
randval = val;
_DkInternalUnlock(&lock);
return 0;
}
int _DkCpuIdRetrieve (unsigned int leaf, unsigned int subleaf,
unsigned int values[4])
{
return -PAL_ERROR_NOTIMPLEMENTED;
}
+29 -1
View File
@@ -35,7 +35,6 @@
#include <limits.h>
#include <atomic.h>
#include <cmpxchg.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
@@ -203,3 +202,32 @@ int _DkMutexUnlock (struct mutex_handle * mut)
out:
return ret;
}
int _DkMutexAcquireTimeout (PAL_HANDLE handle, int timeout)
{
return _DkMutexLockTimeout(&handle->mutex.mut, timeout);
}
void _DkMutexRelease (PAL_HANDLE handle)
{
_DkMutexUnlock(&handle->mutex.mut);
return;
}
static int mutex_wait (PAL_HANDLE handle, uint64_t timeout)
{
return _DkMutexAcquireTimeout(handle, timeout);
}
struct handle_ops mutex_ops = {
.wait = &mutex_wait,
};
int _DkMutexCreate (PAL_HANDLE *handle, int count) {
PAL_HANDLE mut = malloc(HANDLE_SIZE(mutex));
SET_HANDLE_TYPE(mut, mutex);
atomic_set(&mut->mutex.mut.value, 0);
*handle = mut;
return 0;
}
+23 -24
View File
@@ -36,7 +36,6 @@
#include <sys/poll.h>
#include <sys/wait.h>
#include <atomic.h>
#include <cmpxchg.h>
#include <errno.h>
#define DEFAULT_QUANTUM 500
@@ -47,24 +46,24 @@ static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout)
{
/* only for all these handle which has a file descriptor, or
a eventfd. events and semaphores will skip this part */
if (handle->__in.flags & HAS_FDS) {
if (handle->hdr.flags & HAS_FDS) {
struct pollfd fds[MAX_FDS];
int off[MAX_FDS];
int nfds = 0;
for (int i = 0 ; i < MAX_FDS ; i++) {
int events = 0;
if ((handle->__in.flags & RFD(i)) &&
!(handle->__in.flags & ERROR(i)))
if ((handle->hdr.flags & RFD(i)) &&
!(handle->hdr.flags & ERROR(i)))
events |= POLLIN;
if ((handle->__in.flags & WFD(i)) &&
!(handle->__in.flags & WRITEABLE(i)) &&
!(handle->__in.flags & ERROR(i)))
if ((handle->hdr.flags & WFD(i)) &&
!(handle->hdr.flags & WRITEABLE(i)) &&
!(handle->hdr.flags & ERROR(i)))
events |= POLLOUT;
if (events) {
fds[nfds].fd = handle->__in.fds[i];
fds[nfds].fd = handle->hdr.fds[i];
fds[nfds].events = events|POLLHUP|POLLERR;
fds[nfds].revents = 0;
off[nfds] = i;
@@ -93,9 +92,9 @@ static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout)
if (!fds[i].revents)
continue;
if (fds[i].revents & POLLOUT)
handle->__in.flags |= WRITEABLE(off[i]);
handle->hdr.flags |= WRITEABLE(off[i]);
if (fds[i].revents & (POLLHUP|POLLERR))
handle->__in.flags |= ERROR(off[i]);
handle->hdr.flags |= ERROR(off[i]);
}
return 0;
@@ -111,7 +110,7 @@ static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout)
/* _DkObjectsWaitAny for internal use. The function wait for any of the handle
in the handle array. timeout can be set for the wait. */
int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, uint64_t timeout,
PAL_HANDLE * polled)
{
if (count <= 0)
@@ -133,7 +132,7 @@ int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
if (!hdl)
continue;
if (!(hdl->__in.flags & HAS_FDS))
if (!(hdl->hdr.flags & HAS_FDS))
return -PAL_ERROR_NOTSUPPORT;
/* eliminate repeated entries */
@@ -142,7 +141,7 @@ int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
break;
if (j == i) {
for (j = 0 ; j < MAX_FDS ; j++)
if (hdl->__in.flags & (RFD(j)|WFD(j)))
if (hdl->hdr.flags & (RFD(j)|WFD(j)))
maxfds++;
}
}
@@ -165,17 +164,17 @@ int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
for (j = 0 ; j < MAX_FDS ; j++) {
int events = 0;
if ((hdl->__in.flags & RFD(j)) &&
!(hdl->__in.flags & ERROR(j)))
if ((hdl->hdr.flags & RFD(j)) &&
!(hdl->hdr.flags & ERROR(j)))
events |= POLLIN;
if ((hdl->__in.flags & WFD(j)) &&
!(hdl->__in.flags & WRITEABLE(j)) &&
!(hdl->__in.flags & ERROR(j)))
if ((hdl->hdr.flags & WFD(j)) &&
!(hdl->hdr.flags & WRITEABLE(j)) &&
!(hdl->hdr.flags & ERROR(j)))
events |= POLLOUT;
if (events && hdl->__in.fds[j] != PAL_IDX_POISON) {
fds[nfds].fd = hdl->__in.fds[j];
if (events && hdl->hdr.fds[j] != PAL_IDX_POISON) {
fds[nfds].fd = hdl->hdr.fds[j];
fds[nfds].events = events|POLLHUP|POLLERR;
fds[nfds].revents = 0;
hdls[nfds] = hdl;
@@ -216,17 +215,17 @@ int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
}
for (j = 0 ; j < MAX_FDS ; j++)
if ((hdl->__in.flags & (RFD(j)|WFD(j))) &&
hdl->__in.fds[j] == fds[i].fd)
if ((hdl->hdr.flags & (RFD(j)|WFD(j))) &&
hdl->hdr.fds[j] == fds[i].fd)
break;
if (j == MAX_FDS)
continue;
if (fds[i].revents & POLLOUT)
hdl->__in.flags |= WRITEABLE(j);
hdl->hdr.flags |= WRITEABLE(j);
if (fds[i].revents & (POLLHUP|POLLERR))
hdl->__in.flags |= ERROR(j);
hdl->hdr.flags |= ERROR(j);
}
*polled = polled_hdl;
+18 -18
View File
@@ -102,7 +102,7 @@ static int pipe_listen (PAL_HANDLE * handle, PAL_NUM pipeid, int options)
PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipe));
SET_HANDLE_TYPE(hdl, pipesrv);
hdl->__in.flags |= RFD(0);
hdl->hdr.flags |= RFD(0);
hdl->pipe.fd = fd;
hdl->pipe.pipeid = pipeid;
hdl->pipe.nonblocking = options & O_NONBLOCK ?
@@ -160,14 +160,14 @@ static int pipe_waitforclient (PAL_HANDLE handle, PAL_HANDLE * client)
PAL_HANDLE clnt = malloc(HANDLE_SIZE(pipeprv));
SET_HANDLE_TYPE(clnt, pipeprv);
clnt->__in.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
clnt->hdr.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
clnt->pipeprv.fds[0] = pipes[0];
clnt->pipeprv.fds[1] = pipes[1];
*client = clnt;
#else
PAL_HANDLE clnt = malloc(HANDLE_SIZE(pipe));
SET_HANDLE_TYPE(clnt, pipecli);
clnt->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
clnt->hdr.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
clnt->pipe.fd = newfd;
clnt->pipe.nonblocking = PAL_FALSE;
clnt->pipe.pipeid = handle->pipe.pipeid;
@@ -254,7 +254,7 @@ static int pipe_connect (PAL_HANDLE * handle, PAL_NUM pipeid, int options)
PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipeprv));
SET_HANDLE_TYPE(hdl, pipeprv);
hdl->__in.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
hdl->hdr.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
hdl->pipeprv.fds[0] = pipes[0];
hdl->pipeprv.fds[1] = pipes[1];
hdl->pipeprv.nonblocking = (options & O_NONBLOCK) ?
@@ -262,7 +262,7 @@ static int pipe_connect (PAL_HANDLE * handle, PAL_NUM pipeid, int options)
#else
PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipe));
SET_HANDLE_TYPE(hdl, pipe);
hdl->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
hdl->hdr.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
hdl->pipe.fd = fd;
hdl->pipe.pipeid = pipeid;
hdl->pipe.nonblocking = (options & O_NONBLOCK) ?
@@ -290,7 +290,7 @@ static int pipe_private (PAL_HANDLE * handle, int options)
PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipeprv));
SET_HANDLE_TYPE(hdl, pipeprv);
hdl->__in.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
hdl->hdr.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
hdl->pipeprv.fds[0] = fds[0];
hdl->pipeprv.fds[1] = fds[1];
hdl->pipeprv.nonblocking = (options & O_NONBLOCK) ?
@@ -420,7 +420,7 @@ static int pipe_write (PAL_HANDLE handle, int offset, int len,
if (IS_ERR(bytes))
switch(ERRNO(bytes)) {
case EWOULDBLOCK:
handle->__in.flags &= ~writeable;
handle->hdr.flags &= ~writeable;
return-PAL_ERROR_TRYAGAIN;
case EINTR:
return -PAL_ERROR_INTERRUPTED;
@@ -429,9 +429,9 @@ static int pipe_write (PAL_HANDLE handle, int offset, int len,
}
if (bytes == len)
handle->__in.flags |= writeable;
handle->hdr.flags |= writeable;
else
handle->__in.flags &= ~writeable;
handle->hdr.flags &= ~writeable;
return bytes;
}
@@ -518,38 +518,38 @@ static int pipe_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
{
int ret, val;
if (handle->__in.fds[0] == PAL_IDX_POISON)
if (handle->hdr.fds[0] == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
ret = INLINE_SYSCALL(ioctl, 3, handle->__in.fds[0], FIONREAD, &val);
ret = INLINE_SYSCALL(ioctl, 3, handle->hdr.fds[0], FIONREAD, &val);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->handle_type = pal_type_pipe;
attr->disconnected = handle->__in.flags & ERROR(0);
attr->nonblocking = (handle->__in.type == pal_type_pipeprv) ?
attr->disconnected = handle->hdr.flags & ERROR(0);
attr->nonblocking = (handle->hdr.type == pal_type_pipeprv) ?
handle->pipeprv.nonblocking : handle->pipe.nonblocking;
attr->readable = val > 0;
if (PAL_GET_TYPE(handle) == pal_type_pipeprv)
attr->writeable = handle->__in.flags & WRITEABLE(1);
attr->writeable = handle->hdr.flags & WRITEABLE(1);
else
attr->writeable = handle->__in.flags & WRITEABLE(0);
attr->writeable = handle->hdr.flags & WRITEABLE(0);
attr->pending_size = val;
return 0;
}
static int pipe_attrsetbyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
{
if (handle->__in.fds[0] == PAL_IDX_POISON)
if (handle->hdr.fds[0] == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
int ret;
PAL_BOL * nonblocking = (handle->__in.type == pal_type_pipeprv) ?
PAL_BOL * nonblocking = (handle->hdr.type == pal_type_pipeprv) ?
&handle->pipeprv.nonblocking :
&handle->pipe.nonblocking;
if (attr->nonblocking != *nonblocking) {
ret = INLINE_SYSCALL(fcntl, 3, handle->__in.fds[0], F_SETFL,
ret = INLINE_SYSCALL(fcntl, 3, handle->hdr.fds[0], F_SETFL,
*nonblocking ? O_NONBLOCK : 0);
if (IS_ERR(ret))
+13 -7
View File
@@ -79,7 +79,7 @@ static inline int create_process_handle (PAL_HANDLE * parent,
}
SET_HANDLE_TYPE(phdl, process);
phdl->__in.flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITEABLE(1)|WRITEABLE(2);
phdl->hdr.flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITEABLE(1)|WRITEABLE(2);
phdl->process.stream_in = proc_fds[0][0];
phdl->process.stream_out = proc_fds[0][1];
phdl->process.cargo = proc_fds[0][2];
@@ -93,7 +93,7 @@ static inline int create_process_handle (PAL_HANDLE * parent,
}
SET_HANDLE_TYPE(chdl, process);
chdl->__in.flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITEABLE(1)|WRITEABLE(2);
chdl->hdr.flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITEABLE(1)|WRITEABLE(2);
chdl->process.stream_in = proc_fds[1][0];
chdl->process.stream_out = proc_fds[1][1];
chdl->process.cargo = proc_fds[1][2];
@@ -124,6 +124,7 @@ struct proc_param {
};
struct proc_args {
PAL_NUM parent_process_id;
struct pal_sec pal_sec;
unsigned long memory_quota;
unsigned int parent_data_size;
@@ -220,6 +221,7 @@ int _DkProcessCreate (PAL_HANDLE * handle,
struct proc_args * proc_args =
__alloca(sizeof(struct proc_args) + datasz);
proc_args->parent_process_id = bsd_state.parent_pid;
memcpy(&proc_args->pal_sec, &pal_sec, sizeof(struct pal_sec));
proc_args->pal_sec.r_debug_state = NULL;
proc_args->pal_sec.r_debug = NULL;
@@ -391,6 +393,10 @@ void _DkProcessExit (int exitcode)
int _DkProcessSandboxCreate (const char * manifest, int flags)
{
PAL_HANDLE handle = NULL;
_DkStreamOpen(&handle, manifest, PAL_ACCESS_RDONLY, 0, 0, 0);
pal_state.manifest_handle = handle;
pal_state.manifest = manifest;
return -PAL_ERROR_NOTIMPLEMENTED;
}
@@ -422,7 +428,7 @@ static int proc_write (PAL_HANDLE handle, int offset, int count,
if (IS_ERR(bytes))
switch(ERRNO(bytes)) {
case EWOULDBLOCK:
handle->__in.flags &= ~WRITEABLE(1);
handle->hdr.flags &= ~WRITEABLE(1);
return-PAL_ERROR_TRYAGAIN;
case EINTR:
return -PAL_ERROR_INTERRUPTED;
@@ -431,9 +437,9 @@ static int proc_write (PAL_HANDLE handle, int offset, int count,
}
if (bytes == count)
handle->__in.flags |= WRITEABLE(1);
handle->hdr.flags |= WRITEABLE(1);
else
handle->__in.flags &= ~WRITEABLE(1);
handle->hdr.flags &= ~WRITEABLE(1);
return bytes;
}
@@ -506,9 +512,9 @@ static int proc_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
attr->handle_type = pal_type_process;
attr->nonblocking = handle->process.nonblocking;
attr->disconnected = handle->__in.flags & (ERROR(0)|ERROR(1));
attr->disconnected = handle->hdr.flags & (ERROR(0)|ERROR(1));
attr->readable = !!val;
attr->writeable = handle->__in.flags & WRITEABLE(1);
attr->writeable = handle->hdr.flags & WRITEABLE(1);
attr->runnable = PAL_FALSE;
attr->pending_size = val;
+1 -1
View File
@@ -39,7 +39,7 @@
#include <sysdeps/generic/ldsodefs.h>
#include <elf/elf.h>
#include <bits/dlfcn.h>
#include <dlfcn.h>
#include "elf-x86_64.h"
-264
View File
@@ -1,264 +0,0 @@
/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
/* Copyright (C) 2014 Stony Brook University
This file is part of Graphene Library OS.
Graphene Library OS is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Graphene Library OS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/*
* db_semaphore.c
*
* This file contains APIs that provides operations of semaphores.
*/
#include "pal_defs.h"
#include "pal_freebsd_defs.h"
#include "pal.h"
#include "pal_internal.h"
#include "pal_freebsd.h"
#include "pal_error.h"
#include "api.h"
#include <cmpxchg.h>
#include <atomic.h>
#include <limits.h>
#include <errno.h>
#include <sys/time.h>
static inline int atomic_dec_if_positive (struct atomic_int *v)
{
int c, old, dec;
c = atomic_read(v);
for (;;) {
dec = c - 1;
if (unlikely(dec < 0))
break;
old = atomic_cmpxchg((v), c, dec);
if (likely(old == c))
break;
c = old;
}
return dec;
}
int _DkSemaphoreCreate (PAL_HANDLE handle, int initialCount, int maxCount)
{
/*
* 1. Allocate memory for db_sem (this includes a futex variable).
* 2. Pack it into a PAL_HANDLE
* 3. Set the semaphore object with the argument values (count, maxCount)
*/
SET_HANDLE_TYPE(handle, semaphore);
atomic_set(&handle->semaphore.nwaiters, 0);
handle->semaphore.max_value = maxCount;
/* optimization: if maxCount == 1, we make it into mutex */
if (handle->semaphore.max_value == 1) {
atomic_set(&handle->semaphore.value.mut.value, 1 - initialCount);
} else {
atomic_set(&handle->semaphore.value.i, maxCount - initialCount);
}
return 0;
}
void _DkSemaphoreDestroy (PAL_HANDLE semaphoreHandle)
{
free(semaphoreHandle);
}
int _DkMutexLockTimeout (struct mutex_handle * mut, int timeout);
int _DkSemaphoreAcquire (PAL_HANDLE sem, int count)
{
/* optimization: use it as a mutex */
if (sem->semaphore.max_value == 1) {
struct mutex_handle * mut = &sem->semaphore.value.mut;
_DkMutexLock(mut);
return 0;
}
if (count > sem->semaphore.max_value)
return -PAL_ERROR_INVAL;
struct atomic_int * value = &sem->semaphore.value.i;
int c = 0;
if (!value)
return -PAL_ERROR_BADHANDLE;
if (count == 1)
c = atomic_dec_and_test_nonnegative (value);
else
c = atomic_sub_and_test_nonnegative (count, value);
if (c)
return 0;
/* We didn't get the lock. Bump the count back up. */
if (count == 1)
atomic_inc (value);
else
atomic_add (count, value);
int ret = 0;
atomic_inc (&sem->semaphore.nwaiters);
while (1) {
ret = INLINE_SYSCALL(_umtx_op, 5, value, UMTX_OP_WAIT, 0,
NULL, NULL);
if (IS_ERR(ret)) {
if (ERRNO(ret) == EWOULDBLOCK) {
ret = 0;
} else {
ret = unix_to_pal_error(ERRNO(ret));
break;
}
}
if (count == 1)
c = atomic_dec_and_test_nonnegative (value);
else
c = atomic_sub_and_test_nonnegative (count, value);
if (c)
break;
/* We didn't get the lock. Bump the count back up. */
if (count == 1)
atomic_inc (value);
else
atomic_add (count, value);
}
atomic_dec (&sem->semaphore.nwaiters);
return ret;
}
int _DkSemaphoreAcquireTimeout (PAL_HANDLE sem, int count, int timeout)
{
/* Pass it up to the no-timeout version if no timeout requested */
if (timeout == -1)
return _DkSemaphoreAcquire(sem, count);
/* optimization: use it as a mutex */
if (sem->semaphore.max_value == 1) {
struct mutex_handle * mut = & sem->semaphore.value.mut;
_DkMutexLockTimeout(mut, timeout);
return 0;
}
if (count > sem->semaphore.max_value)
return -PAL_ERROR_INVAL;
struct atomic_int * value = &sem->semaphore.value.i;
int c = 0;
if (!value)
return -PAL_ERROR_BADHANDLE;
if (count == 1)
c = atomic_dec_and_test_nonnegative (value);
else
c = atomic_sub_and_test_nonnegative (count, value);
if (c)
return 0;
/* We didn't get the lock. Bump the count back up. */
if (count == 1)
atomic_inc (value);
else
atomic_add (count, value);
if (!timeout)
return 0;
struct timespec waittime;
long sec = timeout / 1000000;
long microsec = timeout - (sec * 1000000);
waittime.tv_sec = sec;
waittime.tv_nsec = microsec * 1000;
int ret = 0;
atomic_inc (&sem->semaphore.nwaiters);
while (1) {
ret = INLINE_SYSCALL(_umtx_op, 5, value, UMTX_OP_WAIT_UINT, 0,
NULL, &waittime);
if (ERRNO(ret) == EWOULDBLOCK) {
ret = 0;
} else {
ret = unix_to_pal_error(ERRNO(ret));
break;
}
if (count == 1)
c = atomic_dec_and_test_nonnegative (value);
else
c = atomic_sub_and_test_nonnegative (count, value);
if (c)
break;
}
/* We didn't get the lock. Bump the count back up. */
if (count == 1)
atomic_inc (value);
else
atomic_add (count, value);
atomic_dec (&sem->semaphore.nwaiters);
return ret;
}
void _DkSemaphoreRelease (PAL_HANDLE sem, int count)
{
/* optimization: use it as a mutex */
if (sem->semaphore.max_value == 1) {
struct mutex_handle * mut =
&sem->semaphore.value.mut;
_DkMutexUnlock(mut);
return;
}
struct atomic_int * value = &sem->semaphore.value.i;
if (count == 1)
atomic_inc (value);
else
atomic_add (count, value);
int nwaiters = atomic_read (&sem->semaphore.nwaiters);
if (nwaiters > 0)
INLINE_SYSCALL(_umtx_op, 5, value, UMTX_OP_WAKE,
nwaiters, NULL, NULL);
}
int _DkSemaphoreGetCurrentCount (PAL_HANDLE sem)
{
if (sem->semaphore.max_value == 1) {
struct mutex_handle * mut =
&sem->semaphore.value.mut;
return atomic_read(&mut->value);
}
int c = atomic_read(&sem->semaphore.value.i);
return sem->semaphore.max_value - c;
}
+24 -20
View File
@@ -45,6 +45,10 @@ typedef __kernel_pid_t pid_t;
#include <errno.h>
#include <sys/filio.h>
/* FreeBSD doesn't have addr_check_any. */
#undef ALLOW_BIND_ANY
#define ALLOW_BIND_ANY 1
/* 96 bytes is the minimal size of buffer to store a IPv4/IPv6
address */
#define PAL_SOCKADDR_SIZE 96
@@ -233,7 +237,7 @@ PAL_HANDLE socket_create_handle (int type, int fd, int options,
memset(hdl, 0, sizeof(union pal_handle));
PAL_GET_TYPE(hdl) = type;
hdl->__in.flags |= RFD(0)|(type != pal_type_tcpsrv ? WFD(0) : 0);
hdl->hdr.flags |= RFD(0)|(type != pal_type_tcpsrv ? WFD(0) : 0);
hdl->sock.fd = fd;
void * addr = (void *) hdl + HANDLE_SIZE(sock);
if (bind_addr) {
@@ -351,7 +355,7 @@ static int tcp_listen (PAL_HANDLE * handle, char * uri, int options)
options = HOST_SOCKET_OPTIONS(options);
/* the socket need to have a binding address, a null address or an
any address is not allowed */
if (!bind_addr || addr_check_any(bind_addr) == 0)
if (!bind_addr == 0)
return -PAL_ERROR_INVAL;
fd = INLINE_SYSCALL(socket, 3, bind_addr->sa_family,
@@ -619,16 +623,16 @@ static int tcp_write (PAL_HANDLE handle, int offset, int len, const void * buf)
case EPIPE:
return -PAL_ERROR_CONNFAILED;
case EWOULDBLOCK:
handle->__in.flags &= ~WRITEABLE(0);
handle->hdr.flags &= ~WRITEABLE(0);
return -PAL_ERROR_TRYAGAIN;
default:
return unix_to_pal_error(ERRNO(bytes));
}
if (bytes == len)
handle->__in.flags |= WRITEABLE(0);
handle->hdr.flags |= WRITEABLE(0);
else
handle->__in.flags &= ~WRITEABLE(0);
handle->hdr.flags &= ~WRITEABLE(0);
return bytes;
}
@@ -882,7 +886,7 @@ static int udp_send (PAL_HANDLE handle, int offset, int len, const void * buf)
if (IS_ERR(bytes))
switch(ERRNO(bytes)) {
case EAGAIN:
handle->__in.flags &= ~WRITEABLE(0);
handle->hdr.flags &= ~WRITEABLE(0);
return -PAL_ERROR_TRYAGAIN;
case ECONNRESET:
case EPIPE:
@@ -892,9 +896,9 @@ static int udp_send (PAL_HANDLE handle, int offset, int len, const void * buf)
}
if (bytes == len)
handle->__in.flags |= WRITEABLE(0);
handle->hdr.flags |= WRITEABLE(0);
else
handle->__in.flags &= ~WRITEABLE(0);
handle->hdr.flags &= ~WRITEABLE(0);
return bytes;
}
@@ -943,15 +947,15 @@ static int udp_sendbyaddr (PAL_HANDLE handle, int offset, int len,
case EPIPE:
return -PAL_ERROR_CONNFAILED;
case EAGAIN:
handle->__in.flags &= ~WRITEABLE(0);
handle->hdr.flags &= ~WRITEABLE(0);
default:
return unix_to_pal_error(ERRNO(bytes));
}
if (bytes == len)
handle->__in.flags |= WRITEABLE(0);
handle->hdr.flags |= WRITEABLE(0);
else
handle->__in.flags &= ~WRITEABLE(0);
handle->hdr.flags &= ~WRITEABLE(0);
return bytes;
}
@@ -1022,10 +1026,10 @@ static int socket_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
attr->readable = !attr->disconnected;
}
attr->handle_type = handle->__in.type;
attr->disconnected = handle->__in.flags & ERROR(0);
attr->handle_type = handle->hdr.type;
attr->disconnected = handle->hdr.flags & ERROR(0);
attr->nonblocking = handle->sock.nonblocking;
attr->writeable = handle->__in.flags & WRITEABLE(0);
attr->writeable = handle->hdr.flags & WRITEABLE(0);
attr->socket.linger = handle->sock.linger;
attr->socket.receivebuf = handle->sock.receivebuf;
attr->socket.sendbuf = handle->sock.sendbuf;
@@ -1275,7 +1279,7 @@ static int mcast_s (PAL_HANDLE handle, int port)
if (IS_ERR(ret))
return -PAL_ERROR_DENIED;
handle->__in.flags |= WFD(1)|WRITEABLE(1);
handle->hdr.flags |= WFD(1)|WRITEABLE(1);
handle->mcast.srv = fd;
return 0;
}
@@ -1375,15 +1379,15 @@ static int mcast_send (PAL_HANDLE handle, int offset, int size,
case EPIPE:
return -PAL_ERROR_CONNFAILED;
case EAGAIN:
handle->__in.flags &= ~WRITEABLE(1);
handle->hdr.flags &= ~WRITEABLE(1);
default:
return unix_to_pal_error(ERRNO(bytes));
}
if (bytes == size)
handle->__in.flags |= WRITEABLE(1);
handle->hdr.flags |= WRITEABLE(1);
else
handle->__in.flags &= ~WRITEABLE(1);
handle->hdr.flags &= ~WRITEABLE(1);
return bytes;
}
@@ -1437,10 +1441,10 @@ static int mcast_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
return unix_to_pal_error(ERRNO(ret));
attr->handle_type = pal_type_mcast;
attr->disconnected = handle->__in.flags & (ERROR(0)|ERROR(1));
attr->disconnected = handle->hdr.flags & (ERROR(0)|ERROR(1));
attr->nonblocking = handle->mcast.nonblocking;
attr->readable = !!val;
attr->writeable = handle->__in.flags & WRITEABLE(1);
attr->writeable = handle->hdr.flags & WRITEABLE(1);
attr->runnable = PAL_FALSE;
attr->pending_size = val;
return 0;
+7 -7
View File
@@ -73,10 +73,10 @@ out:
int handle_set_cloexec (PAL_HANDLE handle, bool enable)
{
for (int i = 0 ; i < MAX_FDS ; i++)
if (handle->__in.flags & (RFD(i)|WFD(i))) {
if (handle->hdr.flags & (RFD(i)|WFD(i))) {
long flags = enable ? FD_CLOEXEC : 0;
int ret = INLINE_SYSCALL(fcntl, 3,
handle->__in.fds[i], F_SETFD,
handle->hdr.fds[i], F_SETFD,
flags);
if (IS_ERR(ret) && ERRNO(ret) != EBADF)
return -PAL_ERROR_DENIED;
@@ -87,7 +87,7 @@ int handle_set_cloexec (PAL_HANDLE handle, bool enable)
/* _DkStreamUnmap for internal use. Unmap stream at certain memory address.
The memory is unmapped as a whole.*/
int _DkStreamUnmap (void * addr, int size)
int _DkStreamUnmap (void * addr, uint64_t size)
{
/* Just let the kernel tell us if the mapping isn't good. */
int ret = INLINE_SYSCALL(munmap, 2, addr, size);
@@ -289,9 +289,9 @@ int _DkSendHandle (PAL_HANDLE hdl, PAL_HANDLE cargo)
int fds[MAX_FDS];
int nfds = 0;
for (int i = 0 ; i < MAX_FDS ; i++)
if (cargo->__in.flags & (RFD(i)|WFD(1))) {
if (cargo->hdr.flags & (RFD(i)|WFD(1))) {
hdl_hdr.fds |= 1U << i;
fds[nfds++] = cargo->__in.fds[i];
fds[nfds++] = cargo->hdr.fds[i];
}
// ~ Initialize common parameter formessage passing
// Channel between parent and child
@@ -434,9 +434,9 @@ int _DkReceiveHandle(PAL_HANDLE hdl, PAL_HANDLE * cargo)
for (int i = 0 ; i < MAX_FDS ; i++)
if (hdl_hdr.fds & (1U << i)) {
if (n < total_fds) {
handle->__in.fds[i] = ((int *) CMSG_DATA(chdr))[n++];
handle->hdr.fds[i] = ((int *) CMSG_DATA(chdr))[n++];
} else {
handle->__in.flags &= ~(RFD(i)|WFD(i));
handle->hdr.flags &= ~(RFD(i)|WFD(i));
}
}
+4 -4
View File
@@ -47,7 +47,7 @@ typedef int __kernel_pid_t;
#define ERRNO INTERNAL_SYSCALL_ERRNO
#define ERRNO_P INTERNAL_SYSCALL_ERRNO_P
int getrand (void * buffer, int size);
int getrand (void * buffer, size_t size);
struct timespec;
struct timeval;
@@ -58,10 +58,10 @@ extern struct pal_bsd_state {
/* credentails */
unsigned int pid;
unsigned int uid, gid;
unsigned int parent_pid;
/* currently enabled signals */
_sigset_t sigset;
unsigned long memory_quota;
} bsd_state;
@@ -99,7 +99,7 @@ extern struct pal_bsd_state {
static inline int HOST_FLAGS (int alloc_type, int prot)
{
return ((alloc_type & PAL_ALLOC_RESERVE) ? MAP_NORESERVE : 0) |
return
((prot & PAL_PROT_WRITECOPY) ? MAP_PRIVATE : MAP_SHARED);
}
+128 -14
View File
@@ -57,16 +57,20 @@ typedef union pal_handle
* handle, also there is no need to allocate the internal
* handles, so we hide the type name of these handles on purpose.
*/
struct {
PAL_HDR hdr;
struct mutex_handle mut;
} mutex;
struct {
PAL_IDX type;
PAL_FLG flags;
PAL_REF ref;
PAL_IDX fds[];
} __in;
} hdr;
struct {
PAL_HDR __in;
PAL_HDR hdr;
PAL_IDX fd;
PAL_NUM offset;
PAL_BOL append;
@@ -75,20 +79,20 @@ typedef union pal_handle
} file;
struct {
PAL_HDR __in;
PAL_HDR hdr;
PAL_IDX fd;
PAL_NUM pipeid;
PAL_BOL nonblocking;
} pipe;
struct {
PAL_HDR __in;
PAL_HDR hdr;
PAL_IDX fds[2];
PAL_BOL nonblocking;
} pipeprv;
struct {
PAL_HDR __in;
PAL_HDR hdr;
PAL_IDX fd_in, fd_out;
PAL_IDX dev_type;
PAL_BOL destroy;
@@ -96,7 +100,7 @@ typedef union pal_handle
} dev;
struct {
PAL_HDR __in;
PAL_HDR hdr;
PAL_IDX fd;
PAL_STR realpath;
PAL_PTR buf;
@@ -106,13 +110,13 @@ typedef union pal_handle
} dir;
struct {
PAL_HDR __in;
PAL_HDR hdr;
PAL_IDX fd;
PAL_NUM token;
} gipc;
struct {
PAL_HDR __in;
PAL_HDR hdr;
PAL_IDX fd;
PAL_PTR bind;
PAL_PTR conn;
@@ -129,7 +133,7 @@ typedef union pal_handle
} sock;
struct {
PAL_HDR __in;
PAL_HDR hdr;
PAL_IDX stream_in, stream_out;
PAL_IDX cargo;
PAL_IDX pid;
@@ -137,7 +141,7 @@ typedef union pal_handle
} process;
struct {
PAL_HDR __in;
PAL_HDR hdr;
PAL_IDX cli;
PAL_IDX srv;
PAL_IDX port;
@@ -145,12 +149,12 @@ typedef union pal_handle
} mcast;
struct {
PAL_HDR __in;
PAL_HDR hdr;
PAL_IDX tid;
} thread;
struct {
PAL_HDR __in;
PAL_HDR hdr;
struct atomic_int nwaiters;
PAL_NUM max_value;
union {
@@ -160,7 +164,7 @@ typedef union pal_handle
} semaphore;
struct {
PAL_HDR __in;
PAL_HDR hdr;
struct atomic_int signaled;
struct atomic_int nwaiters;
PAL_BOL isnotification;
@@ -174,5 +178,115 @@ typedef union pal_handle
#define MAX_FDS (3)
#define HAS_FDS (00077)
#define HANDLE_TYPE(handle) ((handle)->__in.type)
#define HANDLE_TYPE(handle) ((handle)->hdr.type)
struct arch_frame {
#ifdef __x86_64__
uint64_t rsp, rbp, rbx, rsi, rdi, r12, r13, r14, r15;
#else
# error "unsupported architecture"
#endif
};
#ifdef __x86_64__
# define store_register(reg, var) \
asm volatile ("movq %%" #reg ", %0" : "=a" (var) :: "memory");
# define store_register_in_frame(reg, f) store_register(reg, (f)->reg)
# define arch_store_frame(f) \
store_register_in_frame(rsp, f) \
store_register_in_frame(rbp, f) \
store_register_in_frame(rbx, f) \
store_register_in_frame(rsi, f) \
store_register_in_frame(rdi, f) \
store_register_in_frame(r12, f) \
store_register_in_frame(r13, f) \
store_register_in_frame(r14, f) \
store_register_in_frame(r15, f)
# define restore_register(reg, var, clobber...) \
asm volatile ("movq %0, %%" #reg :: "g" (var) : "memory", ##clobber);
# define restore_register_in_frame(reg, f) \
restore_register(reg, (f)->reg, \
"r15", "r14", "r13", "r12", "rdi", "rsi", "rbx")
# define arch_restore_frame(f) \
restore_register_in_frame(r15, f) \
restore_register_in_frame(r14, f) \
restore_register_in_frame(r13, f) \
restore_register_in_frame(r12, f) \
restore_register_in_frame(rdi, f) \
restore_register_in_frame(rsi, f) \
restore_register_in_frame(rbx, f) \
restore_register_in_frame(rbp, f) \
restore_register_in_frame(rsp, f)
#else /* __x86_64__ */
# error "unsupported architecture"
#endif
#define PAL_FRAME_IDENTIFIER (0xdeaddeadbeefbeef)
struct pal_frame {
volatile uint64_t identifier;
void * func;
const char * funcname;
struct arch_frame arch;
};
/* When a PAL call is issued, a special PAL_FRAME is placed on the stack.
* This stores both a magic identifier, debugging information,
* as well as callee-saved state. This is used as a way to deal
* with PAL-internal failures where the goal is to exit the PAL and return a
* failure.
*
* Arguably, an alternative is to unwind the stack and handle error cases at
* each stage. In general, this is probably more robust, but would take work
* in the short term. The one exception where the current strategy is
* probably better is when the PAL gets in a state where the code is
* unrecoverable, but ideally, this shouldn't happen.
*/
/* DEP 12/25/17: This frame storage thing is important to mark volatile.
* The compiler should not optimize out any of these changes, and
* because some accesses can happen during an exception, these are not
* visible to the compiler in an otherwise stack-local variable (so the
* compiler will try to optimize out these assignments.
*/
static inline
void __store_frame (volatile struct pal_frame * frame,
void * func, const char * funcname)
{
arch_store_frame(&frame->arch)
frame->func = func;
frame->funcname = funcname;
asm volatile ("nop" ::: "memory");
frame->identifier = PAL_FRAME_IDENTIFIER;
}
#define ENTER_PAL_CALL(name) \
struct pal_frame frame; \
__store_frame(&frame, &(name), #name)
static inline
void __clear_frame (volatile struct pal_frame * frame)
{
if (frame->identifier == PAL_FRAME_IDENTIFIER) {
asm volatile ("nop" ::: "memory");
frame->identifier = 0;
}
}
#define LEAVE_PAL_CALL() \
do { \
__clear_frame(&frame); \
} while (0)
#define LEAVE_PAL_CALL_RETURN(retval) \
do { \
__clear_frame(&frame); \
return (retval); \
} while (0)
#endif /* PAL_HOST_H */