]> gitweb.factorcode.org Git - factor.git/blobdiff - vm/os-unix.c
Initial import
[factor.git] / vm / os-unix.c
index 8f46169d9d57e153ec9d088c195d6d68ad1e859f..2d9ba02ca5ca4d93ed21732a66b58f5d47e414d3 100644 (file)
@@ -1,4 +1,4 @@
-#include "factor.h"
+#include "master.h"
 
 static void *null_dll;
 
@@ -6,12 +6,18 @@ s64 current_millis(void)
 {
        struct timeval t;
        gettimeofday(&t,NULL);
-       return (s64)t.tv_sec * 1000 + t.tv_usec/1000;
+       return (s64)t.tv_sec * 1000 + t.tv_usec / 1000;
+}
+
+void sleep_millis(CELL msec)
+{
+       usleep(msec * 1000);
 }
 
 void init_ffi(void)
 {
-       null_dll = dlopen(NULL,RTLD_LAZY);
+       /* NULL_DLL is "libfactor.dylib" for OS X and NULL for generic unix */
+       null_dll = dlopen(NULL_DLL,RTLD_LAZY);
 }
 
 void ffi_dlopen(F_DLL *dll, bool error)
@@ -22,8 +28,9 @@ void ffi_dlopen(F_DLL *dll, bool error)
        {
                if(error)
                {
-                       simple_error(ERROR_FFI,F,
-                               tag_object(from_char_string(dlerror())));
+                       general_error(ERROR_FFI,F,
+                               tag_object(from_char_string(dlerror())),
+                               NULL);
                }
                else
                        dll->dll = NULL;
@@ -34,35 +41,23 @@ void ffi_dlopen(F_DLL *dll, bool error)
        dll->dll = dllptr;
 }
 
-void *ffi_dlsym(F_DLL *dll, char *symbol, bool error)
+void *ffi_dlsym(F_DLL *dll, F_SYMBOL *symbol)
 {
        void *handle = (dll == NULL ? null_dll : dll->dll);
-       void *sym = dlsym(handle,symbol);
-       if(sym == NULL)
-       {
-               if(error)
-               {
-                       simple_error(ERROR_FFI,
-                               tag_object(from_char_string(symbol)),
-                               tag_object(from_char_string(dlerror())));
-               }
-
-               return NULL;
-       }
-       return sym;
+       return dlsym(handle,symbol);
 }
 
 void ffi_dlclose(F_DLL *dll)
 {
        if(dlclose(dll->dll))
        {
-               simple_error(ERROR_FFI,tag_object(
-                       from_char_string(dlerror())),F);
+               general_error(ERROR_FFI,tag_object(
+                       from_char_string(dlerror())),F,NULL);
        }
        dll->dll = NULL;
 }
 
-void primitive_stat(void)
+DEFINE_PRIMITIVE(stat)
 {
        struct stat sb;
 
@@ -82,7 +77,20 @@ void primitive_stat(void)
        }
 }
 
-void primitive_read_dir(void)
+/* Allocates memory */
+CELL parse_dir_entry(struct dirent *file)
+{
+       CELL name = tag_object(from_char_string(file->d_name));
+       if(UNKNOWN_TYPE_P(file))
+               return name;
+       else
+       {
+               CELL dirp = tag_boolean(DIRECTORY_P(file));
+               return allot_array_2(name,dirp);
+       }
+}
+
+DEFINE_PRIMITIVE(read_dir)
 {
        DIR* dir = opendir(unbox_char_string());
        GROWABLE_ARRAY(result);
@@ -93,10 +101,10 @@ void primitive_read_dir(void)
 
                while((file = readdir(dir)) != NULL)
                {
-                       REGISTER_ARRAY(result);
-                       CELL name = tag_object(from_char_string(file->d_name));
-                       UNREGISTER_ARRAY(result);
-                       GROWABLE_ADD(result,name);
+                       REGISTER_UNTAGGED(result);
+                       CELL pair = parse_dir_entry(file);
+                       UNREGISTER_UNTAGGED(result);
+                       GROWABLE_ADD(result,pair);
                }
 
                closedir(dir);
@@ -107,7 +115,7 @@ void primitive_read_dir(void)
        dpush(tag_object(result));
 }
 
-void primitive_cwd(void)
+DEFINE_PRIMITIVE(cwd)
 {
        char wd[MAXPATHLEN];
        if(getcwd(wd,MAXPATHLEN) == NULL)
@@ -115,7 +123,7 @@ void primitive_cwd(void)
        box_char_string(wd);
 }
 
-void primitive_cd(void)
+DEFINE_PRIMITIVE(cd)
 {
        chdir(unbox_char_string());
 }
