3 void start_thread(void *(*start_routine
)(void *))
8 if (pthread_attr_init (&attr
) != 0)
9 fatal_error("pthread_attr_init() failed",0);
10 if (pthread_attr_setdetachstate (&attr
, PTHREAD_CREATE_DETACHED
) != 0)
11 fatal_error("pthread_attr_setdetachstate() failed",0);
12 if (pthread_create (&thread
, &attr
, start_routine
, NULL
) != 0)
13 fatal_error("pthread_create() failed",0);
14 pthread_attr_destroy (&attr
);
17 static void *null_dll
;
19 s64
current_micros(void)
22 gettimeofday(&t
,NULL
);
23 return (s64
)t
.tv_sec
* 1000000 + t
.tv_usec
;
26 void sleep_micros(CELL usec
)
33 /* NULL_DLL is "libfactor.dylib" for OS X and NULL for generic unix */
34 null_dll
= dlopen(NULL_DLL
,RTLD_LAZY
);
37 void ffi_dlopen(F_DLL
*dll
)
39 dll
->dll
= dlopen(alien_offset(dll
->path
), RTLD_LAZY
);
42 void *ffi_dlsym(F_DLL
*dll
, F_SYMBOL
*symbol
)
44 void *handle
= (dll
== NULL
? null_dll
: dll
->dll
);
45 return dlsym(handle
,symbol
);
48 void ffi_dlclose(F_DLL
*dll
)
52 general_error(ERROR_FFI
,tag_object(
53 from_char_string(dlerror())),F
,NULL
);
58 void primitive_existsp(void)
61 box_boolean(stat(unbox_char_string(),&sb
) >= 0);
64 F_SEGMENT
*alloc_segment(CELL size
)
66 int pagesize
= getpagesize();
68 char *array
= mmap(NULL
,pagesize
+ size
+ pagesize
,
69 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
70 MAP_ANON
| MAP_PRIVATE
,-1,0);
72 if(array
== (char*)-1)
75 if(mprotect(array
,pagesize
,PROT_NONE
) == -1)
76 fatal_error("Cannot protect low guard page",(CELL
)array
);
78 if(mprotect(array
+ pagesize
+ size
,pagesize
,PROT_NONE
) == -1)
79 fatal_error("Cannot protect high guard page",(CELL
)array
);
81 F_SEGMENT
*retval
= safe_malloc(sizeof(F_SEGMENT
));
83 retval
->start
= (CELL
)(array
+ pagesize
);
85 retval
->end
= retval
->start
+ size
;
90 void dealloc_segment(F_SEGMENT
*block
)
92 int pagesize
= getpagesize();
94 int retval
= munmap((void*)(block
->start
- pagesize
),
95 pagesize
+ block
->size
+ pagesize
);
98 fatal_error("dealloc_segment failed",0);
103 INLINE F_STACK_FRAME
*uap_stack_pointer(void *uap
)
105 /* There is a race condition here, but in practice a signal
106 delivered during stack frame setup/teardown or while transitioning
107 from Factor to C is a sign of things seriously gone wrong, not just
108 a divide by zero or stack underflow in the listener */
109 if(in_code_heap_p(UAP_PROGRAM_COUNTER(uap
)))
111 F_STACK_FRAME
*ptr
= ucontext_stack_pointer(uap
);
113 critical_error("Invalid uap",(CELL
)uap
);
120 void memory_signal_handler(int signal
, siginfo_t
*siginfo
, void *uap
)
122 signal_fault_addr
= (CELL
)siginfo
->si_addr
;
123 signal_callstack_top
= uap_stack_pointer(uap
);
124 UAP_PROGRAM_COUNTER(uap
) = (CELL
)memory_signal_handler_impl
;
127 void misc_signal_handler(int signal
, siginfo_t
*siginfo
, void *uap
)
129 signal_number
= signal
;
130 signal_callstack_top
= uap_stack_pointer(uap
);
131 UAP_PROGRAM_COUNTER(uap
) = (CELL
)misc_signal_handler_impl
;
134 static void sigaction_safe(int signum
, const struct sigaction
*act
, struct sigaction
*oldact
)
139 ret
= sigaction(signum
, act
, oldact
);
141 while(ret
== -1 && errno
== EINTR
);
144 fatal_error("sigaction failed", 0);
147 void unix_init_signals(void)
149 struct sigaction memory_sigaction
;
150 struct sigaction misc_sigaction
;
151 struct sigaction ignore_sigaction
;
153 memset(&memory_sigaction
,0,sizeof(struct sigaction
));
154 sigemptyset(&memory_sigaction
.sa_mask
);
155 memory_sigaction
.sa_sigaction
= memory_signal_handler
;
156 memory_sigaction
.sa_flags
= SA_SIGINFO
;
158 sigaction_safe(SIGBUS
,&memory_sigaction
,NULL
);
159 sigaction_safe(SIGSEGV
,&memory_sigaction
,NULL
);
161 memset(&misc_sigaction
,0,sizeof(struct sigaction
));
162 sigemptyset(&misc_sigaction
.sa_mask
);
163 misc_sigaction
.sa_sigaction
= misc_signal_handler
;
164 misc_sigaction
.sa_flags
= SA_SIGINFO
;
166 sigaction_safe(SIGABRT
,&misc_sigaction
,NULL
);
167 sigaction_safe(SIGFPE
,&misc_sigaction
,NULL
);
168 sigaction_safe(SIGQUIT
,&misc_sigaction
,NULL
);
169 sigaction_safe(SIGILL
,&misc_sigaction
,NULL
);
171 memset(&ignore_sigaction
,0,sizeof(struct sigaction
));
172 sigemptyset(&ignore_sigaction
.sa_mask
);
173 ignore_sigaction
.sa_handler
= SIG_IGN
;
174 sigaction_safe(SIGPIPE
,&ignore_sigaction
,NULL
);
177 /* On Unix, shared fds such as stdin cannot be set to non-blocking mode
178 (http://homepages.tesco.net/J.deBoynePollard/FGA/dont-set-shared-file-descriptors-to-non-blocking-mode.html)
179 so we kludge around this by spawning a thread, which waits on a control pipe
180 for a signal, upon receiving this signal it reads one block of data from stdin
181 and writes it to a data pipe. Upon completion, it writes a 4-byte integer to
182 the size pipe, indicating how much data was written to the data pipe.
184 The read end of the size pipe can be set to non-blocking. */
185 __attribute__((visibility("default"))) int stdin_read
;
186 __attribute__((visibility("default"))) int stdin_write
;
188 __attribute__((visibility("default"))) int control_read
;
189 __attribute__((visibility("default"))) int control_write
;
191 __attribute__((visibility("default"))) int size_read
;
192 __attribute__((visibility("default"))) int size_write
;
194 void safe_close(int fd
)
197 fatal_error("error closing fd",errno
);
200 bool check_write(int fd
, void *data
, size_t size
)
202 if(write(fd
,data
,size
) == size
)
207 return check_write(fd
,data
,size
);
213 void safe_write(int fd
, void *data
, size_t size
)
215 if(!check_write(fd
,data
,size
))
216 fatal_error("error writing fd",errno
);
219 bool safe_read(int fd
, void *data
, size_t size
)
221 ssize_t bytes
= read(fd
,data
,size
);
225 return safe_read(fd
,data
,size
);
228 fatal_error("error reading fd",errno
);
233 return (bytes
== size
);
236 void *stdin_loop(void *arg
)
238 unsigned char buf
[4096];
239 bool loop_running
= true;
243 if(!safe_read(control_read
,buf
,1))
247 fatal_error("stdin_loop: bad data on control fd",buf
[0]);
251 ssize_t bytes
= read(0,buf
,sizeof(buf
));
258 loop_running
= false;
264 safe_write(size_write
,&bytes
,sizeof(bytes
));
266 if(!check_write(stdin_write
,buf
,bytes
))
267 loop_running
= false;
273 safe_close(stdin_write
);
274 safe_close(control_read
);
279 void open_console(void)
283 if(pipe(filedes
) < 0)
284 fatal_error("Error opening control pipe",errno
);
286 control_read
= filedes
[0];
287 control_write
= filedes
[1];
289 if(pipe(filedes
) < 0)
290 fatal_error("Error opening size pipe",errno
);
292 size_read
= filedes
[0];
293 size_write
= filedes
[1];
295 if(pipe(filedes
) < 0)
296 fatal_error("Error opening stdin pipe",errno
);
298 stdin_read
= filedes
[0];
299 stdin_write
= filedes
[1];
301 start_thread(stdin_loop
);
304 DLLEXPORT
void wait_for_stdin(void)
306 if(write(control_write
,"X",1) != 1)
311 fatal_error("Error writing control fd",errno
);