-#include "factor.h"
+#include "master.h"
static void *null_dll;
{
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)
{
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;
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;
}
}
-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);
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);
dpush(tag_object(result));
}
-void primitive_cwd(void)
+DEFINE_PRIMITIVE(cwd)
{
char wd[MAXPATHLEN];
if(getcwd(wd,MAXPATHLEN) == NULL)
box_char_string(wd);
}
-void primitive_cd(void)
+DEFINE_PRIMITIVE(cd)
{
chdir(unbox_char_string());
}
{
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);
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;
}
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)
{
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;
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;
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)