@@ -124,12 +132,12 @@ F_SEGMENT *alloc_segment(CELL size)
 {
        int pagesize = getpagesize();
 
-       char *array = mmap((void*)0,pagesize + size + pagesize,
+       char *array = mmap(NULL,pagesize + size + pagesize,
                PROT_READ | PROT_WRITE | PROT_EXEC,
                MAP_ANON | MAP_PRIVATE,-1,0);
 
-       if(array == NULL)
-               fatal_error("Cannot allocate memory region",0);
+       if(array == (char*)-1)
+               fatal_error("Out of memory in alloc_segment",0);
 
        if(mprotect(array,pagesize,PROT_NONE) == -1)
                fatal_error("Cannot protect low guard page",(CELL)array);
@@ -138,9 +146,10 @@ F_SEGMENT *alloc_segment(CELL size)
                fatal_error("Cannot protect high guard page",(CELL)array);
 
        F_SEGMENT *retval = safe_malloc(sizeof(F_SEGMENT));
-       
+
        retval->start = (CELL)(array + pagesize);
        retval->size = size;
+       retval->end = retval->start + size;
 
        return retval;
 }
@@ -153,26 +162,45 @@ void dealloc_segment(F_SEGMENT *block)
                pagesize + block->size + pagesize);
        
        if(retval)
-               fatal_error("Failed to unmap region",0);
+               fatal_error("dealloc_segment failed",0);
 
        free(block);
 }
-
+  
 INLINE F_STACK_FRAME *uap_stack_pointer(void *uap)
 {
-       ucontext_t *ucontext = (ucontext_t *)uap;
-       return (F_STACK_FRAME *)ucontext->uc_stack.ss_sp;
+       /* There is a race condition here, but in practice a signal
+       delivered during stack frame setup/teardown or while transitioning
+       from Factor to C is a sign of things seriously gone wrong, not just
+       a divide by zero or stack underflow in the listener */
+       if(in_code_heap_p(UAP_PROGRAM_COUNTER(uap)))
+               return ucontext_stack_pointer(uap);
+       else
+               return NULL;
+}
+
+void memory_signal_handler_impl(void)
+{
+       memory_protection_error(signal_fault_addr,signal_callstack_top);
 }
 
 void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
 {
-       memory_protection_error((CELL)siginfo->si_addr,signal,
-               uap_stack_pointer(uap));
+       signal_fault_addr = (CELL)siginfo->si_addr;
+       signal_callstack_top = uap_stack_pointer(uap);
+       UAP_PROGRAM_COUNTER(uap) = (CELL)memory_signal_handler_impl;
+}
+
+void misc_signal_handler_impl(void)
+{
+       signal_error(signal_number,signal_callstack_top);
 }
 
 void misc_signal_handler(int signal, siginfo_t *siginfo, void *uap)
 {
-       signal_error(signal,uap_stack_pointer(uap));
+       signal_number = signal;
+       signal_callstack_top = uap_stack_pointer(uap);
+       UAP_PROGRAM_COUNTER(uap) = (CELL)misc_signal_handler_impl;
 }
 
 static void sigaction_safe(int signum, const struct sigaction *act, struct sigaction *oldact)
@@ -189,8 +217,9 @@ void unix_init_signals(void)
 {
        struct sigaction memory_sigaction;
        struct sigaction misc_sigaction;
-       struct sigaction ign_sigaction;
-       
+       struct sigaction ignore_sigaction;
+
+       memset(&memory_sigaction,0,sizeof(struct sigaction));
        sigemptyset(&memory_sigaction.sa_mask);
        memory_sigaction.sa_sigaction = memory_signal_handler;
        memory_sigaction.sa_flags = SA_SIGINFO;
@@ -198,6 +227,7 @@ void unix_init_signals(void)
        sigaction_safe(SIGBUS,&memory_sigaction,NULL);
        sigaction_safe(SIGSEGV,&memory_sigaction,NULL);
 
+       memset(&misc_sigaction,0,sizeof(struct sigaction));
        sigemptyset(&misc_sigaction.sa_mask);
        misc_sigaction.sa_sigaction = misc_signal_handler;
        misc_sigaction.sa_flags = SA_SIGINFO;
@@ -206,10 +236,11 @@ void unix_init_signals(void)
        sigaction_safe(SIGFPE,&misc_sigaction,NULL);
        sigaction_safe(SIGQUIT,&misc_sigaction,NULL);
        sigaction_safe(SIGILL,&misc_sigaction,NULL);
-       
-       sigemptyset(&ign_sigaction.sa_mask);
-       ign_sigaction.sa_handler = SIG_IGN;
-       sigaction_safe(SIGPIPE,&ign_sigaction,NULL);
+
+       memset(&ignore_sigaction,0,sizeof(struct sigaction));
+       sigemptyset(&ignore_sigaction.sa_mask);
+       ignore_sigaction.sa_handler = SIG_IGN;
+       sigaction_safe(SIGPIPE,&ignore_sigaction,NULL);
 }
 
 void reset_stdio(void)