From 200fbe924466720bd2a8c5eb05b05d67b0a2414c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 14 Mar 2013 15:42:19 +0100 Subject: Added support for ENEA OSE This port has support for both non-smp and smp. It contains a new way to do io checking in which erts_poll_wait receives the payload of the polled entity. This has implications for all linked-in drivers. --- erts/emulator/sys/common/erl_check_io.c | 115 +- erts/emulator/sys/common/erl_poll.h | 10 +- erts/emulator/sys/ose/default.lmconf | 10 + erts/emulator/sys/ose/erl_main.c | 70 ++ erts/emulator/sys/ose/erl_ose_sys.h | 238 ++++ erts/emulator/sys/ose/erl_ose_sys_ddll.c | 197 +++ erts/emulator/sys/ose/erl_poll.c | 748 ++++++++++++ erts/emulator/sys/ose/gcc_lm.lcf | 146 +++ erts/emulator/sys/ose/gcc_lm_ppc.lcf | 219 ++++ erts/emulator/sys/ose/gcc_lm_x86_4.4.3.lcf | 277 +++++ erts/emulator/sys/ose/gcc_lm_x86_4.6.3.lcf | 252 ++++ erts/emulator/sys/ose/sys.c | 1820 ++++++++++++++++++++++++++++ erts/emulator/sys/ose/sys_float.c | 844 +++++++++++++ erts/emulator/sys/ose/sys_time.c | 56 + 14 files changed, 4992 insertions(+), 10 deletions(-) create mode 100644 erts/emulator/sys/ose/default.lmconf create mode 100644 erts/emulator/sys/ose/erl_main.c create mode 100644 erts/emulator/sys/ose/erl_ose_sys.h create mode 100644 erts/emulator/sys/ose/erl_ose_sys_ddll.c create mode 100644 erts/emulator/sys/ose/erl_poll.c create mode 100644 erts/emulator/sys/ose/gcc_lm.lcf create mode 100644 erts/emulator/sys/ose/gcc_lm_ppc.lcf create mode 100644 erts/emulator/sys/ose/gcc_lm_x86_4.4.3.lcf create mode 100644 erts/emulator/sys/ose/gcc_lm_x86_4.6.3.lcf create mode 100644 erts/emulator/sys/ose/sys.c create mode 100644 erts/emulator/sys/ose/sys_float.c create mode 100644 erts/emulator/sys/ose/sys_time.c (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c index 7035dc77df..dab056e2df 100644 --- a/erts/emulator/sys/common/erl_check_io.c +++ b/erts/emulator/sys/common/erl_check_io.c @@ -34,6 +34,7 @@ #endif #include "sys.h" #include "global.h" +#include "erl_port.h" #include "erl_check_io.h" #include "erl_thr_progress.h" #include "dtrace-wrapper.h" @@ -78,6 +79,12 @@ typedef char EventStateFlags; #define ERTS_CIO_POLL_INIT ERTS_POLL_EXPORT(erts_poll_init) #define ERTS_CIO_POLL_INFO ERTS_POLL_EXPORT(erts_poll_info) +#ifdef __OSE__ +#define GET_FD(fd) fd->id +#else +#define GET_FD(fd) fd +#endif + static struct pollset_info { ErtsPollSet ps; @@ -435,7 +442,11 @@ deselect(ErtsDrvEventState *state, int mode) } } - state->events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, rm_events, 0, &do_wake); + state->events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, rm_events, 0, &do_wake +#ifdef __OSE__ + ,NULL +#endif + ); if (!(state->events)) { switch (state->type) { @@ -584,7 +595,11 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix, wake_poller = 1; } - new_events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, ctl_events, on, &wake_poller); + new_events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, ctl_events, on, &wake_poller +#ifdef __OSE__ + ,prt->drv_ptr->resolve_signal +#endif + ); if (new_events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL)) { if (state->type == ERTS_EV_TYPE_DRV_SEL && !state->events) { @@ -894,7 +909,7 @@ print_driver_name(erts_dsprintf_buf_t *dsbufp, Eterm id) static void steal(erts_dsprintf_buf_t *dsbufp, ErtsDrvEventState *state, int mode) { - erts_dsprintf(dsbufp, "stealing control of fd=%d from ", (int) state->fd); + erts_dsprintf(dsbufp, "stealing control of fd=%d from ", (int) GET_FD(state->fd)); switch (state->type) { case ERTS_EV_TYPE_DRV_SEL: { int deselect_mode = 0; @@ -918,7 +933,7 @@ steal(erts_dsprintf_buf_t *dsbufp, ErtsDrvEventState *state, int mode) if (deselect_mode) deselect(state, deselect_mode); else { - erts_dsprintf(dsbufp, "no one", (int) state->fd); + erts_dsprintf(dsbufp, "no one", (int) GET_FD(state->fd)); ASSERT(0); } erts_dsprintf(dsbufp, "\n"); @@ -946,7 +961,7 @@ steal(erts_dsprintf_buf_t *dsbufp, ErtsDrvEventState *state, int mode) break; } default: - erts_dsprintf(dsbufp, "no one\n", (int) state->fd); + erts_dsprintf(dsbufp, "no one\n", (int) GET_FD(state->fd)); ASSERT(0); } } @@ -957,14 +972,21 @@ print_select_op(erts_dsprintf_buf_t *dsbufp, { Port *pp = erts_drvport2port(ix); erts_dsprintf(dsbufp, +#ifdef __OSE__ + "driver_select(%p, %d,%s%s%s%s | %d, %d) " +#else "driver_select(%p, %d,%s%s%s%s, %d) " +#endif "by ", ix, - (int) fd, + (int) GET_FD(fd), mode & ERL_DRV_READ ? " ERL_DRV_READ" : "", mode & ERL_DRV_WRITE ? " ERL_DRV_WRITE" : "", mode & ERL_DRV_USE ? " ERL_DRV_USE" : "", mode & (ERL_DRV_USE_NO_CALLBACK & ~ERL_DRV_USE) ? "_NO_CALLBACK" : "", +#ifdef __OSE__ + fd->signo, +#endif on); print_driver_name(dsbufp, pp != ERTS_INVALID_ERL_DRV_PORT ? pp->common.id : NIL); erts_dsprintf(dsbufp, "driver %T ", pp != ERTS_INVALID_ERL_DRV_PORT ? pp->common.id : NIL); @@ -1010,7 +1032,7 @@ steal_pending_stop_select(erts_dsprintf_buf_t *dsbufp, ErlDrvPort ix, ASSERT(state->type == ERTS_EV_TYPE_STOP_USE); erts_dsprintf(dsbufp, "failed: fd=%d (re)selected before stop_select " "was called for driver %s\n", - (int) state->fd, state->driver.drv_ptr->name); + (int) GET_FD(state->fd), state->driver.drv_ptr->name); erts_send_error_to_logger_nogl(dsbufp); if (on) { @@ -1395,6 +1417,20 @@ stale_drv_select(Eterm id, ErtsDrvEventState *state, int mode) } #ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS +#ifdef __OSE__ +static SafeHashValue drv_ev_state_hash(void *des) +{ + SafeHashValue val = (SafeHashValue) ((ErtsDrvEventState *) des)->fd; + return val ^ (val >> 8); /* Good enough for aligned pointer values? */ +} + +static int drv_ev_state_cmp(void *des1, void *des2) +{ + return ( ((((ErtsDrvEventState *) des1)->fd->id == ((ErtsDrvEventState *) des2)->fd->id) + && (((ErtsDrvEventState *) des1)->fd->signo == ((ErtsDrvEventState *) des2)->fd->signo)) + ? 0 : 1); +} +#else static SafeHashValue drv_ev_state_hash(void *des) { SafeHashValue val = (SafeHashValue) ((ErtsDrvEventState *) des)->fd; @@ -1406,6 +1442,7 @@ static int drv_ev_state_cmp(void *des1, void *des2) return ( ((ErtsDrvEventState *) des1)->fd == ((ErtsDrvEventState *) des2)->fd ? 0 : 1); } +#endif static void *drv_ev_state_alloc(void *des_tmpl) { @@ -1436,7 +1473,69 @@ static void drv_ev_state_free(void *des) erts_smp_spin_unlock(&state_prealloc_lock); } #endif +#ifdef __OSE__ +OseSignal *erl_drv_ose_get_input_signal(ErlDrvEvent drv_ev) { + struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; + ethr_mutex_lock(&ev->mtx); + if (ev->imsgs == NULL) { + ethr_mutex_unlock(&ev->mtx); + return NULL; + } else { + ErtsPollOseMsgList *msg = ev->imsgs; + OseSignal *sig = (OseSignal*)msg->data; + ASSERT(msg->data); + ev->imsgs = msg->next; + ethr_mutex_unlock(&ev->mtx); + erts_free(ERTS_ALC_T_FD_SIG_LIST,msg); + restore(sig); + return sig; + } +} + +OseSignal *erl_drv_ose_get_output_signal(ErlDrvEvent drv_ev) { + struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; + ethr_mutex_lock(&ev->mtx); + if (ev->omsgs == NULL) { + ethr_mutex_unlock(&ev->mtx); + return NULL; + } else { + ErtsPollOseMsgList *msg = ev->omsgs; + OseSignal *sig = (OseSignal*)msg->data; + ASSERT(msg->data); + ev->omsgs = msg->next; + ethr_mutex_unlock(&ev->mtx); + erts_free(ERTS_ALC_T_FD_SIG_LIST,msg); + restore(sig); + return sig; + } +} +ErlDrvEvent erl_drv_ose_event_alloc(SIGSELECT signo, int id) { + struct erts_sys_fd_type *ev = erts_alloc(ERTS_ALC_T_DRV_EV, + sizeof(struct erts_sys_fd_type)); + ev->signo = signo; + ev->id = id; + ev->imsgs = NULL; + ev->omsgs = NULL; + ethr_mutex_init(&ev->mtx); + return (ErlDrvEvent)ev; +} + +void erl_drv_ose_event_free(ErlDrvEvent drv_ev) { + struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; + ethr_mutex_destroy(&ev->mtx); + erts_free(ERTS_ALC_T_DRV_EV,ev); +} + +void erl_drv_ose_event_fetch(ErlDrvEvent drv_ev, SIGSELECT *signo, int *id) { + struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; + if (signo) + *signo = ev->signo; + if (id) + *id = ev->id; +} + +#endif void ERTS_CIO_EXPORT(erts_init_check_io)(void) { @@ -1882,12 +1981,14 @@ ERTS_CIO_EXPORT(erts_check_io_debug)(void) int fd, len; #endif IterDebugCounters counters; +#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS ErtsDrvEventState null_des; null_des.driver.select = NULL; null_des.events = 0; null_des.remove_cnt = 0; null_des.type = ERTS_EV_TYPE_NONE; +#endif erts_printf("--- fds in pollset --------------------------------------\n"); diff --git a/erts/emulator/sys/common/erl_poll.h b/erts/emulator/sys/common/erl_poll.h index 09ed9f41af..e1ea8fb207 100644 --- a/erts/emulator/sys/common/erl_poll.h +++ b/erts/emulator/sys/common/erl_poll.h @@ -90,7 +90,7 @@ # if defined(ERTS_USE_POLL) # undef ERTS_POLL_USE_POLL # define ERTS_POLL_USE_POLL 1 -# elif !defined(__WIN32__) +# elif !defined(__WIN32__) && !defined(__OSE__) # undef ERTS_POLL_USE_SELECT # define ERTS_POLL_USE_SELECT 1 # endif @@ -99,7 +99,7 @@ typedef Uint32 ErtsPollEvents; #undef ERTS_POLL_EV_E2N -#if defined(__WIN32__) /* --- win32 ------------------------------- */ +#if defined(__WIN32__) || defined(__OSE__) /* --- win32 or ose -------- */ #define ERTS_POLL_EV_IN 1 #define ERTS_POLL_EV_OUT 2 @@ -228,7 +228,11 @@ ErtsPollEvents ERTS_POLL_EXPORT(erts_poll_control)(ErtsPollSet, ErtsSysFdType, ErtsPollEvents, int on, - int* wake_poller); + int* wake_poller +#ifdef __OSE__ + ,int (*decode)(OseSignal* sig, int* mode) +#endif + ); void ERTS_POLL_EXPORT(erts_poll_controlv)(ErtsPollSet, ErtsPollControlEntry [], int on); diff --git a/erts/emulator/sys/ose/default.lmconf b/erts/emulator/sys/ose/default.lmconf new file mode 100644 index 0000000000..f897872fa2 --- /dev/null +++ b/erts/emulator/sys/ose/default.lmconf @@ -0,0 +1,10 @@ +OSE_LM_STACK_SIZES=256,512,1024,2048,4096,8192,16384,65536 +OSE_LM_SIGNAL_SIZES=31,63,127,255,1023,4095,16383,65535 +OSE_LM_POOL_SIZE=0x200000 +OSE_LM_MAIN_NAME=main +OSE_LM_MAIN_STACK_SIZE=0x400 +OSE_LM_MAIN_PRIORITY=20 +OSE_LM_PROGRAM_TYPE=SYS_RAM +OSE_LM_DATA_INIT=YES +OSE_LM_BSS_INIT=YES +OSE_LM_EXEC_MODEL=SHARED diff --git a/erts/emulator/sys/ose/erl_main.c b/erts/emulator/sys/ose/erl_main.c new file mode 100644 index 0000000000..21cfce9463 --- /dev/null +++ b/erts/emulator/sys/ose/erl_main.c @@ -0,0 +1,70 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2000-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "sys.h" +#include "erl_vm.h" +#include "global.h" + +#include "shell.h" +#include "ramlog.h" +#include "ose_err/ose_err.h" + +static PROCESS mainPid; + +#ifdef DEBUG +static OSADDRESS err_handler(OSBOOLEAN user_called, OSERRCODE ecode, OSERRCODE extra) { + fprintf(stderr,"err_handler: %p %p\n",ecode,extra); + return 1; +} +#endif + +static int +cmd_ek(int argc, char **argv) { + kill_proc(mainPid); + return 0; +} + +static int +cmd_erl_start(int argc, char **argv) { + ramlog_printf("\n"); + ramlog_printf("================================================================\n"); + ramlog_printf("\n"); +#ifdef DEBUG + create_error_handler(get_bid(current_process()),err_handler,0x100); +#endif + erl_start(argc, argv); + return 0; +} + +int +main(int argc, char **argv) { + mainPid = current_process(); + + shell_add_cmd_attrs("start_beam", "start_beam [params]", "Start the Erlang VM", + cmd_erl_start, OS_PRI_PROC, 20, 0xF000); + + shell_add_cmd_attrs("ek", "ek", "Kills the Erlang VM", + cmd_ek, OS_PRI_PROC, 20, 0x100); + + stop(current_process()); + + return 0; +} diff --git a/erts/emulator/sys/ose/erl_ose_sys.h b/erts/emulator/sys/ose/erl_ose_sys.h new file mode 100644 index 0000000000..a3308e9ba4 --- /dev/null +++ b/erts/emulator/sys/ose/erl_ose_sys.h @@ -0,0 +1,238 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1997-2011. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + * This file handles differences between different Unix systems. + * This should be the only place with conditional compilation + * depending on the type of OS. + */ + +#ifndef _ERL_OSE_SYS_H +#define _ERL_OSE_SYS_H + +#include "ose.h" +#undef NIL +#include "ramlog.h" + +#include "fcntl.h" +#include "math.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "sys/param.h" +#include "sys/time.h" +#include "time.h" +#include "dirent.h" +#include "ethread.h" + +/* FIXME: configuration options */ +#define ERTS_SCHED_MIN_SPIN +#define ERTS_SCHED_ONLY_POLL_SCHED_1 +#define NO_SYSCONF 1 +#define OPEN_MAX FOPEN_MAX + +#define MAP_ANON MAP_ANONYMOUS + +#ifndef HAVE_MMAP +# define HAVE_MMAP 0 +#endif + +#if HAVE_MMAP +# include "sys/mman.h" +#endif + +typedef struct ErtsPollOseMsgList_ { + struct ErtsPollOseMsgList_ *next; + void *data; +} ErtsPollOseMsgList; + +struct erts_sys_fd_type { + SIGSELECT signo; + int id; + ErtsPollOseMsgList *imsgs; + ErtsPollOseMsgList *omsgs; + ethr_mutex mtx; +}; + + +/* + * Our own type of "FD's" + */ +#define ERTS_SYS_FD_TYPE struct erts_sys_fd_type* +#define NO_FSTAT_ON_SYS_FD_TYPE 1 /* They are signals, not files */ + +#include "sys/stat.h" + +/* FIXME mremap is not defined in OSE - POSIX issue */ +extern void *mremap (void *__addr, size_t __old_len, size_t __new_len, + int __flags, ...); + +/* FIXME: mremap constants */ +#define MREMAP_MAYMOVE 1 +#define MREMAP_FIXED 2 + +typedef void *GETENV_STATE; + +/* +** For the erl_timer_sup module. +*/ +#define HAVE_GETHRTIME + +typedef long long SysHrTime; +extern SysHrTime sys_gethrtime(void); + +void sys_init_hrtime(void); + +typedef time_t erts_time_t; + +typedef struct timeval SysTimeval; + +#define sys_gettimeofday(Arg) ((void) gettimeofday((Arg), NULL)) + +typedef struct { + clock_t tms_utime; + clock_t tms_stime; + clock_t tms_cutime; + clock_t tms_cstime; +} SysTimes; + +extern int erts_ticks_per_sec; + +#define SYS_CLK_TCK (erts_ticks_per_sec) + +extern clock_t sys_times(SysTimes *buffer); + +/* No use in having other resolutions than 1 Ms. */ +#define SYS_CLOCK_RESOLUTION 1 + +#ifdef NO_FPE_SIGNALS + +#define erts_get_current_fp_exception() NULL +#ifdef ERTS_SMP +#define erts_thread_init_fp_exception() do{}while(0) +#endif +# define __ERTS_FP_CHECK_INIT(fpexnp) do {} while (0) +# define __ERTS_FP_ERROR(fpexnp, f, Action) if (!finite(f)) { Action; } else {} +# define __ERTS_FP_ERROR_THOROUGH(fpexnp, f, Action) __ERTS_FP_ERROR(fpexnp, f, Action) +# define __ERTS_SAVE_FP_EXCEPTION(fpexnp) +# define __ERTS_RESTORE_FP_EXCEPTION(fpexnp) + +#define erts_sys_block_fpe() 0 +#define erts_sys_unblock_fpe(x) do{}while(0) + +#else /* !NO_FPE_SIGNALS */ + +extern volatile unsigned long *erts_get_current_fp_exception(void); +#ifdef ERTS_SMP +extern void erts_thread_init_fp_exception(void); +#endif +# if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__) +# define erts_fwait(fpexnp,f) \ + __asm__ __volatile__("fwait" : "=m"(*(fpexnp)) : "m"(f)) +# elif (defined(__powerpc__) || defined(__ppc__)) && defined(__GNUC__) +# define erts_fwait(fpexnp,f) \ + __asm__ __volatile__("" : "=m"(*(fpexnp)) : "fm"(f)) +# elif defined(__sparc__) && defined(__linux__) && defined(__GNUC__) +# define erts_fwait(fpexnp,f) \ + __asm__ __volatile__("" : "=m"(*(fpexnp)) : "em"(f)) +# else +# define erts_fwait(fpexnp,f) \ + __asm__ __volatile__("" : "=m"(*(fpexnp)) : "g"(f)) +# endif +# if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__) + extern void erts_restore_fpu(void); +# else +# define erts_restore_fpu() /*empty*/ +# endif +# if (!defined(__GNUC__) || \ + (__GNUC__ < 2) || \ + (__GNUC__ == 2 && __GNUC_MINOR < 96)) && \ + !defined(__builtin_expect) +# define __builtin_expect(x, expected_value) (x) +# endif +static __inline__ int erts_check_fpe(volatile unsigned long *fp_exception, double f) +{ + erts_fwait(fp_exception, f); + if (__builtin_expect(*fp_exception == 0, 1)) + return 0; + *fp_exception = 0; + erts_restore_fpu(); + return 1; +} +# undef erts_fwait +# undef erts_restore_fpu +extern void erts_fp_check_init_error(volatile unsigned long *fp_exception); +static __inline__ void __ERTS_FP_CHECK_INIT(volatile unsigned long *fp_exception) +{ + if (__builtin_expect(*fp_exception == 0, 1)) + return; + erts_fp_check_init_error(fp_exception); +} +# define __ERTS_FP_ERROR(fpexnp, f, Action) do { if (erts_check_fpe((fpexnp),(f))) { Action; } } while (0) +# define __ERTS_SAVE_FP_EXCEPTION(fpexnp) unsigned long old_erl_fp_exception = *(fpexnp) +# define __ERTS_RESTORE_FP_EXCEPTION(fpexnp) \ + do { *(fpexnp) = old_erl_fp_exception; } while (0) + /* This is for library calls where we don't trust the external + code to always throw floating-point exceptions on errors. */ +static __inline__ int erts_check_fpe_thorough(volatile unsigned long *fp_exception, double f) +{ + return erts_check_fpe(fp_exception, f) || !finite(f); +} +# define __ERTS_FP_ERROR_THOROUGH(fpexnp, f, Action) \ + do { if (erts_check_fpe_thorough((fpexnp),(f))) { Action; } } while (0) + +int erts_sys_block_fpe(void); +void erts_sys_unblock_fpe(int); + +#endif /* !NO_FPE_SIGNALS */ + +#define ERTS_FP_CHECK_INIT(p) __ERTS_FP_CHECK_INIT(&(p)->fp_exception) +#define ERTS_FP_ERROR(p, f, A) __ERTS_FP_ERROR(&(p)->fp_exception, f, A) +#define ERTS_FP_ERROR_THOROUGH(p, f, A) __ERTS_FP_ERROR_THOROUGH(&(p)->fp_exception, f, A) + +/* FIXME: force HAVE_GETPAGESIZE and stub getpagesize */ +#ifndef HAVE_GETPAGESIZE +#define HAVE_GETPAGESIZE 1 +#endif + +extern int getpagesize(void); + +#ifndef HZ +#define HZ 60 +#endif + +/* OSE5 doesn't provide limits.h so a number of macros should be + * added manually */ + +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + +/* Minimum and maximum values a `signed int' can hold. */ +#ifndef INT_MAX +#define INT_MAX 2147483647 +#endif + +#ifndef INT_MIN +#define INT_MIN (-INT_MAX - 1) +#endif + +#ifndef UINT_MAX +# define UINT_MAX 4294967295U +#endif + +#endif /* _ERL_OSE_SYS_H */ diff --git a/erts/emulator/sys/ose/erl_ose_sys_ddll.c b/erts/emulator/sys/ose/erl_ose_sys_ddll.c new file mode 100644 index 0000000000..4121199096 --- /dev/null +++ b/erts/emulator/sys/ose/erl_ose_sys_ddll.c @@ -0,0 +1,197 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2006-2013. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Interface functions to the dynamic linker using dl* functions. + * (As far as I know it works on SunOS 4, 5, Linux and FreeBSD. /Seb) + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "sys.h" +#include "erl_vm.h" +#include "global.h" +#ifdef HAVE_DLFCN_H +#include +#endif + + +/* some systems do not have RTLD_NOW defined, and require the "mode" + * argument to dload() always be 1. + */ +#ifndef RTLD_NOW +# define RTLD_NOW 1 +#endif + +#define MAX_NAME_LEN 255 /* XXX should we get the system path size? */ +#define EXT_LEN 3 +#define FILE_EXT ".so" /* extension appended to the filename */ + +static char **errcodes = NULL; +static int num_errcodes = 0; +static int num_errcodes_allocated = 0; + +#define my_strdup(WHAT) my_strdup_in(ERTS_ALC_T_DDLL_ERRCODES, WHAT); + +static char *my_strdup_in(ErtsAlcType_t type, char *what) +{ + char *res = erts_alloc(type, strlen(what) + 1); + strcpy(res, what); + return res; +} + + +static int find_errcode(char *string, ErtsSysDdllError* err) +{ + int i; + + if (err != NULL) { + erts_sys_ddll_free_error(err); /* in case we ignored an earlier error */ + err->str = my_strdup_in(ERTS_ALC_T_DDLL_TMP_BUF, string); + return 0; + } + for(i=0;i ERL_DE_DYNAMIC_ERROR_OFFSET) { + return "Unspecified error"; + } + actual_code = -1*(code - ERL_DE_DYNAMIC_ERROR_OFFSET); +#if defined(HAVE_DLOPEN) + { + char *msg; + + if (actual_code >= num_errcodes) { + msg = "Unknown dlload error"; + } else { + msg = errcodes[actual_code]; + } + return msg; + } +#endif + return "no error"; +} + +void erts_sys_ddll_free_error(ErtsSysDdllError* err) +{ + if (err->str != NULL) { + erts_free(ERTS_ALC_T_DDLL_TMP_BUF, err->str); + } +} diff --git a/erts/emulator/sys/ose/erl_poll.c b/erts/emulator/sys/ose/erl_poll.c new file mode 100644 index 0000000000..878bd362e4 --- /dev/null +++ b/erts/emulator/sys/ose/erl_poll.c @@ -0,0 +1,748 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2006-2012. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Description: Poll interface suitable for ERTS on OSE with or without + * SMP support. + * + * The interface is currently implemented using: + * - receive + receive_fsem + * + * Author: Lukas Larsson + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "erl_thr_progress.h" +#include "erl_driver.h" +#include "erl_alloc.h" +#include "erl_poll.h" + +#define NOFILE 4096 + +/* + * Some debug macros + */ + +/* #define HARDDEBUG +#define HARDTRACE*/ +#ifdef HARDDEBUG +#ifdef HARDTRACE +#define HARDTRACEF(X, ...) { fprintf(stderr, X, __VA_ARGS__); fprintf(stderr,"\r\n"); } +#else +#define HARDTRACEF(...) +#endif + +#else +#define HARDTRACEF(X,...) +#define HARDDEBUGF(...) +#endif + +#if 0 +#define ERTS_POLL_DEBUG_PRINT +#endif + +#if defined(DEBUG) && 0 +#define HARD_DEBUG +#endif + +# define SEL_ALLOC erts_alloc +# define SEL_REALLOC realloc_wrap +# define SEL_FREE erts_free + +#define ERTS_POLL_INVALID_SIGNO 12345 + +#ifdef ERTS_SMP + +#define ERTS_POLLSET_LOCK(PS) \ + erts_smp_mtx_lock(&(PS)->mtx) +#define ERTS_POLLSET_UNLOCK(PS) \ + erts_smp_mtx_unlock(&(PS)->mtx) + +#else + +#define ERTS_POLLSET_LOCK(PS) +#define ERTS_POLLSET_UNLOCK(PS) + +#endif + +/* + * --- Data types ------------------------------------------------------------ + */ + +union SIGNAL { + SIGSELECT sig_no; +}; + +typedef struct erts_sigsel_item_ ErtsSigSelItem; + +struct erts_sigsel_item_ { + ErtsSigSelItem *next; + ErtsSysFdType fd; + ErtsPollEvents events; +}; + +typedef struct erts_sigsel_info_ ErtsSigSelInfo; + +struct erts_sigsel_info_ { + ErtsSigSelInfo *next; + SIGSELECT signo; + int (*decode)(OseSignal* sig, int* mode); + ErtsSigSelItem *fds; +}; + +struct ErtsPollSet_ { + SIGSELECT *sigs; + ErtsSigSelInfo *info; + Uint sig_count; + Uint item_count; + PROCESS interrupt; + erts_atomic32_t wakeup_state; + erts_smp_atomic32_t timeout; +#ifdef ERTS_SMP + erts_smp_mtx_t mtx; +#endif +}; + +static int max_fds = -1; + +#define ERTS_POLL_NOT_WOKEN ((erts_aint32_t) (1 << 0)) +#define ERTS_POLL_WOKEN_INTR ((erts_aint32_t) (1 << 1)) +#define ERTS_POLL_WOKEN_TIMEDOUT ((erts_aint32_t) (1 << 2)) +#define ERTS_POLL_WOKEN_IO_READY ((erts_aint32_t) (1 << 3)) +#define ERTS_POLL_SLEEPING ((erts_aint32_t) (1 << 4)) + +/* signal list prototypes */ +static ErtsSigSelInfo *get_sigsel_info(ErtsPollSet ps, SIGSELECT signo); +static ErtsSigSelItem *get_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd); +static ErtsSigSelInfo *add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd, int (*decode)(OseSignal* sig, int* mode)); +static ErtsSigSelItem *add_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd, int (*decode)(OseSignal* sig, int* mode)); +static int del_sigsel_info(ErtsPollSet ps, ErtsSigSelInfo *info); +static int del_sigsel_item(ErtsPollSet ps, ErtsSigSelItem *item); +static int update_sigsel(ErtsPollSet ps); + +static ErtsSigSelInfo * +get_sigsel_info(ErtsPollSet ps, SIGSELECT signo) { + ErtsSigSelInfo *curr = ps->info; + while (curr != NULL) { + if (curr->signo == signo) + return curr; + curr = curr->next; + } + return NULL; +} + +static ErtsSigSelItem * +get_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd) { + ErtsSigSelInfo *info = get_sigsel_info(ps,fd->signo); + ErtsSigSelItem *curr; + + if (info == NULL) + return NULL; + + curr = info->fds; + + while (curr != NULL) { + if (curr->fd->id == fd->id) { + ASSERT(curr->fd->signo == fd->signo); + return curr; + } + curr = curr->next; + } + return NULL; +} + +static ErtsSigSelInfo * +add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd, + int (*decode)(OseSignal* sig, int* mode)) { + ErtsSigSelInfo *info = SEL_ALLOC(ERTS_ALC_T_POLLSET, + sizeof(ErtsSigSelInfo)); + info->next = ps->info; + info->fds = NULL; + info->signo = fd->signo; + info->decode = decode; + ps->info = info; + ps->sig_count++; + return info; +} + +static ErtsSigSelItem * +add_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd, + int (*decode)(OseSignal* sig, int* mode)) { + ErtsSigSelInfo *info = get_sigsel_info(ps,fd->signo); + ErtsSigSelItem *item = SEL_ALLOC(ERTS_ALC_T_POLLSET, + sizeof(ErtsSigSelItem)); + if (info == NULL) + info = add_sigsel_info(ps, fd, decode); + if (info->decode != decode) { + erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); + erts_dsprintf(dsbufp, "erts_poll_control() inconsistency: multiple resolve_signal functions for same signal (%d)\n", + fd->signo); + erts_send_error_to_logger_nogl(dsbufp); + } + ASSERT(info->decode == decode); + item->next = info->fds; + item->fd = fd; + item->events = 0; + info->fds = item; + ps->item_count++; + return item; +} + +static int del_sigsel_info(ErtsPollSet ps, ErtsSigSelInfo *info) { + ErtsSigSelInfo *curr, *prev; + + if (ps->info == info) { + ps->info = ps->info->next; + } else { + curr = ps->info->next; + prev = ps->info; + + while (curr != info) { + if (curr == NULL) + return 1; + prev = curr; + curr = curr->next; + } + prev->next = curr->next; + } + + ps->sig_count--; + SEL_FREE(ERTS_ALC_T_POLLSET, info); + return 0; +} + +static int del_sigsel_item(ErtsPollSet ps, ErtsSigSelItem *item) { + ErtsSigSelInfo *info = get_sigsel_info(ps,item->fd->signo); + ErtsSigSelItem *curr, *prev; + + ps->item_count--; + ASSERT(ps->item_count >= 0); + + if (info->fds == item) { + info->fds = info->fds->next; + SEL_FREE(ERTS_ALC_T_POLLSET,item); + if (info->fds == NULL) + return del_sigsel_info(ps,info); + return 0; + } + + curr = info->fds->next; + prev = info->fds; + + while (curr != item) { + if (curr == NULL) { + /* We did not find an item to delete so we have to + * increment item count again. + */ + ps->item_count++; + return 1; + } + prev = curr; + curr = curr->next; + } + prev->next = curr->next; + SEL_FREE(ERTS_ALC_T_POLLSET,item); + return 0; +} + +#ifdef ERTS_SMP + +static void update_redir_tables(ErtsPollSet ps) { + struct OS_redir_entry *redir_table; + PROCESS sched_1 = ERTS_SCHEDULER_IX(0)->tid.id; + int i; + redir_table = SEL_ALLOC(ERTS_ALC_T_POLLSET, + sizeof(struct OS_redir_entry)*(ps->sig_count+1)); + + redir_table[0].sig = ps->sig_count+1; + redir_table[0].pid = 0; + + for (i = 1; i < ps->sig_count+1; i++) { + ramlog_printf("Adding 0x%p -> 0x%p to redir table\n",ps->sigs[i],sched_1); + redir_table[i].sig = ps->sigs[i]; + redir_table[i].pid = sched_1; + } + + for (i = 1; i < erts_no_schedulers; i++) { + ErtsSchedulerData *esdp = ERTS_SCHEDULER_IX(i); + set_redirection(esdp->tid.id,redir_table); + ramlog_printf("Setting redir table to 0x%p\n",esdp->tid.id); + } + + SEL_FREE(ERTS_ALC_T_POLLSET,redir_table); +} + +#endif + +static int update_sigsel(ErtsPollSet ps) { + ErtsSigSelInfo *info = ps->info; + + int i; + + if (ps->sigs != NULL) + SEL_FREE(ERTS_ALC_T_POLLSET,ps->sigs); + + if (ps->sig_count == 0) { + /* If there are no signals we place a non-valid signal to make sure that + * we do not trigger on a any unrelated signals which are sent to the + * process. + */ + ps->sigs = SEL_ALLOC(ERTS_ALC_T_POLLSET,sizeof(SIGSELECT)*(2)); + ps->sigs[0] = 1; + ps->sigs[1] = ERTS_POLL_INVALID_SIGNO; + return 0; + } + + ps->sigs = SEL_ALLOC(ERTS_ALC_T_POLLSET,sizeof(SIGSELECT)*(ps->sig_count+1)); + ps->sigs[0] = ps->sig_count; + + for (i = 1; info != NULL; i++, info = info->next) + ps->sigs[i] = info->signo; + +#ifdef ERTS_SMP + update_redir_tables(ps); +#endif + + return 0; +} + +static ERTS_INLINE void +wake_poller(ErtsPollSet ps) +{ + erts_aint32_t wakeup_state; + + ERTS_THR_MEMORY_BARRIER; + wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state); + while (wakeup_state != ERTS_POLL_WOKEN_IO_READY + && wakeup_state != ERTS_POLL_WOKEN_INTR) { + erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state, + ERTS_POLL_WOKEN_INTR, + wakeup_state); + if (act == wakeup_state) { + wakeup_state = act; + break; + } + wakeup_state = act; + } + if (wakeup_state == ERTS_POLL_SLEEPING) { + /* + * Since we don't know the internals of signal_fsem() we issue + * a memory barrier as a safety precaution ensuring that + * the store we just made to wakeup_state wont be reordered + * with loads in signal_fsem(). + */ + ERTS_THR_MEMORY_BARRIER; + signal_fsem(ps->interrupt); + } +} + +static ERTS_INLINE void +reset_interrupt(ErtsPollSet ps) +{ + /* We need to keep io-ready if set */ + erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state); + while (wakeup_state != ERTS_POLL_NOT_WOKEN && + wakeup_state != ERTS_POLL_SLEEPING) { + erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state, + ERTS_POLL_NOT_WOKEN, + wakeup_state); + if (wakeup_state == act) + break; + wakeup_state = act; + } + ERTS_THR_MEMORY_BARRIER; +} + +static ERTS_INLINE void +set_interrupt(ErtsPollSet ps) +{ + wake_poller(ps); +} + +void erts_poll_interrupt(ErtsPollSet ps,int set) { + HARDTRACEF("erts_poll_interrupt called!\n"); + + if (!set) + reset_interrupt(ps); + else + set_interrupt(ps); + +} + +void erts_poll_interrupt_timed(ErtsPollSet ps,int set,erts_short_time_t msec) { + HARDTRACEF("erts_poll_interrupt_timed called!\n"); + + if (!set) + reset_interrupt(ps); + else if (erts_smp_atomic32_read_acqb(&ps->timeout) > (erts_aint32_t) msec) + set_interrupt(ps); +} + +ErtsPollEvents erts_poll_control(ErtsPollSet ps, ErtsSysFdType fd, + ErtsPollEvents pe, int on, int* do_wake, + int(*decode)(OseSignal* sig, int* mode)) { + ErtsSigSelItem *curr; + ErtsPollEvents new_events; + int old_sig_count; + + HARDTRACEF( + "%ux: In erts_poll_control, fd = %d, pe = %d, on = %d, *do_wake = %d, curr = 0x%xu", + ps, fd, pe, on, do_wake, curr); + + ERTS_POLLSET_LOCK(ps); + + curr = get_sigsel_item(ps, fd); + old_sig_count = ps->sig_count; + + if (curr == NULL && on) { + curr = add_sigsel_item(ps, fd, decode); + } else if (curr == NULL && !on) { + new_events = ERTS_POLL_EV_NVAL; + goto done; + } + + new_events = curr->events; + + if (pe == 0) { + *do_wake = 0; + goto done; + } + + if (on) { + new_events |= pe; + curr->events = new_events; + } else { + new_events &= ~pe; + curr->events = new_events; + if (new_events == 0 && del_sigsel_item(ps, curr)) { + new_events = ERTS_POLL_EV_NVAL; + goto done; + } + } + + if (ps->sig_count != old_sig_count) { + if (update_sigsel(ps)) + new_events = ERTS_POLL_EV_NVAL; + } +done: + ERTS_POLLSET_UNLOCK(ps); + HARDTRACEF("%ux: Out erts_poll_control", ps); + return new_events; +} + +int erts_poll_wait(ErtsPollSet ps, + ErtsPollResFd pr[], + int *len, + SysTimeval *utvp) { + int res = ETIMEDOUT, no_fds, currid = 0; + OSTIME timeout; + OseSignal *sig; + // HARDTRACEF("%ux: In erts_poll_wait",ps); + if (ps->interrupt == (PROCESS)0) + ps->interrupt = current_process(); + + ASSERT(current_process() == ps->interrupt); + ASSERT(get_fsem(current_process()) == 0); + ASSERT(erts_atomic32_read_nob(&ps->wakeup_state) & + (ERTS_POLL_NOT_WOKEN | ERTS_POLL_WOKEN_INTR)); + /* Max no of spots avable in pr */ + no_fds = *len; + + *len = 0; + + ASSERT(utvp); + + /* erts_printf("Entering erts_poll_wait(), timeout=%d\n", + (int) utvp->tv_sec*1000 + utvp->tv_usec/1000); */ + + timeout = utvp->tv_sec*1000 + utvp->tv_usec/1000; + + if (timeout > ((time_t) ERTS_AINT32_T_MAX)) + timeout = ERTS_AINT32_T_MAX; + erts_smp_atomic32_set_relb(&ps->timeout, (erts_aint32_t) timeout); + + while (currid < no_fds) { + if (timeout > 0) { + erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state, + ERTS_POLL_SLEEPING, + ERTS_POLL_NOT_WOKEN); + if (act == ERTS_POLL_NOT_WOKEN) { +#ifdef ERTS_SMP + erts_thr_progress_prepare_wait(NULL); +#endif + sig = receive_fsem(timeout, ps->sigs, 1); +#ifdef ERTS_SMP + erts_thr_progress_finalize_wait(NULL); +#endif + } else { + ASSERT(act == ERTS_POLL_WOKEN_INTR); + sig = OS_RCV_FSEM; + } + } else + sig = receive_w_tmo(0, ps->sigs); + + if (sig == NULL) { + if (timeout > 0) { + erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state, + ERTS_POLL_WOKEN_TIMEDOUT, + ERTS_POLL_SLEEPING); + if (act == ERTS_POLL_WOKEN_INTR) + /* Restore fsem as it was signaled but we got a timeout */ + wait_fsem(1); + } else + erts_atomic32_cmpxchg_nob(&ps->wakeup_state, + ERTS_POLL_WOKEN_TIMEDOUT, + ERTS_POLL_NOT_WOKEN); + break; + } else if (sig == OS_RCV_FSEM) { + ASSERT(erts_atomic32_read_nob(&ps->wakeup_state) == ERTS_POLL_WOKEN_INTR); + break; + } + { + ErtsSigSelInfo *info = get_sigsel_info(ps, sig->sig_no); + int mode = -1; + struct erts_sys_fd_type fd = { sig->sig_no, info->decode(sig, &mode) }; + ErtsSigSelItem *item = get_sigsel_item(ps, &fd); + + ASSERT(sig); + if (currid == 0 && timeout > 0) { + erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state, + ERTS_POLL_WOKEN_IO_READY, + ERTS_POLL_SLEEPING); + if (act == ERTS_POLL_WOKEN_INTR) { + /* Restore fsem as it was signaled but we got a msg */ + wait_fsem(1); + act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state, + ERTS_POLL_WOKEN_IO_READY, + ERTS_POLL_WOKEN_INTR); + } + } else if (currid == 0) { + erts_atomic32_set_nob(&ps->wakeup_state, + ERTS_POLL_WOKEN_IO_READY); + } + + if (item == NULL) { + erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); + erts_dsprintf( + dsbufp, + "erts_poll_wait() failed: found unkown signal id %d (signo %u) " + "(curr_proc 0x%x /sender 0x%x)\n", + fd.id, fd.signo, current_process(), sender(&sig)); + erts_send_error_to_logger_nogl(dsbufp); + timeout = 0; + ASSERT(0); + } else if (mode == -1 && item->events == (ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) { + erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); + erts_dsprintf( + dsbufp, + "erts_poll_wait() failed: found ambigous signal id %d (signo %u) " + "(curr_proc 0x%x /sender 0x%x)\n You have to give a specify a mode " + "in the resolve_signal callback for this signal.\n", + fd.id, fd.signo, current_process(), sender(&sig)); + erts_send_error_to_logger_nogl(dsbufp); + timeout = 0; + ASSERT(0); + } else { + int i; + struct erts_sys_fd_type *fd = NULL; + ErtsPollOseMsgList *tl,*new; + + /* Figure out which mode to set and which queue to store + the signal in */ + if (mode == -1) + mode = item->events; + else if (mode == 0) + mode = ERTS_POLL_EV_IN; + else if (mode == 1) + mode = ERTS_POLL_EV_OUT; + else + abort(); + + /* Check if this fd has already been triggered by a previous signal */ + for (i = 0; i < currid;i++) { + if (pr[i].fd == item->fd) { + fd = pr[i].fd; + pr[i].events |= mode; + break; + } + } + + /* First time this fd is triggered */ + if (fd == NULL) { + pr[currid].fd = item->fd; + pr[currid].events = mode; + fd = item->fd; + timeout = 0; + currid++; + } + + /* Insert new signal in approriate list */ + new = erts_alloc(ERTS_ALC_T_FD_SIG_LIST,sizeof(ErtsPollOseMsgList)); + new->next = NULL; + new->data = sig; + + ethr_mutex_lock(&fd->mtx); + if (mode & ERTS_POLL_EV_IN) + tl = fd->imsgs; + else if (mode & ERTS_POLL_EV_OUT) + tl = fd->omsgs; + + if (tl == NULL) { + if (mode & ERTS_POLL_EV_IN) + fd->imsgs = new; + else if (mode & ERTS_POLL_EV_OUT) + fd->omsgs = new; + } else { + while (tl->next != NULL) + tl = tl->next; + tl->next = new; + } + ethr_mutex_unlock(&fd->mtx); + } + + } + } + + { + erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state); + + switch (wakeup_state) { + case ERTS_POLL_WOKEN_IO_READY: + res = 0; + break; + case ERTS_POLL_WOKEN_INTR: + res = EINTR; + break; + case ERTS_POLL_WOKEN_TIMEDOUT: + res = ETIMEDOUT; + break; + case ERTS_POLL_NOT_WOKEN: + /* This happens when we get an invalid signal only */ + res = EINVAL; + break; + default: + res = 0; + erl_exit(ERTS_ABORT_EXIT, + "%s:%d: Internal error: Invalid wakeup_state=%d\n", + __FILE__, __LINE__, (int) wakeup_state); + } + } + + erts_atomic32_set_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN); + erts_smp_atomic32_set_nob(&ps->timeout, ERTS_AINT32_T_MAX); + + *len = currid; + + // HARDTRACEF("%ux: Out erts_poll_wait",ps); + return res; +} + +int erts_poll_max_fds(void) +{ + + HARDTRACEF("In/Out erts_poll_max_fds -> %d",max_fds); + return max_fds; +} + +void erts_poll_info(ErtsPollSet ps, + ErtsPollInfo *pip) +{ + Uint size = 0; + Uint num_events = 0; + + size += sizeof(struct ErtsPollSet_); + size += sizeof(ErtsSigSelInfo)*ps->sig_count; + size += sizeof(ErtsSigSelItem)*ps->item_count; + size += sizeof(SIGSELECT)*(ps->sig_count+1); + + pip->primary = "receive_fsem"; + + pip->fallback = NULL; + + pip->kernel_poll = NULL; + + pip->memory_size = size; + + pip->poll_set_size = num_events; + + pip->fallback_poll_set_size = 0; + + pip->lazy_updates = 0; + + pip->pending_updates = 0; + + pip->batch_updates = 0; + + pip->concurrent_updates = 0; + + + pip->max_fds = erts_poll_max_fds(); + HARDTRACEF("%ux: Out erts_poll_info",ps); + +} + +ErtsPollSet erts_poll_create_pollset(void) +{ + ErtsPollSet ps = SEL_ALLOC(ERTS_ALC_T_POLLSET, + sizeof(struct ErtsPollSet_)); + + ps->sigs = NULL; + ps->sig_count = 0; + ps->item_count = 0; + ps->info = NULL; + ps->interrupt = (PROCESS)0; + erts_atomic32_init_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN); + erts_smp_atomic32_init_nob(&ps->timeout, ERTS_AINT32_T_MAX); +#ifdef ERTS_SMP + erts_smp_mtx_init(&ps->mtx, "pollset"); +#endif + update_sigsel(ps); + HARDTRACEF("%ux: Out erts_poll_create_pollset",ps); + return ps; +} + +void erts_poll_destroy_pollset(ErtsPollSet ps) +{ + ErtsSigSelInfo *info; + for (info = ps->info; ps->info != NULL; info = ps->info, ps->info = ps->info->next) { + ErtsSigSelItem *item; + for (item = info->fds; info->fds != NULL; item = info->fds, info->fds = info->fds->next) + SEL_FREE(ERTS_ALC_T_POLLSET, item); + SEL_FREE(ERTS_ALC_T_POLLSET, info); + } + + SEL_FREE(ERTS_ALC_T_POLLSET,ps->sigs); + +#ifdef ERTS_SMP + erts_smp_mtx_destroy(&ps->mtx); +#endif + + SEL_FREE(ERTS_ALC_T_POLLSET,ps); +} + +void erts_poll_init(void) +{ + HARDTRACEF("In %s", __FUNCTION__); + max_fds = 256; + + HARDTRACEF("Out %s", __FUNCTION__); +} diff --git a/erts/emulator/sys/ose/gcc_lm.lcf b/erts/emulator/sys/ose/gcc_lm.lcf new file mode 100644 index 0000000000..42b6f89851 --- /dev/null +++ b/erts/emulator/sys/ose/gcc_lm.lcf @@ -0,0 +1,146 @@ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH("i386") +ENTRY("crt0_lm") +MEMORY +{ + rom : ORIGIN = 0x01000000, LENGTH = 0x01000000 + ram : ORIGIN = 0x02000000, LENGTH = 0x01000000 +} +PHDRS +{ + ph_conf PT_LOAD ; + ph_rom PT_LOAD ; + ph_ram PT_LOAD ; +} +SECTIONS +{ + .text : + { + *(.text_first) + *(.text) + *(.text.*) + *(.stub) + *(oscode) + *(.init*) + *(.fini*) + *(.gnu.warning) + *(.gnu.linkonce.t.*) + *(.glue_7t) + *(.glue_7) + } > rom :ph_rom = 0 + .ose_sfk_biosentry : + { + *(.ose_sfk_biosentry) + } > rom :ph_rom + .ctors : + { + __CTOR_LIST__ = .; + *(.ctors) + *(SORT(.ctors.*)) + __CTOR_END__ = .; + } > rom :ph_rom + .dtors : + { + __DTOR_LIST__ = .; + *(.dtors) + *(SORT(.dtors.*)) + __DTOR_END__ = .; + } > rom :ph_rom + OSESYMS : + { + *(.osesyms) + } > rom :ph_rom + .rodata : + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } > rom :ph_rom + .eh_frame : + { + __EH_FRAME_BEGIN__ = .; + *(.eh_frame) + LONG(0) + __EH_FRAME_END__ = .; + } > rom :ph_rom + .gcc_except_table : + { + *(.gcc_except_table) + } > rom :ph_rom + .sdata2 : + { + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + } > rom :ph_rom + .sbss2 : + { + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + } > rom :ph_rom + LMCONF : + { + obj/?*?/ose_confd.o(.rodata) + *(LMCONF) + } > rom :ph_conf + .data : + { + LONG(0xDEADBABE) + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + . = ALIGN(0x10); + } > ram :ph_ram = 0 + .sdata2 : + { + _SDA2_BASE_ = .; + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + }> ram :ph_ram + .sdata : + { + _SDA_BASE_ = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } > ram :ph_ram + .sbss : + { + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.gnu.linkonce.sb.*) + } > ram :ph_ram + .bss (NOLOAD) : + { + *(.bss) + *(.bss.*) + *(COMMON) + *(.gnu.linkonce.b.*) + *(.osvars) + } > ram :ph_ram + .ignore (NOLOAD) : + { + *(.rel.dyn) + } > ram :ph_ram + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} +__OSESYMS_START = ADDR(OSESYMS); +__OSESYMS_END = ADDR(OSESYMS) + SIZEOF(OSESYMS); diff --git a/erts/emulator/sys/ose/gcc_lm_ppc.lcf b/erts/emulator/sys/ose/gcc_lm_ppc.lcf new file mode 100644 index 0000000000..a2399c93da --- /dev/null +++ b/erts/emulator/sys/ose/gcc_lm_ppc.lcf @@ -0,0 +1,219 @@ +/******************************************************************************* + * gcc_lm_ppc.lcf: GCC linker control file for PowerPC load modules + * @(#) $FilePath: /vobs/ose5/system/refsys/compilers/gcc_lm_ppc.lcf $ + * @(#) $FileRevision: /main/tb_current_ose5/10 $ + * $Author: joka $$Date: 01/21/13 16:35:41 $ + * $Copyright: (C) 2006 by Enea AB. All rights reserved. $ + ******************************************************************************/ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH("powerpc") + +ENTRY("crt0_lm") + +/* Note: + * You may have to increase the length of the "rom" memory region and the + * origin and length of the "ram" memory region below depending on the size + * of the code and data in your load module. + */ + +MEMORY +{ + conf : ORIGIN = 0x00100000, LENGTH = 0x00030000 + rom : ORIGIN = 0x01000000, LENGTH = 0x01000000 + ram : ORIGIN = 0x03000000, LENGTH = 0x01000000 +} + +PHDRS +{ + ph_conf PT_LOAD ; + ph_rom PT_LOAD ; + ph_ram PT_LOAD ; +} + +SECTIONS +{ +/*--------------------------------------------------------------------------- + * Load module configuration area + *-------------------------------------------------------------------------*/ + + /* Load module configuration section. */ + LMCONF : + { + obj/?*?/ose_confd.o(.rodata) + *(LMCONF) + } > conf :ph_conf + +/*--------------------------------------------------------------------------- + * Read-only area + *-------------------------------------------------------------------------*/ + + /* Code section. */ + .text : + { + *(.text) + *(.text.*) + *(.stub) + *(oscode) + *(.init*) + *(.fini*) + *(.gnu.warning) + *(.gnu.linkonce.t.*) + } > rom :ph_rom = 0 + + /* OSE symbols section. */ + OSESYMS : + { + *(.osesyms) + } > rom :ph_rom + + /* Read-only data section. */ + .rodata : + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } > rom :ph_rom + + /* C++ exception handling section. */ + .eh_frame : + { + __EH_FRAME_BEGIN__ = .; + *(.eh_frame) + LONG(0) + __EH_FRAME_END__ = .; + } > rom :ph_rom + + /* C++ exception handling section. */ + .gcc_except_table : + { + *(.gcc_except_table .gcc_except_table.*) + } > rom :ph_rom + + /* PowerPC EABI initialized read-only data section. */ + .sdata2 : + { + PROVIDE (_SDA2_BASE_ = .); + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + } > rom :ph_rom + + /* PowerPC EABI uninitialized read-only data section. */ + .sbss2 : + { + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + } > rom :ph_rom + +/*--------------------------------------------------------------------------- + * Read-write area + *-------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------- + * Initialized data (copied by PM) + *-----------------------------------------------------------------*/ + + /* Data section. */ + .data : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } > ram :ph_ram + + /* C++ constructor section. */ + .ctors : + { + __CTOR_LIST__ = .; + *(.ctors) + *(SORT(.ctors.*)) + __CTOR_END__ = .; + } > ram :ph_ram + + /* C++ destructor section. */ + .dtors : + { + __DTOR_LIST__ = .; + *(.dtors) + *(SORT(.dtors.*)) + __DTOR_END__ = .; + } > ram :ph_ram + + + /* Small data section. */ + .sdata ALIGN(0x10) : + { + PROVIDE (_SDA_BASE_ = .); + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } > ram :ph_ram + + /*------------------------------------------------------------------- + * Uninitialized data (cleared by PM) + *-----------------------------------------------------------------*/ + + /* Small bss section. */ + .sbss : + { + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.gnu.linkonce.sb.*) + } > ram :ph_ram + + /* Bss section. */ + .bss : + { + *(.bss) + *(.bss.*) + *(COMMON) + *(.gnu.linkonce.b.*) + } > ram :ph_ram + +/*--------------------------------------------------------------------------- + * Debug information + *-------------------------------------------------------------------------*/ + + /* + * Stabs debug sections. + */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + /* + * DWARF debug sections. + */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/erts/emulator/sys/ose/gcc_lm_x86_4.4.3.lcf b/erts/emulator/sys/ose/gcc_lm_x86_4.4.3.lcf new file mode 100644 index 0000000000..d64fd91604 --- /dev/null +++ b/erts/emulator/sys/ose/gcc_lm_x86_4.4.3.lcf @@ -0,0 +1,277 @@ +/* COPYRIGHT-ENEA-EXAMPLE-R2 * +************************************************************************** +* Copyright (C) 2010 by Enea Software AB. +* All rights reserved. +* +* This Example is furnished under a Software License Agreement and +* may be used only in accordance with the terms of such agreement. +* No title to and ownership of the Example is hereby transferred. +* +* The information in this Example is subject to change +* without notice and should not be construed as a commitment +* by Enea Software AB. +* +* DISCLAIMER +* This Example is delivered "AS IS", consequently +* Enea Software AB makes no representations or warranties, +* expressed or implied, for the Example. +************************************************************************** +* COPYRIGHT-END */ + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH("i386") + +ENTRY("crt0_lm") + +MEMORY +{ + rom : ORIGIN = 0x01000000, LENGTH = 0x01000000 + ram : ORIGIN = 0x02000000, LENGTH = 0x01000000 +} + +PHDRS +{ + ph_conf PT_LOAD ; + ph_rom PT_LOAD ; + ph_ram PT_LOAD ; +} + +SECTIONS +{ +/*--------------------------------------------------------------------------- + * Read-only area + *-------------------------------------------------------------------------*/ + + /* Code section. */ + .text : + { + *(.text_first) + *(.text) + *(.text.*) + *(.stub) + *(oscode) + *(.init*) + *(.fini*) + *(.gnu.warning) + *(.gnu.linkonce.t.*) + *(.glue_7t) + *(.glue_7) + } > rom :ph_rom = 0 + + + .ose_sfk_biosentry : + { + *(.ose_sfk_biosentry) + } > rom :ph_rom + + /* C++ constructor section. */ + .ctors : + { + __CTOR_LIST__ = .; + *(.ctors) + *(SORT(.ctors.*)) + __CTOR_END__ = .; + } > rom :ph_rom + + /* C++ destructor section. */ + .dtors : + { + __DTOR_LIST__ = .; + *(.dtors) + *(SORT(.dtors.*)) + __DTOR_END__ = .; + } > rom :ph_rom + + /* OSE symbols section. */ + OSESYMS : + { + *(.osesyms) + } > rom :ph_rom + + .plt : + { + *(.plt) + *(.iplt) + } > rom :ph_rom + + + /* Read-only data section. */ + .rodata : + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } > rom :ph_rom + + /* C++ exception handling section. */ + .eh_frame : + { + __EH_FRAME_BEGIN__ = .; + *(.eh_frame) + LONG(0) + __EH_FRAME_END__ = .; + } > rom :ph_rom + + /* C++ exception handling section. */ + .gcc_except_table : + { + *(.gcc_except_table) + } > rom :ph_rom + + /* PowerPC EABI initialized read-only data section. */ + .sdata2 : + { + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + } > rom :ph_rom + + /* PowerPC EABI uninitialized read-only data section. */ + .sbss2 : + { + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + } > rom :ph_rom + + /* Dynamic relocations */ + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rel.ifunc) + } > rom :ph_rom + +/*--------------------------------------------------------------------------- + * Load module configuration area + *-------------------------------------------------------------------------*/ + + /* Load module configuration section. */ + LMCONF : + { + obj/?*?/ose_confd.o(.rodata) + *(LMCONF) + } > rom :ph_conf + + +/*--------------------------------------------------------------------------- + * Read-write area + *-------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------- + * Initialized data (copied by PM ) + *-----------------------------------------------------------------*/ + + /* Data section. */ + .data : + { + LONG(0xDEADBABE) + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + . = ALIGN(0x10); + } > ram :ph_ram = 0 + + .got : + { + *(.got.plt) + *(.got) + } > rom :ph_ram + + /* Global offset table for dynamically linked procedures. */ + .got.plt : + { + *(.got.plt) + *(.igot.plt) + } > rom :ph_ram + + /* Small data section. */ + .sdata2 : + { + _SDA2_BASE_ = .; + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + }> ram :ph_ram + .sdata : + { + _SDA_BASE_ = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } > ram :ph_ram + + /*------------------------------------------------------------------- + * Uninitialized data (cleared by PM ) + *-----------------------------------------------------------------*/ + + /* Small bss section. */ + .sbss : + { + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.gnu.linkonce.sb.*) + } > ram :ph_ram + + /* Bss section. */ + .bss (NOLOAD) : + { + *(.bss) + *(.bss.*) + *(COMMON) + *(.gnu.linkonce.b.*) + *(.osvars) + } > ram :ph_ram + + /* Ignore unwanted sections that are not used in OSE. */ + .ignore (NOLOAD) : + { + *(.rel.dyn) + } > ram :ph_ram + +/*--------------------------------------------------------------------------- + * Debug information + *-------------------------------------------------------------------------*/ + + /* + * DWARF debug sections. + */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + +} + +/* Symbols used by DDA. */ +__OSESYMS_START = ADDR(OSESYMS); +__OSESYMS_END = ADDR(OSESYMS) + SIZEOF(OSESYMS); diff --git a/erts/emulator/sys/ose/gcc_lm_x86_4.6.3.lcf b/erts/emulator/sys/ose/gcc_lm_x86_4.6.3.lcf new file mode 100644 index 0000000000..bb357afcb1 --- /dev/null +++ b/erts/emulator/sys/ose/gcc_lm_x86_4.6.3.lcf @@ -0,0 +1,252 @@ +/******************************************************************************* + * gcc_lm_x86.lcf: GCC linker control file for x86 load modules + * @(#) $FilePath: /vobs/ose5/system/refsys/compilers/gcc_lm_x86.lcf $ + * @(#) $FileRevision: /main/tb_current_ose5/9 $ + * $Author: rand $$Date: 10/29/12 17:45:04 $ + * $Copyright: (C) 2006 by Enea AB. All rights reserved. $ + ******************************************************************************/ + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH("i386") + +ENTRY("crt0_lm") + +/* Note: + * You may have to increase the length of the "rom" memory region below + * depending on the size of the code and data in your load module. + */ + +MEMORY +{ + conf : ORIGIN = 0x00300000, LENGTH = 0x00001000 + rom : ORIGIN = 0x00000000, LENGTH = 0x00300000 +} + +PHDRS +{ + ph_conf PT_LOAD ; + ph_rom PT_LOAD ; + ph_ram PT_LOAD ; +} + +SECTIONS +{ +/*--------------------------------------------------------------------------- + * Load module configuration area + *-------------------------------------------------------------------------*/ + + /* Load module configuration section. */ + LMCONF : + { + dummy = ALIGN(0x10000); + */?*?/*ose_confd.o(LMCONF*) + *(LMCONF*) + *ose_confd.o(.rodata) + } > conf :ph_conf + +/*--------------------------------------------------------------------------- + * Read-only area + *-------------------------------------------------------------------------*/ + + /* Init section. */ + .init : + { + KEEP(*(.init)) + } > rom :ph_rom = 0x90909090 + + /* Code section. */ + .text : + { + *(.text) + *(.text.*) + *(.stub) + *(oscode) + *(.init*) + *(.fini*) + *(.gnu.warning) + *(.gnu.linkonce.t.*) + } > rom :ph_rom = 0 + + /* Read-only data section. */ + .rodata : + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } > rom :ph_rom + + /* OSE symbols section. */ + OSESYMS : + { + *(.osesyms) + } > rom :ph_rom + + /* Procedure linkage table section. */ + .plt : + { + *(.plt) + *(.iplt) + } > rom :ph_rom + + /* Dynamic relocations */ + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rel.ifunc) + } > rom :ph_rom + +/*--------------------------------------------------------------------------- + * Read-write area + *-------------------------------------------------------------------------*/ + + /* C++ constructor section. */ + .ctors : + { + __CTOR_LIST__ = .; + *(.ctors) + *(SORT(.ctors.*)) + __CTOR_END__ = .; + } > rom :ph_rom + + /* C++ destructor section. */ + .dtors : + { + __DTOR_LIST__ = .; + *(.dtors) + *(SORT(.dtors.*)) + __DTOR_END__ = .; + } > rom :ph_rom + + /* C++ exception handling section. */ + .eh_frame : + { + __EH_FRAME_BEGIN__ = .; + *(.eh_frame) + LONG(0) + __EH_FRAME_END__ = .; + } > rom :ph_rom + + /*------------------------------------------------------------------- + * Initialized data (copied by PM) + *-----------------------------------------------------------------*/ + + /* Data section. */ + .data : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } > rom :ph_ram + + /* Global offset table section. */ + .got : + { + *(.got.plt) + *(.got) + } > rom :ph_ram + + /* Global offset table for dynamically linked procedures. */ + .got.plt : + { + *(.got.plt) + *(.igot.plt) + } > rom :ph_ram + + /* SFK BIOS entry section. */ + .ose_sfk_biosentry : + { + *(.ose_sfk_biosentry) + } > rom :ph_ram + + /* C++ exception handling section. */ + .gcc_except_table : + { + *(.gcc_except_table .gcc_except_table.*) + } > rom :ph_ram + + /* Small data section. */ + .sdata ALIGN(0x10) : + { + PROVIDE (_SDA_BASE_ = .); + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } > rom :ph_ram + + /*------------------------------------------------------------------- + * Uninitialized data (cleared by PM) + *-----------------------------------------------------------------*/ + + /* Bss section. */ + .bss : + { + *(.bss) + *(.bss.*) + *(COMMON) + *(.gnu.linkonce.b.*) + } > rom :ph_ram + + /* Small bss section. */ + .sbss ALIGN(0x10) : + { + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.gnu.linkonce.sb.*) + } > rom :ph_ram + +/*--------------------------------------------------------------------------- + * Debug information + *-------------------------------------------------------------------------*/ + + /* + * Stabs debug sections. + */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + /* + * DWARF debug sections. + */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c new file mode 100644 index 0000000000..c475aafe38 --- /dev/null +++ b/erts/emulator/sys/ose/sys.c @@ -0,0 +1,1820 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1996-2013. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef ISC32 +#define _POSIX_SOURCE +#define _XOPEN_SOURCE +#endif + +#include /* ose*/ +#include +/* ose +#include +#include +#include +*/ + +#include +#include +#include + +#ifdef ISC32 +#include +#endif + +#include +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#define ERTS_WANT_BREAK_HANDLING +#define WANT_NONBLOCKING /* must define this to pull in defs from sys.h */ +#include "sys.h" +#include "erl_thr_progress.h" + +#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__) +#define __DARWIN__ 1 +#endif + +#ifdef USE_THREADS +#include "erl_threads.h" +#endif + +#include "erl_mseg.h" + +/*ose*/ +#include "unistd.h" +#include "efs.h" +#include "erl_printf.h" +#if 0 +#define TRACE do { \ + erts_fprintf(stderr, " %s / %d / pid 0x%x\n", __FUNCTION__, __LINE__, current_process()); \ + } while(0) +#else +#define TRACE do {} while(0) +#endif +/*ose*/ + +extern char **environ; +static erts_smp_rwmtx_t environ_rwmtx; + +#define MAX_VSIZE 16 /* Max number of entries allowed in an I/O + * vector sock_sendv(). + */ +/* + * Don't need global.h, but bif_table.h (included by bif.h), + * won't compile otherwise + */ +#include "global.h" +#include "bif.h" + +#include "erl_sys_driver.h" +#include "erl_check_io.h" +#include "erl_cpu_topology.h" + +#ifndef DISABLE_VFORK +#define DISABLE_VFORK 0 +#endif + +/* The priority for reader/writer processes */ +#define FD_PROC_PRI 20 + +/* + * [OTP-3906] + * Solaris signal management gets confused when threads are used and a + * lot of child processes dies. The confusion results in that SIGCHLD + * signals aren't delivered to the emulator which in turn results in + * a lot of defunct processes in the system. + * + * The problem seems to appear when a signal is frequently + * blocked/unblocked at the same time as the signal is frequently + * propagated. The child waiter thread is a workaround for this problem. + * The SIGCHLD signal is always blocked (in all threads), and the child + * waiter thread fetches the signal by a call to sigwait(). See + * child_waiter(). + */ + +typedef struct ErtsSysReportExit_ ErtsSysReportExit; +struct ErtsSysReportExit_ { + ErtsSysReportExit *next; + Eterm port; + int pid; + int ifd; + int ofd; + ErlDrvEvent in_sig_descr; + ErlDrvEvent out_sig_descr; +}; + +/* This data is shared by these drivers - initialized by spawn_init() */ +static struct driver_data { + ErlDrvPort port_num; + int ofd, packet_bytes; + ErtsSysReportExit *report_exit; + int pid; + int alive; + int status; + ErlDrvEvent in_sig_descr; + ErlDrvEvent out_sig_descr; + PROCESS in_proc; + PROCESS out_proc; + ErlDrvPDL pdl; +} *driver_data; /* indexed by fd */ + +static ErtsSysReportExit *report_exit_list; + +extern int driver_interrupt(int, int); +extern void do_break(void); + +extern void erl_sys_args(int*, char**); + +/* The following two defs should probably be moved somewhere else */ + +extern void erts_sys_init_float(void); + +extern void erl_crash_dump(char* file, int line, char* fmt, ...); + +#define DIR_SEPARATOR_CHAR '/' + +#if defined(DEBUG) +#define ERL_BUILD_TYPE_MARKER ".debug" +#else /* opt */ +#define ERL_BUILD_TYPE_MARKER +#endif + +#define CHILD_SETUP_PROG_NAME "child_setup" ERL_BUILD_TYPE_MARKER + +#ifdef DEBUG +static int debug_log = 0; +#endif + +#ifdef ERTS_SMP +static erts_smp_atomic32_t have_prepared_crash_dump; +#define ERTS_PREPARED_CRASH_DUMP \ + ((int) erts_smp_atomic32_xchg_nob(&have_prepared_crash_dump, 1)) +#else +static volatile int have_prepared_crash_dump; +#define ERTS_PREPARED_CRASH_DUMP \ + (have_prepared_crash_dump++) +#endif + +static erts_smp_atomic_t sys_misc_mem_sz; + +#if defined(ERTS_SMP) +erts_mtx_t chld_stat_mtx; +#endif + +#if defined(ERTS_SMP) /* ------------------------------------------------- */ +#define CHLD_STAT_LOCK erts_mtx_lock(&chld_stat_mtx) +#define CHLD_STAT_UNLOCK erts_mtx_unlock(&chld_stat_mtx) + +#else /* ------------------------------------------------------------------- */ +#define CHLD_STAT_LOCK +#define CHLD_STAT_UNLOCK +static volatile int children_died; +#endif + + +static struct fd_data { + char pbuf[4]; /* hold partial packet bytes */ + int psz; /* size of pbuf */ + char *buf; + char *cpos; + int sz; + int remain; /* for input on fd */ +} *fd_data; /* indexed by fd */ + +/********************* General functions ****************************/ + +/* This is used by both the drivers and general I/O, must be set early */ +static int max_files = -1; + +/* + * a few variables used by the break handler + */ +#ifdef ERTS_SMP +erts_smp_atomic32_t erts_break_requested; +#define ERTS_SET_BREAK_REQUESTED \ + erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 1) +#define ERTS_UNSET_BREAK_REQUESTED \ + erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 0) +#else +volatile int erts_break_requested = 0; +#define ERTS_SET_BREAK_REQUESTED (erts_break_requested = 1) +#define ERTS_UNSET_BREAK_REQUESTED (erts_break_requested = 0) +#endif +/* set early so the break handler has access to initial mode */ +static struct termios initial_tty_mode; +static int replace_intr = 0; +/* assume yes initially, ttsl_init will clear it */ +int using_oldshell = 1; + +static void +init_check_io(void) +{ + erts_init_check_io(); + max_files = erts_check_io_max_files(); +} + +#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT +#define ERTS_CHK_IO_AS_INTR() erts_check_io_async_sig_interrupt() +#else +#define ERTS_CHK_IO_AS_INTR() erts_check_io_interrupt(1) +#endif +#define ERTS_CHK_IO_INTR erts_check_io_interrupt +#define ERTS_CHK_IO_INTR_TMD erts_check_io_interrupt_timed +#define ERTS_CHK_IO erts_check_io +#define ERTS_CHK_IO_SZ erts_check_io_size + + +void +erts_sys_schedule_interrupt(int set) +{ + ERTS_CHK_IO_INTR(set); +} + +#ifdef ERTS_SMP +void +erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec) +{ + ERTS_CHK_IO_INTR_TMD(set, msec); +} +#endif + +Uint +erts_sys_misc_mem_sz(void) +{ + Uint res = ERTS_CHK_IO_SZ(); + res += erts_smp_atomic_read_mb(&sys_misc_mem_sz); + return res; +} + +/* + * reset the terminal to the original settings on exit + */ +void sys_tty_reset(int exit_code) +{ + if (using_oldshell && !replace_intr) { + SET_BLOCKING(0); + } + else if (isatty(0)) { + tcsetattr(0,TCSANOW,&initial_tty_mode); + } +} + +#ifdef USE_THREADS + +typedef struct { + int sched_bind_data; +} erts_thr_create_data_t; + +/* + * thr_create_prepare() is called in parent thread before thread creation. + * Returned value is passed as argument to thr_create_cleanup(). + */ +static void * +thr_create_prepare(void) +{ + erts_thr_create_data_t *tcdp; + + tcdp = erts_alloc(ERTS_ALC_T_TMP, sizeof(erts_thr_create_data_t)); + + tcdp->sched_bind_data = erts_sched_bind_atthrcreate_prepare(); + + return (void *) tcdp; +} + + +/* thr_create_cleanup() is called in parent thread after thread creation. */ +static void +thr_create_cleanup(void *vtcdp) +{ + erts_thr_create_data_t *tcdp = (erts_thr_create_data_t *) vtcdp; + + erts_sched_bind_atthrcreate_parent(tcdp->sched_bind_data); + + erts_free(ERTS_ALC_T_TMP, tcdp); +} + +static void +thr_create_prepare_child(void *vtcdp) +{ + erts_thr_create_data_t *tcdp = (erts_thr_create_data_t *) vtcdp; + +#ifdef ERTS_ENABLE_LOCK_COUNT + erts_lcnt_thread_setup(); +#endif + + erts_sched_bind_atthrcreate_child(tcdp->sched_bind_data); +} + +#endif /* #ifdef USE_THREADS */ + +void +erts_sys_pre_init(void) +{ + erts_printf_add_cr_to_stdout = 1; + erts_printf_add_cr_to_stderr = 1; +#ifdef USE_THREADS + { + erts_thr_init_data_t eid = ERTS_THR_INIT_DATA_DEF_INITER; + + eid.thread_create_child_func = thr_create_prepare_child; + /* Before creation in parent */ + eid.thread_create_prepare_func = thr_create_prepare; + /* After creation in parent */ + eid.thread_create_parent_func = thr_create_cleanup, + + erts_thr_init(&eid); + + report_exit_list = NULL; + +#ifdef ERTS_ENABLE_LOCK_COUNT + erts_lcnt_init(); +#endif + +#if defined(ERTS_SMP) + erts_mtx_init(&chld_stat_mtx, "child_status"); +#endif + } +#ifdef ERTS_SMP + erts_smp_atomic32_init_nob(&erts_break_requested, 0); + erts_smp_atomic32_init_nob(&have_prepared_crash_dump, 0); +#else + erts_break_requested = 0; + have_prepared_crash_dump = 0; +#endif +#if !defined(ERTS_SMP) + children_died = 0; +#endif +#endif /* USE_THREADS */ + erts_smp_atomic_init_nob(&sys_misc_mem_sz, 0); +} + +void +erl_sys_init(void) +{ + +#ifdef USE_SETLINEBUF + setlinebuf(stdout); +#else + setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ); +#endif + + erts_sys_init_float(); + + /* we save this so the break handler can set and reset it properly */ + /* also so that we can reset on exit (break handler or not) */ + if (isatty(0)) { + tcgetattr(0,&initial_tty_mode); + } + tzset(); /* Required at least for NetBSD with localtime_r() */ +} + +static ERTS_INLINE int +prepare_crash_dump(int secs) +{ +#define NUFBUF (3) + int i, max; + char env[21]; /* enough to hold any 64-bit integer */ + size_t envsz; + /*DeclareTmpHeapNoproc(heap,NUFBUF);*/ + /*Eterm *hp = heap;*/ + /*Eterm list = NIL;*/ + int has_heart = 0; + + UseTmpHeapNoproc(NUFBUF); + + if (ERTS_PREPARED_CRASH_DUMP) + return 0; /* We have already been called */ + + + /* Positive secs means an alarm must be set + * 0 or negative means no alarm + * + * Set alarm before we try to write to a port + * we don't want to hang on a port write with + * no alarm. + * + */ + +#if 0 /*ose TBD!!!*/ + if (secs >= 0) { + alarm((unsigned int)secs); + } +#endif + + /* Make sure we unregister at epmd (unknown fd) and get at least + one free filedescriptor (for erl_crash.dump) */ + + max = max_files; + if (max < 1024) + max = 1024; + for (i = 3; i < max; i++) { + close(i); + } + + envsz = sizeof(env); + i = erts_sys_getenv__("ERL_CRASH_DUMP_NICE", env, &envsz); + if (i >= 0) { + int nice_val; + nice_val = i != 0 ? 0 : atoi(env); + if (nice_val > 39) { + nice_val = 39; + } + set_pri(nice_val); + } + + UnUseTmpHeapNoproc(NUFBUF); +#undef NUFBUF + return has_heart; +} + +int erts_sys_prepare_crash_dump(int secs) +{ + return prepare_crash_dump(secs); +} + +static ERTS_INLINE void +break_requested(void) +{ + /* + * just set a flag - checked for and handled by + * scheduler threads erts_check_io() (not signal handler). + */ +#ifdef DEBUG + fprintf(stderr,"break!\n"); +#endif + if (ERTS_BREAK_REQUESTED) + erl_exit(ERTS_INTR_EXIT, ""); + + ERTS_SET_BREAK_REQUESTED; + ERTS_CHK_IO_AS_INTR(); /* Make sure we don't sleep in poll */ +} + +/* Disable break */ +void erts_set_ignore_break(void) { + +} + +/* Don't use ctrl-c for break handler but let it be + used by the shell instead (see user_drv.erl) */ +void erts_replace_intr(void) { + struct termios mode; + + if (isatty(0)) { + tcgetattr(0, &mode); + + /* here's an example of how to replace ctrl-c with ctrl-u */ + /* mode.c_cc[VKILL] = 0; + mode.c_cc[VINTR] = CKILL; */ + + mode.c_cc[VINTR] = 0; /* disable ctrl-c */ + tcsetattr(0, TCSANOW, &mode); + replace_intr = 1; + } +} + +void init_break_handler(void) +{ + +} + +int sys_max_files(void) +{ + return(max_files); +} + + +/************************** OS info *******************************/ + +/* Used by erlang:info/1. */ +/* (This code was formerly in drv.XXX/XXX_os_drv.c) */ + +char os_type[] = "ose"; + +void +os_flavor(char* namebuf, /* Where to return the name. */ + unsigned size) /* Size of name buffer. */ +{ +#if 0 + struct utsname uts; /* Information about the system. */ + char* s; + + (void) uname(&uts); + for (s = uts.sysname; *s; s++) { + if (isupper((int) *s)) { + *s = tolower((int) *s); + } + } + strcpy(namebuf, uts.sysname); +#else + strncpy(namebuf, "release", size); +#endif +} + +void +os_version(pMajor, pMinor, pBuild) +int* pMajor; /* Pointer to major version. */ +int* pMinor; /* Pointer to minor version. */ +int* pBuild; /* Pointer to build number. */ +{ + *pMajor = 5; + *pMinor = 7; + *pBuild = 0; +} + +void init_getenv_state(GETENV_STATE *state) +{ + erts_smp_rwmtx_rlock(&environ_rwmtx); + *state = NULL; +} + +char **environ; /*ose - needs replacement*/ + +char *getenv_string(GETENV_STATE *state0) +{ + char **state = (char **) *state0; + char *cp; + + ERTS_SMP_LC_ASSERT(erts_smp_lc_rwmtx_is_rlocked(&environ_rwmtx)); + + if (state == NULL) + state = environ; + + cp = *state++; + *state0 = (GETENV_STATE) state; + + return cp; +} + +void fini_getenv_state(GETENV_STATE *state) +{ + *state = NULL; + erts_smp_rwmtx_runlock(&environ_rwmtx); +} + + +/************************** Port I/O *******************************/ + + + +/* I. Common stuff */ + +/* + * Decreasing the size of it below 16384 is not allowed. + */ +#define SYSDRIVERASYNCSIG 1000 +#define SYSDRIVERCONFSIG 1001 + +typedef struct SysDriverAsyncSignal_ { + SIGSELECT sig_no; + int type; + byte *buff; + ssize_t res; + int errno_copy; +} SysDriverAsyncSignal; + +typedef struct SysDriverConfSignal_ { + SIGSELECT sig_no; + int fd; + PROCESS parent; +} SysDriverConfSignal; + +union SIGNAL { + SIGSELECT sig_no; + SysDriverAsyncSignal sys_async; + SysDriverConfSignal conf_async; +}; + +/* II. The spawn/fd drivers */ + +#define ERTS_SYS_READ_BUF_SZ (64*1024) + +/* Driver interfaces */ +static ErlDrvData spawn_start(ErlDrvPort, char*, SysDriverOpts*); +static ErlDrvData fd_start(ErlDrvPort, char*, SysDriverOpts*); +static ErlDrvSSizeT fd_control(ErlDrvData, unsigned int, char *, ErlDrvSizeT, + char **, ErlDrvSizeT); +static int spawn_init(void); +static void fd_stop(ErlDrvData); +static void erl_stop(ErlDrvData); +static void ready_input(ErlDrvData, ErlDrvEvent); +static void ready_output(ErlDrvData, ErlDrvEvent); +static void output(ErlDrvData, char*, ErlDrvSizeT); +static void outputv(ErlDrvData, ErlIOVec*); +static void stop_select(ErlDrvEvent, void*); +static int resolve_signal(OseSignal* sig, int *mode) { + return sig->sig_no == SYSDRIVERASYNCSIG ? sig->sys_async.type : -1; +} + +OS_PROCESS(fd_writer_process); +OS_PROCESS(fd_reader_process); + +struct erl_drv_entry spawn_driver_entry = { + spawn_init, + spawn_start, + erl_stop, + output, + ready_input, + ready_output, + "spawn", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL, NULL, + stop_select, + resolve_signal +}; +struct erl_drv_entry fd_driver_entry = { + NULL, + fd_start, + fd_stop, + output, + ready_input, + ready_output, + "fd", + NULL, + NULL, + fd_control, + NULL, + outputv, + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, /* ERL_DRV_FLAGs */ + NULL, /* handle2 */ + NULL, /* process_exit */ + stop_select, + resolve_signal +}; + +static int set_driver_data(ErlDrvPort port_num, + int ifd, + int ofd, + int packet_bytes, + int read_write, + int exit_status, + int pid) +{ + Port *prt; + ErtsSysReportExit *report_exit; + OseSignal *sig; + + /*erts_fprintf(stderr, " %s / pid %x / ofd %d / ifd %d\n", __FUNCTION__, current_process(), ofd, ifd);*/ + + + if (!exit_status) + report_exit = NULL; + else { + report_exit = erts_alloc(ERTS_ALC_T_PRT_REP_EXIT, + sizeof(ErtsSysReportExit)); + report_exit->next = report_exit_list; + report_exit->port = erts_drvport2id(port_num); + report_exit->pid = pid; + report_exit->ifd = read_write & DO_READ ? ifd : -1; + report_exit->ofd = read_write & DO_WRITE ? ofd : -1; + + if (read_write & DO_READ) + report_exit->in_sig_descr = erl_drv_ose_event_alloc(SYSDRIVERASYNCSIG, ifd); + if (read_write & DO_WRITE) + report_exit->out_sig_descr = erl_drv_ose_event_alloc(SYSDRIVERASYNCSIG, ofd); + + report_exit_list = report_exit; + } + + prt = erts_drvport2port(port_num); + if (prt != ERTS_INVALID_ERL_DRV_PORT) + prt->os_pid = pid; + + if (read_write & DO_READ) { + driver_data[ifd].packet_bytes = packet_bytes; + driver_data[ifd].port_num = port_num; + driver_data[ifd].report_exit = report_exit; + driver_data[ifd].pid = pid; + driver_data[ifd].alive = 1; + driver_data[ifd].status = 0; + driver_data[ifd].in_sig_descr = erl_drv_ose_event_alloc(SYSDRIVERASYNCSIG,ifd); + + driver_data[ifd].in_proc = create_process(OS_PRI_PROC,"beam_fd_reader", + fd_reader_process, 0x800, + FD_PROC_PRI, 0, 0, NULL, 0, 0); + efs_clone(driver_data[ifd].in_proc); + sig = alloc(sizeof(SysDriverConfSignal), SYSDRIVERCONFSIG); + sig->conf_async.fd = ifd; + sig->conf_async.parent = current_process(); + send(&sig, driver_data[ifd].in_proc); + start(driver_data[ifd].in_proc); + + if (read_write & DO_WRITE) { + driver_data[ifd].ofd = ofd; + driver_data[ifd].out_sig_descr = + erl_drv_ose_event_alloc(SYSDRIVERASYNCSIG,ofd); + driver_data[ifd].pdl = driver_pdl_create(port_num); + driver_data[ifd].out_proc = create_process(OS_PRI_PROC, "beam_fd_writer", + fd_writer_process, 0x800, + FD_PROC_PRI, 0, 0, NULL, 0, 0); + sig = alloc(sizeof(SysDriverConfSignal), SYSDRIVERCONFSIG); + sig->conf_async.fd = ofd; + sig->conf_async.parent = current_process(); + send(&sig, driver_data[ifd].out_proc); + // efs_clone(driver_data[ifd].out_proc); + start(driver_data[ifd].out_proc); + if (ifd != ofd) + driver_data[ofd] = driver_data[ifd]; /* structure copy */ + } else { /* DO_READ only */ + driver_data[ifd].ofd = -1; + } + (void) driver_select(port_num, driver_data[ifd].in_sig_descr, (ERL_DRV_READ | ERL_DRV_USE), 1); + return(ifd); + } else { /* DO_WRITE only */ + driver_data[ofd].packet_bytes = packet_bytes; + driver_data[ofd].port_num = port_num; + driver_data[ofd].report_exit = report_exit; + driver_data[ofd].ofd = ofd; + driver_data[ofd].pid = pid; + driver_data[ofd].alive = 1; + driver_data[ofd].status = 0; + driver_data[ofd].in_sig_descr = erl_drv_ose_event_alloc(SYSDRIVERASYNCSIG, + ofd); + driver_data[ofd].out_sig_descr = driver_data[ofd].in_sig_descr; + driver_data[ofd].out_proc = create_process(OS_PRI_PROC, "beam_fd_writer", + fd_writer_process, 0x800, + FD_PROC_PRI, 0, 0, NULL, 0, 0); + sig = alloc(sizeof(SysDriverConfSignal), SYSDRIVERCONFSIG); + sig->conf_async.fd = ofd; + sig->conf_async.parent = current_process(); + send(&sig, driver_data[ofd].out_proc); + start(driver_data[ofd].out_proc); + //efs_clone(driver_data[ifd].out_proc); + driver_data[ofd].pdl = driver_pdl_create(port_num); + return(ofd); + } +} + +static int spawn_init() +{ + int i; + TRACE; + + driver_data = (struct driver_data *) + erts_alloc(ERTS_ALC_T_DRV_TAB, max_files * sizeof(struct driver_data)); + erts_smp_atomic_add_nob(&sys_misc_mem_sz, max_files * sizeof(struct driver_data)); + + for (i = 0; i < max_files; i++) + driver_data[i].pid = -1; + + return 1; +} + +static void init_fd_data(int fd, ErlDrvPort port_num) +{ + TRACE; + + fd_data[fd].buf = NULL; + fd_data[fd].cpos = NULL; + fd_data[fd].remain = 0; + fd_data[fd].sz = 0; + fd_data[fd].psz = 0; +} + +static ErlDrvData spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts) +{ + + long res = 0; + + TRACE; + /* Have to implement for OSE */ + return (ErlDrvData)res; +} + +OS_PROCESS(fd_reader_process) { + OseSignal *sig; + PROCESS parent; + int fd; + byte *read_buf; + + SIGSELECT sigsel[] = {1,SYSDRIVERCONFSIG}; + +#ifdef ERTS_ENABLE_LOCK_COUNT + erts_lcnt_init(); +#endif + + TRACE; + + sig = receive(sigsel); + + TRACE; + + fd = sig->conf_async.fd; + + parent = sig->conf_async.parent; + free_buf(&sig); + +#ifdef ERTS_ENABLE_LOCK_CHECK + { + char buf[31]; + erts_snprintf(&buf[0], 31, "fd_reader %beu", fd); + erts_lc_set_thread_name(&buf[0]); + } +#endif + + sigsel[1] = SYSDRIVERASYNCSIG; + + read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF, + ERTS_SYS_READ_BUF_SZ); + while (1) { + int errno_copy = errno; + ssize_t res; + res = read(fd, read_buf, ERTS_SYS_READ_BUF_SZ); + sig = alloc(sizeof(SysDriverAsyncSignal), SYSDRIVERASYNCSIG); + sig->sys_async.buff = read_buf; + sig->sys_async.res = res; + if (res <= 0 && errno == EBADF) { + fprintf(stderr,"Could not read from input fd (fd %d/ errno %d/ res %d)\n", + fd, errno, res); + break; + } + if (errno != errno_copy) + sig->sys_async.errno_copy = errno; + else + sig->sys_async.errno_copy = -1; + sig->sys_async.type = fd; + send(&sig,parent); + /* Wait for acc from async_read */ + sig = receive(sigsel); + free_buf(&sig); + } + erts_free(ERTS_ALC_T_SYS_READ_BUF, read_buf); +} + +OS_PROCESS(fd_writer_process) { + OseSignal *sig; + PROCESS parent; + int fd; + SIGSELECT sigsel[] = { 1, SYSDRIVERCONFSIG, SYSDRIVERASYNCSIG }; + + TRACE; + /* Only wait for config event with the fd which we are printing to */ + sig = receive(sigsel); + + TRACE; + + fd = sig->conf_async.fd; + parent = sig->conf_async.parent; + free_buf(&sig); + +#ifdef ERTS_ENABLE_LOCK_COUNT + { + char buf[31]; + erts_snprintf(&buf[0], 31, "fd_writer %beu", fd); + erts_lc_set_thread_name(&buf[0]); + } +#endif + + sigsel[0] = 2; + /* Why do I need these?!? */ + if (fd == 1) { + FILE* ffd = stdout; + } else if (fd == 2) { + FILE* ffd = stderr; + } + + while (1) { + int errno_copy = errno; + int res; + SysIOVec *iov0; + SysIOVec *iov; + int iovlen; + int iovcnt; + int n = 0, i; + size_t p; + /* fprintf(stderr,"0x%x: fd_writer, receive\n", current_process()); */ + sig = receive(sigsel); + /* size = sig->sys_async.res;*/ + if (sig->sig_no == SYSDRIVERCONFSIG) + return; + driver_pdl_lock(driver_data[fd].pdl); + + iov0 = driver_peekq(driver_data[fd].port_num, &iovlen); + + /* Calculate iovcnt */ + for (p = 0, iovcnt = 0; iovcnt < iovlen; + p += iov0[iovcnt++].iov_len) + ; + iov = driver_alloc(sizeof(SysIOVec) * iovcnt); + memcpy(iov, iov0, iovcnt * sizeof(SysIOVec)); + driver_pdl_unlock(driver_data[fd].pdl); + /* Let go of lock until we deque from original vector */ + + if (iovlen > 0) { + for (i = 0; i < iovcnt; i++) { + res = write(fd, iov[i].iov_base, iov[i].iov_len > 256 ? 256 : iov[i].iov_len); + if (res < 0) + break; + n += res; + } + if (res > 0) + res = n; + } else if (iovlen == 0) { + res = 0; + } else { /* Port has terminated */ + res = -1; + } + driver_free(iov); + + sig->sys_async.buff = NULL; + sig->sys_async.res = res; + if (errno != errno_copy) + sig->sys_async.errno_copy = errno; + else + sig->sys_async.errno_copy = -1; + sig->sys_async.type = fd; + send(&sig, parent); + } +} + +#define FD_DEF_HEIGHT 24 +#define FD_DEF_WIDTH 80 +/* Control op */ +#define FD_CTRL_OP_GET_WINSIZE 100 + +static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height) +{ +#ifdef TIOCGWINSZ + struct winsize ws; + if (ioctl(fd,TIOCGWINSZ,&ws) == 0) { + *width = (Uint32) ws.ws_col; + *height = (Uint32) ws.ws_row; + return 0; + } +#endif + return -1; +} + +static ErlDrvSSizeT fd_control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) +{ + int fd = (int)(long)drv_data; + char resbuff[2*sizeof(Uint32)]; + switch (command) { + case FD_CTRL_OP_GET_WINSIZE: + { + Uint32 w,h; + if (fd_get_window_size(fd,&w,&h)) + return 0; + memcpy(resbuff,&w,sizeof(Uint32)); + memcpy(resbuff+sizeof(Uint32),&h,sizeof(Uint32)); + } + break; + default: + return 0; + } + if (rlen < 2*sizeof(Uint32)) { + *rbuf = driver_alloc(2*sizeof(Uint32)); + } + memcpy(*rbuf,resbuff,2*sizeof(Uint32)); + return 2*sizeof(Uint32); +} + +static ErlDrvData fd_start(ErlDrvPort port_num, char* name, + SysDriverOpts* opts) +{ + ErlDrvData res; + + TRACE; + + CHLD_STAT_LOCK; + if (opts->read_write & DO_READ) { + init_fd_data(opts->ifd, port_num); + } + if (opts->read_write & DO_WRITE) { + init_fd_data(opts->ofd, port_num); + } + res = (ErlDrvData)(long)set_driver_data(port_num, opts->ifd, opts->ofd, + opts->packet_bytes, + opts->read_write, 0, -1); + CHLD_STAT_UNLOCK; + return res; +} + +static void clear_fd_data(int fd) +{ + TRACE; + + if (fd_data[fd].sz > 0) { + erts_free(ERTS_ALC_T_FD_ENTRY_BUF, (void *) fd_data[fd].buf); + ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= fd_data[fd].sz); + erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*fd_data[fd].sz); + } + fd_data[fd].buf = NULL; + fd_data[fd].sz = 0; + fd_data[fd].remain = 0; + fd_data[fd].cpos = NULL; + fd_data[fd].psz = 0; +} + +static void nbio_stop_fd(ErlDrvPort prt, ErlDrvEvent ev) +{ + int fd; + TRACE; + driver_select(prt,ev,DO_READ|DO_WRITE,0); + erl_drv_ose_event_fetch(ev, NULL, &fd); + clear_fd_data(fd); + SET_BLOCKING(fd); +} + +static void fd_stop(ErlDrvData fd) /* Does not close the fds */ +{ + int ofd; + + TRACE; + + nbio_stop_fd(driver_data[(int)(long)fd].port_num, driver_data[(int)(long)fd].in_sig_descr); + ofd = driver_data[(int)(long)fd].ofd; + if (ofd != (int)(long)fd && ofd != -1) + nbio_stop_fd(driver_data[(int)(long)fd].port_num, driver_data[(int)(long)fd].out_sig_descr); +} + +/* Note that driver_data[fd].ifd == fd if the port was opened for reading, */ +/* otherwise (i.e. write only) driver_data[fd].ofd = fd. */ + +static void erl_stop(ErlDrvData fd) +{ + ErlDrvPort prt; + int ofd; + + TRACE; + + prt = driver_data[(int)(long)fd].port_num; + nbio_stop_fd(prt, driver_data[(int)(long)fd].in_sig_descr); + + ofd = driver_data[(int)(long)fd].ofd; + if (ofd != (int)(long)fd && (int)(long)ofd != -1) + nbio_stop_fd(prt, driver_data[(int)(long)fd].out_sig_descr); + else + ofd = -1; + + CHLD_STAT_LOCK; + + /* Mark as unused. */ + driver_data[(int)(long)fd].pid = -1; + + CHLD_STAT_UNLOCK; + + /* SMP note: Close has to be last thing done (open file descriptors work + as locks on driver_data[] entries) */ + driver_select(prt, driver_data[(int)(long)fd].in_sig_descr, ERL_DRV_USE, 0); /* close(fd); */ + if (ofd >= 0) { + driver_select(prt, driver_data[(int)(long)fd].out_sig_descr, ERL_DRV_USE, 0); /* close(ofd); */ + } +} + +static void outputv(ErlDrvData e, ErlIOVec* ev) +{ + int fd = (int)(long)e; + ErlDrvPort ix = driver_data[fd].port_num; + int pb = driver_data[fd].packet_bytes; + ErlDrvSizeT sz; + char lb[4]; + char* lbp; + ErlDrvSizeT len = ev->size; + + TRACE; + + /* (len > ((unsigned long)-1 >> (4-pb)*8)) */ + /* if (pb >= 0 && (len & (((ErlDrvSizeT)1 << (pb*8))) - 1) != len) {*/ + if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) { + driver_failure_posix(ix, EINVAL); + return; /* -1; */ + } + /* Handles 0 <= pb <= 4 only */ + put_int32((Uint32) len, lb); + lbp = lb + (4-pb); + + ev->iov[0].iov_base = lbp; + ev->iov[0].iov_len = pb; + ev->size += pb; + driver_pdl_lock(driver_data[fd].pdl); + if ((sz = driver_sizeq(ix)) > 0) { + /* fprintf(stderr,"0x%x: outputv, enq\n", current_process()); */ + driver_enqv(ix, ev, 0); + if (sz + ev->size >= (1 << 13)) + set_busy_port(ix, 1); + driver_pdl_unlock(driver_data[fd].pdl); + } + else { + OseSignal *sig; + /* fprintf(stderr,"0x%x: outputv, enq+sel\n", current_process()); */ + driver_enqv(ix, ev, 0); /* n is the skip value */ + driver_pdl_unlock(driver_data[fd].pdl); + driver_select(ix, driver_data[fd].out_sig_descr, ERL_DRV_WRITE|ERL_DRV_USE, 1); + sig = alloc(sizeof(SysDriverAsyncSignal),SYSDRIVERASYNCSIG); + sig->sys_async.type = fd; + sig->sys_async.res = pb+len; + send(&sig,driver_data[fd].out_proc); + } + /* return 0;*/ +} + + +static void output(ErlDrvData e, char* buf, ErlDrvSizeT len) +{ + int fd = (int)(long)e; + ErlDrvPort ix = driver_data[fd].port_num; + int pb = driver_data[fd].packet_bytes; + int ofd = driver_data[fd].ofd; + ErlDrvSizeT sz; + char lb[4]; + char* lbp; +#if 0 + struct iovec iv[2]; +#endif + + TRACE; + + /* (len > ((unsigned long)-1 >> (4-pb)*8)) */ + if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) { + driver_failure_posix(ix, EINVAL); + return; /* -1; */ + } + put_int32(len, lb); + lbp = lb + (4-pb); + + driver_pdl_lock(driver_data[fd].pdl); + if ((sz = driver_sizeq(ix)) > 0) { + /* fprintf(stderr,"0x%x: output, enq\n", current_process()); */ + driver_enq(ix, lbp, pb); + driver_enq(ix, buf, len); + driver_pdl_unlock(driver_data[fd].pdl); + if (sz + len + pb >= (1 << 13)) + set_busy_port(ix, 1); + } + else { + OseSignal *sig; + /* fprintf(stderr,"0x%x: output, enq+select\n", current_process()); */ +#if 0 + iv[0].iov_base = lbp; + iv[0].iov_len = pb; /* should work for pb=0 */ + iv[1].iov_base = buf; + iv[1].iov_len = len; +#endif + driver_enq(ix, lbp, pb); + driver_enq(ix, buf, len); + driver_pdl_unlock(driver_data[fd].pdl); + driver_select(ix, driver_data[ofd].out_sig_descr, ERL_DRV_WRITE|ERL_DRV_USE, 1); + sig = alloc(sizeof(SysDriverAsyncSignal),SYSDRIVERASYNCSIG); + sig->sys_async.type = fd; + sig->sys_async.res = pb+len; + send(&sig,driver_data[fd].out_proc); + } + return; /* 0; */ +} + +static int port_inp_failure(ErlDrvPort port_num, ErlDrvEvent ready_fd, int res) + /* Result: 0 (eof) or -1 (error) */ +{ + int err = errno; + int fd; + + ASSERT(res <= 0); + (void) driver_select(port_num, ready_fd, ERL_DRV_READ|ERL_DRV_WRITE, 0); + erl_drv_ose_event_fetch(ready_fd,NULL,&fd); + clear_fd_data(fd); + if (res == 0) { + if (driver_data[fd].report_exit) { + CHLD_STAT_LOCK; + + if (driver_data[fd].alive) { + /* + * We have eof and want to report exit status, but the process + * hasn't exited yet. When it does report_exit_status() will + * driver_select() this fd which will make sure that we get + * back here with driver_data[ready_fd].alive == 0 and + * driver_data[ready_fd].status set. + */ + CHLD_STAT_UNLOCK; + return 0; + } + else { + int status = driver_data[fd].status; + CHLD_STAT_UNLOCK; + +#if 0 /*ose we should find something for these statuses*/ + /* We need not be prepared for stopped/continued processes. */ + if (WIFSIGNALED(status)) + status = 128 + WTERMSIG(status); + else + status = WEXITSTATUS(status); +#endif + driver_report_exit(driver_data[fd].port_num, status); + } + } + driver_failure_eof(port_num); + } else { + driver_failure_posix(port_num, err); + } + return 0; +} + +static int async_read(ErlDrvEvent fd, byte *buff, int size) { + OseSignal *sigptr = erl_drv_ose_get_input_signal(fd); + int res = sigptr->sys_async.res; + if (res > 0) + memcpy(buff,sigptr->sys_async.buff,sigptr->sys_async.res); + errno = sigptr->sys_async.errno_copy; + send(&sigptr,sender(&sigptr)); + ASSERT(erl_drv_ose_get_input_signal(fd) == NULL); + return res; +} + +/* fd is the drv_data that is returned from the */ +/* initial start routine */ +/* ready_fd is the descriptor that is ready to read */ + +static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd) +{ + int fd = (int)(long)e; + ErlDrvPort port_num; + int packet_bytes; + int res; + Uint h; + + TRACE; + + port_num = driver_data[fd].port_num; + packet_bytes = driver_data[fd].packet_bytes; + + if (packet_bytes == 0) { + byte *read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF, + ERTS_SYS_READ_BUF_SZ); + res = async_read(ready_fd, read_buf, ERTS_SYS_READ_BUF_SZ); + if (res < 0) { + if ((errno != EINTR) && (errno != ERRNO_BLOCK)) + port_inp_failure(port_num, ready_fd, res); + } + else if (res == 0) + port_inp_failure(port_num, ready_fd, res); + else + driver_output(port_num, (char*) read_buf, res); + erts_free(ERTS_ALC_T_SYS_READ_BUF, (void *) read_buf); + } + else if (fd_data[fd].remain > 0) { /* We try to read the remainder */ + /* space is allocated in buf */ + res = async_read(ready_fd, (byte*)fd_data[fd].cpos, + fd_data[fd].remain); + if (res < 0) { + if ((errno != EINTR) && (errno != ERRNO_BLOCK)) + port_inp_failure(port_num, ready_fd, res); + } + else if (res == 0) { + port_inp_failure(port_num, ready_fd, res); + } + else if (res == fd_data[fd].remain) { /* we're done */ + driver_output(port_num, fd_data[fd].buf, + fd_data[fd].sz); + clear_fd_data(fd); + } + else { /* if (res < fd_data[ready_fd].remain) */ + fd_data[fd].cpos += res; + fd_data[fd].remain -= res; + } + } + else if (fd_data[fd].remain == 0) { /* clean fd */ + byte *read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF, + ERTS_SYS_READ_BUF_SZ); + /* We make one read attempt and see what happens */ + res = async_read(ready_fd, read_buf, ERTS_SYS_READ_BUF_SZ); + if (res < 0) { + if ((errno != EINTR) && (errno != ERRNO_BLOCK)) + port_inp_failure(port_num, ready_fd, res); + } + else if (res == 0) { /* eof */ + port_inp_failure(port_num, ready_fd, res); + } + else if (res < packet_bytes - fd_data[fd].psz) { + memcpy(fd_data[fd].pbuf+fd_data[fd].psz, + read_buf, res); + fd_data[fd].psz += res; + } + else { /* if (res >= packet_bytes) */ + unsigned char* cpos = read_buf; + int bytes_left = res; + + while (1) { + int psz = fd_data[fd].psz; + char* pbp = fd_data[fd].pbuf + psz; + + while(bytes_left && (psz < packet_bytes)) { + *pbp++ = *cpos++; + bytes_left--; + psz++; + } + + if (psz < packet_bytes) { + fd_data[fd].psz = psz; + break; + } + fd_data[fd].psz = 0; + + switch (packet_bytes) { + case 1: h = get_int8(fd_data[fd].pbuf); break; + case 2: h = get_int16(fd_data[fd].pbuf); break; + case 4: h = get_int32(fd_data[fd].pbuf); break; + default: ASSERT(0); return; /* -1; */ + } + + if (h <= (bytes_left)) { + driver_output(port_num, (char*) cpos, h); + cpos += h; + bytes_left -= h; + continue; + } + else { /* The last message we got was split */ + char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h); + if (!buf) { + errno = ENOMEM; + port_inp_failure(port_num, ready_fd, -1); + } + else { + erts_smp_atomic_add_nob(&sys_misc_mem_sz, h); + sys_memcpy(buf, cpos, bytes_left); + fd_data[fd].buf = buf; + fd_data[fd].sz = h; + fd_data[fd].remain = h - bytes_left; + fd_data[fd].cpos = buf + bytes_left; + } + break; + } + } + } + erts_free(ERTS_ALC_T_SYS_READ_BUF, (void *) read_buf); + } +} + + +/* fd is the drv_data that is returned from the */ +/* initial start routine */ +/* ready_fd is the descriptor that is ready to read */ + +static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) +{ + int fd = (int)(long)e; + ErlDrvPort ix = driver_data[fd].port_num; + OseSignal *sigptr = erl_drv_ose_get_output_signal(ready_fd); + ssize_t n; + struct iovec* iv; + int vsize; + + while (sigptr != NULL) { + + driver_pdl_lock(driver_data[fd].pdl); + if ((iv = (struct iovec*) driver_peekq(ix, &vsize)) == NULL) { + /* fprintf(stderr,"0x%x: ready_output, unselect\n", current_process()); */ + driver_pdl_unlock(driver_data[fd].pdl); + driver_select(ix, ready_fd, ERL_DRV_WRITE, 0); + set_busy_port(ix, 0); + free_buf(&sigptr); + if ((sigptr = erl_drv_ose_get_output_signal(ready_fd)) == NULL) + return; /* 0; */ + continue; + } + driver_pdl_unlock(driver_data[fd].pdl); + n = sigptr->sys_async.res; + if (n < 0) { + if (errno == ERRNO_BLOCK || errno == EINTR) { + /* fprintf(stderr,"0x%x: ready_output, send to %x\n", current_process(),driver_data[fd].out_proc);*/ + send(&sigptr,driver_data[fd].out_proc); + if ((sigptr = erl_drv_ose_get_output_signal(ready_fd)) == NULL) + return; /* 0; */ + continue; + } else { + int res = sigptr->sys_async.errno_copy; + /* fprintf(stderr,"0x%x: ready_output, error\n", current_process()); */ + free_buf(&sigptr); + driver_select(ix, ready_fd, ERL_DRV_WRITE, 0); + driver_failure_posix(ix, res); + if ((sigptr = erl_drv_ose_get_output_signal(ready_fd)) == NULL) + return; /* -1; */ + continue; + } + } else { + int remain; + driver_pdl_lock(driver_data[fd].pdl); + if ((remain = driver_deq(driver_data[fd].port_num, n)) == -1) + abort(); + /* fprintf(stderr, "0x%x: ready_output, %d to %x, remain %d\n", current_process(), + n, driver_data[fd].out_proc, remain); */ + driver_pdl_unlock(driver_data[fd].pdl); + if (remain != 0) + send(&sigptr, driver_data[fd].out_proc); + else + continue; + } + sigptr = erl_drv_ose_get_output_signal(ready_fd); + } + return; /* 0; */ +} + +static void stop_select(ErlDrvEvent fd, void* _) +{ + close((int)fd); +} + + +void erts_do_break_handling(void) +{ + struct termios temp_mode; + int saved = 0; + + /* + * Most functions that do_break() calls are intentionally not thread safe; + * therefore, make sure that all threads but this one are blocked before + * proceeding! + */ + erts_smp_thr_progress_block(); + + /* during break we revert to initial settings */ + /* this is done differently for oldshell */ + if (using_oldshell && !replace_intr) { + SET_BLOCKING(1); + } + else if (isatty(0)) { + tcgetattr(0,&temp_mode); + tcsetattr(0,TCSANOW,&initial_tty_mode); + saved = 1; + } + + /* call the break handling function, reset the flag */ + do_break(); + + fflush(stdout); + + /* after break we go back to saved settings */ + if (using_oldshell && !replace_intr) { + SET_NONBLOCKING(1); + } + else if (saved) { + tcsetattr(0,TCSANOW,&temp_mode); + } + + erts_smp_thr_progress_unblock(); +} + +static pid_t +getpid(void) +{ + return get_bid(current_process()); +} + +int getpagesize(void) +{ + return 1024; +} + + +/* Fills in the systems representation of the jam/beam process identifier. +** The Pid is put in STRING representation in the supplied buffer, +** no interpretatione of this should be done by the rest of the +** emulator. The buffer should be at least 21 bytes long. +*/ +void sys_get_pid(char *buffer, size_t buffer_size){ + pid_t p = getpid(); + /* Assume the pid is scalar and can rest in an unsigned long... */ + erts_snprintf(buffer, buffer_size, "%lu",(unsigned long) p); +} + +int +erts_sys_putenv_raw(char *key, char *value) { + return erts_sys_putenv(key, value); +} +int +erts_sys_putenv(char *key, char *value) +{ + int res; + char *env; + Uint need = strlen(key) + strlen(value) + 2; + +#ifdef HAVE_COPYING_PUTENV + env = erts_alloc(ERTS_ALC_T_TMP, need); +#else + env = erts_alloc(ERTS_ALC_T_PUTENV_STR, need); + erts_smp_atomic_add_nob(&sys_misc_mem_sz, need); +#endif + strcpy(env,key); + strcat(env,"="); + strcat(env,value); + erts_smp_rwmtx_rwlock(&environ_rwmtx); + res = putenv(env); + erts_smp_rwmtx_rwunlock(&environ_rwmtx); +#ifdef HAVE_COPYING_PUTENV + erts_free(ERTS_ALC_T_TMP, env); +#endif + return res; +} + +int +erts_sys_getenv__(char *key, char *value, size_t *size) +{ + int res; + char *orig_value = getenv(key); + if (!orig_value) + res = -1; + else { + size_t len = sys_strlen(orig_value); + if (len >= *size) { + *size = len + 1; + res = 1; + } + else { + *size = len; + sys_memcpy((void *) value, (void *) orig_value, len+1); + res = 0; + } + } + return res; +} + +int +erts_sys_getenv_raw(char *key, char *value, size_t *size) { + return erts_sys_getenv(key, value, size); +} + +/* + * erts_sys_getenv + * returns: + * -1, if environment key is not set with a value + * 0, if environment key is set and value fits into buffer res + * 1, if environment key is set but does not fit into buffer res + * res is set with the needed buffer res value + */ + +int +erts_sys_getenv(char *key, char *value, size_t *size) +{ + int res; + erts_smp_rwmtx_rlock(&environ_rwmtx); + res = erts_sys_getenv__(key, value, size); + erts_smp_rwmtx_runlock(&environ_rwmtx); + return res; +} + +void +sys_init_io(void) +{ + fd_data = (struct fd_data *) + erts_alloc(ERTS_ALC_T_FD_TAB, max_files * sizeof(struct fd_data)); + erts_smp_atomic_add_nob(&sys_misc_mem_sz, + max_files * sizeof(struct fd_data)); +} + +extern const char pre_loaded_code[]; +extern Preload pre_loaded[]; + +void erts_sys_alloc_init(void) +{ +} + +void *erts_sys_alloc(ErtsAlcType_t t, void *x, Uint sz) +{ + void *res = malloc((size_t) sz); +#if HAVE_ERTS_MSEG + if (!res) { + erts_mseg_clear_cache(); + return malloc((size_t) sz); + } +#endif + return res; +} + +void *erts_sys_realloc(ErtsAlcType_t t, void *x, void *p, Uint sz) +{ + void *res = realloc(p, (size_t) sz); +#if HAVE_ERTS_MSEG + if (!res) { + erts_mseg_clear_cache(); + return realloc(p, (size_t) sz); + } +#endif + return res; +} + +void erts_sys_free(ErtsAlcType_t t, void *x, void *p) +{ + free(p); +} + +/* Return a pointer to a vector of names of preloaded modules */ + +Preload* +sys_preloaded(void) +{ + return pre_loaded; +} + +/* Return a pointer to preloaded code for module "module" */ +unsigned char* +sys_preload_begin(Preload* p) +{ + return p->code; +} + +/* Clean up if allocated */ +void sys_preload_end(Preload* p) +{ + /* Nothing */ +} + +/* Read a key from console (?) */ + +int sys_get_key(fd) +int fd; +{ + int c; + unsigned char rbuf[64]; + + TRACE; + + fflush(stdout); /* Flush query ??? */ + + if ((c = read(fd,rbuf,64)) <= 0) { + return c; + } + + return rbuf[0]; +} + + +#ifdef DEBUG + +extern int erts_initialized; +void +erl_assert_error(char* expr, char* file, int line) +{ + fflush(stdout); + fprintf(stderr, "Assertion failed: %s in %s, line %d\n", + expr, file, line); + fflush(stderr); + ramlog_printf("%d: Assertion failed: %s in %s, line %d\n", + current_process(), expr, file, line); + abort(); +} + +void +erl_debug(char* fmt, ...) +{ + char sbuf[1024]; /* Temporary buffer. */ + va_list va; + + if (debug_log) { + va_start(va, fmt); + vsprintf(sbuf, fmt, va); + va_end(va); + fprintf(stderr, "%s", sbuf); + } +} + +#endif /* DEBUG */ + +static ERTS_INLINE void +report_exit_status(ErtsSysReportExit *rep, int status) +{ + Port *pp; +#ifdef ERTS_SMP + CHLD_STAT_UNLOCK; + pp = erts_thr_id2port_sflgs(rep->port, + ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP); + CHLD_STAT_LOCK; +#else + pp = erts_id2port_sflgs(rep->port, + NULL, + 0, + ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP); +#endif + if (pp) { + if (rep->ifd >= 0) { + driver_data[rep->ifd].alive = 0; + driver_data[rep->ifd].status = status; + (void) driver_select(ERTS_Port2ErlDrvPort(pp), + rep->in_sig_descr, + (ERL_DRV_READ|ERL_DRV_USE), + 1); + } + if (rep->ofd >= 0) { + driver_data[rep->ofd].alive = 0; + driver_data[rep->ofd].status = status; + (void) driver_select(ERTS_Port2ErlDrvPort(pp), + rep->out_sig_descr, + (ERL_DRV_WRITE|ERL_DRV_USE), + 1); + } +#ifdef ERTS_SMP + erts_thr_port_release(pp); +#else + erts_port_release(pp); +#endif + } + erts_free(ERTS_ALC_T_PRT_REP_EXIT, rep); +} + +#define ERTS_REPORT_EXIT_STATUS report_exit_status + +/* + * Called from schedule() when it runs out of runnable processes, + * or when Erlang code has performed INPUT_REDUCTIONS reduction + * steps. runnable == 0 iff there are no runnable Erlang processes. + */ +void +erl_sys_schedule(int runnable) +{ + ASSERT(get_fsem(current_process()) == 0); +#ifdef ERTS_SMP + ERTS_CHK_IO(!runnable); +#else + ERTS_CHK_IO( 1 ); +#endif + ASSERT(get_fsem(current_process()) == 0); + ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking()); +} + + +#ifdef ERTS_SMP + +void +erts_sys_main_thread(void) +{ + erts_thread_disable_fpe(); + + /* Become signal receiver thread... */ +#ifdef ERTS_ENABLE_LOCK_CHECK + erts_lc_set_thread_name("signal_receiver"); +#endif + + while (1) { + static const SIGSELECT sigsel[] = {0}; + OseSignal *msg = receive(sigsel); + + fprintf(stderr,"Main thread got message %d from 0x%x!!\r\n", + msg->sig_no, sender(&msg)); + free_buf(&msg); + } +} + +#endif /* ERTS_SMP */ + +void +erl_sys_args(int* argc, char** argv) +{ + int i, j; + + erts_smp_rwmtx_init(&environ_rwmtx, "environ"); + + init_check_io(); + + /* Handled arguments have been marked with NULL. Slide arguments + not handled towards the beginning of argv. */ + for (i = 0, j = 0; i < *argc; i++) { + if (argv[i]) + argv[j++] = argv[i]; + } + *argc = j; + +} diff --git a/erts/emulator/sys/ose/sys_float.c b/erts/emulator/sys/ose/sys_float.c new file mode 100644 index 0000000000..d9d6bb7c04 --- /dev/null +++ b/erts/emulator/sys/ose/sys_float.c @@ -0,0 +1,844 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2013. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "sys.h" +#include "global.h" +#include "erl_process.h" + + +#ifdef NO_FPE_SIGNALS + +void +erts_sys_init_float(void) +{ +# ifdef SIGFPE + sys_sigset(SIGFPE, SIG_IGN); /* Ignore so we can test for NaN and Inf */ +# endif +} + +#else /* !NO_FPE_SIGNALS */ + +#ifdef ERTS_SMP +static erts_tsd_key_t fpe_key; + +/* once-only initialisation early in the main thread (via erts_sys_init_float()) */ +static void erts_init_fp_exception(void) +{ + /* XXX: the wrappers prevent using a pthread destructor to + deallocate the key's value; so when/where do we do that? */ + erts_tsd_key_create(&fpe_key); +} + +void erts_thread_init_fp_exception(void) +{ + unsigned long *fpe = erts_alloc(ERTS_ALC_T_FP_EXCEPTION, sizeof(*fpe)); + *fpe = 0L; + erts_tsd_set(fpe_key, fpe); +} + +static ERTS_INLINE volatile unsigned long *erts_thread_get_fp_exception(void) +{ + return (volatile unsigned long*)erts_tsd_get(fpe_key); +} +#else /* !SMP */ +#define erts_init_fp_exception() /*empty*/ +static volatile unsigned long fp_exception; +#define erts_thread_get_fp_exception() (&fp_exception) +#endif /* SMP */ + +volatile unsigned long *erts_get_current_fp_exception(void) +{ + Process *c_p; + + c_p = erts_get_current_process(); + if (c_p) + return &c_p->fp_exception; + return erts_thread_get_fp_exception(); +} + +static void set_current_fp_exception(unsigned long pc) +{ + volatile unsigned long *fpexnp = erts_get_current_fp_exception(); + ASSERT(fpexnp != NULL); + *fpexnp = pc; +} + +void erts_fp_check_init_error(volatile unsigned long *fpexnp) +{ + char buf[64]; + snprintf(buf, sizeof buf, "ERTS_FP_CHECK_INIT at %p: detected unhandled FPE at %p\r\n", + __builtin_return_address(0), (void*)*fpexnp); + if (write(2, buf, strlen(buf)) <= 0) + erl_exit(ERTS_ABORT_EXIT, "%s", buf); + *fpexnp = 0; +#if defined(__i386__) || defined(__x86_64__) + erts_restore_fpu(); +#endif +} + +/* Is there no standard identifier for Darwin/MacOSX ? */ +#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__) +#define __DARWIN__ 1 +#endif + +#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__) + +static void unmask_x87(void) +{ + unsigned short cw; + + __asm__ __volatile__("fstcw %0" : "=m"(cw)); + cw &= ~(0x01|0x04|0x08); /* unmask IM, ZM, OM */ + __asm__ __volatile__("fldcw %0" : : "m"(cw)); +} + +/* mask x87 FPE, return true if the previous state was unmasked */ +static int mask_x87(void) +{ + unsigned short cw; + int unmasked; + + __asm__ __volatile__("fstcw %0" : "=m"(cw)); + unmasked = (cw & (0x01|0x04|0x08)) == 0; + /* or just set cw = 0x37f */ + cw |= (0x01|0x04|0x08); /* mask IM, ZM, OM */ + __asm__ __volatile__("fldcw %0" : : "m"(cw)); + return unmasked; +} + +static void unmask_sse2(void) +{ + unsigned int mxcsr; + + __asm__ __volatile__("stmxcsr %0" : "=m"(mxcsr)); + mxcsr &= ~(0x003F|0x0680); /* clear exn flags, unmask OM, ZM, IM (not PM, UM, DM) */ + __asm__ __volatile__("ldmxcsr %0" : : "m"(mxcsr)); +} + +/* mask SSE2 FPE, return true if the previous state was unmasked */ +static int mask_sse2(void) +{ + unsigned int mxcsr; + int unmasked; + + __asm__ __volatile__("stmxcsr %0" : "=m"(mxcsr)); + unmasked = (mxcsr & 0x0680) == 0; + /* or just set mxcsr = 0x1f80 */ + mxcsr &= ~0x003F; /* clear exn flags */ + mxcsr |= 0x0680; /* mask OM, ZM, IM (not PM, UM, DM) */ + __asm__ __volatile__("ldmxcsr %0" : : "m"(mxcsr)); + return unmasked; +} + +#if defined(__x86_64__) + +static inline int cpu_has_sse2(void) { return 1; } + +#else /* !__x86_64__ */ + +/* + * Check if an x86-32 processor has SSE2. + */ +static unsigned int xor_eflags(unsigned int mask) +{ + unsigned int eax, edx; + + eax = mask; /* eax = mask */ + __asm__("pushfl\n\t" + "popl %0\n\t" /* edx = original EFLAGS */ + "xorl %0, %1\n\t" /* eax = mask ^ EFLAGS */ + "pushl %1\n\t" + "popfl\n\t" /* new EFLAGS = mask ^ original EFLAGS */ + "pushfl\n\t" + "popl %1\n\t" /* eax = new EFLAGS */ + "xorl %0, %1\n\t" /* eax = new EFLAGS ^ old EFLAGS */ + "pushl %0\n\t" + "popfl" /* restore original EFLAGS */ + : "=d"(edx), "=a"(eax) + : "1"(eax)); + return eax; +} + +static __inline__ unsigned int cpuid_eax(unsigned int op) +{ + unsigned int eax, save_ebx; + + /* In PIC mode i386 reserves EBX. So we must save + and restore it ourselves to not upset gcc. */ + __asm__( + "movl %%ebx, %1\n\t" + "cpuid\n\t" + "movl %1, %%ebx" + : "=a"(eax), "=m"(save_ebx) + : "0"(op) + : "cx", "dx"); + return eax; +} + +static __inline__ unsigned int cpuid_edx(unsigned int op) +{ + unsigned int eax, edx, save_ebx; + + /* In PIC mode i386 reserves EBX. So we must save + and restore it ourselves to not upset gcc. */ + __asm__( + "movl %%ebx, %2\n\t" + "cpuid\n\t" + "movl %2, %%ebx" + : "=a"(eax), "=d"(edx), "=m"(save_ebx) + : "0"(op) + : "cx"); + return edx; +} + +/* The AC bit, bit #18, is a new bit introduced in the EFLAGS + * register on the Intel486 processor to generate alignment + * faults. This bit cannot be set on the Intel386 processor. + */ +static __inline__ int is_386(void) +{ + return ((xor_eflags(1<<18) >> 18) & 1) == 0; +} + +/* Newer x86 processors have a CPUID instruction, as indicated by + * the ID bit (#21) in EFLAGS being modifiable. + */ +static __inline__ int has_CPUID(void) +{ + return (xor_eflags(1<<21) >> 21) & 1; +} + +static int cpu_has_sse2(void) +{ + unsigned int maxlev, features; + static int has_sse2 = -1; + + if (has_sse2 >= 0) + return has_sse2; + has_sse2 = 0; + + if (is_386()) + return 0; + if (!has_CPUID()) + return 0; + maxlev = cpuid_eax(0); + /* Intel A-step Pentium had a preliminary version of CPUID. + It also didn't have SSE2. */ + if ((maxlev & 0xFFFFFF00) == 0x0500) + return 0; + /* If max level is zero then CPUID cannot report any features. */ + if (maxlev == 0) + return 0; + features = cpuid_edx(1); + has_sse2 = (features & (1 << 26)) != 0; + + return has_sse2; +} +#endif /* !__x86_64__ */ + +static void unmask_fpe(void) +{ + __asm__ __volatile__("fnclex"); + unmask_x87(); + if (cpu_has_sse2()) + unmask_sse2(); +} + +static void unmask_fpe_conditional(int unmasked) +{ + if (unmasked) + unmask_fpe(); +} + +/* mask x86 FPE, return true if the previous state was unmasked */ +static int mask_fpe(void) +{ + int unmasked; + + unmasked = mask_x87(); + if (cpu_has_sse2()) + unmasked |= mask_sse2(); + return unmasked; +} + +void erts_restore_fpu(void) +{ + __asm__ __volatile__("fninit"); + unmask_x87(); + if (cpu_has_sse2()) + unmask_sse2(); +} + +#elif defined(__sparc__) && defined(__linux__) + +#if defined(__arch64__) +#define LDX "ldx" +#define STX "stx" +#else +#define LDX "ld" +#define STX "st" +#endif + +static void unmask_fpe(void) +{ + unsigned long fsr; + + __asm__(STX " %%fsr, %0" : "=m"(fsr)); + fsr &= ~(0x1FUL << 23); /* clear FSR[TEM] field */ + fsr |= (0x1AUL << 23); /* enable NV, OF, DZ exceptions */ + __asm__ __volatile__(LDX " %0, %%fsr" : : "m"(fsr)); +} + +static void unmask_fpe_conditional(int unmasked) +{ + if (unmasked) + unmask_fpe(); +} + +/* mask SPARC FPE, return true if the previous state was unmasked */ +static int mask_fpe(void) +{ + unsigned long fsr; + int unmasked; + + __asm__(STX " %%fsr, %0" : "=m"(fsr)); + unmasked = ((fsr >> 23) & 0x1A) == 0x1A; + fsr &= ~(0x1FUL << 23); /* clear FSR[TEM] field */ + __asm__ __volatile__(LDX " %0, %%fsr" : : "m"(fsr)); + return unmasked; +} + +#elif (defined(__powerpc__) && defined(__linux__)) || (defined(__ppc__) && defined(__DARWIN__)) + +#if defined(__linux__) +#include + +static void set_fpexc_precise(void) +{ + if (prctl(PR_SET_FPEXC, PR_FP_EXC_PRECISE) < 0) { + perror("PR_SET_FPEXC"); + exit(1); + } +} + +#elif defined(__DARWIN__) + +#include +#include + +/* + * FE0 FE1 MSR bits + * 0 0 floating-point exceptions disabled + * 0 1 floating-point imprecise nonrecoverable + * 1 0 floating-point imprecise recoverable + * 1 1 floating-point precise mode + * + * Apparently: + * - Darwin 5.5 (MacOS X <= 10.1) starts with FE0 == FE1 == 0, + * and resets FE0 and FE1 to 0 after each SIGFPE. + * - Darwin 6.0 (MacOS X 10.2) starts with FE0 == FE1 == 1, + * and does not reset FE0 or FE1 after a SIGFPE. + */ +#define FE0_MASK (1<<11) +#define FE1_MASK (1<<8) + +/* a thread cannot get or set its own MSR bits */ +static void *fpu_fpe_enable(void *arg) +{ + thread_t t = *(thread_t*)arg; + struct ppc_thread_state state; + unsigned int state_size = PPC_THREAD_STATE_COUNT; + + if (thread_get_state(t, PPC_THREAD_STATE, (natural_t*)&state, &state_size) != KERN_SUCCESS) { + perror("thread_get_state"); + exit(1); + } + if ((state.srr1 & (FE1_MASK|FE0_MASK)) != (FE1_MASK|FE0_MASK)) { +#if 1 + /* This would also have to be performed in the SIGFPE handler + to work around the MSR reset older Darwin releases do. */ + state.srr1 |= (FE1_MASK|FE0_MASK); + thread_set_state(t, PPC_THREAD_STATE, (natural_t*)&state, state_size); +#else + fprintf(stderr, "srr1 == 0x%08x, your Darwin is too old\n", state.srr1); + exit(1); +#endif + } + return NULL; /* Ok, we appear to be on Darwin 6.0 or later */ +} + +static void set_fpexc_precise(void) +{ + thread_t self = mach_thread_self(); + pthread_t enabler; + + if (pthread_create(&enabler, NULL, fpu_fpe_enable, &self)) { + perror("pthread_create"); + } else if (pthread_join(enabler, NULL)) { + perror("pthread_join"); + } +} + +#endif + +static void set_fpscr(unsigned int fpscr) +{ + union { + double d; + unsigned int fpscr[2]; + } u; + + u.fpscr[0] = 0xFFF80000; + u.fpscr[1] = fpscr; + __asm__ __volatile__("mtfsf 255,%0" : : "f"(u.d)); +} + +static unsigned int get_fpscr(void) +{ + union { + double d; + unsigned int fpscr[2]; + } u; + + __asm__("mffs %0" : "=f"(u.d)); + return u.fpscr[1]; +} + +static void unmask_fpe(void) +{ + set_fpexc_precise(); + set_fpscr(0x80|0x40|0x10); /* VE, OE, ZE; not UE or XE */ +} + +static void unmask_fpe_conditional(int unmasked) +{ + if (unmasked) + unmask_fpe(); +} + +/* mask PowerPC FPE, return true if the previous state was unmasked */ +static int mask_fpe(void) +{ + int unmasked; + + unmasked = (get_fpscr() & (0x80|0x40|0x10)) == (0x80|0x40|0x10); + set_fpscr(0x00); + return unmasked; +} + +#else + +static void unmask_fpe(void) +{ + fpsetmask(FP_X_INV | FP_X_OFL | FP_X_DZ); +} + +static void unmask_fpe_conditional(int unmasked) +{ + if (unmasked) + unmask_fpe(); +} + +/* mask IEEE FPE, return true if previous state was unmasked */ +static int mask_fpe(void) +{ + const fp_except unmasked_mask = FP_X_INV | FP_X_OFL | FP_X_DZ; + fp_except old_mask; + + old_mask = fpsetmask(0); + return (old_mask & unmasked_mask) == unmasked_mask; +} + +#endif + +#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__))) || ((defined(__NetBSD__) || defined(__OpenBSD__)) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__)) + +#if defined(__linux__) && defined(__i386__) +#if !defined(X86_FXSR_MAGIC) +#define X86_FXSR_MAGIC 0x0000 +#endif +#elif defined(__FreeBSD__) && defined(__x86_64__) +#include +#include +#elif defined(__FreeBSD__) && defined(__i386__) +#include +#include +#elif defined(__DARWIN__) +#include +#elif defined(__OpenBSD__) && defined(__x86_64__) +#include +#include +#endif +#if !(defined(__OpenBSD__) && defined(__x86_64__)) +#include +#endif +#include + +#if defined(__linux__) && defined(__x86_64__) +#define mc_pc(mc) ((mc)->gregs[REG_RIP]) +#elif defined(__linux__) && defined(__i386__) +#define mc_pc(mc) ((mc)->gregs[REG_EIP]) +#elif defined(__DARWIN__) && defined(__i386__) +#ifdef DARWIN_MODERN_MCONTEXT +#define mc_pc(mc) ((mc)->__ss.__eip) +#else +#define mc_pc(mc) ((mc)->ss.eip) +#endif +#elif defined(__DARWIN__) && defined(__x86_64__) +#ifdef DARWIN_MODERN_MCONTEXT +#define mc_pc(mc) ((mc)->__ss.__rip) +#else +#define mc_pc(mc) ((mc)->ss.rip) +#endif +#elif defined(__FreeBSD__) && defined(__x86_64__) +#define mc_pc(mc) ((mc)->mc_rip) +#elif defined(__FreeBSD__) && defined(__i386__) +#define mc_pc(mc) ((mc)->mc_eip) +#elif defined(__NetBSD__) && defined(__x86_64__) +#define mc_pc(mc) ((mc)->__gregs[_REG_RIP]) +#elif defined(__NetBSD__) && defined(__i386__) +#define mc_pc(mc) ((mc)->__gregs[_REG_EIP]) +#elif defined(__OpenBSD__) && defined(__x86_64__) +#define mc_pc(mc) ((mc)->sc_rip) +#elif defined(__sun__) && defined(__x86_64__) +#define mc_pc(mc) ((mc)->gregs[REG_RIP]) +#endif + +static void fpe_sig_action(int sig, siginfo_t *si, void *puc) +{ + ucontext_t *uc = puc; + unsigned long pc; + +#if defined(__linux__) +#if defined(__x86_64__) + mcontext_t *mc = &uc->uc_mcontext; + fpregset_t fpstate = mc->fpregs; + pc = mc_pc(mc); + /* A failed SSE2 instruction will restart. To avoid + looping we mask SSE2 exceptions now and unmask them + again later in erts_check_fpe()/erts_restore_fpu(). + On RISCs we update PC to skip the failed instruction, + but the ever increasing complexity of the x86 instruction + set encoding makes that a poor solution here. */ + fpstate->mxcsr = 0x1F80; + fpstate->swd &= ~0xFF; +#elif defined(__i386__) + mcontext_t *mc = &uc->uc_mcontext; + fpregset_t fpstate = mc->fpregs; + pc = mc_pc(mc); + if ((fpstate->status >> 16) == X86_FXSR_MAGIC) + ((struct _fpstate*)fpstate)->mxcsr = 0x1F80; + fpstate->sw &= ~0xFF; +#elif defined(__sparc__) && defined(__arch64__) + /* on SPARC the 3rd parameter points to a sigcontext not a ucontext */ + struct sigcontext *sc = (struct sigcontext*)puc; + pc = sc->sigc_regs.tpc; + sc->sigc_regs.tpc = sc->sigc_regs.tnpc; + sc->sigc_regs.tnpc += 4; +#elif defined(__sparc__) + /* on SPARC the 3rd parameter points to a sigcontext not a ucontext */ + struct sigcontext *sc = (struct sigcontext*)puc; + pc = sc->si_regs.pc; + sc->si_regs.pc = sc->si_regs.npc; + sc->si_regs.npc = (unsigned long)sc->si_regs.npc + 4; +#elif defined(__powerpc__) +#if defined(__powerpc64__) + mcontext_t *mc = &uc->uc_mcontext; + unsigned long *regs = &mc->gp_regs[0]; +#else + mcontext_t *mc = uc->uc_mcontext.uc_regs; + unsigned long *regs = &mc->gregs[0]; +#endif + pc = regs[PT_NIP]; + regs[PT_NIP] += 4; + regs[PT_FPSCR] = 0x80|0x40|0x10; /* VE, OE, ZE; not UE or XE */ +#endif +#elif defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__)) +#ifdef DARWIN_MODERN_MCONTEXT + mcontext_t mc = uc->uc_mcontext; + pc = mc_pc(mc); + mc->__fs.__fpu_mxcsr = 0x1F80; + *(unsigned short *)&mc->__fs.__fpu_fsw &= ~0xFF; +#else + mcontext_t mc = uc->uc_mcontext; + pc = mc_pc(mc); + mc->fs.fpu_mxcsr = 0x1F80; + *(unsigned short *)&mc->fs.fpu_fsw &= ~0xFF; +#endif /* DARWIN_MODERN_MCONTEXT */ +#elif defined(__DARWIN__) && defined(__ppc__) + mcontext_t mc = uc->uc_mcontext; + pc = mc->ss.srr0; + mc->ss.srr0 += 4; + mc->fs.fpscr = 0x80|0x40|0x10; +#elif defined(__FreeBSD__) && defined(__x86_64__) + mcontext_t *mc = &uc->uc_mcontext; + struct savefpu *savefpu = (struct savefpu*)&mc->mc_fpstate; + struct envxmm *envxmm = &savefpu->sv_env; + pc = mc_pc(mc); + envxmm->en_mxcsr = 0x1F80; + envxmm->en_sw &= ~0xFF; +#elif defined(__FreeBSD__) && defined(__i386__) + mcontext_t *mc = &uc->uc_mcontext; + union savefpu *savefpu = (union savefpu*)&mc->mc_fpstate; + pc = mc_pc(mc); + if (mc->mc_fpformat == _MC_FPFMT_XMM) { + struct envxmm *envxmm = &savefpu->sv_xmm.sv_env; + envxmm->en_mxcsr = 0x1F80; + envxmm->en_sw &= ~0xFF; + } else { + struct env87 *env87 = &savefpu->sv_87.sv_env; + env87->en_sw &= ~0xFF; + } +#elif defined(__NetBSD__) && defined(__x86_64__) + mcontext_t *mc = &uc->uc_mcontext; + struct fxsave64 *fxsave = (struct fxsave64 *)&mc->__fpregs; + pc = mc_pc(mc); + fxsave->fx_mxcsr = 0x1F80; + fxsave->fx_fsw &= ~0xFF; +#elif defined(__NetBSD__) && defined(__i386__) + mcontext_t *mc = &uc->uc_mcontext; + pc = mc_pc(mc); + if (uc->uc_flags & _UC_FXSAVE) { + struct envxmm *envxmm = (struct envxmm *)&mc->__fpregs; + envxmm->en_mxcsr = 0x1F80; + envxmm->en_sw &= ~0xFF; + } else { + struct env87 *env87 = (struct env87 *)&mc->__fpregs; + env87->en_sw &= ~0xFF; + } +#elif defined(__OpenBSD__) && defined(__x86_64__) + struct fxsave64 *fxsave = uc->sc_fpstate; + pc = mc_pc(uc); + fxsave->fx_mxcsr = 0x1F80; + fxsave->fx_fsw &= ~0xFF; +#elif defined(__sun__) && defined(__x86_64__) + mcontext_t *mc = &uc->uc_mcontext; + struct fpchip_state *fpstate = &mc->fpregs.fp_reg_set.fpchip_state; + pc = mc_pc(mc); + fpstate->mxcsr = 0x1F80; + fpstate->sw &= ~0xFF; +#endif +#if 0 + { + char buf[64]; + snprintf(buf, sizeof buf, "%s: FPE at %p\r\n", __FUNCTION__, (void*)pc); + write(2, buf, strlen(buf)); + } +#endif + set_current_fp_exception(pc); +} + +static void erts_thread_catch_fp_exceptions(void) +{ + struct sigaction act; + memset(&act, 0, sizeof act); + act.sa_sigaction = fpe_sig_action; + act.sa_flags = SA_SIGINFO; + sigaction(SIGFPE, &act, NULL); + unmask_fpe(); +} + +#else /* !((__linux__ && (__i386__ || __x86_64__ || __powerpc__)) || (__DARWIN__ && (__i386__ || __x86_64__ || __ppc__))) */ + +static void fpe_sig_handler(int sig) +{ + set_current_fp_exception(1); /* XXX: convert to sigaction so we can get the trap PC */ +} + +static void erts_thread_catch_fp_exceptions(void) +{ + sys_sigset(SIGFPE, fpe_sig_handler); + unmask_fpe(); +} + +#endif /* (__linux__ && (__i386__ || __x86_64__ || __powerpc__)) || (__DARWIN__ && (__i386__ || __x86_64__ || __ppc__))) */ + +/* once-only initialisation early in the main thread */ +void erts_sys_init_float(void) +{ + erts_init_fp_exception(); + erts_thread_catch_fp_exceptions(); + erts_printf_block_fpe = erts_sys_block_fpe; + erts_printf_unblock_fpe = erts_sys_unblock_fpe; +} + +#endif /* NO_FPE_SIGNALS */ + +void erts_thread_init_float(void) +{ +#ifdef ERTS_SMP + /* This allows Erlang schedulers to leave Erlang-process context + and still have working FP exceptions. XXX: is this needed? */ + erts_thread_init_fp_exception(); +#endif + +#ifndef NO_FPE_SIGNALS + /* NOTE: + * erts_thread_disable_fpe() is called in all threads at + * creation. We at least need to call unmask_fpe() + */ +#if defined(__DARWIN__) || defined(__FreeBSD__) + /* Darwin (7.9.0) does not appear to propagate FP exception settings + to a new thread from its parent. So if we want FP exceptions, we + must manually re-enable them in each new thread. + FreeBSD 6.1 appears to suffer from a similar issue. */ + erts_thread_catch_fp_exceptions(); +#else + unmask_fpe(); +#endif + +#endif +} + +void erts_thread_disable_fpe(void) +{ +#if !defined(NO_FPE_SIGNALS) + (void)mask_fpe(); +#endif +} + +#if !defined(NO_FPE_SIGNALS) +int erts_sys_block_fpe(void) +{ + return mask_fpe(); +} + +void erts_sys_unblock_fpe(int unmasked) +{ + unmask_fpe_conditional(unmasked); +} +#endif + +/* The following check is incorporated from the Vee machine */ + +#define ISDIGIT(d) ((d) >= '0' && (d) <= '9') + +/* + ** Convert a double to ascii format 0.dddde[+|-]ddd + ** return number of characters converted or -1 if error. + ** + ** These two functions should maybe use localeconv() to pick up + ** the current radix character, but since it is uncertain how + ** expensive such a system call is, and since no-one has heard + ** of other radix characters than '.' and ',' an ad-hoc + ** low execution time solution is used instead. + */ + +int +sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t decimals) +{ + char *s = buffer; + + if (erts_snprintf(buffer, buffer_size, "%.*e", decimals, fp) >= buffer_size) + return -1; + /* Search upto decimal point */ + if (*s == '+' || *s == '-') s++; + while (ISDIGIT(*s)) s++; + if (*s == ',') *s++ = '.'; /* Replace ',' with '.' */ + /* Scan to end of string */ + while (*s) s++; + return s-buffer; /* i.e strlen(buffer) */ +} + +/* Float conversion */ + +int +sys_chars_to_double(char* buf, double* fp) +{ +#ifndef NO_FPE_SIGNALS + volatile unsigned long *fpexnp = erts_get_current_fp_exception(); +#endif + char *s = buf, *t, *dp; + + /* Robert says that something like this is what he really wanted: + * (The [.,] radix test is NOT what Robert wanted - it was added later) + * + * 7 == sscanf(Tbuf, "%[+-]%[0-9][.,]%[0-9]%[eE]%[+-]%[0-9]%s", ....); + * if (*s2 == 0 || *s3 == 0 || *s4 == 0 || *s6 == 0 || *s7) + * break; + */ + + /* Scan string to check syntax. */ + if (*s == '+' || *s == '-') s++; + if (!ISDIGIT(*s)) /* Leading digits. */ + return -1; + while (ISDIGIT(*s)) s++; + if (*s != '.' && *s != ',') /* Decimal part. */ + return -1; + dp = s++; /* Remember decimal point pos just in case */ + if (!ISDIGIT(*s)) + return -1; + while (ISDIGIT(*s)) s++; + if (*s == 'e' || *s == 'E') { + /* There is an exponent. */ + s++; + if (*s == '+' || *s == '-') s++; + if (!ISDIGIT(*s)) + return -1; + while (ISDIGIT(*s)) s++; + } + if (*s) /* That should be it */ + return -1; + +#ifdef NO_FPE_SIGNALS + errno = 0; +#endif + __ERTS_FP_CHECK_INIT(fpexnp); + *fp = strtod(buf, &t); + __ERTS_FP_ERROR_THOROUGH(fpexnp, *fp, return -1); + if (t != s) { /* Whole string not scanned */ + /* Try again with other radix char */ + *dp = (*dp == '.') ? ',' : '.'; + errno = 0; + __ERTS_FP_CHECK_INIT(fpexnp); + *fp = strtod(buf, &t); + __ERTS_FP_ERROR_THOROUGH(fpexnp, *fp, return -1); + } + +#ifdef NO_FPE_SIGNALS + if (errno == ERANGE) { + if (*fp == HUGE_VAL || *fp == -HUGE_VAL) { + /* overflow, should give error */ + return -1; + } else if (t == s && *fp == 0.0) { + /* This should give 0.0 - OTP-7178 */ + errno = 0; + + } else if (*fp == 0.0) { + return -1; + } + } +#endif + return 0; +} + +int +matherr(struct exception *exc) +{ +#if !defined(NO_FPE_SIGNALS) + volatile unsigned long *fpexnp = erts_get_current_fp_exception(); + if (fpexnp != NULL) + *fpexnp = (unsigned long)__builtin_return_address(0); +#endif + return 1; +} diff --git a/erts/emulator/sys/ose/sys_time.c b/erts/emulator/sys/ose/sys_time.c new file mode 100644 index 0000000000..7e96f68424 --- /dev/null +++ b/erts/emulator/sys/ose/sys_time.c @@ -0,0 +1,56 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2005-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "sys.h" +#include "global.h" + +/******************* Routines for time measurement *********************/ + +int erts_ticks_per_sec = 0; /* Will be SYS_CLK_TCK in erl_unix_sys.h */ + +int sys_init_time(void) +{ + return SYS_CLOCK_RESOLUTION; +} + +clock_t sys_times(SysTimes *now) { + now->tms_utime = now->tms_stime = now->tms_cutime = now->tms_cstime = 0; + return 0; +} + +static OSTICK last_tick_count = 0; +static SysHrTime wrap = 0; +static OSTICK us_per_tick; + +void sys_init_hrtime() { + us_per_tick = system_tick(); +} + +SysHrTime sys_gethrtime() { + OSTICK ticks = get_ticks(); + if (ticks < (SysHrTime) last_tick_count) { + wrap += 1ULL << 32; + } + last_tick_count = ticks; + return ((((SysHrTime) ticks) + wrap) * 1000*us_per_tick); +} -- cgit v1.2.3 From 8084f0f9797daf83bf6da698e5e1e5784c11601b Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Sun, 23 Feb 2014 16:48:17 +0100 Subject: ose: Add unsetenv and update to use get_env Before get_envp was used and this caused the environment variables to not be accessible in the correct way by use debug tools. --- erts/emulator/sys/ose/sys.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index c475aafe38..4fd740b02a 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -1530,24 +1530,24 @@ int erts_sys_putenv(char *key, char *value) { int res; - char *env; - Uint need = strlen(key) + strlen(value) + 2; -#ifdef HAVE_COPYING_PUTENV - env = erts_alloc(ERTS_ALC_T_TMP, need); -#else - env = erts_alloc(ERTS_ALC_T_PUTENV_STR, need); - erts_smp_atomic_add_nob(&sys_misc_mem_sz, need); -#endif - strcpy(env,key); - strcat(env,"="); - strcat(env,value); erts_smp_rwmtx_rwlock(&environ_rwmtx); - res = putenv(env); + res = set_env(get_bid(current_process()), key, + value); erts_smp_rwmtx_rwunlock(&environ_rwmtx); -#ifdef HAVE_COPYING_PUTENV - erts_free(ERTS_ALC_T_TMP, env); -#endif + return res; +} + + +int +erts_sys_unsetenv(char *key) +{ + int res; + + erts_smp_rwmtx_rwlock(&environ_rwmtx); + res = set_env(get_bid(current_process()),key,NULL); + erts_smp_rwmtx_rwunlock(&environ_rwmtx); + return res; } @@ -1555,7 +1555,7 @@ int erts_sys_getenv__(char *key, char *value, size_t *size) { int res; - char *orig_value = getenv(key); + char *orig_value = get_env(get_bid(current_process()), key); if (!orig_value) res = -1; else { @@ -1569,6 +1569,7 @@ erts_sys_getenv__(char *key, char *value, size_t *size) sys_memcpy((void *) value, (void *) orig_value, len+1); res = 0; } + free_buf((union SIGNAL **)&orig_value); } return res; } -- cgit v1.2.3 From 33f5280f9e130ebbf19c63470e38c1dc71fd0003 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Sun, 23 Feb 2014 16:50:00 +0100 Subject: ose: Add signal debugging macros To enable just uncomment and all signals going in or out will be printed to stdout. --- erts/emulator/sys/ose/erl_ose_sys.h | 122 ++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/erl_ose_sys.h b/erts/emulator/sys/ose/erl_ose_sys.h index a3308e9ba4..94f1e58883 100644 --- a/erts/emulator/sys/ose/erl_ose_sys.h +++ b/erts/emulator/sys/ose/erl_ose_sys.h @@ -235,4 +235,126 @@ extern int getpagesize(void); # define UINT_MAX 4294967295U #endif +/* +static void erts_ose_sys_send(union SIGNAL **signal,PROCESS dst, + char* file,int line) { + SIGSELECT **ziggy = (SIGSELECT**)signal; + printf("%s:%d 0x%x Send signal 0x%x(0x%x) to 0x%x\r\n", + file,line,current_process(),ziggy[0][0],*ziggy,dst); + send(signal,dst); +} +#define send(signal,dst) erts_ose_sys_send(signal,dst,__FILE__,__LINE__) + +static void erts_ose_sys_send_w_sender(union SIGNAL **signal, + PROCESS sender,PROCESS dst, + char* file,int line) { + SIGSELECT **ziggy = (SIGSELECT**)signal; + printf("%s:%d 0x%x Send signal 0x%x(0x%x) to 0x%x as 0x%x\r\n", + file,line,current_process(),ziggy[0][0],*ziggy,dst,sender); + send_w_sender(signal,sender,dst); +} +#define send_w_sender(signal,sender,dst) \ + erts_ose_sys_send_w_sender(signal,sender,dst,__FILE__,__LINE__) + + +static union SIGNAL *erts_ose_sys_receive(SIGSELECT *sigsel, + char *file, + int line) { + SIGSELECT *sig; + int i; + + printf("%s:%d 0x%x receive({%d,",file,line,current_process(),sigsel[0]); + for (i = 1; i < sigsel[0]; i++) + printf("0x%x, ",sigsel[i]); + if (sigsel[0] != 0) + printf("0x%x",sigsel[i]); + printf("})\n"); + sig = (SIGSELECT*)receive(sigsel); + printf("%s:%d 0x%x got 0x%x from 0x%x\n",file,line,current_process(), + *sig,sender((union SIGNAL**)(&sig))); + return (union SIGNAL*)sig; +} +#define receive(SIGSEL) erts_ose_sys_receive(SIGSEL,__FILE__,__LINE__) + +static union SIGNAL *erts_ose_sys_receive_w_tmo(OSTIME tmo,SIGSELECT *sigsel, + char *file,int line) { + SIGSELECT *sig; + int i; + if (tmo == 0) { + sig = (SIGSELECT*)receive_w_tmo(tmo,sigsel); + if (sig != NULL) { + printf("%s:%d 0x%x receive_w_tmo(0,{%d,",file,line,current_process(), + sigsel[0]); + for (i = 1; i < sigsel[0]; i++) + printf("0x%x, ",sigsel[i]); + if (sigsel[0] != 0) + printf("0x%x",sigsel[i]); + printf("})\n"); + printf("%s:%d 0x%x got 0x%x from 0x%x\n",file,line,current_process(), + *sig,sender((union SIGNAL**)(&sig))); + } + } else { + printf("%s:%d 0x%x receive_w_tmo(%u,{%d,",file,line,current_process(),tmo, + sigsel[0]); + for (i = 1; i < sigsel[0]; i++) + printf("0x%x, ",sigsel[i]); + if (sigsel[0] != 0) + printf("0x%x",sigsel[i]); + printf("})\n"); + sig = (SIGSELECT*)receive_w_tmo(tmo,sigsel); + printf("%s:%d 0x%x got ",file,line,current_process()); + if (sig == NULL) + printf("TIMEOUT\n"); + else + printf("0x%x from 0x%x\n",*sig,sender((union SIGNAL**)(&sig))); + } + + return (union SIGNAL*)sig; +} + +#define receive_w_tmo(tmo,sigsel) erts_ose_sys_receive_w_tmo(tmo,sigsel, \ + __FILE__,__LINE__) + +static union SIGNAL *erts_ose_sys_receive_fsem(OSTIME tmo,SIGSELECT *sigsel, + OSFSEMVAL fsem, + char *file,int line) { + SIGSELECT *sig; + int i; + if (tmo == 0) { + sig = (SIGSELECT*)receive_fsem(tmo,sigsel,fsem); + if (sig != NULL && sig != OS_RCV_FSEM) { + printf("%s:%d 0x%x receive_fsem(0,{%d,",file,line,current_process(), + sigsel[0]); + for (i = 1; i < sigsel[0]; i++) + printf("0x%x, ",sigsel[i]); + if (sigsel[0] != 0) + printf("0x%x",sigsel[i]); + printf("},%d)\n",fsem); + printf("%s:%d 0x%x got 0x%x from 0x%x\n",file,line,current_process(), + *sig,sender((union SIGNAL**)(&sig))); + } + } else { + printf("%s:%d 0x%x receive_fsem(%u,{%d,",file,line,current_process(),tmo, + sigsel[0]); + for (i = 1; i < sigsel[0]; i++) + printf("0x%x, ",sigsel[i]); + if (sigsel[0] != 0) + printf("0x%x",sigsel[i]); + printf("},%d)\n",fsem); + sig = (SIGSELECT*)receive_fsem(tmo,sigsel,fsem); + printf("%s:%d 0x%x got ",file,line,current_process()); + if (sig == NULL) + printf("TIMEOUT\n"); + else if (sig == OS_RCV_FSEM) + printf("FSEM\n"); + else + printf("0x%x from 0x%x\n",*sig,sender((union SIGNAL**)(&sig))); + } + + return (union SIGNAL*)sig; +} + +#define receive_fsem(tmo,sigsel,fsem) \ + erts_ose_sys_receive_fsem(tmo,sigsel,fsem,__FILE__,__LINE__) +*/ #endif /* _ERL_OSE_SYS_H */ -- cgit v1.2.3 From c743ed359f16f791dd15b58b86af7f77db4799aa Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Sun, 23 Feb 2014 17:00:41 +0100 Subject: ose: Force atleast one async thread for ose This is needed because a file has to be opened and operated on in the same process at all times. Using async threads guarantee this. --- erts/emulator/sys/ose/erl_ose_sys.h | 5 +++++ erts/emulator/sys/unix/erl_unix_sys.h | 5 +++++ erts/emulator/sys/win32/erl_win_sys.h | 4 ++++ 3 files changed, 14 insertions(+) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/erl_ose_sys.h b/erts/emulator/sys/ose/erl_ose_sys.h index 94f1e58883..5243886bac 100644 --- a/erts/emulator/sys/ose/erl_ose_sys.h +++ b/erts/emulator/sys/ose/erl_ose_sys.h @@ -69,6 +69,11 @@ struct erts_sys_fd_type { }; +/* + * Min number of async threads + */ +#define ERTS_MIN_NO_OF_ASYNC_THREADS 1 + /* * Our own type of "FD's" */ diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h index 2c47aa06c2..176fc049a7 100644 --- a/erts/emulator/sys/unix/erl_unix_sys.h +++ b/erts/emulator/sys/unix/erl_unix_sys.h @@ -127,6 +127,11 @@ # endif #endif +/* + * Min number of async threads + */ +#define ERTS_MIN_NO_OF_ASYNC_THREADS 0 + /* File descriptors are numbers anc consecutively allocated on Unix */ #define ERTS_SYS_CONTINOUS_FD_NUMBERS diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h index 0deb097b1a..8015e8f378 100644 --- a/erts/emulator/sys/win32/erl_win_sys.h +++ b/erts/emulator/sys/win32/erl_win_sys.h @@ -103,6 +103,10 @@ #define CreateAutoEvent(state) CreateEvent(NULL, FALSE, state, NULL) #define CreateManualEvent(state) CreateEvent(NULL, TRUE, state, NULL) +/* + * Min number of async threads + */ +#define ERTS_MIN_NO_OF_ASYNC_THREADS 0 /* * Our own type of "FD's" -- cgit v1.2.3 From 3a4bdad8b488a6e7a4a18a95573059d5a21589c8 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 30 Sep 2013 15:06:57 +0200 Subject: ose: Extract signal numbers to common file --- erts/emulator/sys/ose/erl_ose_sys.h | 1 + erts/emulator/sys/ose/erl_poll.c | 4 +--- erts/emulator/sys/ose/erts.sig | 12 +++++++++++ erts/emulator/sys/ose/sys.c | 41 +++++++++++++++++-------------------- 4 files changed, 33 insertions(+), 25 deletions(-) create mode 100644 erts/emulator/sys/ose/erts.sig (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/erl_ose_sys.h b/erts/emulator/sys/ose/erl_ose_sys.h index 5243886bac..8c72afa9a5 100644 --- a/erts/emulator/sys/ose/erl_ose_sys.h +++ b/erts/emulator/sys/ose/erl_ose_sys.h @@ -27,6 +27,7 @@ #include "ose.h" #undef NIL #include "ramlog.h" +#include "erts.sig" #include "fcntl.h" #include "math.h" diff --git a/erts/emulator/sys/ose/erl_poll.c b/erts/emulator/sys/ose/erl_poll.c index 878bd362e4..0bea6865ca 100644 --- a/erts/emulator/sys/ose/erl_poll.c +++ b/erts/emulator/sys/ose/erl_poll.c @@ -68,8 +68,6 @@ # define SEL_REALLOC realloc_wrap # define SEL_FREE erts_free -#define ERTS_POLL_INVALID_SIGNO 12345 - #ifdef ERTS_SMP #define ERTS_POLLSET_LOCK(PS) \ @@ -308,7 +306,7 @@ static int update_sigsel(ErtsPollSet ps) { */ ps->sigs = SEL_ALLOC(ERTS_ALC_T_POLLSET,sizeof(SIGSELECT)*(2)); ps->sigs[0] = 1; - ps->sigs[1] = ERTS_POLL_INVALID_SIGNO; + ps->sigs[1] = ERTS_SIGNAL_INVALID; return 0; } diff --git a/erts/emulator/sys/ose/erts.sig b/erts/emulator/sys/ose/erts.sig new file mode 100644 index 0000000000..760d0896c0 --- /dev/null +++ b/erts/emulator/sys/ose/erts.sig @@ -0,0 +1,12 @@ +#ifndef ERTS_OSE_SIGNALS +#define ERTS_OSE_SIGNALS + +#ifndef ERTS_OSE_SIGNAL_BASE +#define ERTS_OSE_SIGNAL_BASE 1000 +#endif + +#define ERTS_SIGNAL_INVALID ERTS_OSE_SIGNAL_BASE +#define ERTS_SIGNAL_FD_DRV_CONFIG ERTS_OSE_SIGNAL_BASE+1 +#define ERTS_SIGNAL_FD_DRV_ASYNC ERTS_OSE_SIGNAL_BASE+2 + +#endif diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index 4fd740b02a..a8eb0b93b4 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -583,12 +583,6 @@ void fini_getenv_state(GETENV_STATE *state) /* I. Common stuff */ -/* - * Decreasing the size of it below 16384 is not allowed. - */ -#define SYSDRIVERASYNCSIG 1000 -#define SYSDRIVERCONFSIG 1001 - typedef struct SysDriverAsyncSignal_ { SIGSELECT sig_no; int type; @@ -611,6 +605,9 @@ union SIGNAL { /* II. The spawn/fd drivers */ +/* + * Decreasing the size of it below 16384 is not allowed. + */ #define ERTS_SYS_READ_BUF_SZ (64*1024) /* Driver interfaces */ @@ -627,7 +624,7 @@ static void output(ErlDrvData, char*, ErlDrvSizeT); static void outputv(ErlDrvData, ErlIOVec*); static void stop_select(ErlDrvEvent, void*); static int resolve_signal(OseSignal* sig, int *mode) { - return sig->sig_no == SYSDRIVERASYNCSIG ? sig->sys_async.type : -1; + return sig->sig_no == ERTS_SIGNAL_FD_DRV_ASYNC ? sig->sys_async.type : -1; } OS_PROCESS(fd_writer_process); @@ -712,9 +709,9 @@ static int set_driver_data(ErlDrvPort port_num, report_exit->ofd = read_write & DO_WRITE ? ofd : -1; if (read_write & DO_READ) - report_exit->in_sig_descr = erl_drv_ose_event_alloc(SYSDRIVERASYNCSIG, ifd); + report_exit->in_sig_descr = erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ifd); if (read_write & DO_WRITE) - report_exit->out_sig_descr = erl_drv_ose_event_alloc(SYSDRIVERASYNCSIG, ofd); + report_exit->out_sig_descr = erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ofd); report_exit_list = report_exit; } @@ -730,13 +727,13 @@ static int set_driver_data(ErlDrvPort port_num, driver_data[ifd].pid = pid; driver_data[ifd].alive = 1; driver_data[ifd].status = 0; - driver_data[ifd].in_sig_descr = erl_drv_ose_event_alloc(SYSDRIVERASYNCSIG,ifd); + driver_data[ifd].in_sig_descr = erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ifd); driver_data[ifd].in_proc = create_process(OS_PRI_PROC,"beam_fd_reader", fd_reader_process, 0x800, FD_PROC_PRI, 0, 0, NULL, 0, 0); efs_clone(driver_data[ifd].in_proc); - sig = alloc(sizeof(SysDriverConfSignal), SYSDRIVERCONFSIG); + sig = alloc(sizeof(SysDriverConfSignal), ERTS_SIGNAL_FD_DRV_CONFIG); sig->conf_async.fd = ifd; sig->conf_async.parent = current_process(); send(&sig, driver_data[ifd].in_proc); @@ -745,12 +742,12 @@ static int set_driver_data(ErlDrvPort port_num, if (read_write & DO_WRITE) { driver_data[ifd].ofd = ofd; driver_data[ifd].out_sig_descr = - erl_drv_ose_event_alloc(SYSDRIVERASYNCSIG,ofd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd); driver_data[ifd].pdl = driver_pdl_create(port_num); driver_data[ifd].out_proc = create_process(OS_PRI_PROC, "beam_fd_writer", fd_writer_process, 0x800, FD_PROC_PRI, 0, 0, NULL, 0, 0); - sig = alloc(sizeof(SysDriverConfSignal), SYSDRIVERCONFSIG); + sig = alloc(sizeof(SysDriverConfSignal), ERTS_SIGNAL_FD_DRV_CONFIG); sig->conf_async.fd = ofd; sig->conf_async.parent = current_process(); send(&sig, driver_data[ifd].out_proc); @@ -771,13 +768,13 @@ static int set_driver_data(ErlDrvPort port_num, driver_data[ofd].pid = pid; driver_data[ofd].alive = 1; driver_data[ofd].status = 0; - driver_data[ofd].in_sig_descr = erl_drv_ose_event_alloc(SYSDRIVERASYNCSIG, + driver_data[ofd].in_sig_descr = erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ofd); driver_data[ofd].out_sig_descr = driver_data[ofd].in_sig_descr; driver_data[ofd].out_proc = create_process(OS_PRI_PROC, "beam_fd_writer", fd_writer_process, 0x800, FD_PROC_PRI, 0, 0, NULL, 0, 0); - sig = alloc(sizeof(SysDriverConfSignal), SYSDRIVERCONFSIG); + sig = alloc(sizeof(SysDriverConfSignal), ERTS_SIGNAL_FD_DRV_CONFIG); sig->conf_async.fd = ofd; sig->conf_async.parent = current_process(); send(&sig, driver_data[ofd].out_proc); @@ -830,7 +827,7 @@ OS_PROCESS(fd_reader_process) { int fd; byte *read_buf; - SIGSELECT sigsel[] = {1,SYSDRIVERCONFSIG}; + SIGSELECT sigsel[] = {1,ERTS_SIGNAL_FD_DRV_CONFIG}; #ifdef ERTS_ENABLE_LOCK_COUNT erts_lcnt_init(); @@ -855,7 +852,7 @@ OS_PROCESS(fd_reader_process) { } #endif - sigsel[1] = SYSDRIVERASYNCSIG; + sigsel[1] = ERTS_SIGNAL_FD_DRV_ASYNC; read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF, ERTS_SYS_READ_BUF_SZ); @@ -863,7 +860,7 @@ OS_PROCESS(fd_reader_process) { int errno_copy = errno; ssize_t res; res = read(fd, read_buf, ERTS_SYS_READ_BUF_SZ); - sig = alloc(sizeof(SysDriverAsyncSignal), SYSDRIVERASYNCSIG); + sig = alloc(sizeof(SysDriverAsyncSignal), ERTS_SIGNAL_FD_DRV_ASYNC); sig->sys_async.buff = read_buf; sig->sys_async.res = res; if (res <= 0 && errno == EBADF) { @@ -888,7 +885,7 @@ OS_PROCESS(fd_writer_process) { OseSignal *sig; PROCESS parent; int fd; - SIGSELECT sigsel[] = { 1, SYSDRIVERCONFSIG, SYSDRIVERASYNCSIG }; + SIGSELECT sigsel[] = { 1, ERTS_SIGNAL_FD_DRV_CONFIG, ERTS_SIGNAL_FD_DRV_ASYNC }; TRACE; /* Only wait for config event with the fd which we are printing to */ @@ -928,7 +925,7 @@ OS_PROCESS(fd_writer_process) { /* fprintf(stderr,"0x%x: fd_writer, receive\n", current_process()); */ sig = receive(sigsel); /* size = sig->sys_async.res;*/ - if (sig->sig_no == SYSDRIVERCONFSIG) + if (sig->sig_no == ERTS_SIGNAL_FD_DRV_CONFIG) return; driver_pdl_lock(driver_data[fd].pdl); @@ -1147,7 +1144,7 @@ static void outputv(ErlDrvData e, ErlIOVec* ev) driver_enqv(ix, ev, 0); /* n is the skip value */ driver_pdl_unlock(driver_data[fd].pdl); driver_select(ix, driver_data[fd].out_sig_descr, ERL_DRV_WRITE|ERL_DRV_USE, 1); - sig = alloc(sizeof(SysDriverAsyncSignal),SYSDRIVERASYNCSIG); + sig = alloc(sizeof(SysDriverAsyncSignal),ERTS_SIGNAL_FD_DRV_ASYNC); sig->sys_async.type = fd; sig->sys_async.res = pb+len; send(&sig,driver_data[fd].out_proc); @@ -1201,7 +1198,7 @@ static void output(ErlDrvData e, char* buf, ErlDrvSizeT len) driver_enq(ix, buf, len); driver_pdl_unlock(driver_data[fd].pdl); driver_select(ix, driver_data[ofd].out_sig_descr, ERL_DRV_WRITE|ERL_DRV_USE, 1); - sig = alloc(sizeof(SysDriverAsyncSignal),SYSDRIVERASYNCSIG); + sig = alloc(sizeof(SysDriverAsyncSignal),ERTS_SIGNAL_FD_DRV_ASYNC); sig->sys_async.type = fd; sig->sys_async.res = pb+len; send(&sig,driver_data[fd].out_proc); -- cgit v1.2.3 From 8ed59e4a9dddf083d2046e1bd58f397221928c0e Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 15 Oct 2013 18:10:47 +0200 Subject: ose: Change start way to use arguments to beam.smp directly The old way registered a shell command that needed to be executed. This way is more flexible as you can also use the lmconf file to set arguments there. --- erts/emulator/sys/ose/default.lmconf | 7 ++++-- erts/emulator/sys/ose/erl_main.c | 44 +----------------------------------- 2 files changed, 6 insertions(+), 45 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/default.lmconf b/erts/emulator/sys/ose/default.lmconf index f897872fa2..150111b1f6 100644 --- a/erts/emulator/sys/ose/default.lmconf +++ b/erts/emulator/sys/ose/default.lmconf @@ -2,9 +2,12 @@ OSE_LM_STACK_SIZES=256,512,1024,2048,4096,8192,16384,65536 OSE_LM_SIGNAL_SIZES=31,63,127,255,1023,4095,16383,65535 OSE_LM_POOL_SIZE=0x200000 OSE_LM_MAIN_NAME=main -OSE_LM_MAIN_STACK_SIZE=0x400 +OSE_LM_MAIN_STACK_SIZE=0xF000 OSE_LM_MAIN_PRIORITY=20 -OSE_LM_PROGRAM_TYPE=SYS_RAM +OSE_LM_PROGRAM_TYPE=APP_RAM OSE_LM_DATA_INIT=YES OSE_LM_BSS_INIT=YES OSE_LM_EXEC_MODEL=SHARED +HEAP_MAX_SIZE=1000000000 +HEAP_SMALL_BUF_INIT_SIZE=64000000 +HEAP_LARGE_BUF_THRESHOLD=16000000 \ No newline at end of file diff --git a/erts/emulator/sys/ose/erl_main.c b/erts/emulator/sys/ose/erl_main.c index 21cfce9463..322058c87b 100644 --- a/erts/emulator/sys/ose/erl_main.c +++ b/erts/emulator/sys/ose/erl_main.c @@ -16,53 +16,11 @@ * * %CopyrightEnd% */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "sys.h" -#include "erl_vm.h" -#include "global.h" - -#include "shell.h" -#include "ramlog.h" -#include "ose_err/ose_err.h" - -static PROCESS mainPid; - -#ifdef DEBUG -static OSADDRESS err_handler(OSBOOLEAN user_called, OSERRCODE ecode, OSERRCODE extra) { - fprintf(stderr,"err_handler: %p %p\n",ecode,extra); - return 1; -} -#endif - -static int -cmd_ek(int argc, char **argv) { - kill_proc(mainPid); - return 0; -} - -static int -cmd_erl_start(int argc, char **argv) { - ramlog_printf("\n"); - ramlog_printf("================================================================\n"); - ramlog_printf("\n"); -#ifdef DEBUG - create_error_handler(get_bid(current_process()),err_handler,0x100); -#endif - erl_start(argc, argv); - return 0; -} int main(int argc, char **argv) { - mainPid = current_process(); - - shell_add_cmd_attrs("start_beam", "start_beam [params]", "Start the Erlang VM", - cmd_erl_start, OS_PRI_PROC, 20, 0xF000); - shell_add_cmd_attrs("ek", "ek", "Kills the Erlang VM", - cmd_ek, OS_PRI_PROC, 20, 0x100); + erl_start(argc,argv); stop(current_process()); -- cgit v1.2.3 From fa3dd14716b2a7ad0c223ebacd2ffc6ecf6437e6 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 30 Sep 2013 15:07:49 +0200 Subject: ose: Add module that allows interaction with any OSE process The interface of this module is made to be as generic as possible in order for other IPC mechanisms to mimic it and allow porting of code between different os:es. --- erts/emulator/sys/ose/erl_poll.c | 2 -- erts/emulator/sys/ose/erts.sig | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/erl_poll.c b/erts/emulator/sys/ose/erl_poll.c index 0bea6865ca..b1e256afc3 100644 --- a/erts/emulator/sys/ose/erl_poll.c +++ b/erts/emulator/sys/ose/erl_poll.c @@ -275,7 +275,6 @@ static void update_redir_tables(ErtsPollSet ps) { redir_table[0].pid = 0; for (i = 1; i < ps->sig_count+1; i++) { - ramlog_printf("Adding 0x%p -> 0x%p to redir table\n",ps->sigs[i],sched_1); redir_table[i].sig = ps->sigs[i]; redir_table[i].pid = sched_1; } @@ -283,7 +282,6 @@ static void update_redir_tables(ErtsPollSet ps) { for (i = 1; i < erts_no_schedulers; i++) { ErtsSchedulerData *esdp = ERTS_SCHEDULER_IX(i); set_redirection(esdp->tid.id,redir_table); - ramlog_printf("Setting redir table to 0x%p\n",esdp->tid.id); } SEL_FREE(ERTS_ALC_T_POLLSET,redir_table); diff --git a/erts/emulator/sys/ose/erts.sig b/erts/emulator/sys/ose/erts.sig index 760d0896c0..4bd2056cb0 100644 --- a/erts/emulator/sys/ose/erts.sig +++ b/erts/emulator/sys/ose/erts.sig @@ -8,5 +8,7 @@ #define ERTS_SIGNAL_INVALID ERTS_OSE_SIGNAL_BASE #define ERTS_SIGNAL_FD_DRV_CONFIG ERTS_OSE_SIGNAL_BASE+1 #define ERTS_SIGNAL_FD_DRV_ASYNC ERTS_OSE_SIGNAL_BASE+2 +#define ERTS_SIGNAL_OSE_DRV_ATTACH ERTS_OSE_SIGNAL_BASE+3 +#define ERTS_SIGNAL_OSE_DRV_HUNT ERTS_OSE_SIGNAL_BASE+4 #endif -- cgit v1.2.3 From 7e6cdce4925cd033812bbb9b9f113c1862225439 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 15 Oct 2013 18:40:03 +0200 Subject: ose: Copied driver_int.h from unix --- erts/emulator/sys/ose/driver_int.h | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 erts/emulator/sys/ose/driver_int.h (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/driver_int.h b/erts/emulator/sys/ose/driver_int.h new file mode 100644 index 0000000000..2c9ac955d8 --- /dev/null +++ b/erts/emulator/sys/ose/driver_int.h @@ -0,0 +1,41 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +/* + * System dependant driver declarations + */ + +#ifndef __DRIVER_INT_H__ +#define __DRIVER_INT_H__ + +#ifdef HAVE_SYS_UIO_H +#include +#include + +typedef struct iovec SysIOVec; + +#else + +typedef struct { + char* iov_base; + int iov_len; +} SysIOVec; + +#endif + +#endif -- cgit v1.2.3 From 51a07bb5770ddbbf10c5be969985c5f6b36e4a4c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 22 Oct 2013 17:49:17 +0200 Subject: ose: Add link conf for gcc 4.4.3 --- erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf | 147 +++++++++++++++++++ erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf | 219 +++++++++++++++++++++++++++++ erts/emulator/sys/ose/gcc_lm_ppc.lcf | 219 ----------------------------- 3 files changed, 366 insertions(+), 219 deletions(-) create mode 100644 erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf create mode 100644 erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf delete mode 100644 erts/emulator/sys/ose/gcc_lm_ppc.lcf (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf b/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf new file mode 100644 index 0000000000..65a3f1757d --- /dev/null +++ b/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf @@ -0,0 +1,147 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH("powerpc") +ENTRY("crt0_lm") +MEMORY +{ + rom : ORIGIN = 0x01000000, LENGTH = 0x01000000 + ram : ORIGIN = 0x02000000, LENGTH = 0x01000000 +} +PHDRS +{ + ph_conf PT_LOAD ; + ph_rom PT_LOAD ; + ph_ram PT_LOAD ; +} +SECTIONS +{ + .text : + { + *(.text_first) + *(.text) + *(.text.*) + *(.stub) + *(oscode) + *(.init*) + *(.fini*) + *(.gnu.warning) + *(.gnu.linkonce.t.*) + *(.glue_7t) + *(.glue_7) + } > rom :ph_rom = 0 + .ose_sfk_biosentry : + { + *(.ose_sfk_biosentry) + } > rom :ph_rom + .ctors : + { + __CTOR_LIST__ = .; + *(.ctors) + *(SORT(.ctors.*)) + __CTOR_END__ = .; + } > rom :ph_rom + .dtors : + { + __DTOR_LIST__ = .; + *(.dtors) + *(SORT(.dtors.*)) + __DTOR_END__ = .; + } > rom :ph_rom + OSESYMS : + { + *(.osesyms) + } > rom :ph_rom + .rodata : + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } > rom :ph_rom + .eh_frame : + { + __EH_FRAME_BEGIN__ = .; + *(.eh_frame) + LONG(0) + __EH_FRAME_END__ = .; + } > rom :ph_rom + .gcc_except_table : + { + *(.gcc_except_table .gcc_except_table.*) + } > rom :ph_rom + .sdata2 : + { + PROVIDE (_SDA2_BASE_ = .); + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + } > rom :ph_rom + .sbss2 : + { + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + } > rom :ph_rom + LMCONF : + { + obj/?*?/ose_confd.o(.rodata) + *(LMCONF) + } > rom :ph_conf + .data : + { + LONG(0xDEADBABE) + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + . = ALIGN(0x10); + } > ram :ph_ram = 0 + .sdata2 : + { + _SDA2_BASE_ = .; + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + }> ram :ph_ram + .sdata : + { + PROVIDE (_SDA_BASE_ = .); + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } > ram :ph_ram + .sbss : + { + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.gnu.linkonce.sb.*) + } > ram :ph_ram + .bss (NOLOAD) : + { + *(.bss) + *(.bss.*) + *(COMMON) + *(.gnu.linkonce.b.*) + *(.osvars) + } > ram :ph_ram + .ignore (NOLOAD) : + { + *(.rel.dyn) + } > ram :ph_ram + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} +__OSESYMS_START = ADDR(OSESYMS); +__OSESYMS_END = ADDR(OSESYMS) + SIZEOF(OSESYMS); diff --git a/erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf b/erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf new file mode 100644 index 0000000000..a2399c93da --- /dev/null +++ b/erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf @@ -0,0 +1,219 @@ +/******************************************************************************* + * gcc_lm_ppc.lcf: GCC linker control file for PowerPC load modules + * @(#) $FilePath: /vobs/ose5/system/refsys/compilers/gcc_lm_ppc.lcf $ + * @(#) $FileRevision: /main/tb_current_ose5/10 $ + * $Author: joka $$Date: 01/21/13 16:35:41 $ + * $Copyright: (C) 2006 by Enea AB. All rights reserved. $ + ******************************************************************************/ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH("powerpc") + +ENTRY("crt0_lm") + +/* Note: + * You may have to increase the length of the "rom" memory region and the + * origin and length of the "ram" memory region below depending on the size + * of the code and data in your load module. + */ + +MEMORY +{ + conf : ORIGIN = 0x00100000, LENGTH = 0x00030000 + rom : ORIGIN = 0x01000000, LENGTH = 0x01000000 + ram : ORIGIN = 0x03000000, LENGTH = 0x01000000 +} + +PHDRS +{ + ph_conf PT_LOAD ; + ph_rom PT_LOAD ; + ph_ram PT_LOAD ; +} + +SECTIONS +{ +/*--------------------------------------------------------------------------- + * Load module configuration area + *-------------------------------------------------------------------------*/ + + /* Load module configuration section. */ + LMCONF : + { + obj/?*?/ose_confd.o(.rodata) + *(LMCONF) + } > conf :ph_conf + +/*--------------------------------------------------------------------------- + * Read-only area + *-------------------------------------------------------------------------*/ + + /* Code section. */ + .text : + { + *(.text) + *(.text.*) + *(.stub) + *(oscode) + *(.init*) + *(.fini*) + *(.gnu.warning) + *(.gnu.linkonce.t.*) + } > rom :ph_rom = 0 + + /* OSE symbols section. */ + OSESYMS : + { + *(.osesyms) + } > rom :ph_rom + + /* Read-only data section. */ + .rodata : + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } > rom :ph_rom + + /* C++ exception handling section. */ + .eh_frame : + { + __EH_FRAME_BEGIN__ = .; + *(.eh_frame) + LONG(0) + __EH_FRAME_END__ = .; + } > rom :ph_rom + + /* C++ exception handling section. */ + .gcc_except_table : + { + *(.gcc_except_table .gcc_except_table.*) + } > rom :ph_rom + + /* PowerPC EABI initialized read-only data section. */ + .sdata2 : + { + PROVIDE (_SDA2_BASE_ = .); + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + } > rom :ph_rom + + /* PowerPC EABI uninitialized read-only data section. */ + .sbss2 : + { + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + } > rom :ph_rom + +/*--------------------------------------------------------------------------- + * Read-write area + *-------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------- + * Initialized data (copied by PM) + *-----------------------------------------------------------------*/ + + /* Data section. */ + .data : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } > ram :ph_ram + + /* C++ constructor section. */ + .ctors : + { + __CTOR_LIST__ = .; + *(.ctors) + *(SORT(.ctors.*)) + __CTOR_END__ = .; + } > ram :ph_ram + + /* C++ destructor section. */ + .dtors : + { + __DTOR_LIST__ = .; + *(.dtors) + *(SORT(.dtors.*)) + __DTOR_END__ = .; + } > ram :ph_ram + + + /* Small data section. */ + .sdata ALIGN(0x10) : + { + PROVIDE (_SDA_BASE_ = .); + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } > ram :ph_ram + + /*------------------------------------------------------------------- + * Uninitialized data (cleared by PM) + *-----------------------------------------------------------------*/ + + /* Small bss section. */ + .sbss : + { + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.gnu.linkonce.sb.*) + } > ram :ph_ram + + /* Bss section. */ + .bss : + { + *(.bss) + *(.bss.*) + *(COMMON) + *(.gnu.linkonce.b.*) + } > ram :ph_ram + +/*--------------------------------------------------------------------------- + * Debug information + *-------------------------------------------------------------------------*/ + + /* + * Stabs debug sections. + */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + /* + * DWARF debug sections. + */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/erts/emulator/sys/ose/gcc_lm_ppc.lcf b/erts/emulator/sys/ose/gcc_lm_ppc.lcf deleted file mode 100644 index a2399c93da..0000000000 --- a/erts/emulator/sys/ose/gcc_lm_ppc.lcf +++ /dev/null @@ -1,219 +0,0 @@ -/******************************************************************************* - * gcc_lm_ppc.lcf: GCC linker control file for PowerPC load modules - * @(#) $FilePath: /vobs/ose5/system/refsys/compilers/gcc_lm_ppc.lcf $ - * @(#) $FileRevision: /main/tb_current_ose5/10 $ - * $Author: joka $$Date: 01/21/13 16:35:41 $ - * $Copyright: (C) 2006 by Enea AB. All rights reserved. $ - ******************************************************************************/ - -OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") -OUTPUT_ARCH("powerpc") - -ENTRY("crt0_lm") - -/* Note: - * You may have to increase the length of the "rom" memory region and the - * origin and length of the "ram" memory region below depending on the size - * of the code and data in your load module. - */ - -MEMORY -{ - conf : ORIGIN = 0x00100000, LENGTH = 0x00030000 - rom : ORIGIN = 0x01000000, LENGTH = 0x01000000 - ram : ORIGIN = 0x03000000, LENGTH = 0x01000000 -} - -PHDRS -{ - ph_conf PT_LOAD ; - ph_rom PT_LOAD ; - ph_ram PT_LOAD ; -} - -SECTIONS -{ -/*--------------------------------------------------------------------------- - * Load module configuration area - *-------------------------------------------------------------------------*/ - - /* Load module configuration section. */ - LMCONF : - { - obj/?*?/ose_confd.o(.rodata) - *(LMCONF) - } > conf :ph_conf - -/*--------------------------------------------------------------------------- - * Read-only area - *-------------------------------------------------------------------------*/ - - /* Code section. */ - .text : - { - *(.text) - *(.text.*) - *(.stub) - *(oscode) - *(.init*) - *(.fini*) - *(.gnu.warning) - *(.gnu.linkonce.t.*) - } > rom :ph_rom = 0 - - /* OSE symbols section. */ - OSESYMS : - { - *(.osesyms) - } > rom :ph_rom - - /* Read-only data section. */ - .rodata : - { - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - } > rom :ph_rom - - /* C++ exception handling section. */ - .eh_frame : - { - __EH_FRAME_BEGIN__ = .; - *(.eh_frame) - LONG(0) - __EH_FRAME_END__ = .; - } > rom :ph_rom - - /* C++ exception handling section. */ - .gcc_except_table : - { - *(.gcc_except_table .gcc_except_table.*) - } > rom :ph_rom - - /* PowerPC EABI initialized read-only data section. */ - .sdata2 : - { - PROVIDE (_SDA2_BASE_ = .); - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - } > rom :ph_rom - - /* PowerPC EABI uninitialized read-only data section. */ - .sbss2 : - { - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - } > rom :ph_rom - -/*--------------------------------------------------------------------------- - * Read-write area - *-------------------------------------------------------------------------*/ - - /*------------------------------------------------------------------- - * Initialized data (copied by PM) - *-----------------------------------------------------------------*/ - - /* Data section. */ - .data : - { - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - } > ram :ph_ram - - /* C++ constructor section. */ - .ctors : - { - __CTOR_LIST__ = .; - *(.ctors) - *(SORT(.ctors.*)) - __CTOR_END__ = .; - } > ram :ph_ram - - /* C++ destructor section. */ - .dtors : - { - __DTOR_LIST__ = .; - *(.dtors) - *(SORT(.dtors.*)) - __DTOR_END__ = .; - } > ram :ph_ram - - - /* Small data section. */ - .sdata ALIGN(0x10) : - { - PROVIDE (_SDA_BASE_ = .); - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - } > ram :ph_ram - - /*------------------------------------------------------------------- - * Uninitialized data (cleared by PM) - *-----------------------------------------------------------------*/ - - /* Small bss section. */ - .sbss : - { - *(.sbss) - *(.sbss.*) - *(.scommon) - *(.gnu.linkonce.sb.*) - } > ram :ph_ram - - /* Bss section. */ - .bss : - { - *(.bss) - *(.bss.*) - *(COMMON) - *(.gnu.linkonce.b.*) - } > ram :ph_ram - -/*--------------------------------------------------------------------------- - * Debug information - *-------------------------------------------------------------------------*/ - - /* - * Stabs debug sections. - */ - - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - - /* - * DWARF debug sections. - */ - - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } -} -- cgit v1.2.3 From 5009faf90001b6fdba3226c227db758b75627a20 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 23 Oct 2013 10:26:15 +0200 Subject: ose: Add eh_frame_hdr section to linker file --- erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf b/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf index 65a3f1757d..5ebc328616 100644 --- a/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf +++ b/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf @@ -56,6 +56,10 @@ SECTIONS *(.rodata.*) *(.gnu.linkonce.r.*) } > rom :ph_rom + .eh_frame_hdr : + { + *(.eh_frame_hdr) + } > rom :ph_rom .eh_frame : { __EH_FRAME_BEGIN__ = .; -- cgit v1.2.3 From a3eba23b0caedcbd1d4cf181cb06b6f0d86f8bd4 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 28 Oct 2013 12:11:18 +0100 Subject: ose: Change signal base to registered range --- erts/emulator/sys/ose/erts.sig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/erts.sig b/erts/emulator/sys/ose/erts.sig index 4bd2056cb0..95c12652f2 100644 --- a/erts/emulator/sys/ose/erts.sig +++ b/erts/emulator/sys/ose/erts.sig @@ -2,7 +2,7 @@ #define ERTS_OSE_SIGNALS #ifndef ERTS_OSE_SIGNAL_BASE -#define ERTS_OSE_SIGNAL_BASE 1000 +#define ERTS_OSE_SIGNAL_BASE 0x01900280 #endif #define ERTS_SIGNAL_INVALID ERTS_OSE_SIGNAL_BASE -- cgit v1.2.3 From a6788ea337a2319a2d1a42ee4618553a1c7765bf Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 30 Oct 2013 17:56:37 +0100 Subject: ose: Fix various build environment issues --- erts/emulator/sys/ose/erl_main.c | 15 +++++++++++++++ erts/emulator/sys/ose/sys.c | 7 +++++++ 2 files changed, 22 insertions(+) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/erl_main.c b/erts/emulator/sys/ose/erl_main.c index 322058c87b..a17fc7eabc 100644 --- a/erts/emulator/sys/ose/erl_main.c +++ b/erts/emulator/sys/ose/erl_main.c @@ -17,10 +17,25 @@ * %CopyrightEnd% */ +#include + int main(int argc, char **argv) { + /* When starting using pm_create -c ARGV="-- -root ..", argv[0] is the first + part of ARGV and not the name of the executable. So we shuffle some + pointers here to make erl_start happy. */ + if (argv[0][0] == '-') { + int i; + char **tmp_argv = malloc(sizeof(char*)*(argc+1)); + for (i = 0; i < argc; i++) + tmp_argv[i+1] = argv[i]; + tmp_argv = "beam"; + erl_start(argc,tmp_argv); + free(tmp_argv); + } else { erl_start(argc,argv); + } stop(current_process()); diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index a8eb0b93b4..a8a99ceca6 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -852,6 +852,11 @@ OS_PROCESS(fd_reader_process) { } #endif + if (fd == 0) { + FILE *ffd = stdin; + (void)stdin; + } + sigsel[1] = ERTS_SIGNAL_FD_DRV_ASYNC; read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF, @@ -909,8 +914,10 @@ OS_PROCESS(fd_writer_process) { /* Why do I need these?!? */ if (fd == 1) { FILE* ffd = stdout; + (void)stdout; } else if (fd == 2) { FILE* ffd = stderr; + (void)stderr; } while (1) { -- cgit v1.2.3 From fd3aa9d63649084b345d0977fa121805f13c9d33 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 31 Oct 2013 11:29:25 +0100 Subject: ose: Style updates only --- erts/emulator/sys/ose/sys.c | 145 +++++++++++++++----------------------------- 1 file changed, 50 insertions(+), 95 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index a8a99ceca6..6e55301d6e 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -26,13 +26,8 @@ #define _XOPEN_SOURCE #endif -#include /* ose*/ +#include #include -/* ose -#include -#include -#include -*/ #include #include @@ -51,32 +46,19 @@ #endif #define ERTS_WANT_BREAK_HANDLING -#define WANT_NONBLOCKING /* must define this to pull in defs from sys.h */ +#define WANT_NONBLOCKING #include "sys.h" #include "erl_thr_progress.h" -#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__) -#define __DARWIN__ 1 -#endif - #ifdef USE_THREADS #include "erl_threads.h" #endif #include "erl_mseg.h" -/*ose*/ #include "unistd.h" #include "efs.h" #include "erl_printf.h" -#if 0 -#define TRACE do { \ - erts_fprintf(stderr, " %s / %d / pid 0x%x\n", __FUNCTION__, __LINE__, current_process()); \ - } while(0) -#else -#define TRACE do {} while(0) -#endif -/*ose*/ extern char **environ; static erts_smp_rwmtx_t environ_rwmtx; @@ -95,28 +77,9 @@ static erts_smp_rwmtx_t environ_rwmtx; #include "erl_check_io.h" #include "erl_cpu_topology.h" -#ifndef DISABLE_VFORK -#define DISABLE_VFORK 0 -#endif - /* The priority for reader/writer processes */ #define FD_PROC_PRI 20 -/* - * [OTP-3906] - * Solaris signal management gets confused when threads are used and a - * lot of child processes dies. The confusion results in that SIGCHLD - * signals aren't delivered to the emulator which in turn results in - * a lot of defunct processes in the system. - * - * The problem seems to appear when a signal is frequently - * blocked/unblocked at the same time as the signal is frequently - * propagated. The child waiter thread is a workaround for this problem. - * The SIGCHLD signal is always blocked (in all threads), and the child - * waiter thread fetches the signal by a call to sigwait(). See - * child_waiter(). - */ - typedef struct ErtsSysReportExit_ ErtsSysReportExit; struct ErtsSysReportExit_ { ErtsSysReportExit *next; @@ -516,8 +479,8 @@ int sys_max_files(void) char os_type[] = "ose"; void -os_flavor(char* namebuf, /* Where to return the name. */ - unsigned size) /* Size of name buffer. */ +os_flavor(char* namebuf, /* Where to return the name. */ + unsigned size) /* Size of name buffer. */ { #if 0 struct utsname uts; /* Information about the system. */ @@ -694,7 +657,8 @@ static int set_driver_data(ErlDrvPort port_num, ErtsSysReportExit *report_exit; OseSignal *sig; - /*erts_fprintf(stderr, " %s / pid %x / ofd %d / ifd %d\n", __FUNCTION__, current_process(), ofd, ifd);*/ + /*erts_fprintf(stderr, " %s / pid %x / ofd %d / ifd %d\n", + __FUNCTION__, current_process(), ofd, ifd);*/ if (!exit_status) @@ -709,9 +673,11 @@ static int set_driver_data(ErlDrvPort port_num, report_exit->ofd = read_write & DO_WRITE ? ofd : -1; if (read_write & DO_READ) - report_exit->in_sig_descr = erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ifd); + report_exit->in_sig_descr = + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ifd); if (read_write & DO_WRITE) - report_exit->out_sig_descr = erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ofd); + report_exit->out_sig_descr = + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ofd); report_exit_list = report_exit; } @@ -727,11 +693,13 @@ static int set_driver_data(ErlDrvPort port_num, driver_data[ifd].pid = pid; driver_data[ifd].alive = 1; driver_data[ifd].status = 0; - driver_data[ifd].in_sig_descr = erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ifd); + driver_data[ifd].in_sig_descr = + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ifd); driver_data[ifd].in_proc = create_process(OS_PRI_PROC,"beam_fd_reader", fd_reader_process, 0x800, - FD_PROC_PRI, 0, 0, NULL, 0, 0); + FD_PROC_PRI, 0, 0, + NULL, 0, 0); efs_clone(driver_data[ifd].in_proc); sig = alloc(sizeof(SysDriverConfSignal), ERTS_SIGNAL_FD_DRV_CONFIG); sig->conf_async.fd = ifd; @@ -744,9 +712,10 @@ static int set_driver_data(ErlDrvPort port_num, driver_data[ifd].out_sig_descr = erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd); driver_data[ifd].pdl = driver_pdl_create(port_num); - driver_data[ifd].out_proc = create_process(OS_PRI_PROC, "beam_fd_writer", - fd_writer_process, 0x800, - FD_PROC_PRI, 0, 0, NULL, 0, 0); + driver_data[ifd].out_proc = + create_process(OS_PRI_PROC,"beam_fd_writer", + fd_writer_process, 0x800, + FD_PROC_PRI, 0, 0, NULL, 0, 0); sig = alloc(sizeof(SysDriverConfSignal), ERTS_SIGNAL_FD_DRV_CONFIG); sig->conf_async.fd = ofd; sig->conf_async.parent = current_process(); @@ -758,7 +727,8 @@ static int set_driver_data(ErlDrvPort port_num, } else { /* DO_READ only */ driver_data[ifd].ofd = -1; } - (void) driver_select(port_num, driver_data[ifd].in_sig_descr, (ERL_DRV_READ | ERL_DRV_USE), 1); + (void) driver_select(port_num, driver_data[ifd].in_sig_descr, + (ERL_DRV_READ | ERL_DRV_USE), 1); return(ifd); } else { /* DO_WRITE only */ driver_data[ofd].packet_bytes = packet_bytes; @@ -768,12 +738,13 @@ static int set_driver_data(ErlDrvPort port_num, driver_data[ofd].pid = pid; driver_data[ofd].alive = 1; driver_data[ofd].status = 0; - driver_data[ofd].in_sig_descr = erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, - ofd); + driver_data[ofd].in_sig_descr = + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd); driver_data[ofd].out_sig_descr = driver_data[ofd].in_sig_descr; - driver_data[ofd].out_proc = create_process(OS_PRI_PROC, "beam_fd_writer", - fd_writer_process, 0x800, - FD_PROC_PRI, 0, 0, NULL, 0, 0); + driver_data[ofd].out_proc = + create_process(OS_PRI_PROC, "beam_fd_writer", + fd_writer_process, 0x800, + FD_PROC_PRI, 0, 0, NULL, 0, 0); sig = alloc(sizeof(SysDriverConfSignal), ERTS_SIGNAL_FD_DRV_CONFIG); sig->conf_async.fd = ofd; sig->conf_async.parent = current_process(); @@ -788,11 +759,11 @@ static int set_driver_data(ErlDrvPort port_num, static int spawn_init() { int i; - TRACE; driver_data = (struct driver_data *) erts_alloc(ERTS_ALC_T_DRV_TAB, max_files * sizeof(struct driver_data)); - erts_smp_atomic_add_nob(&sys_misc_mem_sz, max_files * sizeof(struct driver_data)); + erts_smp_atomic_add_nob(&sys_misc_mem_sz, + max_files * sizeof(struct driver_data)); for (i = 0; i < max_files; i++) driver_data[i].pid = -1; @@ -802,7 +773,6 @@ static int spawn_init() static void init_fd_data(int fd, ErlDrvPort port_num) { - TRACE; fd_data[fd].buf = NULL; fd_data[fd].cpos = NULL; @@ -811,12 +781,13 @@ static void init_fd_data(int fd, ErlDrvPort port_num) fd_data[fd].psz = 0; } -static ErlDrvData spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts) +static ErlDrvData spawn_start(ErlDrvPort port_num, + char* name, + SysDriverOpts* opts) { long res = 0; - TRACE; /* Have to implement for OSE */ return (ErlDrvData)res; } @@ -833,12 +804,8 @@ OS_PROCESS(fd_reader_process) { erts_lcnt_init(); #endif - TRACE; - sig = receive(sigsel); - TRACE; - fd = sig->conf_async.fd; parent = sig->conf_async.parent; @@ -890,14 +857,12 @@ OS_PROCESS(fd_writer_process) { OseSignal *sig; PROCESS parent; int fd; - SIGSELECT sigsel[] = { 1, ERTS_SIGNAL_FD_DRV_CONFIG, ERTS_SIGNAL_FD_DRV_ASYNC }; + SIGSELECT sigsel[] = { 1, ERTS_SIGNAL_FD_DRV_CONFIG, + ERTS_SIGNAL_FD_DRV_ASYNC }; - TRACE; /* Only wait for config event with the fd which we are printing to */ sig = receive(sigsel); - TRACE; - fd = sig->conf_async.fd; parent = sig->conf_async.parent; free_buf(&sig); @@ -944,12 +909,13 @@ OS_PROCESS(fd_writer_process) { ; iov = driver_alloc(sizeof(SysIOVec) * iovcnt); memcpy(iov, iov0, iovcnt * sizeof(SysIOVec)); - driver_pdl_unlock(driver_data[fd].pdl); /* Let go of lock until we deque from original vector */ + driver_pdl_unlock(driver_data[fd].pdl); if (iovlen > 0) { for (i = 0; i < iovcnt; i++) { - res = write(fd, iov[i].iov_base, iov[i].iov_len > 256 ? 256 : iov[i].iov_len); + res = write(fd, iov[i].iov_base, + iov[i].iov_len > 256 ? 256 : iov[i].iov_len); if (res < 0) break; n += res; @@ -1024,8 +990,6 @@ static ErlDrvData fd_start(ErlDrvPort port_num, char* name, { ErlDrvData res; - TRACE; - CHLD_STAT_LOCK; if (opts->read_write & DO_READ) { init_fd_data(opts->ifd, port_num); @@ -1042,8 +1006,6 @@ static ErlDrvData fd_start(ErlDrvPort port_num, char* name, static void clear_fd_data(int fd) { - TRACE; - if (fd_data[fd].sz > 0) { erts_free(ERTS_ALC_T_FD_ENTRY_BUF, (void *) fd_data[fd].buf); ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= fd_data[fd].sz); @@ -1059,7 +1021,6 @@ static void clear_fd_data(int fd) static void nbio_stop_fd(ErlDrvPort prt, ErlDrvEvent ev) { int fd; - TRACE; driver_select(prt,ev,DO_READ|DO_WRITE,0); erl_drv_ose_event_fetch(ev, NULL, &fd); clear_fd_data(fd); @@ -1070,12 +1031,12 @@ static void fd_stop(ErlDrvData fd) /* Does not close the fds */ { int ofd; - TRACE; - - nbio_stop_fd(driver_data[(int)(long)fd].port_num, driver_data[(int)(long)fd].in_sig_descr); + nbio_stop_fd(driver_data[(int)(long)fd].port_num, + driver_data[(int)(long)fd].in_sig_descr); ofd = driver_data[(int)(long)fd].ofd; if (ofd != (int)(long)fd && ofd != -1) - nbio_stop_fd(driver_data[(int)(long)fd].port_num, driver_data[(int)(long)fd].out_sig_descr); + nbio_stop_fd(driver_data[(int)(long)fd].port_num, + driver_data[(int)(long)fd].out_sig_descr); } /* Note that driver_data[fd].ifd == fd if the port was opened for reading, */ @@ -1086,8 +1047,6 @@ static void erl_stop(ErlDrvData fd) ErlDrvPort prt; int ofd; - TRACE; - prt = driver_data[(int)(long)fd].port_num; nbio_stop_fd(prt, driver_data[(int)(long)fd].in_sig_descr); @@ -1106,9 +1065,11 @@ static void erl_stop(ErlDrvData fd) /* SMP note: Close has to be last thing done (open file descriptors work as locks on driver_data[] entries) */ - driver_select(prt, driver_data[(int)(long)fd].in_sig_descr, ERL_DRV_USE, 0); /* close(fd); */ + driver_select(prt, driver_data[(int)(long)fd].in_sig_descr, + ERL_DRV_USE, 0); /* close(fd); */ if (ofd >= 0) { - driver_select(prt, driver_data[(int)(long)fd].out_sig_descr, ERL_DRV_USE, 0); /* close(ofd); */ + driver_select(prt, driver_data[(int)(long)fd].out_sig_descr, + ERL_DRV_USE, 0); /* close(ofd); */ } } @@ -1122,8 +1083,6 @@ static void outputv(ErlDrvData e, ErlIOVec* ev) char* lbp; ErlDrvSizeT len = ev->size; - TRACE; - /* (len > ((unsigned long)-1 >> (4-pb)*8)) */ /* if (pb >= 0 && (len & (((ErlDrvSizeT)1 << (pb*8))) - 1) != len) {*/ if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) { @@ -1150,7 +1109,8 @@ static void outputv(ErlDrvData e, ErlIOVec* ev) /* fprintf(stderr,"0x%x: outputv, enq+sel\n", current_process()); */ driver_enqv(ix, ev, 0); /* n is the skip value */ driver_pdl_unlock(driver_data[fd].pdl); - driver_select(ix, driver_data[fd].out_sig_descr, ERL_DRV_WRITE|ERL_DRV_USE, 1); + driver_select(ix, driver_data[fd].out_sig_descr, + ERL_DRV_WRITE|ERL_DRV_USE, 1); sig = alloc(sizeof(SysDriverAsyncSignal),ERTS_SIGNAL_FD_DRV_ASYNC); sig->sys_async.type = fd; sig->sys_async.res = pb+len; @@ -1173,8 +1133,6 @@ static void output(ErlDrvData e, char* buf, ErlDrvSizeT len) struct iovec iv[2]; #endif - TRACE; - /* (len > ((unsigned long)-1 >> (4-pb)*8)) */ if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) { driver_failure_posix(ix, EINVAL); @@ -1204,7 +1162,8 @@ static void output(ErlDrvData e, char* buf, ErlDrvSizeT len) driver_enq(ix, lbp, pb); driver_enq(ix, buf, len); driver_pdl_unlock(driver_data[fd].pdl); - driver_select(ix, driver_data[ofd].out_sig_descr, ERL_DRV_WRITE|ERL_DRV_USE, 1); + driver_select(ix, driver_data[ofd].out_sig_descr, + ERL_DRV_WRITE|ERL_DRV_USE, 1); sig = alloc(sizeof(SysDriverAsyncSignal),ERTS_SIGNAL_FD_DRV_ASYNC); sig->sys_async.type = fd; sig->sys_async.res = pb+len; @@ -1282,8 +1241,6 @@ static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd) int res; Uint h; - TRACE; - port_num = driver_data[fd].port_num; packet_bytes = driver_data[fd].packet_bytes; @@ -1331,7 +1288,7 @@ static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd) if ((errno != EINTR) && (errno != ERRNO_BLOCK)) port_inp_failure(port_num, ready_fd, res); } - else if (res == 0) { /* eof */ + else if (res == 0) { /* eof */ port_inp_failure(port_num, ready_fd, res); } else if (res < packet_bytes - fd_data[fd].psz) { @@ -1373,7 +1330,7 @@ static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd) continue; } else { /* The last message we got was split */ - char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h); + char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h); if (!buf) { errno = ENOMEM; port_inp_failure(port_num, ready_fd, -1); @@ -1676,8 +1633,6 @@ int fd; int c; unsigned char rbuf[64]; - TRACE; - fflush(stdout); /* Flush query ??? */ if ((c = read(fd,rbuf,64)) <= 0) { -- cgit v1.2.3 From 8103fed4090e9f1457fb1705e9a4df0821f5db9b Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 31 Oct 2013 14:40:33 +0100 Subject: ose,erts: Specify name for tsd keys This simplified debugging on OSE and also limits the number of ppdata keys that are created when beam is restarted. --- erts/emulator/sys/unix/sys_float.c | 2 +- erts/emulator/sys/win32/sys.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c index 689be98969..cafeab547e 100644 --- a/erts/emulator/sys/unix/sys_float.c +++ b/erts/emulator/sys/unix/sys_float.c @@ -46,7 +46,7 @@ static void erts_init_fp_exception(void) { /* XXX: the wrappers prevent using a pthread destructor to deallocate the key's value; so when/where do we do that? */ - erts_tsd_key_create(&fpe_key); + erts_tsd_key_create(&fpe_key,"fp_exception"); } void erts_thread_init_fp_exception(void) diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c index 5ea4703a7a..296da90c6c 100755 --- a/erts/emulator/sys/win32/sys.c +++ b/erts/emulator/sys/win32/sys.c @@ -3197,7 +3197,7 @@ void erl_sys_init(void) noinherit_std_handle(STD_ERROR_HANDLE); #ifdef ERTS_SMP - erts_smp_tsd_key_create(&win32_errstr_key); + erts_smp_tsd_key_create(&win32_errstr_key,"win32_errstr_key"); InitializeCriticalSection(&htbc_lock); #endif erts_smp_atomic_init_nob(&pipe_creation_counter,0); -- cgit v1.2.3 From 5352e800edf7e59d352a8d2dc7a7bee7ba916e1b Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Mon, 4 Nov 2013 13:36:37 +0100 Subject: ose: Use spinlock as default heap lock mechanism --- erts/emulator/sys/ose/default.lmconf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/default.lmconf b/erts/emulator/sys/ose/default.lmconf index 150111b1f6..6d3499df8f 100644 --- a/erts/emulator/sys/ose/default.lmconf +++ b/erts/emulator/sys/ose/default.lmconf @@ -10,4 +10,5 @@ OSE_LM_BSS_INIT=YES OSE_LM_EXEC_MODEL=SHARED HEAP_MAX_SIZE=1000000000 HEAP_SMALL_BUF_INIT_SIZE=64000000 -HEAP_LARGE_BUF_THRESHOLD=16000000 \ No newline at end of file +HEAP_LARGE_BUF_THRESHOLD=16000000 +HEAP_LOCK_TYPE=2 -- cgit v1.2.3 From 7d924d6c1279178db9c81fd04dd87c8d902a6549 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 12 Nov 2013 18:27:53 +0100 Subject: ose: Fix printout to stdout to not duplicate long buffers --- erts/emulator/sys/ose/sys.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index 6e55301d6e..ba8851e203 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -892,7 +892,7 @@ OS_PROCESS(fd_writer_process) { SysIOVec *iov; int iovlen; int iovcnt; - int n = 0, i; + int n = 0, i = 0, offset = 0; size_t p; /* fprintf(stderr,"0x%x: fd_writer, receive\n", current_process()); */ sig = receive(sigsel); @@ -913,12 +913,22 @@ OS_PROCESS(fd_writer_process) { driver_pdl_unlock(driver_data[fd].pdl); if (iovlen > 0) { - for (i = 0; i < iovcnt; i++) { - res = write(fd, iov[i].iov_base, - iov[i].iov_len > 256 ? 256 : iov[i].iov_len); + while(i < iovcnt) { + /* We only write 256 chars at the time in order to + not overflow the stdout process */ + if ((iov[i].iov_len-offset) > 256) { + res = write(fd, iov[i].iov_base+offset, 256); if (res < 0) break; - n += res; + offset += res; + } else { + res = write(fd, iov[i].iov_base+offset, iov[i].iov_len-offset); + if (res < 0) + break; + offset = 0; + i++; + } + n += res; } if (res > 0) res = n; -- cgit v1.2.3 From 2145db903b665622ea885db175c5e606d9f840a4 Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Fri, 22 Nov 2013 09:50:34 +0100 Subject: ose: OSE port related cleanup and fixes Some OSE cross-chains have problems with system includes being used, so for atleast OSE specific parts we use "" instead of <>. --- erts/emulator/sys/ose/sys.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index ba8851e203..a62d7c150b 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -20,29 +20,19 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#include "sys/time.h" +#include "time.h" +#include "sys/uio.h" +#include "termios.h" +#include "ctype.h" +#include "termios.h" -#ifdef ISC32 -#define _POSIX_SOURCE -#define _XOPEN_SOURCE -#endif - -#include -#include - -#include -#include -#include - -#ifdef ISC32 -#include -#endif - -#include #ifdef HAVE_FCNTL_H -#include +#include "fcntl.h" #endif + #ifdef HAVE_SYS_IOCTL_H -#include +#include "sys/ioctl.h" #endif #define ERTS_WANT_BREAK_HANDLING -- cgit v1.2.3 From 8080aa615ad9d82bfb7e2d9b92d45b9c81a95929 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 11 Dec 2013 17:17:56 +0100 Subject: ose: Update erl_assert_error after R16B03 api change --- erts/emulator/sys/ose/sys.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index a62d7c150b..b786d19ecf 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -1647,14 +1647,16 @@ int fd; extern int erts_initialized; void -erl_assert_error(char* expr, char* file, int line) +erl_assert_error(const char* expr, const char* func, + const char* file, int line) { fflush(stdout); - fprintf(stderr, "Assertion failed: %s in %s, line %d\n", - expr, file, line); + fprintf(stderr, "%s:%d:%s() Assertion failed: %s\n", + file, func, line, expr); fflush(stderr); - ramlog_printf("%d: Assertion failed: %s in %s, line %d\n", - current_process(), expr, file, line); + ramlog_printf("%s:%d:%s() Assertion failed: %s\n", + file, func, line, expr); + abort(); } -- cgit v1.2.3 From 809ee10f37bac29b3056f4fb09c072b951e29f0c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 14 Nov 2013 18:18:12 +0100 Subject: ose: Fix starting with pm_create For some reason starting with pm_create offsets the input argument list by one, so we have to adjust them before calling erl_start. --- erts/emulator/sys/ose/erl_main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/erl_main.c b/erts/emulator/sys/ose/erl_main.c index a17fc7eabc..03119c3fec 100644 --- a/erts/emulator/sys/ose/erl_main.c +++ b/erts/emulator/sys/ose/erl_main.c @@ -17,8 +17,16 @@ * %CopyrightEnd% */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include +#include "sys.h" +#include "erl_vm.h" +#include "global.h" +#include "ose.h" + int main(int argc, char **argv) { @@ -30,8 +38,8 @@ main(int argc, char **argv) { char **tmp_argv = malloc(sizeof(char*)*(argc+1)); for (i = 0; i < argc; i++) tmp_argv[i+1] = argv[i]; - tmp_argv = "beam"; - erl_start(argc,tmp_argv); + tmp_argv[0] = "beam"; + erl_start(argc+1,tmp_argv); free(tmp_argv); } else { erl_start(argc,argv); -- cgit v1.2.3 From c64851d619fb916362abc8db9c28534eff39f53c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 10 Jan 2014 17:17:58 +0100 Subject: ose: Rewrite resolve_signal API for ose drivers This new API has less impact on the check_io code and also removes the callback from ErlDrvEntry. The downside is that you have to give the resolve function when creating each event. Also the mode if the resolve was removed as this mimics the win32 code and decreases complexity. --- erts/emulator/sys/common/erl_check_io.c | 99 ++++----------------------- erts/emulator/sys/common/erl_poll.h | 20 +++++- erts/emulator/sys/ose/erl_ose_sys.h | 14 ---- erts/emulator/sys/ose/erl_poll.c | 116 ++++++++++++++++++++------------ erts/emulator/sys/ose/sys.c | 49 +++++++------- 5 files changed, 129 insertions(+), 169 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c index dab056e2df..245841a768 100644 --- a/erts/emulator/sys/common/erl_check_io.c +++ b/erts/emulator/sys/common/erl_check_io.c @@ -79,11 +79,7 @@ typedef char EventStateFlags; #define ERTS_CIO_POLL_INIT ERTS_POLL_EXPORT(erts_poll_init) #define ERTS_CIO_POLL_INFO ERTS_POLL_EXPORT(erts_poll_info) -#ifdef __OSE__ -#define GET_FD(fd) fd->id -#else #define GET_FD(fd) fd -#endif static struct pollset_info { @@ -442,11 +438,7 @@ deselect(ErtsDrvEventState *state, int mode) } } - state->events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, rm_events, 0, &do_wake -#ifdef __OSE__ - ,NULL -#endif - ); + state->events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, rm_events, 0, &do_wake); if (!(state->events)) { switch (state->type) { @@ -595,11 +587,7 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix, wake_poller = 1; } - new_events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, ctl_events, on, &wake_poller -#ifdef __OSE__ - ,prt->drv_ptr->resolve_signal -#endif - ); + new_events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, ctl_events, on, &wake_poller); if (new_events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL)) { if (state->type == ERTS_EV_TYPE_DRV_SEL && !state->events) { @@ -984,9 +972,6 @@ print_select_op(erts_dsprintf_buf_t *dsbufp, mode & ERL_DRV_WRITE ? " ERL_DRV_WRITE" : "", mode & ERL_DRV_USE ? " ERL_DRV_USE" : "", mode & (ERL_DRV_USE_NO_CALLBACK & ~ERL_DRV_USE) ? "_NO_CALLBACK" : "", -#ifdef __OSE__ - fd->signo, -#endif on); print_driver_name(dsbufp, pp != ERTS_INVALID_ERL_DRV_PORT ? pp->common.id : NIL); erts_dsprintf(dsbufp, "driver %T ", pp != ERTS_INVALID_ERL_DRV_PORT ? pp->common.id : NIL); @@ -1417,20 +1402,26 @@ stale_drv_select(Eterm id, ErtsDrvEventState *state, int mode) } #ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS + #ifdef __OSE__ static SafeHashValue drv_ev_state_hash(void *des) { - SafeHashValue val = (SafeHashValue) ((ErtsDrvEventState *) des)->fd; - return val ^ (val >> 8); /* Good enough for aligned pointer values? */ + ErtsSysFdType fd = ((ErtsDrvEventState *) des)->fd; + /* We use hash on signo ^ id in order for steal to happen when the + same signo + fd is selected on by two different ports */ + SafeHashValue val = (SafeHashValue)(fd->signo ^ fd->id); + return val ^ (val >> 8); } static int drv_ev_state_cmp(void *des1, void *des2) { - return ( ((((ErtsDrvEventState *) des1)->fd->id == ((ErtsDrvEventState *) des2)->fd->id) - && (((ErtsDrvEventState *) des1)->fd->signo == ((ErtsDrvEventState *) des2)->fd->signo)) - ? 0 : 1); + ErtsSysFdType fd1 = ((ErtsDrvEventState *) des1)->fd; + ErtsSysFdType fd2 = ((ErtsDrvEventState *) des2)->fd; + if (fd1->signo == fd2->signo && fd1->id == fd2->id) + return 0; + return 1; } -#else +#else /* !__OSE__ && !ERTS_SYS_CONTINOUS_FD_NUMBERS i.e. probably windows */ static SafeHashValue drv_ev_state_hash(void *des) { SafeHashValue val = (SafeHashValue) ((ErtsDrvEventState *) des)->fd; @@ -1473,69 +1464,7 @@ static void drv_ev_state_free(void *des) erts_smp_spin_unlock(&state_prealloc_lock); } #endif -#ifdef __OSE__ -OseSignal *erl_drv_ose_get_input_signal(ErlDrvEvent drv_ev) { - struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; - ethr_mutex_lock(&ev->mtx); - if (ev->imsgs == NULL) { - ethr_mutex_unlock(&ev->mtx); - return NULL; - } else { - ErtsPollOseMsgList *msg = ev->imsgs; - OseSignal *sig = (OseSignal*)msg->data; - ASSERT(msg->data); - ev->imsgs = msg->next; - ethr_mutex_unlock(&ev->mtx); - erts_free(ERTS_ALC_T_FD_SIG_LIST,msg); - restore(sig); - return sig; - } -} - -OseSignal *erl_drv_ose_get_output_signal(ErlDrvEvent drv_ev) { - struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; - ethr_mutex_lock(&ev->mtx); - if (ev->omsgs == NULL) { - ethr_mutex_unlock(&ev->mtx); - return NULL; - } else { - ErtsPollOseMsgList *msg = ev->omsgs; - OseSignal *sig = (OseSignal*)msg->data; - ASSERT(msg->data); - ev->omsgs = msg->next; - ethr_mutex_unlock(&ev->mtx); - erts_free(ERTS_ALC_T_FD_SIG_LIST,msg); - restore(sig); - return sig; - } -} -ErlDrvEvent erl_drv_ose_event_alloc(SIGSELECT signo, int id) { - struct erts_sys_fd_type *ev = erts_alloc(ERTS_ALC_T_DRV_EV, - sizeof(struct erts_sys_fd_type)); - ev->signo = signo; - ev->id = id; - ev->imsgs = NULL; - ev->omsgs = NULL; - ethr_mutex_init(&ev->mtx); - return (ErlDrvEvent)ev; -} - -void erl_drv_ose_event_free(ErlDrvEvent drv_ev) { - struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; - ethr_mutex_destroy(&ev->mtx); - erts_free(ERTS_ALC_T_DRV_EV,ev); -} - -void erl_drv_ose_event_fetch(ErlDrvEvent drv_ev, SIGSELECT *signo, int *id) { - struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; - if (signo) - *signo = ev->signo; - if (id) - *id = ev->id; -} - -#endif void ERTS_CIO_EXPORT(erts_init_check_io)(void) { diff --git a/erts/emulator/sys/common/erl_poll.h b/erts/emulator/sys/common/erl_poll.h index e1ea8fb207..ce8dcd3f90 100644 --- a/erts/emulator/sys/common/erl_poll.h +++ b/erts/emulator/sys/common/erl_poll.h @@ -106,6 +106,23 @@ typedef Uint32 ErtsPollEvents; #define ERTS_POLL_EV_ERR 4 #define ERTS_POLL_EV_NVAL 8 +#ifdef __OSE__ + +typedef struct ErtsPollOseMsgList_ { + struct ErtsPollOseMsgList_ *next; + union SIGNAL *data; +} ErtsPollOseMsgList; + +struct erts_sys_fd_type { + SIGSELECT signo; + ErlDrvOseEventId id; + ErtsPollOseMsgList *msgs; + ErlDrvOseEventId (*resolve_signal)(union SIGNAL *sig); + ethr_mutex mtx; +}; + +#endif + #elif ERTS_POLL_USE_EPOLL /* --- epoll ------------------------------- */ #include @@ -229,9 +246,6 @@ ErtsPollEvents ERTS_POLL_EXPORT(erts_poll_control)(ErtsPollSet, ErtsPollEvents, int on, int* wake_poller -#ifdef __OSE__ - ,int (*decode)(OseSignal* sig, int* mode) -#endif ); void ERTS_POLL_EXPORT(erts_poll_controlv)(ErtsPollSet, ErtsPollControlEntry [], diff --git a/erts/emulator/sys/ose/erl_ose_sys.h b/erts/emulator/sys/ose/erl_ose_sys.h index 8c72afa9a5..db8607b650 100644 --- a/erts/emulator/sys/ose/erl_ose_sys.h +++ b/erts/emulator/sys/ose/erl_ose_sys.h @@ -56,20 +56,6 @@ # include "sys/mman.h" #endif -typedef struct ErtsPollOseMsgList_ { - struct ErtsPollOseMsgList_ *next; - void *data; -} ErtsPollOseMsgList; - -struct erts_sys_fd_type { - SIGSELECT signo; - int id; - ErtsPollOseMsgList *imsgs; - ErtsPollOseMsgList *omsgs; - ethr_mutex mtx; -}; - - /* * Min number of async threads */ diff --git a/erts/emulator/sys/ose/erl_poll.c b/erts/emulator/sys/ose/erl_poll.c index b1e256afc3..78dc275c06 100644 --- a/erts/emulator/sys/ose/erl_poll.c +++ b/erts/emulator/sys/ose/erl_poll.c @@ -103,7 +103,7 @@ typedef struct erts_sigsel_info_ ErtsSigSelInfo; struct erts_sigsel_info_ { ErtsSigSelInfo *next; SIGSELECT signo; - int (*decode)(OseSignal* sig, int* mode); + ErlDrvOseEventId (*decode)(union SIGNAL* sig); ErtsSigSelItem *fds; }; @@ -131,8 +131,10 @@ static int max_fds = -1; /* signal list prototypes */ static ErtsSigSelInfo *get_sigsel_info(ErtsPollSet ps, SIGSELECT signo); static ErtsSigSelItem *get_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd); -static ErtsSigSelInfo *add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd, int (*decode)(OseSignal* sig, int* mode)); -static ErtsSigSelItem *add_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd, int (*decode)(OseSignal* sig, int* mode)); +static ErtsSigSelInfo *add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd, + ErlDrvOseEventId (*decode)(union SIGNAL* sig)); +static ErtsSigSelItem *add_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd, + ErlDrvOseEventId (*decode)(union SIGNAL* sig)); static int del_sigsel_info(ErtsPollSet ps, ErtsSigSelInfo *info); static int del_sigsel_item(ErtsPollSet ps, ErtsSigSelItem *item); static int update_sigsel(ErtsPollSet ps); @@ -170,7 +172,7 @@ get_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd) { static ErtsSigSelInfo * add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd, - int (*decode)(OseSignal* sig, int* mode)) { + ErlDrvOseEventId (*decode)(union SIGNAL* sig)) { ErtsSigSelInfo *info = SEL_ALLOC(ERTS_ALC_T_POLLSET, sizeof(ErtsSigSelInfo)); info->next = ps->info; @@ -184,7 +186,7 @@ add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd, static ErtsSigSelItem * add_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd, - int (*decode)(OseSignal* sig, int* mode)) { + ErlDrvOseEventId (*decode)(union SIGNAL* sig)) { ErtsSigSelInfo *info = get_sigsel_info(ps,fd->signo); ErtsSigSelItem *item = SEL_ALLOC(ERTS_ALC_T_POLLSET, sizeof(ErtsSigSelItem)); @@ -394,8 +396,7 @@ void erts_poll_interrupt_timed(ErtsPollSet ps,int set,erts_short_time_t msec) { } ErtsPollEvents erts_poll_control(ErtsPollSet ps, ErtsSysFdType fd, - ErtsPollEvents pe, int on, int* do_wake, - int(*decode)(OseSignal* sig, int* mode)) { + ErtsPollEvents pe, int on, int* do_wake) { ErtsSigSelItem *curr; ErtsPollEvents new_events; int old_sig_count; @@ -406,11 +407,17 @@ ErtsPollEvents erts_poll_control(ErtsPollSet ps, ErtsSysFdType fd, ERTS_POLLSET_LOCK(ps); + if (on && (pe & ERTS_POLL_EV_IN) && (pe & ERTS_POLL_EV_OUT)) { + /* Check to make sure both in and out are not used at the same time */ + new_events = ERTS_POLL_EV_NVAL; + goto done; + } + curr = get_sigsel_item(ps, fd); old_sig_count = ps->sig_count; if (curr == NULL && on) { - curr = add_sigsel_item(ps, fd, decode); + curr = add_sigsel_item(ps, fd, fd->resolve_signal); } else if (curr == NULL && !on) { new_events = ERTS_POLL_EV_NVAL; goto done; @@ -451,7 +458,7 @@ int erts_poll_wait(ErtsPollSet ps, SysTimeval *utvp) { int res = ETIMEDOUT, no_fds, currid = 0; OSTIME timeout; - OseSignal *sig; + union SIGNAL *sig; // HARDTRACEF("%ux: In erts_poll_wait",ps); if (ps->interrupt == (PROCESS)0) ps->interrupt = current_process(); @@ -515,8 +522,7 @@ int erts_poll_wait(ErtsPollSet ps, } { ErtsSigSelInfo *info = get_sigsel_info(ps, sig->sig_no); - int mode = -1; - struct erts_sys_fd_type fd = { sig->sig_no, info->decode(sig, &mode) }; + struct erts_sys_fd_type fd = { sig->sig_no, info->decode(sig) }; ErtsSigSelItem *item = get_sigsel_item(ps, &fd); ASSERT(sig); @@ -546,38 +552,16 @@ int erts_poll_wait(ErtsPollSet ps, erts_send_error_to_logger_nogl(dsbufp); timeout = 0; ASSERT(0); - } else if (mode == -1 && item->events == (ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) { - erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); - erts_dsprintf( - dsbufp, - "erts_poll_wait() failed: found ambigous signal id %d (signo %u) " - "(curr_proc 0x%x /sender 0x%x)\n You have to give a specify a mode " - "in the resolve_signal callback for this signal.\n", - fd.id, fd.signo, current_process(), sender(&sig)); - erts_send_error_to_logger_nogl(dsbufp); - timeout = 0; - ASSERT(0); - } else { + } else { int i; struct erts_sys_fd_type *fd = NULL; ErtsPollOseMsgList *tl,*new; - /* Figure out which mode to set and which queue to store - the signal in */ - if (mode == -1) - mode = item->events; - else if (mode == 0) - mode = ERTS_POLL_EV_IN; - else if (mode == 1) - mode = ERTS_POLL_EV_OUT; - else - abort(); - /* Check if this fd has already been triggered by a previous signal */ for (i = 0; i < currid;i++) { if (pr[i].fd == item->fd) { fd = pr[i].fd; - pr[i].events |= mode; + pr[i].events |= item->events; break; } } @@ -585,7 +569,7 @@ int erts_poll_wait(ErtsPollSet ps, /* First time this fd is triggered */ if (fd == NULL) { pr[currid].fd = item->fd; - pr[currid].events = mode; + pr[currid].events = item->events; fd = item->fd; timeout = 0; currid++; @@ -597,16 +581,10 @@ int erts_poll_wait(ErtsPollSet ps, new->data = sig; ethr_mutex_lock(&fd->mtx); - if (mode & ERTS_POLL_EV_IN) - tl = fd->imsgs; - else if (mode & ERTS_POLL_EV_OUT) - tl = fd->omsgs; + tl = fd->msgs; if (tl == NULL) { - if (mode & ERTS_POLL_EV_IN) - fd->imsgs = new; - else if (mode & ERTS_POLL_EV_OUT) - fd->omsgs = new; + fd->msgs = new; } else { while (tl->next != NULL) tl = tl->next; @@ -742,3 +720,53 @@ void erts_poll_init(void) HARDTRACEF("Out %s", __FUNCTION__); } + + +/* OSE driver functions */ + +union SIGNAL *erl_drv_ose_get_signal(ErlDrvEvent drv_ev) { + struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; + ethr_mutex_lock(&ev->mtx); + if (ev->msgs == NULL) { + ethr_mutex_unlock(&ev->mtx); + return NULL; + } else { + ErtsPollOseMsgList *msg = ev->msgs; + union SIGNAL *sig = (union SIGNAL*)msg->data; + ASSERT(msg->data); + ev->msgs = msg->next; + ethr_mutex_unlock(&ev->mtx); + erts_free(ERTS_ALC_T_FD_SIG_LIST,msg); + restore(sig); + return sig; + } +} + +ErlDrvEvent +erl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id, + ErlDrvOseEventId (*resolve_signal)(union SIGNAL *sig)) { + struct erts_sys_fd_type *ev = erts_alloc(ERTS_ALC_T_DRV_EV, + sizeof(struct erts_sys_fd_type)); + ev->signo = signo; + ev->id = id; + ev->msgs = NULL; + ev->resolve_signal = resolve_signal; + ethr_mutex_init(&ev->mtx); + return (ErlDrvEvent)ev; +} + +void erl_drv_ose_event_free(ErlDrvEvent drv_ev) { + struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; + ASSERT(ev->msgs == NULL); + ethr_mutex_destroy(&ev->mtx); + erts_free(ERTS_ALC_T_DRV_EV,ev); +} + +void erl_drv_ose_event_fetch(ErlDrvEvent drv_ev, SIGSELECT *signo, + ErlDrvOseEventId *id) { + struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; + if (signo) + *signo = ev->signo; + if (id) + *id = ev->id; +} diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index b786d19ecf..ad82e4587d 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -576,7 +576,7 @@ static void ready_output(ErlDrvData, ErlDrvEvent); static void output(ErlDrvData, char*, ErlDrvSizeT); static void outputv(ErlDrvData, ErlIOVec*); static void stop_select(ErlDrvEvent, void*); -static int resolve_signal(OseSignal* sig, int *mode) { +static ErlDrvOseEventId resolve_signal(union SIGNAL* sig) { return sig->sig_no == ERTS_SIGNAL_FD_DRV_ASYNC ? sig->sys_async.type : -1; } @@ -605,8 +605,7 @@ struct erl_drv_entry spawn_driver_entry = { ERL_DRV_EXTENDED_MINOR_VERSION, ERL_DRV_FLAG_USE_PORT_LOCKING, NULL, NULL, - stop_select, - resolve_signal + stop_select }; struct erl_drv_entry fd_driver_entry = { NULL, @@ -631,8 +630,7 @@ struct erl_drv_entry fd_driver_entry = { 0, /* ERL_DRV_FLAGs */ NULL, /* handle2 */ NULL, /* process_exit */ - stop_select, - resolve_signal + stop_select }; static int set_driver_data(ErlDrvPort port_num, @@ -645,7 +643,7 @@ static int set_driver_data(ErlDrvPort port_num, { Port *prt; ErtsSysReportExit *report_exit; - OseSignal *sig; + union SIGNAL *sig; /*erts_fprintf(stderr, " %s / pid %x / ofd %d / ifd %d\n", __FUNCTION__, current_process(), ofd, ifd);*/ @@ -664,10 +662,12 @@ static int set_driver_data(ErlDrvPort port_num, if (read_write & DO_READ) report_exit->in_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ifd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ifd, + resolve_signal); if (read_write & DO_WRITE) report_exit->out_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ofd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ofd, + resolve_signal); report_exit_list = report_exit; } @@ -684,7 +684,8 @@ static int set_driver_data(ErlDrvPort port_num, driver_data[ifd].alive = 1; driver_data[ifd].status = 0; driver_data[ifd].in_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ifd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ifd, + resolve_signal); driver_data[ifd].in_proc = create_process(OS_PRI_PROC,"beam_fd_reader", fd_reader_process, 0x800, @@ -700,7 +701,8 @@ static int set_driver_data(ErlDrvPort port_num, if (read_write & DO_WRITE) { driver_data[ifd].ofd = ofd; driver_data[ifd].out_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd, + resolve_signal); driver_data[ifd].pdl = driver_pdl_create(port_num); driver_data[ifd].out_proc = create_process(OS_PRI_PROC,"beam_fd_writer", @@ -729,7 +731,8 @@ static int set_driver_data(ErlDrvPort port_num, driver_data[ofd].alive = 1; driver_data[ofd].status = 0; driver_data[ofd].in_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd, + resolve_signal); driver_data[ofd].out_sig_descr = driver_data[ofd].in_sig_descr; driver_data[ofd].out_proc = create_process(OS_PRI_PROC, "beam_fd_writer", @@ -783,7 +786,7 @@ static ErlDrvData spawn_start(ErlDrvPort port_num, } OS_PROCESS(fd_reader_process) { - OseSignal *sig; + union SIGNAL *sig; PROCESS parent; int fd; byte *read_buf; @@ -844,7 +847,7 @@ OS_PROCESS(fd_reader_process) { } OS_PROCESS(fd_writer_process) { - OseSignal *sig; + union SIGNAL *sig; PROCESS parent; int fd; SIGSELECT sigsel[] = { 1, ERTS_SIGNAL_FD_DRV_CONFIG, @@ -1105,7 +1108,7 @@ static void outputv(ErlDrvData e, ErlIOVec* ev) driver_pdl_unlock(driver_data[fd].pdl); } else { - OseSignal *sig; + union SIGNAL *sig; /* fprintf(stderr,"0x%x: outputv, enq+sel\n", current_process()); */ driver_enqv(ix, ev, 0); /* n is the skip value */ driver_pdl_unlock(driver_data[fd].pdl); @@ -1151,7 +1154,7 @@ static void output(ErlDrvData e, char* buf, ErlDrvSizeT len) set_busy_port(ix, 1); } else { - OseSignal *sig; + union SIGNAL *sig; /* fprintf(stderr,"0x%x: output, enq+select\n", current_process()); */ #if 0 iv[0].iov_base = lbp; @@ -1219,13 +1222,13 @@ static int port_inp_failure(ErlDrvPort port_num, ErlDrvEvent ready_fd, int res) } static int async_read(ErlDrvEvent fd, byte *buff, int size) { - OseSignal *sigptr = erl_drv_ose_get_input_signal(fd); + union SIGNAL *sigptr = erl_drv_ose_get_signal(fd); int res = sigptr->sys_async.res; if (res > 0) memcpy(buff,sigptr->sys_async.buff,sigptr->sys_async.res); errno = sigptr->sys_async.errno_copy; send(&sigptr,sender(&sigptr)); - ASSERT(erl_drv_ose_get_input_signal(fd) == NULL); + ASSERT(erl_drv_ose_get_signal(fd) == NULL); return res; } @@ -1360,7 +1363,7 @@ static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) { int fd = (int)(long)e; ErlDrvPort ix = driver_data[fd].port_num; - OseSignal *sigptr = erl_drv_ose_get_output_signal(ready_fd); + union SIGNAL *sigptr = erl_drv_ose_get_signal(ready_fd); ssize_t n; struct iovec* iv; int vsize; @@ -1374,7 +1377,7 @@ static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) driver_select(ix, ready_fd, ERL_DRV_WRITE, 0); set_busy_port(ix, 0); free_buf(&sigptr); - if ((sigptr = erl_drv_ose_get_output_signal(ready_fd)) == NULL) + if ((sigptr = erl_drv_ose_get_signal(ready_fd)) == NULL) return; /* 0; */ continue; } @@ -1384,7 +1387,7 @@ static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) if (errno == ERRNO_BLOCK || errno == EINTR) { /* fprintf(stderr,"0x%x: ready_output, send to %x\n", current_process(),driver_data[fd].out_proc);*/ send(&sigptr,driver_data[fd].out_proc); - if ((sigptr = erl_drv_ose_get_output_signal(ready_fd)) == NULL) + if ((sigptr = erl_drv_ose_get_signal(ready_fd)) == NULL) return; /* 0; */ continue; } else { @@ -1393,7 +1396,7 @@ static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) free_buf(&sigptr); driver_select(ix, ready_fd, ERL_DRV_WRITE, 0); driver_failure_posix(ix, res); - if ((sigptr = erl_drv_ose_get_output_signal(ready_fd)) == NULL) + if ((sigptr = erl_drv_ose_get_signal(ready_fd)) == NULL) return; /* -1; */ continue; } @@ -1410,7 +1413,7 @@ static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) else continue; } - sigptr = erl_drv_ose_get_output_signal(ready_fd); + sigptr = erl_drv_ose_get_signal(ready_fd); } return; /* 0; */ } @@ -1752,7 +1755,7 @@ erts_sys_main_thread(void) while (1) { static const SIGSELECT sigsel[] = {0}; - OseSignal *msg = receive(sigsel); + union SIGNAL *msg = receive(sigsel); fprintf(stderr,"Main thread got message %d from 0x%x!!\r\n", msg->sig_no, sender(&msg)); -- cgit v1.2.3 From 5c299e355e05a464215e49cfd95f62b5194de609 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 8 Jan 2014 11:35:29 +0100 Subject: ose: Port run_erl and to_erl --- erts/emulator/sys/ose/erts.sig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/erts.sig b/erts/emulator/sys/ose/erts.sig index 95c12652f2..78b883ee6c 100644 --- a/erts/emulator/sys/ose/erts.sig +++ b/erts/emulator/sys/ose/erts.sig @@ -11,4 +11,7 @@ #define ERTS_SIGNAL_OSE_DRV_ATTACH ERTS_OSE_SIGNAL_BASE+3 #define ERTS_SIGNAL_OSE_DRV_HUNT ERTS_OSE_SIGNAL_BASE+4 +#define ERTS_SIGNAL_RUN_ERL_SETUP ERTS_OSE_SIGNAL_BASE+100 +#define ERTS_SIGNAL_RUN_ERL_DAEMON ERTS_OSE_SIGNAL_BASE+101 + #endif -- cgit v1.2.3 From ff463a10f37ca74c0b6a8c0e24ce919e56b12bb8 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 29 Jan 2014 14:38:56 +0100 Subject: ose: Add fair scheduling yields This is needed on OSs that do not do round robin scheduling of threads. --- erts/emulator/sys/ose/erl_ose_sys.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/erl_ose_sys.h b/erts/emulator/sys/ose/erl_ose_sys.h index db8607b650..cd66d95c26 100644 --- a/erts/emulator/sys/ose/erl_ose_sys.h +++ b/erts/emulator/sys/ose/erl_ose_sys.h @@ -41,8 +41,9 @@ #include "ethread.h" /* FIXME: configuration options */ -#define ERTS_SCHED_MIN_SPIN -#define ERTS_SCHED_ONLY_POLL_SCHED_1 +#define ERTS_SCHED_MIN_SPIN 1 +#define ERTS_SCHED_ONLY_POLL_SCHED_1 1 +#define ERTS_SCHED_FAIR 1 #define NO_SYSCONF 1 #define OPEN_MAX FOPEN_MAX -- cgit v1.2.3 From e48c536be1b21711e6e4b16bd8a9b74cf2aa019b Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 30 Jan 2014 18:47:52 +0100 Subject: ose: Update ddll interface after rebase to 17.0-rc1 Also deleted all the copy-paste stuff --- erts/emulator/sys/ose/erl_ose_sys_ddll.c | 77 ++------------------------------ 1 file changed, 3 insertions(+), 74 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/erl_ose_sys_ddll.c b/erts/emulator/sys/ose/erl_ose_sys_ddll.c index 4121199096..ebd80deeaf 100644 --- a/erts/emulator/sys/ose/erl_ose_sys_ddll.c +++ b/erts/emulator/sys/ose/erl_ose_sys_ddll.c @@ -19,7 +19,7 @@ /* * Interface functions to the dynamic linker using dl* functions. - * (As far as I know it works on SunOS 4, 5, Linux and FreeBSD. /Seb) + * (No support in OSE, we use static linkage instead) */ #ifdef HAVE_CONFIG_H @@ -29,68 +29,15 @@ #include "sys.h" #include "erl_vm.h" #include "global.h" -#ifdef HAVE_DLFCN_H -#include -#endif - - -/* some systems do not have RTLD_NOW defined, and require the "mode" - * argument to dload() always be 1. - */ -#ifndef RTLD_NOW -# define RTLD_NOW 1 -#endif - -#define MAX_NAME_LEN 255 /* XXX should we get the system path size? */ -#define EXT_LEN 3 -#define FILE_EXT ".so" /* extension appended to the filename */ - -static char **errcodes = NULL; -static int num_errcodes = 0; -static int num_errcodes_allocated = 0; - -#define my_strdup(WHAT) my_strdup_in(ERTS_ALC_T_DDLL_ERRCODES, WHAT); - -static char *my_strdup_in(ErtsAlcType_t type, char *what) -{ - char *res = erts_alloc(type, strlen(what) + 1); - strcpy(res, what); - return res; -} -static int find_errcode(char *string, ErtsSysDdllError* err) -{ - int i; - - if (err != NULL) { - erts_sys_ddll_free_error(err); /* in case we ignored an earlier error */ - err->str = my_strdup_in(ERTS_ALC_T_DDLL_TMP_BUF, string); - return 0; - } - for(i=0;i ERL_DE_DYNAMIC_ERROR_OFFSET) { - return "Unspecified error"; - } - actual_code = -1*(code - ERL_DE_DYNAMIC_ERROR_OFFSET); -#if defined(HAVE_DLOPEN) - { - char *msg; - - if (actual_code >= num_errcodes) { - msg = "Unknown dlload error"; - } else { - msg = errcodes[actual_code]; - } - return msg; - } -#endif - return "no error"; + return "Unspecified error"; } void erts_sys_ddll_free_error(ErtsSysDdllError* err) -- cgit v1.2.3 From b16f213791509f4de13215a83e68208128522520 Mon Sep 17 00:00:00 2001 From: Robert Paal Date: Tue, 18 Feb 2014 11:27:12 +0100 Subject: ose: Eliminating delays when trying to open files When opening filers on not mounted volumes the default timeout on OSE is quite big and since at startup we load something like 20 beam files this slows down startup by as much as 50 seconds. --- erts/emulator/sys/ose/default.lmconf | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/default.lmconf b/erts/emulator/sys/ose/default.lmconf index 6d3499df8f..17b7a1e5fa 100644 --- a/erts/emulator/sys/ose/default.lmconf +++ b/erts/emulator/sys/ose/default.lmconf @@ -12,3 +12,8 @@ HEAP_MAX_SIZE=1000000000 HEAP_SMALL_BUF_INIT_SIZE=64000000 HEAP_LARGE_BUF_THRESHOLD=16000000 HEAP_LOCK_TYPE=2 + +# Setting the environment variable EFS_RESOLVE_TMO on the block to 0. +# This will eliminiate delays when trying to open files on not mounted +# volumes. +EFS_RESOLVE_TMO=0 -- cgit v1.2.3 From 15350e561e8a8feca4a8073ec9db68fa92ed976f Mon Sep 17 00:00:00 2001 From: Robert Paal Date: Tue, 18 Feb 2014 15:55:04 +0100 Subject: ose: Added Enea copyright header to lcf files. Also removed softkernel lcf files. --- erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf | 31 ++++ erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf | 33 +++- erts/emulator/sys/ose/gcc_lm.lcf | 146 --------------- erts/emulator/sys/ose/gcc_lm_x86_4.4.3.lcf | 277 ----------------------------- erts/emulator/sys/ose/gcc_lm_x86_4.6.3.lcf | 252 -------------------------- 5 files changed, 59 insertions(+), 680 deletions(-) delete mode 100644 erts/emulator/sys/ose/gcc_lm.lcf delete mode 100644 erts/emulator/sys/ose/gcc_lm_x86_4.4.3.lcf delete mode 100644 erts/emulator/sys/ose/gcc_lm_x86_4.6.3.lcf (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf b/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf index 5ebc328616..a19d23facf 100644 --- a/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf +++ b/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf @@ -1,3 +1,34 @@ +/******************************************************************************* + * Copyright (C) 2013-2014 by Enea Software AB, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") OUTPUT_ARCH("powerpc") ENTRY("crt0_lm") diff --git a/erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf b/erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf index a2399c93da..3440c2961b 100644 --- a/erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf +++ b/erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf @@ -1,9 +1,32 @@ /******************************************************************************* - * gcc_lm_ppc.lcf: GCC linker control file for PowerPC load modules - * @(#) $FilePath: /vobs/ose5/system/refsys/compilers/gcc_lm_ppc.lcf $ - * @(#) $FileRevision: /main/tb_current_ose5/10 $ - * $Author: joka $$Date: 01/21/13 16:35:41 $ - * $Copyright: (C) 2006 by Enea AB. All rights reserved. $ + * Copyright (C) 2013-2014 by Enea Software AB, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") diff --git a/erts/emulator/sys/ose/gcc_lm.lcf b/erts/emulator/sys/ose/gcc_lm.lcf deleted file mode 100644 index 42b6f89851..0000000000 --- a/erts/emulator/sys/ose/gcc_lm.lcf +++ /dev/null @@ -1,146 +0,0 @@ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -OUTPUT_ARCH("i386") -ENTRY("crt0_lm") -MEMORY -{ - rom : ORIGIN = 0x01000000, LENGTH = 0x01000000 - ram : ORIGIN = 0x02000000, LENGTH = 0x01000000 -} -PHDRS -{ - ph_conf PT_LOAD ; - ph_rom PT_LOAD ; - ph_ram PT_LOAD ; -} -SECTIONS -{ - .text : - { - *(.text_first) - *(.text) - *(.text.*) - *(.stub) - *(oscode) - *(.init*) - *(.fini*) - *(.gnu.warning) - *(.gnu.linkonce.t.*) - *(.glue_7t) - *(.glue_7) - } > rom :ph_rom = 0 - .ose_sfk_biosentry : - { - *(.ose_sfk_biosentry) - } > rom :ph_rom - .ctors : - { - __CTOR_LIST__ = .; - *(.ctors) - *(SORT(.ctors.*)) - __CTOR_END__ = .; - } > rom :ph_rom - .dtors : - { - __DTOR_LIST__ = .; - *(.dtors) - *(SORT(.dtors.*)) - __DTOR_END__ = .; - } > rom :ph_rom - OSESYMS : - { - *(.osesyms) - } > rom :ph_rom - .rodata : - { - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - } > rom :ph_rom - .eh_frame : - { - __EH_FRAME_BEGIN__ = .; - *(.eh_frame) - LONG(0) - __EH_FRAME_END__ = .; - } > rom :ph_rom - .gcc_except_table : - { - *(.gcc_except_table) - } > rom :ph_rom - .sdata2 : - { - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - } > rom :ph_rom - .sbss2 : - { - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - } > rom :ph_rom - LMCONF : - { - obj/?*?/ose_confd.o(.rodata) - *(LMCONF) - } > rom :ph_conf - .data : - { - LONG(0xDEADBABE) - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - . = ALIGN(0x10); - } > ram :ph_ram = 0 - .sdata2 : - { - _SDA2_BASE_ = .; - *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) - }> ram :ph_ram - .sdata : - { - _SDA_BASE_ = .; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - } > ram :ph_ram - .sbss : - { - *(.sbss) - *(.sbss.*) - *(.scommon) - *(.gnu.linkonce.sb.*) - } > ram :ph_ram - .bss (NOLOAD) : - { - *(.bss) - *(.bss.*) - *(COMMON) - *(.gnu.linkonce.b.*) - *(.osvars) - } > ram :ph_ram - .ignore (NOLOAD) : - { - *(.rel.dyn) - } > ram :ph_ram - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } -} -__OSESYMS_START = ADDR(OSESYMS); -__OSESYMS_END = ADDR(OSESYMS) + SIZEOF(OSESYMS); diff --git a/erts/emulator/sys/ose/gcc_lm_x86_4.4.3.lcf b/erts/emulator/sys/ose/gcc_lm_x86_4.4.3.lcf deleted file mode 100644 index d64fd91604..0000000000 --- a/erts/emulator/sys/ose/gcc_lm_x86_4.4.3.lcf +++ /dev/null @@ -1,277 +0,0 @@ -/* COPYRIGHT-ENEA-EXAMPLE-R2 * -************************************************************************** -* Copyright (C) 2010 by Enea Software AB. -* All rights reserved. -* -* This Example is furnished under a Software License Agreement and -* may be used only in accordance with the terms of such agreement. -* No title to and ownership of the Example is hereby transferred. -* -* The information in this Example is subject to change -* without notice and should not be construed as a commitment -* by Enea Software AB. -* -* DISCLAIMER -* This Example is delivered "AS IS", consequently -* Enea Software AB makes no representations or warranties, -* expressed or implied, for the Example. -************************************************************************** -* COPYRIGHT-END */ - -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -OUTPUT_ARCH("i386") - -ENTRY("crt0_lm") - -MEMORY -{ - rom : ORIGIN = 0x01000000, LENGTH = 0x01000000 - ram : ORIGIN = 0x02000000, LENGTH = 0x01000000 -} - -PHDRS -{ - ph_conf PT_LOAD ; - ph_rom PT_LOAD ; - ph_ram PT_LOAD ; -} - -SECTIONS -{ -/*--------------------------------------------------------------------------- - * Read-only area - *-------------------------------------------------------------------------*/ - - /* Code section. */ - .text : - { - *(.text_first) - *(.text) - *(.text.*) - *(.stub) - *(oscode) - *(.init*) - *(.fini*) - *(.gnu.warning) - *(.gnu.linkonce.t.*) - *(.glue_7t) - *(.glue_7) - } > rom :ph_rom = 0 - - - .ose_sfk_biosentry : - { - *(.ose_sfk_biosentry) - } > rom :ph_rom - - /* C++ constructor section. */ - .ctors : - { - __CTOR_LIST__ = .; - *(.ctors) - *(SORT(.ctors.*)) - __CTOR_END__ = .; - } > rom :ph_rom - - /* C++ destructor section. */ - .dtors : - { - __DTOR_LIST__ = .; - *(.dtors) - *(SORT(.dtors.*)) - __DTOR_END__ = .; - } > rom :ph_rom - - /* OSE symbols section. */ - OSESYMS : - { - *(.osesyms) - } > rom :ph_rom - - .plt : - { - *(.plt) - *(.iplt) - } > rom :ph_rom - - - /* Read-only data section. */ - .rodata : - { - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - } > rom :ph_rom - - /* C++ exception handling section. */ - .eh_frame : - { - __EH_FRAME_BEGIN__ = .; - *(.eh_frame) - LONG(0) - __EH_FRAME_END__ = .; - } > rom :ph_rom - - /* C++ exception handling section. */ - .gcc_except_table : - { - *(.gcc_except_table) - } > rom :ph_rom - - /* PowerPC EABI initialized read-only data section. */ - .sdata2 : - { - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - } > rom :ph_rom - - /* PowerPC EABI uninitialized read-only data section. */ - .sbss2 : - { - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - } > rom :ph_rom - - /* Dynamic relocations */ - .rel.dyn : - { - *(.rel.init) - *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) - *(.rel.fini) - *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) - *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) - *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) - *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) - *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) - *(.rel.ctors) - *(.rel.dtors) - *(.rel.got) - *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) - *(.rel.ifunc) - } > rom :ph_rom - -/*--------------------------------------------------------------------------- - * Load module configuration area - *-------------------------------------------------------------------------*/ - - /* Load module configuration section. */ - LMCONF : - { - obj/?*?/ose_confd.o(.rodata) - *(LMCONF) - } > rom :ph_conf - - -/*--------------------------------------------------------------------------- - * Read-write area - *-------------------------------------------------------------------------*/ - - /*------------------------------------------------------------------- - * Initialized data (copied by PM ) - *-----------------------------------------------------------------*/ - - /* Data section. */ - .data : - { - LONG(0xDEADBABE) - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - . = ALIGN(0x10); - } > ram :ph_ram = 0 - - .got : - { - *(.got.plt) - *(.got) - } > rom :ph_ram - - /* Global offset table for dynamically linked procedures. */ - .got.plt : - { - *(.got.plt) - *(.igot.plt) - } > rom :ph_ram - - /* Small data section. */ - .sdata2 : - { - _SDA2_BASE_ = .; - *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) - }> ram :ph_ram - .sdata : - { - _SDA_BASE_ = .; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - } > ram :ph_ram - - /*------------------------------------------------------------------- - * Uninitialized data (cleared by PM ) - *-----------------------------------------------------------------*/ - - /* Small bss section. */ - .sbss : - { - *(.sbss) - *(.sbss.*) - *(.scommon) - *(.gnu.linkonce.sb.*) - } > ram :ph_ram - - /* Bss section. */ - .bss (NOLOAD) : - { - *(.bss) - *(.bss.*) - *(COMMON) - *(.gnu.linkonce.b.*) - *(.osvars) - } > ram :ph_ram - - /* Ignore unwanted sections that are not used in OSE. */ - .ignore (NOLOAD) : - { - *(.rel.dyn) - } > ram :ph_ram - -/*--------------------------------------------------------------------------- - * Debug information - *-------------------------------------------------------------------------*/ - - /* - * DWARF debug sections. - */ - - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - -} - -/* Symbols used by DDA. */ -__OSESYMS_START = ADDR(OSESYMS); -__OSESYMS_END = ADDR(OSESYMS) + SIZEOF(OSESYMS); diff --git a/erts/emulator/sys/ose/gcc_lm_x86_4.6.3.lcf b/erts/emulator/sys/ose/gcc_lm_x86_4.6.3.lcf deleted file mode 100644 index bb357afcb1..0000000000 --- a/erts/emulator/sys/ose/gcc_lm_x86_4.6.3.lcf +++ /dev/null @@ -1,252 +0,0 @@ -/******************************************************************************* - * gcc_lm_x86.lcf: GCC linker control file for x86 load modules - * @(#) $FilePath: /vobs/ose5/system/refsys/compilers/gcc_lm_x86.lcf $ - * @(#) $FileRevision: /main/tb_current_ose5/9 $ - * $Author: rand $$Date: 10/29/12 17:45:04 $ - * $Copyright: (C) 2006 by Enea AB. All rights reserved. $ - ******************************************************************************/ - -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -OUTPUT_ARCH("i386") - -ENTRY("crt0_lm") - -/* Note: - * You may have to increase the length of the "rom" memory region below - * depending on the size of the code and data in your load module. - */ - -MEMORY -{ - conf : ORIGIN = 0x00300000, LENGTH = 0x00001000 - rom : ORIGIN = 0x00000000, LENGTH = 0x00300000 -} - -PHDRS -{ - ph_conf PT_LOAD ; - ph_rom PT_LOAD ; - ph_ram PT_LOAD ; -} - -SECTIONS -{ -/*--------------------------------------------------------------------------- - * Load module configuration area - *-------------------------------------------------------------------------*/ - - /* Load module configuration section. */ - LMCONF : - { - dummy = ALIGN(0x10000); - */?*?/*ose_confd.o(LMCONF*) - *(LMCONF*) - *ose_confd.o(.rodata) - } > conf :ph_conf - -/*--------------------------------------------------------------------------- - * Read-only area - *-------------------------------------------------------------------------*/ - - /* Init section. */ - .init : - { - KEEP(*(.init)) - } > rom :ph_rom = 0x90909090 - - /* Code section. */ - .text : - { - *(.text) - *(.text.*) - *(.stub) - *(oscode) - *(.init*) - *(.fini*) - *(.gnu.warning) - *(.gnu.linkonce.t.*) - } > rom :ph_rom = 0 - - /* Read-only data section. */ - .rodata : - { - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - } > rom :ph_rom - - /* OSE symbols section. */ - OSESYMS : - { - *(.osesyms) - } > rom :ph_rom - - /* Procedure linkage table section. */ - .plt : - { - *(.plt) - *(.iplt) - } > rom :ph_rom - - /* Dynamic relocations */ - .rel.dyn : - { - *(.rel.init) - *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) - *(.rel.fini) - *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) - *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) - *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) - *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) - *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) - *(.rel.ctors) - *(.rel.dtors) - *(.rel.got) - *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) - *(.rel.ifunc) - } > rom :ph_rom - -/*--------------------------------------------------------------------------- - * Read-write area - *-------------------------------------------------------------------------*/ - - /* C++ constructor section. */ - .ctors : - { - __CTOR_LIST__ = .; - *(.ctors) - *(SORT(.ctors.*)) - __CTOR_END__ = .; - } > rom :ph_rom - - /* C++ destructor section. */ - .dtors : - { - __DTOR_LIST__ = .; - *(.dtors) - *(SORT(.dtors.*)) - __DTOR_END__ = .; - } > rom :ph_rom - - /* C++ exception handling section. */ - .eh_frame : - { - __EH_FRAME_BEGIN__ = .; - *(.eh_frame) - LONG(0) - __EH_FRAME_END__ = .; - } > rom :ph_rom - - /*------------------------------------------------------------------- - * Initialized data (copied by PM) - *-----------------------------------------------------------------*/ - - /* Data section. */ - .data : - { - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - } > rom :ph_ram - - /* Global offset table section. */ - .got : - { - *(.got.plt) - *(.got) - } > rom :ph_ram - - /* Global offset table for dynamically linked procedures. */ - .got.plt : - { - *(.got.plt) - *(.igot.plt) - } > rom :ph_ram - - /* SFK BIOS entry section. */ - .ose_sfk_biosentry : - { - *(.ose_sfk_biosentry) - } > rom :ph_ram - - /* C++ exception handling section. */ - .gcc_except_table : - { - *(.gcc_except_table .gcc_except_table.*) - } > rom :ph_ram - - /* Small data section. */ - .sdata ALIGN(0x10) : - { - PROVIDE (_SDA_BASE_ = .); - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - } > rom :ph_ram - - /*------------------------------------------------------------------- - * Uninitialized data (cleared by PM) - *-----------------------------------------------------------------*/ - - /* Bss section. */ - .bss : - { - *(.bss) - *(.bss.*) - *(COMMON) - *(.gnu.linkonce.b.*) - } > rom :ph_ram - - /* Small bss section. */ - .sbss ALIGN(0x10) : - { - *(.sbss) - *(.sbss.*) - *(.scommon) - *(.gnu.linkonce.sb.*) - } > rom :ph_ram - -/*--------------------------------------------------------------------------- - * Debug information - *-------------------------------------------------------------------------*/ - - /* - * Stabs debug sections. - */ - - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - - /* - * DWARF debug sections. - */ - - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } -} -- cgit v1.2.3 From 3b0eb33f899f361d5006824782e1ef1d16f57e5c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 10 Feb 2014 18:48:44 +0100 Subject: ose: Cleanup POLL_SCHED_1 code Now schedulers 2..N make sure to wake sched 1 if they find that all io has been consumed and sched 1 is sleeping. Before sched 1 was spinning in sys_schedule waiting for sched 2..N to finish consuming io jobs --- erts/emulator/sys/ose/sys.c | 1 + 1 file changed, 1 insertion(+) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index ad82e4587d..beb7f5944f 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -1732,6 +1732,7 @@ erl_sys_schedule(int runnable) { ASSERT(get_fsem(current_process()) == 0); #ifdef ERTS_SMP + ASSERT(erts_get_scheduler_data()->no == 1); ERTS_CHK_IO(!runnable); #else ERTS_CHK_IO( 1 ); -- cgit v1.2.3 From a35d0f5f82f8152f1b953eda039807a7d4f4e9b9 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Sun, 23 Feb 2014 18:26:38 +0100 Subject: ose: Thread priorities configurable from lmconf The pattern used for getting the priority from the lmconf is based on the name of the process created. The pattern is: ERTS_%%PROCESS_NAME%%_PRIO with the %%PROCESS_NAME%% replaced by the prefix of the process the priority applies to. eg: ERTS_SCHEDULER_PRIO=24 applies to processes with name SCHEDULER_1, SCHEDULER_2 etc. --- erts/emulator/sys/ose/default.lmconf | 6 ++++++ erts/emulator/sys/ose/sys.c | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/default.lmconf b/erts/emulator/sys/ose/default.lmconf index 17b7a1e5fa..a66b0ece56 100644 --- a/erts/emulator/sys/ose/default.lmconf +++ b/erts/emulator/sys/ose/default.lmconf @@ -13,6 +13,12 @@ HEAP_SMALL_BUF_INIT_SIZE=64000000 HEAP_LARGE_BUF_THRESHOLD=16000000 HEAP_LOCK_TYPE=2 +ERTS_DEFAULT_PRIO=24 +ERTS_SCHEDULER_PRIO=24 +ERTS_ASYNC_PRIO=22 +ERTS_AUX_PRIO=24 +ERTS_SYS_MSG_DISPATCHER_PRIO=21 + # Setting the environment variable EFS_RESOLVE_TMO on the block to 0. # This will eliminiate delays when trying to open files on not mounted # volumes. diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index beb7f5944f..88dbd7fcf8 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -50,6 +50,14 @@ #include "efs.h" #include "erl_printf.h" +/* Set the define to 1 to get some logging */ +#if 0 +#include "ramlog.h" +#define LOG(output) ramlog_printf output +#else +#define LOG(output) +#endif + extern char **environ; static erts_smp_rwmtx_t environ_rwmtx; @@ -68,7 +76,7 @@ static erts_smp_rwmtx_t environ_rwmtx; #include "erl_cpu_topology.h" /* The priority for reader/writer processes */ -#define FD_PROC_PRI 20 +#define FD_PROC_PRI get_pri(current_process()) typedef struct ErtsSysReportExit_ ErtsSysReportExit; struct ErtsSysReportExit_ { -- cgit v1.2.3 From 4a6850e522b91eb009ddd0ed9d9f542f1baf1bee Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Fri, 21 Feb 2014 14:01:38 +0100 Subject: ose: Updating event and signal API for OSE --- erts/emulator/sys/common/erl_poll.h | 1 + erts/emulator/sys/ose/erl_poll.c | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/common/erl_poll.h b/erts/emulator/sys/common/erl_poll.h index ce8dcd3f90..2f1c05f401 100644 --- a/erts/emulator/sys/common/erl_poll.h +++ b/erts/emulator/sys/common/erl_poll.h @@ -119,6 +119,7 @@ struct erts_sys_fd_type { ErtsPollOseMsgList *msgs; ErlDrvOseEventId (*resolve_signal)(union SIGNAL *sig); ethr_mutex mtx; + void *extra; }; #endif diff --git a/erts/emulator/sys/ose/erl_poll.c b/erts/emulator/sys/ose/erl_poll.c index 78dc275c06..ca1ed6e53a 100644 --- a/erts/emulator/sys/ose/erl_poll.c +++ b/erts/emulator/sys/ose/erl_poll.c @@ -547,8 +547,8 @@ int erts_poll_wait(ErtsPollSet ps, erts_dsprintf( dsbufp, "erts_poll_wait() failed: found unkown signal id %d (signo %u) " - "(curr_proc 0x%x /sender 0x%x)\n", - fd.id, fd.signo, current_process(), sender(&sig)); + "(curr_proc 0x%x)\n", + fd.id, fd.signo, current_process()); erts_send_error_to_logger_nogl(dsbufp); timeout = 0; ASSERT(0); @@ -737,17 +737,17 @@ union SIGNAL *erl_drv_ose_get_signal(ErlDrvEvent drv_ev) { ev->msgs = msg->next; ethr_mutex_unlock(&ev->mtx); erts_free(ERTS_ALC_T_FD_SIG_LIST,msg); - restore(sig); return sig; } } ErlDrvEvent erl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id, - ErlDrvOseEventId (*resolve_signal)(union SIGNAL *sig)) { + ErlDrvOseEventId (*resolve_signal)(union SIGNAL *sig), void *extra) { struct erts_sys_fd_type *ev = erts_alloc(ERTS_ALC_T_DRV_EV, sizeof(struct erts_sys_fd_type)); ev->signo = signo; + ev->extra = extra; ev->id = id; ev->msgs = NULL; ev->resolve_signal = resolve_signal; @@ -763,10 +763,12 @@ void erl_drv_ose_event_free(ErlDrvEvent drv_ev) { } void erl_drv_ose_event_fetch(ErlDrvEvent drv_ev, SIGSELECT *signo, - ErlDrvOseEventId *id) { + ErlDrvOseEventId *id, void **extra) { struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; if (signo) *signo = ev->signo; + if (extra) + *extra = ev->extra; if (id) *id = ev->id; } -- cgit v1.2.3 From 06e55b6f2ac30c95717532a259a6148226f63b24 Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Fri, 21 Feb 2014 14:03:00 +0100 Subject: ose: Updating fd_driver and spawn_driver for OSE --- erts/emulator/sys/ose/sys.c | 1339 +++++++++++++++++++++---------------------- 1 file changed, 650 insertions(+), 689 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index 88dbd7fcf8..c892cc69c7 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -49,6 +49,9 @@ #include "unistd.h" #include "efs.h" #include "erl_printf.h" +#include "aio.h" +#include "pm.h" +#include "fcntl.h" /* Set the define to 1 to get some logging */ #if 0 @@ -60,6 +63,7 @@ extern char **environ; static erts_smp_rwmtx_t environ_rwmtx; +static PROCESS sig_proxy_pid = 0; #define MAX_VSIZE 16 /* Max number of entries allowed in an I/O * vector sock_sendv(). @@ -80,31 +84,44 @@ static erts_smp_rwmtx_t environ_rwmtx; typedef struct ErtsSysReportExit_ ErtsSysReportExit; struct ErtsSysReportExit_ { - ErtsSysReportExit *next; - Eterm port; - int pid; - int ifd; - int ofd; - ErlDrvEvent in_sig_descr; - ErlDrvEvent out_sig_descr; + ErtsSysReportExit *next; + Eterm port; + int pid; + int ifd; + int ofd; + ErlDrvEvent attach_event; + ErlDrvEvent input_event; + ErlDrvEvent output_event; }; /* This data is shared by these drivers - initialized by spawn_init() */ static struct driver_data { - ErlDrvPort port_num; - int ofd, packet_bytes; - ErtsSysReportExit *report_exit; - int pid; - int alive; - int status; - ErlDrvEvent in_sig_descr; - ErlDrvEvent out_sig_descr; - PROCESS in_proc; - PROCESS out_proc; - ErlDrvPDL pdl; + ErlDrvPort port_num; + int ofd; + int ifd; + int packet_bytes; + ErtsSysReportExit *report_exit; + int pid; + int alive; + int status; + ErlDrvEvent input_event; + ErlDrvEvent output_event; + struct aiocb aiocb; + FmHandle handle; + char *install_handle; } *driver_data; /* indexed by fd */ +struct async { + SIGSELECT signo; + ErlDrvTermData port; + ErlDrvTermData proc; + PROCESS spid; + PROCESS target; + Uint32 ref; +}; + static ErtsSysReportExit *report_exit_list; +static ERTS_INLINE void report_exit_status(ErtsSysReportExit *rep, int status); extern int driver_interrupt(int, int); extern void do_break(void); @@ -157,6 +174,66 @@ erts_mtx_t chld_stat_mtx; static volatile int children_died; #endif +#define SET_AIO(REQ,FD,SIZE,BUFF) \ + memset(&(REQ),0,sizeof(REQ)); \ + (REQ).aio_fildes = FD; \ + (REQ).aio_offset = FM_POSITION_CURRENT; \ + (REQ).aio_nbytes = SIZE; \ + (REQ).aio_buf = BUFF; \ + (REQ).aio_sigevent.sigev_notify = SIGEV_NONE + +/* the first sizeof(struct aiocb *) bytes of the write buffer + * will contain the pointer to the aiocb struct, this needs + * to be freed between asynchronous writes. + * A write of 0 bytes is ignored. */ +#define WRITE_AIO(FD,SIZE,BUFF) do { \ + if (SIZE > 0) { \ + struct aiocb *write_req = driver_alloc(sizeof(struct aiocb)); \ + char *write_buff = driver_alloc((sizeof(char)*SIZE)+1+ \ + (sizeof(struct aiocb *))); \ + *(struct aiocb **)write_buff = (struct aiocb *)write_req; \ + write_buff += sizeof(struct aiocb *); \ + memcpy(write_buff,BUFF,SIZE+1); \ + SET_AIO(*write_req,FD,SIZE,write_buff); \ + aio_write(write_req); \ + } \ +} while(0) + +/* free the write_buffer and write_req + * created in the WRITE_AIO() request macro */ +#define FREE_AIO(ptr) do { \ + struct aiocb *aiocb_ptr; \ + char *buffer_ptr; \ + aiocb_ptr = *(struct aiocb **)((ptr)-sizeof(struct aiocb *)); \ + buffer_ptr = (((char*)ptr)-sizeof(struct aiocb *)); \ + driver_free(aiocb_ptr); \ + driver_free(buffer_ptr); \ +} while(0) + +/* When we have several schedulers, we need to make sure + * that scheduler issuing aio_dispatch() is the owner on the signal */ +#define DISPATCH_AIO(sig) do { \ + restore(sig); \ + aio_dispatch(sig); \ + } while(0) + + +/* debug print macros */ +#define DEBUG_RES 0 + +#ifdef DEBUG_RES +#define DEBUG_CHECK_RES(actual, expected) \ + do { \ + if (actual != expected ) { \ + ramlog_printf("Result check failed" \ + " got: 0x%08x expected:0x%08x\nat: %s:%d\n", \ + actual, expected, __FILE__, __LINE__); \ + abort(); /* This might perhaps be too harsh? */ \ + } \ + } while(0) +#else +#define DEBUG_CHECK_RES +#endif static struct fd_data { char pbuf[4]; /* hold partial packet bytes */ @@ -191,6 +268,7 @@ static struct termios initial_tty_mode; static int replace_intr = 0; /* assume yes initially, ttsl_init will clear it */ int using_oldshell = 1; +static PROCESS get_signal_proxy_pid(void); static void init_check_io(void) @@ -540,28 +618,13 @@ void fini_getenv_state(GETENV_STATE *state) /************************** Port I/O *******************************/ - - /* I. Common stuff */ -typedef struct SysDriverAsyncSignal_ { - SIGSELECT sig_no; - int type; - byte *buff; - ssize_t res; - int errno_copy; -} SysDriverAsyncSignal; - -typedef struct SysDriverConfSignal_ { - SIGSELECT sig_no; - int fd; - PROCESS parent; -} SysDriverConfSignal; - union SIGNAL { SIGSELECT sig_no; - SysDriverAsyncSignal sys_async; - SysDriverConfSignal conf_async; + struct FmReadPtr fm_read_reply; + struct FmWritePtr fm_write_reply; + struct async async; }; /* II. The spawn/fd drivers */ @@ -582,14 +645,42 @@ static void erl_stop(ErlDrvData); static void ready_input(ErlDrvData, ErlDrvEvent); static void ready_output(ErlDrvData, ErlDrvEvent); static void output(ErlDrvData, char*, ErlDrvSizeT); -static void outputv(ErlDrvData, ErlIOVec*); static void stop_select(ErlDrvEvent, void*); -static ErlDrvOseEventId resolve_signal(union SIGNAL* sig) { - return sig->sig_no == ERTS_SIGNAL_FD_DRV_ASYNC ? sig->sys_async.type : -1; + +static PROCESS +get_signal_proxy_pid(void) { + union SIGNAL *sig; + SIGSELECT any_sig[] = {0}; + + if (!sig_proxy_pid) { + sig = alloc(sizeof(union SIGNAL), ERTS_SIGNAL_OSE_DRV_ATTACH); + hunt("ose_signal_driver_proxy", 0, NULL, &sig); + sig = receive(any_sig); + sig_proxy_pid = sender(&sig); + free_buf(&sig); + } + ASSERT(sig_proxy_pid); + return sig_proxy_pid; } -OS_PROCESS(fd_writer_process); -OS_PROCESS(fd_reader_process); +static ErlDrvOseEventId +resolve_signal(union SIGNAL* sig) { + switch(sig->sig_no) { + + case FM_READ_PTR_REPLY: + return (ErlDrvOseEventId)sig->fm_read_reply.handle; + + case FM_WRITE_PTR_REPLY: + return (ErlDrvOseEventId)sig->fm_write_reply.handle; + + case ERTS_SIGNAL_OSE_DRV_ATTACH: + return (ErlDrvOseEventId)sig->async.target; + + default: + break; + } + return (ErlDrvOseEventId)-1; +} struct erl_drv_entry spawn_driver_entry = { spawn_init, @@ -627,7 +718,7 @@ struct erl_drv_entry fd_driver_entry = { NULL, fd_control, NULL, - outputv, + NULL, NULL, /* ready_async */ NULL, /* flush */ NULL, /* call */ @@ -641,120 +732,167 @@ struct erl_drv_entry fd_driver_entry = { stop_select }; -static int set_driver_data(ErlDrvPort port_num, +static void +set_spawn_fd(int local_fd, int remote_fd, PROCESS remote_pid) { + PROCESS vm_pid; + FmHandle handle; + char env_val[55]; + char env_name[10]; + EfsStatus efs_res; + + /* get pid of pipevm and handle of chosen fd */ + efs_res = efs_examine_fd(local_fd, FLIB_FD_VMPID, &vm_pid, 0); + DEBUG_CHECK_RES(efs_res, EFS_SUCCESS); + + /* setup the file descriptor to buffer per line */ + efs_res = efs_config_fd(local_fd, FLIB_FD_BUFMODE, FM_BUFF_LINE, + FLIB_FD_BUFSIZE, 80, 0); + DEBUG_CHECK_RES(efs_res, EFS_SUCCESS); + + /* duplicate handle and set spawn pid owner */ + efs_res = efs_dup_to(local_fd, remote_pid, &handle); + DEBUG_CHECK_RES(efs_res, EFS_SUCCESS); + + sprintf(env_name, "FD%d", remote_fd); + + /* Syntax of the environment variable: + * "FD#" ",,,," */ + sprintf(env_val, "0x%lx,0x%lx,%lu,%lu,0x%x", + vm_pid, handle, + FM_BUFF_LINE, 80, + O_APPEND); + + set_env(remote_pid, env_name, env_val); +} + +static ErlDrvData +set_driver_data(ErlDrvPort port_num, int ifd, int ofd, int packet_bytes, int read_write, int exit_status, - int pid) + PROCESS pid) { Port *prt; ErtsSysReportExit *report_exit; - union SIGNAL *sig; - - /*erts_fprintf(stderr, " %s / pid %x / ofd %d / ifd %d\n", - __FUNCTION__, current_process(), ofd, ifd);*/ - - - if (!exit_status) - report_exit = NULL; - else { - report_exit = erts_alloc(ERTS_ALC_T_PRT_REP_EXIT, - sizeof(ErtsSysReportExit)); - report_exit->next = report_exit_list; - report_exit->port = erts_drvport2id(port_num); - report_exit->pid = pid; - report_exit->ifd = read_write & DO_READ ? ifd : -1; - report_exit->ofd = read_write & DO_WRITE ? ofd : -1; - - if (read_write & DO_READ) - report_exit->in_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ifd, - resolve_signal); - if (read_write & DO_WRITE) - report_exit->out_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ofd, - resolve_signal); - - report_exit_list = report_exit; - } prt = erts_drvport2port(port_num); - if (prt != ERTS_INVALID_ERL_DRV_PORT) - prt->os_pid = pid; + if (prt != ERTS_INVALID_ERL_DRV_PORT) { + prt->os_pid = pid; + } + /* READ */ if (read_write & DO_READ) { - driver_data[ifd].packet_bytes = packet_bytes; - driver_data[ifd].port_num = port_num; - driver_data[ifd].report_exit = report_exit; - driver_data[ifd].pid = pid; - driver_data[ifd].alive = 1; - driver_data[ifd].status = 0; - driver_data[ifd].in_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ifd, - resolve_signal); - - driver_data[ifd].in_proc = create_process(OS_PRI_PROC,"beam_fd_reader", - fd_reader_process, 0x800, - FD_PROC_PRI, 0, 0, - NULL, 0, 0); - efs_clone(driver_data[ifd].in_proc); - sig = alloc(sizeof(SysDriverConfSignal), ERTS_SIGNAL_FD_DRV_CONFIG); - sig->conf_async.fd = ifd; - sig->conf_async.parent = current_process(); - send(&sig, driver_data[ifd].in_proc); - start(driver_data[ifd].in_proc); - - if (read_write & DO_WRITE) { - driver_data[ifd].ofd = ofd; - driver_data[ifd].out_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd, - resolve_signal); - driver_data[ifd].pdl = driver_pdl_create(port_num); - driver_data[ifd].out_proc = - create_process(OS_PRI_PROC,"beam_fd_writer", - fd_writer_process, 0x800, - FD_PROC_PRI, 0, 0, NULL, 0, 0); - sig = alloc(sizeof(SysDriverConfSignal), ERTS_SIGNAL_FD_DRV_CONFIG); - sig->conf_async.fd = ofd; - sig->conf_async.parent = current_process(); - send(&sig, driver_data[ifd].out_proc); - // efs_clone(driver_data[ifd].out_proc); - start(driver_data[ifd].out_proc); - if (ifd != ofd) - driver_data[ofd] = driver_data[ifd]; /* structure copy */ - } else { /* DO_READ only */ - driver_data[ifd].ofd = -1; - } - (void) driver_select(port_num, driver_data[ifd].in_sig_descr, + efs_examine_fd(ifd, FLIB_FD_HANDLE, &driver_data[ifd].handle, 0); + driver_data[ifd].ifd = ifd; + driver_data[ifd].packet_bytes = packet_bytes; + driver_data[ifd].port_num = port_num; + driver_data[ifd].pid = pid; + + /* async read struct */ + memset(&driver_data[ifd].aiocb, 0, sizeof(struct aiocb)); + driver_data[ifd].aiocb.aio_buf = driver_alloc(255); + driver_data[ifd].aiocb.aio_fildes = ifd; + driver_data[ifd].aiocb.aio_nbytes = 255; + + driver_data[ifd].alive = 1; + driver_data[ifd].status = 0; + driver_data[ifd].input_event = + erl_drv_ose_event_alloc(FM_READ_PTR_REPLY, + driver_data[ifd].handle, resolve_signal, + &driver_data[ifd].ifd); + + /* READ & WRITE */ + if (read_write & DO_WRITE) { + driver_data[ifd].ofd = ofd; + efs_examine_fd(ofd, FLIB_FD_HANDLE, &driver_data[ofd].handle, 0); + + driver_data[ifd].output_event = + erl_drv_ose_event_alloc(FM_WRITE_PTR_REPLY, + driver_data[ofd].handle, resolve_signal, + &driver_data[ofd].ofd); + driver_data[ofd].pid = pid; + if (ifd != ofd) { + driver_data[ofd] = driver_data[ifd]; + driver_data[ofd].aiocb.aio_buf = NULL; + } + } + else { /* READ ONLY */ + driver_data[ifd].ofd = -1; + } + + /* enable input event */ + (void) driver_select(port_num, driver_data[ifd].input_event, (ERL_DRV_READ | ERL_DRV_USE), 1); - return(ifd); - } else { /* DO_WRITE only */ - driver_data[ofd].packet_bytes = packet_bytes; - driver_data[ofd].port_num = port_num; - driver_data[ofd].report_exit = report_exit; - driver_data[ofd].ofd = ofd; - driver_data[ofd].pid = pid; - driver_data[ofd].alive = 1; - driver_data[ofd].status = 0; - driver_data[ofd].in_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd, - resolve_signal); - driver_data[ofd].out_sig_descr = driver_data[ofd].in_sig_descr; - driver_data[ofd].out_proc = - create_process(OS_PRI_PROC, "beam_fd_writer", - fd_writer_process, 0x800, - FD_PROC_PRI, 0, 0, NULL, 0, 0); - sig = alloc(sizeof(SysDriverConfSignal), ERTS_SIGNAL_FD_DRV_CONFIG); - sig->conf_async.fd = ofd; - sig->conf_async.parent = current_process(); - send(&sig, driver_data[ofd].out_proc); - start(driver_data[ofd].out_proc); - //efs_clone(driver_data[ifd].out_proc); - driver_data[ofd].pdl = driver_pdl_create(port_num); - return(ofd); + + aio_read(&driver_data[ifd].aiocb); + } + else { /* WRITE ONLY */ + efs_examine_fd(ofd, FLIB_FD_HANDLE, &driver_data[ofd].handle, 0); + driver_data[ofd].packet_bytes = packet_bytes; + driver_data[ofd].port_num = port_num; + driver_data[ofd].ofd = ofd; + driver_data[ofd].pid = pid; + driver_data[ofd].alive = 1; + driver_data[ofd].status = 0; + driver_data[ofd].output_event = + erl_drv_ose_event_alloc(FM_WRITE_PTR_REPLY, driver_data[ofd].handle, + resolve_signal, &driver_data[ofd].ofd); + driver_data[ofd].input_event = driver_data[ofd].output_event; } + + /* this is used for spawned load modules, and is needed + * to properly uninstall them */ + if (exit_status) { + struct PmProgramInfo *info; + int install_handle_size; + union SIGNAL *sig; + PmStatus pm_status; + report_exit = erts_alloc(ERTS_ALC_T_PRT_REP_EXIT, + sizeof(ErtsSysReportExit)); + report_exit->next = report_exit_list; + report_exit->port = erts_drvport2id(port_num); + report_exit->pid = pid; + report_exit->ifd = (read_write & DO_READ) ? ifd : -1; + report_exit->ofd = (read_write & DO_WRITE) ? ofd : -1; + report_exit_list = report_exit; + report_exit->attach_event = + erl_drv_ose_event_alloc(ERTS_SIGNAL_OSE_DRV_ATTACH, pid, + resolve_signal, &driver_data[ifd].ifd); + + /* setup ifd and ofd report exit */ + driver_data[ifd].report_exit = report_exit; + driver_data[ofd].report_exit = report_exit; + + pm_status = ose_pm_program_info(pid, &info); + DEBUG_CHECK_RES(pm_status, PM_SUCCESS); + + install_handle_size = strlen(info->install_handle)+1; + driver_data[ifd].install_handle = driver_alloc(install_handle_size); + strcpy(driver_data[ifd].install_handle, + info->install_handle); + + free_buf((union SIGNAL **)&info); + + sig = alloc(sizeof(struct async), ERTS_SIGNAL_OSE_DRV_ATTACH); + sig->async.target = pid; + send(&sig, get_signal_proxy_pid()); + + /* this event will trigger when we receive an attach signal + * from the recently dead load module */ + (void)driver_select(port_num,report_exit->attach_event, DO_READ, 1); + } + else { + report_exit = NULL; + } + + /* the return value is the pointer to the driver_data struct we created + * in this function, it will be used in the drivers input + * and output functions */ + return (ErlDrvData)((!(read_write & DO_READ) && read_write & DO_WRITE) + ? &driver_data[ofd] + : &driver_data[ifd]); } static int spawn_init() @@ -772,9 +910,9 @@ static int spawn_init() return 1; } -static void init_fd_data(int fd, ErlDrvPort port_num) +static void +init_fd_data(int fd, ErlDrvPort port_num) { - fd_data[fd].buf = NULL; fd_data[fd].cpos = NULL; fd_data[fd].remain = 0; @@ -782,173 +920,109 @@ static void init_fd_data(int fd, ErlDrvPort port_num) fd_data[fd].psz = 0; } -static ErlDrvData spawn_start(ErlDrvPort port_num, - char* name, - SysDriverOpts* opts) +/* FIXME write a decent text on pipes on ose */ +static ErlDrvData +spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts) { - - long res = 0; - - /* Have to implement for OSE */ - return (ErlDrvData)res; -} - -OS_PROCESS(fd_reader_process) { - union SIGNAL *sig; - PROCESS parent; - int fd; - byte *read_buf; - - SIGSELECT sigsel[] = {1,ERTS_SIGNAL_FD_DRV_CONFIG}; - -#ifdef ERTS_ENABLE_LOCK_COUNT - erts_lcnt_init(); -#endif - - sig = receive(sigsel); - - fd = sig->conf_async.fd; - - parent = sig->conf_async.parent; - free_buf(&sig); - -#ifdef ERTS_ENABLE_LOCK_CHECK - { - char buf[31]; - erts_snprintf(&buf[0], 31, "fd_reader %beu", fd); - erts_lc_set_thread_name(&buf[0]); + int ifd[2]; + int ofd[2]; + static uint32_t ticker = 0; + PmStatus pm_status; + OSDOMAIN domain = PM_NEW_DOMAIN; + PROCESS progpid, mainbid, mainpid; + char *handle = NULL; + struct PmProgramInfo *info; + char *args = NULL; + char *tmp_handle; + ErlDrvData res = (ErlDrvData)-1; + int handle_size; + char *ptr; + + /* handle arguments */ + ptr = strchr(name, ' '); + if (ptr != NULL) { + *ptr ='\0'; + ptr++; + args = ptr; } -#endif - - if (fd == 0) { - FILE *ffd = stdin; - (void)stdin; + else { + args = NULL; } - sigsel[1] = ERTS_SIGNAL_FD_DRV_ASYNC; - - read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF, - ERTS_SYS_READ_BUF_SZ); - while (1) { - int errno_copy = errno; - ssize_t res; - res = read(fd, read_buf, ERTS_SYS_READ_BUF_SZ); - sig = alloc(sizeof(SysDriverAsyncSignal), ERTS_SIGNAL_FD_DRV_ASYNC); - sig->sys_async.buff = read_buf; - sig->sys_async.res = res; - if (res <= 0 && errno == EBADF) { - fprintf(stderr,"Could not read from input fd (fd %d/ errno %d/ res %d)\n", - fd, errno, res); - break; - } - if (errno != errno_copy) - sig->sys_async.errno_copy = errno; - else - sig->sys_async.errno_copy = -1; - sig->sys_async.type = fd; - send(&sig,parent); - /* Wait for acc from async_read */ - sig = receive(sigsel); - free_buf(&sig); + /* create an install handle */ + ptr = strrchr(name, '/'); + if (ptr != NULL) { + ptr++; + tmp_handle = ptr; + } + else { + tmp_handle = name; + } + handle_size = strlen(tmp_handle)+1; + handle_size += (ticker<10)?3:((ticker<100)?4:5); + + handle = driver_alloc(handle_size); + snprintf(handle, handle_size, "%s_%d", tmp_handle, ticker); + + do { + snprintf(handle, handle_size, "%s_%d", tmp_handle, ticker++); + pm_status = ose_pm_install_load_module(0, "ELF", name, handle, + 0, 0, NULL); + + } while (pm_status == PM_EINSTALL_HANDLE_ALREADY_INSTALLED); + DEBUG_CHECK_RES(pm_status, PM_SUCCESS); + + /* Create Program */ + pm_status = ose_pm_create_program(&domain, handle, 0, 0, + NULL, &progpid, &mainbid); + DEBUG_CHECK_RES(pm_status, PM_SUCCESS); + + /* Get the mainpid from the newly created program */ + pm_status = ose_pm_program_info(progpid, &info); + DEBUG_CHECK_RES(pm_status, PM_SUCCESS); + + mainpid = info->main_process; + free_buf ((union SIGNAL **)&info); + + /* pipevm needs to be started + * pipe will return 0 if success, -1 if not, + * errno will be set */ + if (pipe(ifd) != 0 || pipe(ofd) != 0) { + DEBUG_CHECK_RES(0, -1); + ASSERT(0); } - erts_free(ERTS_ALC_T_SYS_READ_BUF, read_buf); -} - -OS_PROCESS(fd_writer_process) { - union SIGNAL *sig; - PROCESS parent; - int fd; - SIGSELECT sigsel[] = { 1, ERTS_SIGNAL_FD_DRV_CONFIG, - ERTS_SIGNAL_FD_DRV_ASYNC }; - /* Only wait for config event with the fd which we are printing to */ - sig = receive(sigsel); + /* setup driver data */ + res = set_driver_data(port_num, ofd[0], ifd[1], opts->packet_bytes, + opts->read_write, 1 /* opts->exit_status */, progpid); - fd = sig->conf_async.fd; - parent = sig->conf_async.parent; - free_buf(&sig); + /* init the fd_data array for read/write */ + init_fd_data(ofd[0], port_num); + init_fd_data(ifd[1], port_num); -#ifdef ERTS_ENABLE_LOCK_COUNT - { - char buf[31]; - erts_snprintf(&buf[0], 31, "fd_writer %beu", fd); - erts_lc_set_thread_name(&buf[0]); + /* setup additional configurations + * for the spawned applications environment */ + if (args != NULL) { + set_env(progpid, "ARGV", args); } -#endif + set_env(mainbid, "EFS_RESOLVE_TMO", 0); + set_spawn_fd(ifd[0], 0, mainpid); + set_spawn_fd(ofd[1], 1, mainpid); + set_spawn_fd(ofd[1], 2, mainpid); - sigsel[0] = 2; - /* Why do I need these?!? */ - if (fd == 1) { - FILE* ffd = stdout; - (void)stdout; - } else if (fd == 2) { - FILE* ffd = stderr; - (void)stderr; - } + /* start the spawned program */ + pm_status = ose_pm_start_program(mainbid); + DEBUG_CHECK_RES(pm_status, PM_SUCCESS); - while (1) { - int errno_copy = errno; - int res; - SysIOVec *iov0; - SysIOVec *iov; - int iovlen; - int iovcnt; - int n = 0, i = 0, offset = 0; - size_t p; - /* fprintf(stderr,"0x%x: fd_writer, receive\n", current_process()); */ - sig = receive(sigsel); - /* size = sig->sys_async.res;*/ - if (sig->sig_no == ERTS_SIGNAL_FD_DRV_CONFIG) - return; - driver_pdl_lock(driver_data[fd].pdl); - - iov0 = driver_peekq(driver_data[fd].port_num, &iovlen); - - /* Calculate iovcnt */ - for (p = 0, iovcnt = 0; iovcnt < iovlen; - p += iov0[iovcnt++].iov_len) - ; - iov = driver_alloc(sizeof(SysIOVec) * iovcnt); - memcpy(iov, iov0, iovcnt * sizeof(SysIOVec)); - /* Let go of lock until we deque from original vector */ - driver_pdl_unlock(driver_data[fd].pdl); - - if (iovlen > 0) { - while(i < iovcnt) { - /* We only write 256 chars at the time in order to - not overflow the stdout process */ - if ((iov[i].iov_len-offset) > 256) { - res = write(fd, iov[i].iov_base+offset, 256); - if (res < 0) - break; - offset += res; - } else { - res = write(fd, iov[i].iov_base+offset, iov[i].iov_len-offset); - if (res < 0) - break; - offset = 0; - i++; - } - n += res; - } - if (res > 0) - res = n; - } else if (iovlen == 0) { - res = 0; - } else { /* Port has terminated */ - res = -1; - } - driver_free(iov); - - sig->sys_async.buff = NULL; - sig->sys_async.res = res; - if (errno != errno_copy) - sig->sys_async.errno_copy = errno; - else - sig->sys_async.errno_copy = -1; - sig->sys_async.type = fd; - send(&sig, parent); + /* close unused fd's */ + close(ifd[0]); + close(ofd[1]); + + if (handle) { + driver_free(handle); } + + return (ErlDrvData)res; } #define FD_DEF_HEIGHT 24 @@ -974,13 +1048,13 @@ static ErlDrvSSizeT fd_control(ErlDrvData drv_data, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { - int fd = (int)(long)drv_data; + struct driver_data *data = (struct driver_data *)drv_data; char resbuff[2*sizeof(Uint32)]; switch (command) { case FD_CTRL_OP_GET_WINSIZE: { Uint32 w,h; - if (fd_get_window_size(fd,&w,&h)) + if (fd_get_window_size(data->ifd,&w,&h)) return 0; memcpy(resbuff,&w,sizeof(Uint32)); memcpy(resbuff+sizeof(Uint32),&h,sizeof(Uint32)); @@ -1008,7 +1082,7 @@ static ErlDrvData fd_start(ErlDrvPort port_num, char* name, if (opts->read_write & DO_WRITE) { init_fd_data(opts->ofd, port_num); } - res = (ErlDrvData)(long)set_driver_data(port_num, opts->ifd, opts->ofd, + res = set_driver_data(port_num, opts->ifd, opts->ofd, opts->packet_bytes, opts->read_write, 0, -1); CHLD_STAT_UNLOCK; @@ -1031,404 +1105,317 @@ static void clear_fd_data(int fd) static void nbio_stop_fd(ErlDrvPort prt, ErlDrvEvent ev) { - int fd; + int *fd; driver_select(prt,ev,DO_READ|DO_WRITE,0); - erl_drv_ose_event_fetch(ev, NULL, &fd); - clear_fd_data(fd); - SET_BLOCKING(fd); + erl_drv_ose_event_fetch(ev, NULL, NULL, (void **)&fd); + clear_fd_data(*fd); + SET_BLOCKING(*fd); } -static void fd_stop(ErlDrvData fd) /* Does not close the fds */ +static void fd_stop(ErlDrvData drv_data) /* Does not close the fds */ { - int ofd; + struct driver_data *data = (struct driver_data *)drv_data; - nbio_stop_fd(driver_data[(int)(long)fd].port_num, - driver_data[(int)(long)fd].in_sig_descr); - ofd = driver_data[(int)(long)fd].ofd; - if (ofd != (int)(long)fd && ofd != -1) - nbio_stop_fd(driver_data[(int)(long)fd].port_num, - driver_data[(int)(long)fd].out_sig_descr); + if (data->ofd != -1) { + if (data->ifd != data->ofd) { /* read and write */ + nbio_stop_fd(data->port_num, data->input_event); + nbio_stop_fd(data->port_num, data->output_event); + } + else { /* write only */ + nbio_stop_fd(data->port_num, data->output_event); + } + } + else { /* read only */ + nbio_stop_fd(data->port_num, data->input_event); + } } -/* Note that driver_data[fd].ifd == fd if the port was opened for reading, */ -/* otherwise (i.e. write only) driver_data[fd].ofd = fd. */ - -static void erl_stop(ErlDrvData fd) -{ - ErlDrvPort prt; - int ofd; - - prt = driver_data[(int)(long)fd].port_num; - nbio_stop_fd(prt, driver_data[(int)(long)fd].in_sig_descr); - - ofd = driver_data[(int)(long)fd].ofd; - if (ofd != (int)(long)fd && (int)(long)ofd != -1) - nbio_stop_fd(prt, driver_data[(int)(long)fd].out_sig_descr); - else - ofd = -1; - - CHLD_STAT_LOCK; - - /* Mark as unused. */ - driver_data[(int)(long)fd].pid = -1; - - CHLD_STAT_UNLOCK; - /* SMP note: Close has to be last thing done (open file descriptors work - as locks on driver_data[] entries) */ - driver_select(prt, driver_data[(int)(long)fd].in_sig_descr, - ERL_DRV_USE, 0); /* close(fd); */ - if (ofd >= 0) { - driver_select(prt, driver_data[(int)(long)fd].out_sig_descr, - ERL_DRV_USE, 0); /* close(ofd); */ - } -} - -static void outputv(ErlDrvData e, ErlIOVec* ev) +static void erl_stop(ErlDrvData drv_data) { - int fd = (int)(long)e; - ErlDrvPort ix = driver_data[fd].port_num; - int pb = driver_data[fd].packet_bytes; - ErlDrvSizeT sz; - char lb[4]; - char* lbp; - ErlDrvSizeT len = ev->size; - - /* (len > ((unsigned long)-1 >> (4-pb)*8)) */ - /* if (pb >= 0 && (len & (((ErlDrvSizeT)1 << (pb*8))) - 1) != len) {*/ - if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) { - driver_failure_posix(ix, EINVAL); - return; /* -1; */ - } - /* Handles 0 <= pb <= 4 only */ - put_int32((Uint32) len, lb); - lbp = lb + (4-pb); - - ev->iov[0].iov_base = lbp; - ev->iov[0].iov_len = pb; - ev->size += pb; - driver_pdl_lock(driver_data[fd].pdl); - if ((sz = driver_sizeq(ix)) > 0) { - /* fprintf(stderr,"0x%x: outputv, enq\n", current_process()); */ - driver_enqv(ix, ev, 0); - if (sz + ev->size >= (1 << 13)) - set_busy_port(ix, 1); - driver_pdl_unlock(driver_data[fd].pdl); - } - else { - union SIGNAL *sig; - /* fprintf(stderr,"0x%x: outputv, enq+sel\n", current_process()); */ - driver_enqv(ix, ev, 0); /* n is the skip value */ - driver_pdl_unlock(driver_data[fd].pdl); - driver_select(ix, driver_data[fd].out_sig_descr, - ERL_DRV_WRITE|ERL_DRV_USE, 1); - sig = alloc(sizeof(SysDriverAsyncSignal),ERTS_SIGNAL_FD_DRV_ASYNC); - sig->sys_async.type = fd; - sig->sys_async.res = pb+len; - send(&sig,driver_data[fd].out_proc); - } - /* return 0;*/ -} - - -static void output(ErlDrvData e, char* buf, ErlDrvSizeT len) + struct driver_data *data = (struct driver_data *)drv_data; + + CHLD_STAT_LOCK; + data->pid = -1; + CHLD_STAT_UNLOCK; + + if (data->ofd != -1) { + if (data->ifd != data->ofd) { /* read and write */ + nbio_stop_fd(data->port_num, data->input_event); + nbio_stop_fd(data->port_num, data->output_event); + driver_select(data->port_num, data->input_event, ERL_DRV_USE, 0); + driver_select(data->port_num, data->output_event, ERL_DRV_USE, 0); + } + else { /* write only */ + nbio_stop_fd(data->port_num, data->output_event); + driver_select(data->port_num, data->output_event, ERL_DRV_USE, 0); + } + } + else { /* read only */ + nbio_stop_fd(data->port_num, data->input_event); + driver_select(data->port_num, data->input_event, ERL_DRV_USE, 0); + } + close(data->ifd); + close(data->ofd); +} + +/* The parameter e is a pointer to the driver_data structure + * related to the fd to be used as output */ +static void output(ErlDrvData drv_data, char* buf, ErlDrvSizeT len) { - int fd = (int)(long)e; - ErlDrvPort ix = driver_data[fd].port_num; - int pb = driver_data[fd].packet_bytes; - int ofd = driver_data[fd].ofd; ErlDrvSizeT sz; char lb[4]; char* lbp; -#if 0 - struct iovec iv[2]; -#endif + struct driver_data *data = (struct driver_data *)drv_data; - /* (len > ((unsigned long)-1 >> (4-pb)*8)) */ - if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) { - driver_failure_posix(ix, EINVAL); + if (((data->packet_bytes == 2) && + (len > 0xffff)) || (data->packet_bytes == 1 && len > 0xff)) { + driver_failure_posix(data->port_num, EINVAL); return; /* -1; */ } put_int32(len, lb); - lbp = lb + (4-pb); - - driver_pdl_lock(driver_data[fd].pdl); - if ((sz = driver_sizeq(ix)) > 0) { - /* fprintf(stderr,"0x%x: output, enq\n", current_process()); */ - driver_enq(ix, lbp, pb); - driver_enq(ix, buf, len); - driver_pdl_unlock(driver_data[fd].pdl); - if (sz + len + pb >= (1 << 13)) - set_busy_port(ix, 1); + lbp = lb + (4-(data->packet_bytes)); + + if ((sz = driver_sizeq(data->port_num)) > 0) { + driver_enq(data->port_num, lbp, data->packet_bytes); + driver_enq(data->port_num, buf, len); + if (sz + len + data->packet_bytes >= (1 << 13)) + set_busy_port(data->port_num, 1); } else { - union SIGNAL *sig; - /* fprintf(stderr,"0x%x: output, enq+select\n", current_process()); */ -#if 0 - iv[0].iov_base = lbp; - iv[0].iov_len = pb; /* should work for pb=0 */ - iv[1].iov_base = buf; - iv[1].iov_len = len; -#endif - driver_enq(ix, lbp, pb); - driver_enq(ix, buf, len); - driver_pdl_unlock(driver_data[fd].pdl); - driver_select(ix, driver_data[ofd].out_sig_descr, + driver_enq(data->port_num, buf, len); /* n is the skip value */ + + driver_select(data->port_num, data->output_event, ERL_DRV_WRITE|ERL_DRV_USE, 1); - sig = alloc(sizeof(SysDriverAsyncSignal),ERTS_SIGNAL_FD_DRV_ASYNC); - sig->sys_async.type = fd; - sig->sys_async.res = pb+len; - send(&sig,driver_data[fd].out_proc); + + WRITE_AIO(data->ofd, len, buf); } return; /* 0; */ } +/* This function is being run when we in recieve + * either a read of 0 bytes, or the attach signal from a dying + * spawned load module */ static int port_inp_failure(ErlDrvPort port_num, ErlDrvEvent ready_fd, int res) /* Result: 0 (eof) or -1 (error) */ { - int err = errno; - int fd; - + int *fd; + SIGSELECT sig_no; ASSERT(res <= 0); - (void) driver_select(port_num, ready_fd, ERL_DRV_READ|ERL_DRV_WRITE, 0); - erl_drv_ose_event_fetch(ready_fd,NULL,&fd); - clear_fd_data(fd); - if (res == 0) { - if (driver_data[fd].report_exit) { - CHLD_STAT_LOCK; - - if (driver_data[fd].alive) { - /* - * We have eof and want to report exit status, but the process - * hasn't exited yet. When it does report_exit_status() will - * driver_select() this fd which will make sure that we get - * back here with driver_data[ready_fd].alive == 0 and - * driver_data[ready_fd].status set. - */ - CHLD_STAT_UNLOCK; - return 0; - } - else { - int status = driver_data[fd].status; - CHLD_STAT_UNLOCK; - -#if 0 /*ose we should find something for these statuses*/ - /* We need not be prepared for stopped/continued processes. */ - if (WIFSIGNALED(status)) - status = 128 + WTERMSIG(status); - else - status = WEXITSTATUS(status); -#endif - driver_report_exit(driver_data[fd].port_num, status); - } - } - driver_failure_eof(port_num); - } else { - driver_failure_posix(port_num, err); + + erl_drv_ose_event_fetch(ready_fd,&sig_no, NULL, (void **)&fd); + + /* As we need to handle two signals, we do this in two steps */ + if (driver_data[*fd].alive) { + report_exit_status(driver_data[*fd].report_exit, 0); /* status? */ + } + else { + clear_fd_data(*fd); + driver_report_exit(driver_data[*fd].port_num, driver_data[*fd].status); + /* As we do not really know if the spawn has crashed or exited nicely + * we do not check the result status of the following call.. FIXME + * can we handle this in a better way? */ + ose_pm_uninstall_load_module(driver_data[*fd].install_handle); + driver_free(driver_data[*fd].install_handle); + driver_free((void *)driver_data[*fd].aiocb.aio_buf); + + close(*fd); } - return 0; -} -static int async_read(ErlDrvEvent fd, byte *buff, int size) { - union SIGNAL *sigptr = erl_drv_ose_get_signal(fd); - int res = sigptr->sys_async.res; - if (res > 0) - memcpy(buff,sigptr->sys_async.buff,sigptr->sys_async.res); - errno = sigptr->sys_async.errno_copy; - send(&sigptr,sender(&sigptr)); - ASSERT(erl_drv_ose_get_signal(fd) == NULL); - return res; + return 0; } -/* fd is the drv_data that is returned from the */ -/* initial start routine */ -/* ready_fd is the descriptor that is ready to read */ - -static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd) +/* The parameter e is a pointer to the driver_data structure + * related to the fd to be used as output. + * ready_fd is the event that triggered this call to ready_input */ +static void ready_input(ErlDrvData drv_data, ErlDrvEvent ready_fd) { - int fd = (int)(long)e; - ErlDrvPort port_num; - int packet_bytes; int res; Uint h; + char *buf; + union SIGNAL *sig; + struct driver_data *data = (struct driver_data *)drv_data; - port_num = driver_data[fd].port_num; - packet_bytes = driver_data[fd].packet_bytes; + sig = erl_drv_ose_get_signal(ready_fd); + ASSERT(sig); - if (packet_bytes == 0) { - byte *read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF, - ERTS_SYS_READ_BUF_SZ); - res = async_read(ready_fd, read_buf, ERTS_SYS_READ_BUF_SZ); - if (res < 0) { - if ((errno != EINTR) && (errno != ERRNO_BLOCK)) - port_inp_failure(port_num, ready_fd, res); - } - else if (res == 0) - port_inp_failure(port_num, ready_fd, res); - else - driver_output(port_num, (char*) read_buf, res); - erts_free(ERTS_ALC_T_SYS_READ_BUF, (void *) read_buf); - } - else if (fd_data[fd].remain > 0) { /* We try to read the remainder */ - /* space is allocated in buf */ - res = async_read(ready_fd, (byte*)fd_data[fd].cpos, - fd_data[fd].remain); - if (res < 0) { - if ((errno != EINTR) && (errno != ERRNO_BLOCK)) - port_inp_failure(port_num, ready_fd, res); - } - else if (res == 0) { - port_inp_failure(port_num, ready_fd, res); - } - else if (res == fd_data[fd].remain) { /* we're done */ - driver_output(port_num, fd_data[fd].buf, - fd_data[fd].sz); - clear_fd_data(fd); - } - else { /* if (res < fd_data[ready_fd].remain) */ - fd_data[fd].cpos += res; - fd_data[fd].remain -= res; - } - } - else if (fd_data[fd].remain == 0) { /* clean fd */ - byte *read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF, - ERTS_SYS_READ_BUF_SZ); - /* We make one read attempt and see what happens */ - res = async_read(ready_fd, read_buf, ERTS_SYS_READ_BUF_SZ); - if (res < 0) { - if ((errno != EINTR) && (errno != ERRNO_BLOCK)) - port_inp_failure(port_num, ready_fd, res); - } - else if (res == 0) { /* eof */ - port_inp_failure(port_num, ready_fd, res); - } - else if (res < packet_bytes - fd_data[fd].psz) { - memcpy(fd_data[fd].pbuf+fd_data[fd].psz, - read_buf, res); - fd_data[fd].psz += res; - } - else { /* if (res >= packet_bytes) */ - unsigned char* cpos = read_buf; - int bytes_left = res; - - while (1) { - int psz = fd_data[fd].psz; - char* pbp = fd_data[fd].pbuf + psz; - - while(bytes_left && (psz < packet_bytes)) { - *pbp++ = *cpos++; - bytes_left--; - psz++; - } - - if (psz < packet_bytes) { - fd_data[fd].psz = psz; - break; - } - fd_data[fd].psz = 0; - - switch (packet_bytes) { - case 1: h = get_int8(fd_data[fd].pbuf); break; - case 2: h = get_int16(fd_data[fd].pbuf); break; - case 4: h = get_int32(fd_data[fd].pbuf); break; - default: ASSERT(0); return; /* -1; */ - } - - if (h <= (bytes_left)) { - driver_output(port_num, (char*) cpos, h); - cpos += h; - bytes_left -= h; - continue; - } - else { /* The last message we got was split */ - char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h); - if (!buf) { - errno = ENOMEM; - port_inp_failure(port_num, ready_fd, -1); - } - else { - erts_smp_atomic_add_nob(&sys_misc_mem_sz, h); - sys_memcpy(buf, cpos, bytes_left); - fd_data[fd].buf = buf; - fd_data[fd].sz = h; - fd_data[fd].remain = h - bytes_left; - fd_data[fd].cpos = buf + bytes_left; - } - break; - } - } - } - erts_free(ERTS_ALC_T_SYS_READ_BUF, (void *) read_buf); + + while (sig) { + /* If we've recieved an attach signal, we need to handle + * it in port_inp_failure */ + if (sig->sig_no == ERTS_SIGNAL_OSE_DRV_ATTACH) { + port_inp_failure(data->port_num, ready_fd, 0); + } + else { + res = sig->fm_read_reply.actual; + + if (data->packet_bytes == 0) { + if (res < 0) { + if ((errno != EINTR) && (errno != ERRNO_BLOCK)) { + port_inp_failure(data->port_num, ready_fd, res); + } + } + else if (res == 0) { + /* read of 0 bytes, eof, otherside of pipe is assumed dead */ + port_inp_failure(data->port_num, ready_fd, res); + } + else { + buf = driver_alloc(res); + memcpy(buf, (void *)data->aiocb.aio_buf, res); + driver_select(data->port_num, data->output_event, + ERL_DRV_WRITE|ERL_DRV_USE, 1); + driver_output(data->port_num, (char*) buf, res); + driver_free(buf); + } + } + /* We try to read the remainder */ + else if (fd_data[data->ifd].remain > 0) { + if (res < 0) { + if ((errno != EINTR) && (errno != ERRNO_BLOCK)) { + port_inp_failure(data->port_num, ready_fd, res); + } + } + else if (res == 0) { + port_inp_failure(data->port_num, ready_fd, res); + } + else if (res == fd_data[data->ifd].remain) { /* we're done */ + driver_output(data->port_num, + fd_data[data->ifd].buf, + fd_data[data->ifd].sz); + clear_fd_data(data->ifd); + } + else { /* if (res < fd_data[fd].remain) */ + fd_data[data->ifd].cpos += res; + fd_data[data->ifd].remain -= res; + } + } + else if (fd_data[data->ifd].remain == 0) { /* clean fd */ + if (res < 0) { + if ((errno != EINTR) && (errno != ERRNO_BLOCK)) { + port_inp_failure(data->port_num, ready_fd, res); + } + } + else if (res == 0) { /* eof */ + port_inp_failure(data->port_num, ready_fd, res); + } + else if (res < data->packet_bytes - fd_data[data->ifd].psz) { + memcpy(fd_data[data->ifd].pbuf+fd_data[data->ifd].psz, + (void *)data->aiocb.aio_buf, res); + fd_data[data->ifd].psz += res; + } + else { /* if (res >= packet_bytes) */ + unsigned char* cpos = (unsigned char*)data->aiocb.aio_buf; + int bytes_left = res; + + while (1) { + int psz = fd_data[data->ifd].psz; + char* pbp = fd_data[data->ifd].pbuf + psz; + + while (bytes_left && (psz < data->packet_bytes)) { + *pbp++ = *cpos++; + bytes_left--; + psz++; + } + + if (psz < data->packet_bytes) { + fd_data[data->ifd].psz = psz; + break; + } + fd_data[data->ifd].psz = 0; + + switch (data->packet_bytes) { + case 1: h = get_int8(fd_data[data->ifd].pbuf); break; + case 2: h = get_int16(fd_data[data->ifd].pbuf); break; + case 4: h = get_int32(fd_data[data->ifd].pbuf); break; + default: ASSERT(0); return; /* -1; */ + } + + if (h <= (bytes_left)) { + driver_output(data->port_num, (char*) cpos, h); + cpos += h; + bytes_left -= h; + continue; + } + else { /* The last message we got was split */ + char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h); + if (!buf) { + errno = ENOMEM; + port_inp_failure(data->port_num, ready_fd, -1); + } + else { + erts_smp_atomic_add_nob(&sys_misc_mem_sz, h); + sys_memcpy(buf, cpos, bytes_left); + fd_data[data->ifd].buf = buf; + fd_data[data->ifd].sz = h; + fd_data[data->ifd].remain = h - bytes_left; + fd_data[data->ifd].cpos = buf + bytes_left; + } + break; + } + } + } + } + + /* reset the read buffer and init next asynch read */ + DISPATCH_AIO(sig); + memset((void *)data->aiocb.aio_buf, 0, 255); + + if (res > 0) { + aio_read(&data->aiocb); + } + } + sig = erl_drv_ose_get_signal(ready_fd); } } -/* fd is the drv_data that is returned from the */ -/* initial start routine */ -/* ready_fd is the descriptor that is ready to read */ - -static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) +/* The parameter e is a pointer to the driver_data structure + * related to the fd to be used as output. + * ready_fd is the event that triggered this call to ready_input */ +static void ready_output(ErlDrvData drv_data, ErlDrvEvent ready_fd) { - int fd = (int)(long)e; - ErlDrvPort ix = driver_data[fd].port_num; - union SIGNAL *sigptr = erl_drv_ose_get_signal(ready_fd); - ssize_t n; - struct iovec* iv; - int vsize; - - while (sigptr != NULL) { - - driver_pdl_lock(driver_data[fd].pdl); - if ((iv = (struct iovec*) driver_peekq(ix, &vsize)) == NULL) { - /* fprintf(stderr,"0x%x: ready_output, unselect\n", current_process()); */ - driver_pdl_unlock(driver_data[fd].pdl); - driver_select(ix, ready_fd, ERL_DRV_WRITE, 0); - set_busy_port(ix, 0); - free_buf(&sigptr); - if ((sigptr = erl_drv_ose_get_signal(ready_fd)) == NULL) - return; /* 0; */ - continue; + SysIOVec *iov; + int vlen; + int res; + union SIGNAL *sig; + struct driver_data *data = (struct driver_data *)drv_data; + + sig = erl_drv_ose_get_signal(ready_fd); + ASSERT(sig); + + while (sig != NULL) { + if (sig->fm_write_reply.actual <= 0) { + int status; + + status = efs_status_to_errno(sig->fm_write_reply.status); + driver_select(data->port_num, ready_fd, ERL_DRV_WRITE, 0); + DISPATCH_AIO(sig); + FREE_AIO(sig->fm_write_reply.buffer); + + driver_failure_posix(data->port_num, status); } - driver_pdl_unlock(driver_data[fd].pdl); - n = sigptr->sys_async.res; - if (n < 0) { - if (errno == ERRNO_BLOCK || errno == EINTR) { - /* fprintf(stderr,"0x%x: ready_output, send to %x\n", current_process(),driver_data[fd].out_proc);*/ - send(&sigptr,driver_data[fd].out_proc); - if ((sigptr = erl_drv_ose_get_signal(ready_fd)) == NULL) - return; /* 0; */ - continue; - } else { - int res = sigptr->sys_async.errno_copy; - /* fprintf(stderr,"0x%x: ready_output, error\n", current_process()); */ - free_buf(&sigptr); - driver_select(ix, ready_fd, ERL_DRV_WRITE, 0); - driver_failure_posix(ix, res); - if ((sigptr = erl_drv_ose_get_signal(ready_fd)) == NULL) - return; /* -1; */ - continue; - } - } else { - int remain; - driver_pdl_lock(driver_data[fd].pdl); - if ((remain = driver_deq(driver_data[fd].port_num, n)) == -1) - abort(); - /* fprintf(stderr, "0x%x: ready_output, %d to %x, remain %d\n", current_process(), - n, driver_data[fd].out_proc, remain); */ - driver_pdl_unlock(driver_data[fd].pdl); - if (remain != 0) - send(&sigptr, driver_data[fd].out_proc); - else - continue; + else { /* written bytes > 0 */ + iov = driver_peekq(data->port_num, &vlen); + if (vlen > 0) { + DISPATCH_AIO(sig); + FREE_AIO(sig->fm_write_reply.buffer); + res = driver_deq(data->port_num, iov[0].iov_len); + if (res > 0) { + iov = driver_peekq(data->port_num, &vlen); + WRITE_AIO(data->ofd, iov[0].iov_len, iov[0].iov_base); + } + } } - sigptr = erl_drv_ose_get_signal(ready_fd); - } - return; /* 0; */ + sig = erl_drv_ose_get_signal(ready_fd); + } } -static void stop_select(ErlDrvEvent fd, void* _) +static void stop_select(ErlDrvEvent ready_fd, void* _) { - close((int)fd); + int *fd; + erl_drv_ose_event_fetch(ready_fd, NULL, NULL, (void **)&fd); + erl_drv_ose_event_free(ready_fd); + close(*fd); } @@ -1690,42 +1677,16 @@ erl_debug(char* fmt, ...) static ERTS_INLINE void report_exit_status(ErtsSysReportExit *rep, int status) { - Port *pp; -#ifdef ERTS_SMP - CHLD_STAT_UNLOCK; - pp = erts_thr_id2port_sflgs(rep->port, - ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP); - CHLD_STAT_LOCK; -#else - pp = erts_id2port_sflgs(rep->port, - NULL, - 0, - ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP); -#endif - if (pp) { - if (rep->ifd >= 0) { - driver_data[rep->ifd].alive = 0; - driver_data[rep->ifd].status = status; - (void) driver_select(ERTS_Port2ErlDrvPort(pp), - rep->in_sig_descr, - (ERL_DRV_READ|ERL_DRV_USE), - 1); - } - if (rep->ofd >= 0) { - driver_data[rep->ofd].alive = 0; - driver_data[rep->ofd].status = status; - (void) driver_select(ERTS_Port2ErlDrvPort(pp), - rep->out_sig_descr, - (ERL_DRV_WRITE|ERL_DRV_USE), - 1); - } -#ifdef ERTS_SMP - erts_thr_port_release(pp); -#else - erts_port_release(pp); -#endif - } - erts_free(ERTS_ALC_T_PRT_REP_EXIT, rep); + if (rep->ifd >= 0) { + driver_data[rep->ifd].alive = 0; + driver_data[rep->ifd].status = status; + } + if (rep->ofd >= 0) { + driver_data[rep->ofd].alive = 0; + driver_data[rep->ofd].status = status; + } + + erts_free(ERTS_ALC_T_PRT_REP_EXIT, rep); } #define ERTS_REPORT_EXIT_STATUS report_exit_status -- cgit v1.2.3