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. --- lib/asn1/Makefile | 2 +- lib/asn1/c_src/Makefile | 7 +++++++ lib/asn1/c_src/asn1_erl_nif.c | 1 + lib/crypto/c_src/Makefile.in | 7 +++++++ lib/erl_interface/aclocal.m4 | 41 ++++++++++++++++++++++++++++++++----- lib/hipe/cerl/erl_bif_types.erl | 3 ++- lib/megaco/aclocal.m4 | 41 ++++++++++++++++++++++++++++++++----- lib/odbc/aclocal.m4 | 41 ++++++++++++++++++++++++++++++++----- lib/runtime_tools/c_src/Makefile.in | 7 +++++++ lib/stdlib/src/filename.erl | 6 ++++-- lib/tools/c_src/Makefile.in | 8 ++++++++ lib/wx/aclocal.m4 | 41 ++++++++++++++++++++++++++++++++----- 12 files changed, 181 insertions(+), 24 deletions(-) (limited to 'lib') diff --git a/lib/asn1/Makefile b/lib/asn1/Makefile index 1bc303b73c..18e95a2471 100644 --- a/lib/asn1/Makefile +++ b/lib/asn1/Makefile @@ -25,6 +25,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk # SUB_DIRECTORIES = src doc/src c_src + static_lib: SUB_DIRECTORIES = c_src @@ -62,7 +63,6 @@ info: version: @echo "$(VSN)" - # ---------------------------------------------------- # Application (source) release targets # ---------------------------------------------------- diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile index ded4b73d1b..a7cd03f516 100644 --- a/lib/asn1/c_src/Makefile +++ b/lib/asn1/c_src/Makefile @@ -96,7 +96,12 @@ endif _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) +ifneq ($(findstring ose,$(TARGET)),ose) opt: $(NIF_SHARED_OBJ_FILE) +else +# Do not build dynamic files on OSE +opt: +endif debug: opt @@ -134,7 +139,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" +ifneq ($(findstring ose,$(TARGET)),ose) $(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) "$(RELSYSDIR)/priv/lib" +endif $(INSTALL_DIR) "$(RELSYSDIR)/c_src" $(INSTALL_DATA) *.c "$(RELSYSDIR)/c_src" diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c index 0930010fda..8a0e4b1cf0 100644 --- a/lib/asn1/c_src/asn1_erl_nif.c +++ b/lib/asn1/c_src/asn1_erl_nif.c @@ -1320,6 +1320,7 @@ static void unload(ErlNifEnv* env, void* priv_data) { } + static ErlNifFunc nif_funcs[] = { { "encode_per_complete", 1, encode_per_complete }, { "decode_ber_tlv_raw", 1, decode_ber_tlv_raw }, diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in index 124d088056..8c92b5ba1b 100644 --- a/lib/crypto/c_src/Makefile.in +++ b/lib/crypto/c_src/Makefile.in @@ -126,7 +126,12 @@ ALL_STATIC_CFLAGS = $(DED_STATIC_CFLAGS) $(INCLUDES) _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) +ifneq ($(findstring ose,$(TARGET)),ose) debug opt valgrind: $(NIF_LIB) $(CALLBACK_LIB) +else +# Do not build dynamic files on OSE +debug opt valgrind: +endif static_lib: $(NIF_ARCHIVE) @@ -197,12 +202,14 @@ release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj" $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" $(INSTALL_DATA) $(NIF_MAKEFILE) "$(RELSYSDIR)/priv/obj" +ifneq ($(findstring ose,$(TARGET)),ose) $(INSTALL_PROGRAM) $(CRYPTO_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(NIF_LIB) "$(RELSYSDIR)/priv/lib" ifeq ($(DYNAMIC_CRYPTO_LIB),yes) $(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(CALLBACK_LIB) "$(RELSYSDIR)/priv/lib" endif +endif release_docs_spec: diff --git a/lib/erl_interface/aclocal.m4 b/lib/erl_interface/aclocal.m4 index 46b30a16b3..4a3407e0eb 100644 --- a/lib/erl_interface/aclocal.m4 +++ b/lib/erl_interface/aclocal.m4 @@ -74,6 +74,17 @@ AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for re AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)]) AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)]) +dnl Cross compilation variables for OSE +AC_ARG_VAR(erl_xcomp_ose_ldflags_pass1, [Linker flags for the OSE module (pass 1) (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_ldflags_pass2, [Linker flags for the OSE module (pass 2) (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_OSEROOT, [OSE installation root directory (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_STRIP, [Strip utility shipped with the OSE distribution(only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_POST_LINK, [OSE postlink tool (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_SET_CONF, [Sets the configuration for an OSE load module (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_ELF_SIZE, [Prints the section size information for an OSE load module (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_LCF, [OSE load module linker configuration file (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_CONF, [OSE load module default configuration file (only used when cross compiling for OSE)]) + ]) AC_DEFUN(ERL_XCOMP_SYSROOT_INIT, @@ -488,6 +499,8 @@ AC_CACHE_VAL(ac_cv_sys_ipv6_support, #ifdef __WIN32__ #include #include +#elif __OSE__ +#error "no ipv6" #else #include #endif], @@ -500,6 +513,8 @@ else #ifdef __WIN32__ #include #include +#elif __OSE__ +#error "no ipv6" #else #include #endif], @@ -728,6 +743,12 @@ if test "X$host_os" = "Xwin32"; then THR_LIBS= THR_LIB_NAME=win32_threads THR_LIB_TYPE=win32_threads +elif test "X$host_os" = "Xose"; then + AC_MSG_RESULT(yes) + THR_DEFS="-DOSE_THREADS" + THR_LIBS= + THR_LIB_NAME=ose_threads + THR_LIB_TYPE=ose_threads else AC_MSG_RESULT(no) THR_DEFS= @@ -1078,9 +1099,17 @@ case "$THR_LIB_NAME" in test "$ethr_have_native_atomics" = "yes" && ethr_have_native_spinlock=yes ;; - pthread) - ETHR_THR_LIB_BASE_DIR=pthread - AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) + pthread|ose_threads) + case "$THR_LIB_NAME" in + pthread) + ETHR_THR_LIB_BASE_DIR=pthread + AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) + ;; + ose_threads) + AC_DEFINE(ETHR_OSE_THREADS, 1, [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose + ;; + esac + if test "x$THR_LIB_NAME" == "xpthread"; then case $host_os in openbsd*) # The default stack size is insufficient for our needs @@ -1139,6 +1168,7 @@ case "$THR_LIB_NAME" in *) ;; esac + fi dnl We sometimes need ETHR_DEFS in order to find certain headers dnl (at least for pthread.h on osf1). saved_cppflags="$CPPFLAGS" @@ -1151,7 +1181,6 @@ case "$THR_LIB_NAME" in dnl dnl Check for headers dnl - AC_CHECK_HEADER(pthread.h, \ AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \ [Define if you have the header file.])) @@ -1184,7 +1213,7 @@ case "$THR_LIB_NAME" in dnl dnl Check for functions dnl - + if test "x$THR_LIB_NAME" == "xpthread"; then AC_CHECK_FUNC(pthread_spin_lock, \ [ethr_have_native_spinlock=yes \ AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \ @@ -1311,6 +1340,8 @@ case "$THR_LIB_NAME" in AC_MSG_RESULT([$linux_futex]) test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.]) + fi + AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 8b610ac893..0512d4bc3c 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -912,7 +912,8 @@ type(erlang, system_info, 1, Xs, Opaques) -> t_list(t_pid()); ['os_type'] -> t_tuple([t_sup([t_atom('unix'), - t_atom('win32')]), + t_atom('win32'), + t_atom('ose')]), t_atom()]); ['os_version'] -> t_sup(t_tuple([t_non_neg_fixnum(), diff --git a/lib/megaco/aclocal.m4 b/lib/megaco/aclocal.m4 index 46b30a16b3..4a3407e0eb 100644 --- a/lib/megaco/aclocal.m4 +++ b/lib/megaco/aclocal.m4 @@ -74,6 +74,17 @@ AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for re AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)]) AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)]) +dnl Cross compilation variables for OSE +AC_ARG_VAR(erl_xcomp_ose_ldflags_pass1, [Linker flags for the OSE module (pass 1) (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_ldflags_pass2, [Linker flags for the OSE module (pass 2) (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_OSEROOT, [OSE installation root directory (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_STRIP, [Strip utility shipped with the OSE distribution(only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_POST_LINK, [OSE postlink tool (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_SET_CONF, [Sets the configuration for an OSE load module (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_ELF_SIZE, [Prints the section size information for an OSE load module (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_LCF, [OSE load module linker configuration file (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_CONF, [OSE load module default configuration file (only used when cross compiling for OSE)]) + ]) AC_DEFUN(ERL_XCOMP_SYSROOT_INIT, @@ -488,6 +499,8 @@ AC_CACHE_VAL(ac_cv_sys_ipv6_support, #ifdef __WIN32__ #include #include +#elif __OSE__ +#error "no ipv6" #else #include #endif], @@ -500,6 +513,8 @@ else #ifdef __WIN32__ #include #include +#elif __OSE__ +#error "no ipv6" #else #include #endif], @@ -728,6 +743,12 @@ if test "X$host_os" = "Xwin32"; then THR_LIBS= THR_LIB_NAME=win32_threads THR_LIB_TYPE=win32_threads +elif test "X$host_os" = "Xose"; then + AC_MSG_RESULT(yes) + THR_DEFS="-DOSE_THREADS" + THR_LIBS= + THR_LIB_NAME=ose_threads + THR_LIB_TYPE=ose_threads else AC_MSG_RESULT(no) THR_DEFS= @@ -1078,9 +1099,17 @@ case "$THR_LIB_NAME" in test "$ethr_have_native_atomics" = "yes" && ethr_have_native_spinlock=yes ;; - pthread) - ETHR_THR_LIB_BASE_DIR=pthread - AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) + pthread|ose_threads) + case "$THR_LIB_NAME" in + pthread) + ETHR_THR_LIB_BASE_DIR=pthread + AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) + ;; + ose_threads) + AC_DEFINE(ETHR_OSE_THREADS, 1, [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose + ;; + esac + if test "x$THR_LIB_NAME" == "xpthread"; then case $host_os in openbsd*) # The default stack size is insufficient for our needs @@ -1139,6 +1168,7 @@ case "$THR_LIB_NAME" in *) ;; esac + fi dnl We sometimes need ETHR_DEFS in order to find certain headers dnl (at least for pthread.h on osf1). saved_cppflags="$CPPFLAGS" @@ -1151,7 +1181,6 @@ case "$THR_LIB_NAME" in dnl dnl Check for headers dnl - AC_CHECK_HEADER(pthread.h, \ AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \ [Define if you have the header file.])) @@ -1184,7 +1213,7 @@ case "$THR_LIB_NAME" in dnl dnl Check for functions dnl - + if test "x$THR_LIB_NAME" == "xpthread"; then AC_CHECK_FUNC(pthread_spin_lock, \ [ethr_have_native_spinlock=yes \ AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \ @@ -1311,6 +1340,8 @@ case "$THR_LIB_NAME" in AC_MSG_RESULT([$linux_futex]) test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.]) + fi + AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) diff --git a/lib/odbc/aclocal.m4 b/lib/odbc/aclocal.m4 index 46b30a16b3..4a3407e0eb 100644 --- a/lib/odbc/aclocal.m4 +++ b/lib/odbc/aclocal.m4 @@ -74,6 +74,17 @@ AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for re AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)]) AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)]) +dnl Cross compilation variables for OSE +AC_ARG_VAR(erl_xcomp_ose_ldflags_pass1, [Linker flags for the OSE module (pass 1) (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_ldflags_pass2, [Linker flags for the OSE module (pass 2) (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_OSEROOT, [OSE installation root directory (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_STRIP, [Strip utility shipped with the OSE distribution(only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_POST_LINK, [OSE postlink tool (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_SET_CONF, [Sets the configuration for an OSE load module (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_ELF_SIZE, [Prints the section size information for an OSE load module (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_LCF, [OSE load module linker configuration file (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_CONF, [OSE load module default configuration file (only used when cross compiling for OSE)]) + ]) AC_DEFUN(ERL_XCOMP_SYSROOT_INIT, @@ -488,6 +499,8 @@ AC_CACHE_VAL(ac_cv_sys_ipv6_support, #ifdef __WIN32__ #include #include +#elif __OSE__ +#error "no ipv6" #else #include #endif], @@ -500,6 +513,8 @@ else #ifdef __WIN32__ #include #include +#elif __OSE__ +#error "no ipv6" #else #include #endif], @@ -728,6 +743,12 @@ if test "X$host_os" = "Xwin32"; then THR_LIBS= THR_LIB_NAME=win32_threads THR_LIB_TYPE=win32_threads +elif test "X$host_os" = "Xose"; then + AC_MSG_RESULT(yes) + THR_DEFS="-DOSE_THREADS" + THR_LIBS= + THR_LIB_NAME=ose_threads + THR_LIB_TYPE=ose_threads else AC_MSG_RESULT(no) THR_DEFS= @@ -1078,9 +1099,17 @@ case "$THR_LIB_NAME" in test "$ethr_have_native_atomics" = "yes" && ethr_have_native_spinlock=yes ;; - pthread) - ETHR_THR_LIB_BASE_DIR=pthread - AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) + pthread|ose_threads) + case "$THR_LIB_NAME" in + pthread) + ETHR_THR_LIB_BASE_DIR=pthread + AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) + ;; + ose_threads) + AC_DEFINE(ETHR_OSE_THREADS, 1, [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose + ;; + esac + if test "x$THR_LIB_NAME" == "xpthread"; then case $host_os in openbsd*) # The default stack size is insufficient for our needs @@ -1139,6 +1168,7 @@ case "$THR_LIB_NAME" in *) ;; esac + fi dnl We sometimes need ETHR_DEFS in order to find certain headers dnl (at least for pthread.h on osf1). saved_cppflags="$CPPFLAGS" @@ -1151,7 +1181,6 @@ case "$THR_LIB_NAME" in dnl dnl Check for headers dnl - AC_CHECK_HEADER(pthread.h, \ AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \ [Define if you have the header file.])) @@ -1184,7 +1213,7 @@ case "$THR_LIB_NAME" in dnl dnl Check for functions dnl - + if test "x$THR_LIB_NAME" == "xpthread"; then AC_CHECK_FUNC(pthread_spin_lock, \ [ethr_have_native_spinlock=yes \ AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \ @@ -1311,6 +1340,8 @@ case "$THR_LIB_NAME" in AC_MSG_RESULT([$linux_futex]) test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.]) + fi + AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in index 2bcb93b4dd..d46b4997f7 100644 --- a/lib/runtime_tools/c_src/Makefile.in +++ b/lib/runtime_tools/c_src/Makefile.in @@ -101,7 +101,12 @@ endif _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) +ifneq ($(findstring ose,$(TARGET)),ose) debug opt valgrind: $(SOLIBS) $(OBJDIR) $(LIBDIR) $(NIF_LIB) +else +# We do not build this on OSE +debug opt valgrind: +endif DYNTRACE_OBJS = $(before_DTrace_OBJS) @@ -153,8 +158,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj" $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" +ifneq ($(findstring ose,$(TARGET)),ose) $(INSTALL_PROGRAM) $(DYNTRACE_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(NIF_LIB) $(SOLIBS) "$(RELSYSDIR)/priv/lib" +endif release_docs_spec: diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl index 66e54ef221..e6bde5673c 100644 --- a/lib/stdlib/src/filename.erl +++ b/lib/stdlib/src/filename.erl @@ -516,8 +516,10 @@ pathtype(Atom) when is_atom(Atom) -> pathtype(atom_to_list(Atom)); pathtype(Name) when is_list(Name) or is_binary(Name) -> case os:type() of - {unix, _} -> unix_pathtype(Name); - {win32, _} -> win32_pathtype(Name) + {win32, _} -> + win32_pathtype(Name); + {_, _} -> + unix_pathtype(Name) end. unix_pathtype(<<$/,_/binary>>) -> diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in index aea5686ae9..b1eb69f9dc 100644 --- a/lib/tools/c_src/Makefile.in +++ b/lib/tools/c_src/Makefile.in @@ -96,8 +96,11 @@ DRIVERS= ifneq ($(strip $(ETHR_LIB_NAME)),) # Need ethread package for emem +ifneq ($(findstring ose,$(TARGET)),ose) +# Do not build on OSE PROGS += $(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@ endif +endif EMEM_OBJ_DIR=$(OBJ_DIR)/emem CREATE_DIRS += $(EMEM_OBJ_DIR) @@ -148,7 +151,12 @@ ERTS_LIB = $(ERL_TOP/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE _create_dirs := $(shell mkdir -p $(CREATE_DIRS)) +ifneq ($(findstring ose,$(TARGET)),ose) all: $(PROGS) $(DRIVERS) +else +# Do not build dynamic files on OSE +all: +endif $(ERTS_LIB): $(make_verbose)cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE) diff --git a/lib/wx/aclocal.m4 b/lib/wx/aclocal.m4 index 46b30a16b3..4a3407e0eb 100644 --- a/lib/wx/aclocal.m4 +++ b/lib/wx/aclocal.m4 @@ -74,6 +74,17 @@ AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for re AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)]) AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)]) +dnl Cross compilation variables for OSE +AC_ARG_VAR(erl_xcomp_ose_ldflags_pass1, [Linker flags for the OSE module (pass 1) (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_ldflags_pass2, [Linker flags for the OSE module (pass 2) (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_OSEROOT, [OSE installation root directory (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_STRIP, [Strip utility shipped with the OSE distribution(only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_POST_LINK, [OSE postlink tool (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_SET_CONF, [Sets the configuration for an OSE load module (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_ELF_SIZE, [Prints the section size information for an OSE load module (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_LCF, [OSE load module linker configuration file (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_LM_CONF, [OSE load module default configuration file (only used when cross compiling for OSE)]) + ]) AC_DEFUN(ERL_XCOMP_SYSROOT_INIT, @@ -488,6 +499,8 @@ AC_CACHE_VAL(ac_cv_sys_ipv6_support, #ifdef __WIN32__ #include #include +#elif __OSE__ +#error "no ipv6" #else #include #endif], @@ -500,6 +513,8 @@ else #ifdef __WIN32__ #include #include +#elif __OSE__ +#error "no ipv6" #else #include #endif], @@ -728,6 +743,12 @@ if test "X$host_os" = "Xwin32"; then THR_LIBS= THR_LIB_NAME=win32_threads THR_LIB_TYPE=win32_threads +elif test "X$host_os" = "Xose"; then + AC_MSG_RESULT(yes) + THR_DEFS="-DOSE_THREADS" + THR_LIBS= + THR_LIB_NAME=ose_threads + THR_LIB_TYPE=ose_threads else AC_MSG_RESULT(no) THR_DEFS= @@ -1078,9 +1099,17 @@ case "$THR_LIB_NAME" in test "$ethr_have_native_atomics" = "yes" && ethr_have_native_spinlock=yes ;; - pthread) - ETHR_THR_LIB_BASE_DIR=pthread - AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) + pthread|ose_threads) + case "$THR_LIB_NAME" in + pthread) + ETHR_THR_LIB_BASE_DIR=pthread + AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) + ;; + ose_threads) + AC_DEFINE(ETHR_OSE_THREADS, 1, [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose + ;; + esac + if test "x$THR_LIB_NAME" == "xpthread"; then case $host_os in openbsd*) # The default stack size is insufficient for our needs @@ -1139,6 +1168,7 @@ case "$THR_LIB_NAME" in *) ;; esac + fi dnl We sometimes need ETHR_DEFS in order to find certain headers dnl (at least for pthread.h on osf1). saved_cppflags="$CPPFLAGS" @@ -1151,7 +1181,6 @@ case "$THR_LIB_NAME" in dnl dnl Check for headers dnl - AC_CHECK_HEADER(pthread.h, \ AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \ [Define if you have the header file.])) @@ -1184,7 +1213,7 @@ case "$THR_LIB_NAME" in dnl dnl Check for functions dnl - + if test "x$THR_LIB_NAME" == "xpthread"; then AC_CHECK_FUNC(pthread_spin_lock, \ [ethr_have_native_spinlock=yes \ AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \ @@ -1311,6 +1340,8 @@ case "$THR_LIB_NAME" in AC_MSG_RESULT([$linux_futex]) test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.]) + fi + AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) -- cgit v1.2.3 From 06928bcd1ff6ede831bb36395ab94761c85d780b Mon Sep 17 00:00:00 2001 From: Rasmuss Graaf Date: Wed, 28 Aug 2013 17:51:59 +0200 Subject: ose: Adapt suite for OSE --- lib/kernel/test/prim_file_SUITE.erl | 52 ++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 199e597e78..ccf325a493 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -78,7 +78,7 @@ _ -> apply(?PRIM_FILE, F, [H | A]) end). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> []. all() -> [read_write_file, {group, dirs}, {group, files}, @@ -407,11 +407,11 @@ cur_dir_1(Config, Handle) -> ?line Dog = test_server:timetrap(test_server:seconds(5)), ?line case os:type() of - {unix, _} -> - ?line {error, enotsup} = - ?PRIM_FILE_call(get_cwd, Handle, ["d:"]); {win32, _} -> - win_cur_dir_1(Config, Handle) + win_cur_dir_1(Config, Handle); + _ -> + ?line {error, enotsup} = + ?PRIM_FILE_call(get_cwd, Handle, ["d:"]) end, ?line test_server:timetrap_cancel(Dog), ok. @@ -843,7 +843,7 @@ file_info_basic_directory(Config, Handle) -> ?line test_directory("/", read_write, Handle), ?line test_directory("c:/", read_write, Handle), ?line test_directory("c:\\", read_write, Handle); - {unix, _} -> + _ -> ?line test_directory("/", read, Handle) end, ?line test_server:timetrap_cancel(Dog). @@ -1568,15 +1568,15 @@ e_delete(Config) when is_list(Config) -> %% No permission. ?line case os:type() of - {unix, _} -> + {win32, _} -> + %% Remove a character device. + ?line {error, eacces} = ?PRIM_FILE:delete("nul"); + _ -> ?line ?PRIM_FILE:write_file_info( Base, #file_info {mode=0}), ?line {error, eacces} = ?PRIM_FILE:delete(Afile), ?line ?PRIM_FILE:write_file_info( - Base, #file_info {mode=8#600}); - {win32, _} -> - %% Remove a character device. - ?line {error, eacces} = ?PRIM_FILE:delete("nul") + Base, #file_info {mode=8#600}) end, ?line test_server:timetrap_cancel(Dog), @@ -1656,7 +1656,12 @@ e_rename(Config) when is_list(Config) -> %% XXX - Gross hack! ?line Comment = case os:type() of - {unix, _} -> + {win32, _} -> + %% At least Windows NT can + %% successfully move a file to + %% another drive. + ok; + _ -> OtherFs = "/tmp", ?line NameOnOtherFs = filename:join(OtherFs, @@ -1680,12 +1685,7 @@ e_rename(Config) when is_list(Config) -> Else -> Else end, - Com; - {win32, _} -> - %% At least Windows NT can - %% successfully move a file to - %% another drive. - ok + Com end, ?line test_server:timetrap_cancel(Dog), Comment. @@ -1714,14 +1714,14 @@ e_make_dir(Config) when is_list(Config) -> %% No permission (on Unix only). case os:type() of - {unix, _} -> + {win32, _} -> + ok; + _ -> ?line ?PRIM_FILE:write_file_info(Base, #file_info {mode=0}), ?line {error, eacces} = ?PRIM_FILE:make_dir(filename:join(Base, "xxxx")), ?line - ?PRIM_FILE:write_file_info(Base, #file_info {mode=8#600}); - {win32, _} -> - ok + ?PRIM_FILE:write_file_info(Base, #file_info {mode=8#600}) end, ?line test_server:timetrap_cancel(Dog), ok. @@ -1767,15 +1767,15 @@ e_del_dir(Config) when is_list(Config) -> %% No permission. case os:type() of - {unix, _} -> + {win32, _} -> + ok; + _ -> ?line ADirectory = filename:join(Base, "no_perm"), ?line ok = ?PRIM_FILE:make_dir(ADirectory), ?line ?PRIM_FILE:write_file_info(Base, #file_info {mode=0}), ?line {error, eacces} = ?PRIM_FILE:del_dir(ADirectory), ?line ?PRIM_FILE:write_file_info( - Base, #file_info {mode=8#600}); - {win32, _} -> - ok + Base, #file_info {mode=8#600}) end, ?line test_server:timetrap_cancel(Dog), ok. -- cgit v1.2.3 From f8cfcf356cf2f8c573713fc89883bb99003f242c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 9 Oct 2013 11:55:26 +0200 Subject: ose: Fix stdlib testcases --- lib/stdlib/test/filename_SUITE.erl | 53 ++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl index 232df6a13f..ecd9cff9f9 100644 --- a/lib/stdlib/test/filename_SUITE.erl +++ b/lib/stdlib/test/filename_SUITE.erl @@ -96,11 +96,19 @@ absname(Config) when is_list(Config) -> ?line file:set_cwd(Cwd), ok; - {unix, _} -> - ?line ok = file:set_cwd("/usr"), - ?line "/usr/foo" = filename:absname(foo), - ?line "/usr/foo" = filename:absname("foo"), - ?line "/usr/../ebin" = filename:absname("../ebin"), + Type -> + case Type of + {unix, _} -> + ?line ok = file:set_cwd("/usr"), + ?line "/usr/foo" = filename:absname(foo), + ?line "/usr/foo" = filename:absname("foo"), + ?line "/usr/../ebin" = filename:absname("../ebin"); + {ose, _} -> + ?line ok = file:set_cwd("/romfs"), + ?line "/romfs/foo" = filename:absname(foo), + ?line "/romfs/foo" = filename:absname("foo"), + ?line "/romfs/../ebin" = filename:absname("../ebin") + end, ?line file:set_cwd("/"), ?line "/foo" = filename:absname(foo), @@ -155,7 +163,7 @@ absname_2(Config) when is_list(Config) -> ?line "a:/erlang" = filename:absname("a:erlang", [Drive|":/"]), ok; - {unix, _} -> + _ -> ?line "/usr/foo" = filename:absname(foo, "/usr"), ?line "/usr/foo" = filename:absname("foo", "/usr"), ?line "/usr/../ebin" = filename:absname("../ebin", "/usr"), @@ -189,7 +197,7 @@ basename_1(Config) when is_list(Config) -> ?line "foo" = filename:basename(["usr\\foo\\"]), ?line "foo" = filename:basename("A:\\usr\\foo"), ?line "foo" = filename:basename("A:foo"); - {unix, _} -> + _ -> ?line "strange\\but\\true" = filename:basename("strange\\but\\true") end, @@ -219,7 +227,7 @@ basename_2(Config) when is_list(Config) -> ?line "foo.erl" = filename:basename("c:\\usr.hrl\\foo.erl", ".hrl"), ?line "foo" = filename:basename("A:\\usr\\foo", ".hrl"); - {unix, _} -> + _ -> ?line "strange\\but\\true" = filename:basename("strange\\but\\true.erl", ".erl"), ?line "strange\\but\\true" = @@ -317,7 +325,7 @@ join(Config) when is_list(Config) -> filename:join(["A:","C:usr","foo.erl"]), ?line "d:/foo" = filename:join([$D, $:, $/, []], "foo"), ok; - {unix, _} -> + _ -> ok end. @@ -332,7 +340,7 @@ pathtype(Config) when is_list(Config) -> ?line volumerelative = filename:pathtype("/usr/local/bin"), ?line volumerelative = filename:pathtype("A:usr/local/bin"), ok; - {unix, _} -> + _ -> ?line absolute = filename:pathtype("/"), ?line absolute = filename:pathtype("/usr/local/bin"), ok @@ -450,10 +458,17 @@ absname_bin(Config) when is_list(Config) -> ?line file:set_cwd(Cwd), ok; - {unix, _} -> - ?line ok = file:set_cwd(<<"/usr">>), - ?line <<"/usr/foo">> = filename:absname(<<"foo">>), - ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>), + Type -> + case Type of + {unix,_} -> + ?line ok = file:set_cwd(<<"/usr">>), + ?line <<"/usr/foo">> = filename:absname(<<"foo">>), + ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>); + {ose,_} -> + ?line ok = file:set_cwd(<<"/romfs">>), + ?line <<"/romfs/foo">> = filename:absname(<<"foo">>), + ?line <<"/romfs/../ebin">> = filename:absname(<<"../ebin">>) + end, ?line file:set_cwd(<<"/">>), ?line <<"/foo">> = filename:absname(<<"foo">>), @@ -503,7 +518,7 @@ absname_bin_2(Config) when is_list(Config) -> ?line <<"a:/erlang">> = filename:absname(<<"a:erlang">>, <>), ok; - {unix, _} -> + _ -> ?line <<"/usr/foo">> = filename:absname(<<"foo">>, <<"/usr">>), ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>, <<"/usr">>), @@ -527,7 +542,7 @@ basename_bin_1(Config) when is_list(Config) -> {win32, _} -> ?line <<"foo">> = filename:basename(<<"A:\\usr\\foo">>), ?line <<"foo">> = filename:basename(<<"A:foo">>); - {unix, _} -> + _ -> ?line <<"strange\\but\\true">> = filename:basename(<<"strange\\but\\true">>) end, @@ -551,7 +566,7 @@ basename_bin_2(Config) when is_list(Config) -> ?line <<"foo.erl">> = filename:basename(<<"c:\\usr.hrl\\foo.erl">>, <<".hrl">>), ?line <<"foo">> = filename:basename(<<"A:\\usr\\foo">>, <<".hrl">>); - {unix, _} -> + _ -> ?line <<"strange\\but\\true">> = filename:basename(<<"strange\\but\\true.erl">>, <<".erl">>), ?line <<"strange\\but\\true">> = @@ -639,7 +654,7 @@ join_bin(Config) when is_list(Config) -> filename:join([<<"A:">>,<<"C:usr">>,<<"foo.erl">>]), ?line <<"d:/foo">> = filename:join([$D, $:, $/, []], <<"foo">>), ok; - {unix, _} -> + _ -> ok end. @@ -653,7 +668,7 @@ pathtype_bin(Config) when is_list(Config) -> volumerelative = filename:pathtype(<<"/usr/local/bin">>), volumerelative = filename:pathtype(<<"A:usr/local/bin">>), ok; - {unix, _} -> + _ -> absolute = filename:pathtype(<<"/">>), absolute = filename:pathtype(<<"/usr/local/bin">>), ok -- 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. --- lib/kernel/doc/src/Makefile | 27 +- lib/kernel/doc/src/ref_man.xml | 68 ---- lib/kernel/doc/src/ref_man.xml.src | 67 ++++ lib/kernel/src/Makefile | 4 + lib/kernel/src/ose.erl | 452 ++++++++++++++++++++++ lib/kernel/test/Makefile | 4 + lib/kernel/test/ose_SUITE.erl | 765 +++++++++++++++++++++++++++++++++++++ 7 files changed, 1316 insertions(+), 71 deletions(-) delete mode 100644 lib/kernel/doc/src/ref_man.xml create mode 100644 lib/kernel/doc/src/ref_man.xml.src create mode 100644 lib/kernel/src/ose.erl create mode 100644 lib/kernel/test/ose_SUITE.erl (limited to 'lib') diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile index de3ca1e176..7f8023aba4 100644 --- a/lib/kernel/doc/src/Makefile +++ b/lib/kernel/doc/src/Makefile @@ -31,6 +31,12 @@ APPLICATION=kernel # ---------------------------------------------------- RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) +# ---------------------------------------------------- +# Help application directory specification +# ---------------------------------------------------- +EDOC_DIR = $(ERL_TOP)/lib/edoc +SYNTAX_TOOLS_DIR = $(ERL_TOP)/lib/syntax_tools + # ---------------------------------------------------- # Target Specs # ---------------------------------------------------- @@ -65,6 +71,12 @@ XML_REF3_FILES = application.xml \ user.xml \ zlib_stub.xml +ifeq ($(findstring ose,$(TARGET)),ose) +XML_EDOC_FILES = ose.xml +else +XML_EDOC_FILES = +endif + XML_REF4_FILES = app.xml config.xml XML_REF6_FILES = kernel_app.xml @@ -76,8 +88,8 @@ BOOK_FILES = book.xml XML_FILES = \ $(BOOK_FILES) $(XML_CHAPTER_FILES) \ - $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF4_FILES) \ - $(XML_REF6_FILES) $(XML_APPLICATION_FILES) + $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_EDOC_FILES)\ + $(XML_REF4_FILES) $(XML_REF6_FILES) $(XML_APPLICATION_FILES) # ---------------------------------------------------- @@ -103,7 +115,7 @@ TOP_SPECS_FILE = specs.xml # ---------------------------------------------------- XML_FLAGS += -SPECS_ESRC = ../../src +SRC_DIR = ../../src SPECS_FLAGS = -I../../include @@ -148,6 +160,15 @@ $(SPECDIR)/specs_zlib_stub.xml: escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ -o$(dir $@) -module zlib_stub +ose.xml: $(SRC_DIR)/ose.erl + escript $(DOCGEN)/priv/bin/xml_from_edoc.escript $(SRC_DIR)/$(@:%.xml=%.erl) +ref_man.xml: ref_man.xml.src +ifeq ($(findstring ose,$(TARGET)),ose) + sed -e 's:\(os.xml"/>\):\1\n:' $< > $@ +else + cp $< $@ +endif + # ---------------------------------------------------- # Release Target # ---------------------------------------------------- diff --git a/lib/kernel/doc/src/ref_man.xml b/lib/kernel/doc/src/ref_man.xml deleted file mode 100644 index c1b9eac9d7..0000000000 --- a/lib/kernel/doc/src/ref_man.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - -
- - 19962013 - Ericsson AB. 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. - - - - Kernel Reference Manual - - - - -
- -

The Kernel application has all the code necessary to run - the Erlang runtime system itself: file servers and code servers - and so on.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- diff --git a/lib/kernel/doc/src/ref_man.xml.src b/lib/kernel/doc/src/ref_man.xml.src new file mode 100644 index 0000000000..bd25d1e78d --- /dev/null +++ b/lib/kernel/doc/src/ref_man.xml.src @@ -0,0 +1,67 @@ + + + + +
+ + 19962013 + Ericsson AB. 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. + + + + Kernel Reference Manual + + + + +
+ +

The Kernel application has all the code necessary to run + the Erlang runtime system itself: file servers and code servers + and so on.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile index cb3c0a49f4..5379006784 100644 --- a/lib/kernel/src/Makefile +++ b/lib/kernel/src/Makefile @@ -117,6 +117,10 @@ MODULES = \ user_sup \ wrap_log_reader +ifeq ($(findstring ose,$(TARGET)),ose) +MODULES+=ose +endif + HRL_FILES= ../include/file.hrl ../include/inet.hrl ../include/inet_sctp.hrl \ ../include/dist.hrl ../include/dist_util.hrl \ ../include/net_address.hrl diff --git a/lib/kernel/src/ose.erl b/lib/kernel/src/ose.erl new file mode 100644 index 0000000000..ff7147233f --- /dev/null +++ b/lib/kernel/src/ose.erl @@ -0,0 +1,452 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 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% +%% +%% @doc Interface module for OSE messaging and process monitoring from Erlang +%% +%% For each mailbox created through {@link open/1} a OSE phantom process with +%% that name is started. Since phantom processes are used the memory footprint +%% of each mailbox is quite small. +%% +%% To receive messages you first have to subscribe to the specific message +%% numbers that you are interested in with {@link listen/2}. The messages +%% will be sent to the Erlang process that created the mailbox. +%% +%% @end +%% +-module(ose). + +%%============================================================================== +%% Exported API +%%============================================================================== +-export([open/1, + close/1, + get_id/1, + get_name/2, + hunt/2, + dehunt/2, + attach/2, + detach/2, + send/4, + send/5, + listen/2 + ]). + +%%============================================================================== +%% Types +%%============================================================================== +-opaque mailbox() :: port(). +%% Mailbox handle. Implemented as an erlang port. + +-opaque mailbox_id() :: integer(). +%% Mailbox ID, this is the same as the process id of an OSE process. +%% An integer. + +-type message_number() :: 0..4294967295. +%% OSE Signal number + +-opaque hunt_ref() :: {mailbox(),integer()}. +%% Reference from a hunt request. This term will be included +%% in a successful hunt response. + +-opaque attach_ref() :: {mailbox(),integer()}. +%% Reference from an attach request. This term will be included +%% in the term returned when the attached mailbox disappears. + +-export_type([mailbox_id/0, + message_number/0, + mailbox/0, + hunt_ref/0, + attach_ref/0]). + +%%============================================================================== +%% Defines +%%============================================================================== +-define(DRIVER_NAME, "ose_signal_drv"). +-define(GET_SPID, 1). +-define(GET_NAME, 2). +-define(HUNT, 100). +-define(DEHUNT, 101). +-define(ATTACH, 102). +-define(DETACH, 103). +-define(SEND, 104). +-define(SEND_W_S, 105). +-define(LISTEN, 106). +-define(OPEN, 200). + +-define(INT_32BIT(Int),(is_integer(Int) andalso (Int >= 0) andalso (Int < (1 bsl 32)))). + +%%============================================================================== +%% API functions +%%============================================================================== + +%%------------------------------------------------------------------------------ +%% @doc Create a mailbox with the given name and return a port that handles +%% the mailbox. +%% +%% An OSE phantom process with the given name will be created that will send any +%% messages sent through this mailbox. Any messages sent to the new OSE process +%% will automatically be converted to an Erlang message and sent to the Erlang +%% process that calls this function. See {@link listen/2} for details about the +%% format of the message sent. +%% +%% The caller gets linked to the created mailbox. +%% +%% raises: `badarg' | `system_limit' +%% +%% @see liten/2 +%% @end +%%------------------------------------------------------------------------------ +-spec open(Name) -> Port when + Name :: iodata(), + Port :: mailbox(). +open(Name) -> + try open_port({spawn_driver,?DRIVER_NAME}, [binary]) of + Port -> + try port_command(Port,[?OPEN,Name]) of + true -> + receive + {ose_drv_reply,Port,{error,Error}} -> + close(Port), + erlang:error(Error,[Name]); + {ose_drv_reply,Port,ok} -> + Port + end + catch + error:badarg -> close(Port),erlang:error(badarg,[Name]) + end + catch + error:badarg -> erlang:error(badarg,[Name]) + end. + +%%------------------------------------------------------------------------------ +%% @doc Close a mailbox +%% +%% This kills the OSE phantom process associated with this mailbox. +%% +%% Will also consume any ``{'EXIT',Port,_}'' message from the port that comes +%% due to the port closing when the calling process traps exits. +%% +%% raises: `badarg' +%% @end +%%------------------------------------------------------------------------------ +-spec close(Port) -> ok when + Port :: mailbox(). +close(Port) when is_port(Port) -> + %% Copied from prim_inet + case erlang:process_info(self(), trap_exit) of + {trap_exit,true} -> + link(Port), + catch erlang:port_close(Port), + receive {'EXIT',Port,_} -> ok end; + {trap_exit,false} -> + catch erlang:port_close(Port), + ok + end; +close(NotPort) -> + erlang:error(badarg,[NotPort]). + +%%------------------------------------------------------------------------------ +%% @doc Get the mailbox id for the given port. +%% +%% The mailbox id is the same as the OSE process id of the OSE phantom process +%% that this mailbox represents. +%% +%% raises: `badarg' +%% @end +%%------------------------------------------------------------------------------ +-spec get_id(Port) -> Pid when + Port :: mailbox(), + Pid :: mailbox_id(). +get_id(Port) -> + try port_control(Port, ?GET_SPID, <<>>) of + <> -> Spid + catch error:_Error -> + erlang:error(badarg,[Port]) + end. + +%%------------------------------------------------------------------------------ +%% @doc Get the mailbox name for the given mailbox id. +%% +%% The mailbox name is the name of the OSE process with process id Pid. +%% +%% This call will fail with badarg if the underlying system does not support +%% getting the name from a process id. +%% +%% raises: `badarg' +%% @end +%%------------------------------------------------------------------------------ +-spec get_name(Port, Pid) -> Name | undefined when + Port :: mailbox(), + Pid :: mailbox_id(), + Name :: binary(). +get_name(Port, Pid) when ?INT_32BIT(Pid) -> + try port_control(Port, ?GET_NAME, <>) of + [] -> undefined; + Res -> Res + catch error:_Error -> + erlang:error(badarg,[Port,Pid]) + end; +get_name(Port, Pid) -> + erlang:error(badarg,[Port,Pid]). + + +%%------------------------------------------------------------------------------ +%% @doc Hunt for OSE process by name. +%% +%% Will send `{mailbox_up, Port, Ref, MboxId}' +%% to the calling process when the OSE process becomes available. +%% +%% Returns a reference term that can be used to cancel the hunt +%% using {@link dehunt/2}. +%% +%% raises: `badarg' +%% +%% @end +%%------------------------------------------------------------------------------ +-spec hunt(Port, HuntPath) -> Ref when + Port :: mailbox(), + HuntPath :: iodata(), + Ref :: hunt_ref(). +hunt(Port, HuntPath) -> + try port_command(Port, [?HUNT,HuntPath]) of + true -> + receive + {ose_drv_reply,Port,{error,Error}} -> + erlang:error(Error,[Port,HuntPath]); + {ose_drv_reply,Port,Ref} -> + Ref + end + catch error:_Error -> + erlang:error(badarg,[Port,HuntPath]) + end. + +%%------------------------------------------------------------------------------ +%% @doc Stop hunting for OSE process. +%% +%% If a message for this hunt has been sent but not received +%% by the calling process, it is removed from the message queue. +%% Note that this only works if the same process that did +%% the hunt does the dehunt. +%% +%% raises: `badarg' +%% +%% @see hunt/2 +%% @end +%%------------------------------------------------------------------------------ +-spec dehunt(Port, Ref) -> ok when + Port :: mailbox(), + Ref :: hunt_ref(). +dehunt(Port, {Port,Ref}) when ?INT_32BIT(Ref) -> + try port_command(Port, <>) of + true -> + receive + {ose_drv_reply,Port,{error,enoent}} -> + %% enoent could mean that it is in the message queue + receive + {mailbox_up, Port, {Port,Ref}, _} -> + ok + after 0 -> + ok + end; + {ose_drv_reply,Port,ok} -> + ok + end + catch error:_Error -> + erlang:error(badarg,[Port,{Port,Ref}]) + end; +dehunt(Port,Ref) -> + erlang:error(badarg,[Port,Ref]). + +%%------------------------------------------------------------------------------ +%% @doc Attach to an OSE process. +%% +%% Will send `{mailbox_down, Port, Ref, MboxId}' +%% to the calling process if the OSE process exits. +%% +%% Returns a reference that can be used to cancel the attachment +%% using {@link detach/2}. +%% +%% raises: `badarg' | `enomem' +%% +%% @end +%%------------------------------------------------------------------------------ +-spec attach(Port,Pid) -> Ref when + Port :: mailbox(), + Pid :: mailbox_id(), + Ref :: attach_ref(). +attach(Port, Spid) when ?INT_32BIT(Spid) -> + try port_command(Port, <>) of + true -> + receive + {ose_drv_reply,Port,{error,Error}} -> + erlang:error(Error,[Port,Spid]); + {ose_drv_reply,Port,Ref} -> + Ref + end + catch error:_Error -> + erlang:error(badarg,[Port,Spid]) + end; +attach(Port,Spid) -> + erlang:error(badarg,[Port,Spid]). + + +%%------------------------------------------------------------------------------ +%% @doc Remove attachment to an OSE process. +%% +%% If a message for this monitor has been sent but not received +%% by the calling process, it is removed from the message queue. +%% Note that this only works of the same process +%% that did the attach does the detach. +%% +%% raises: `badarg' +%% +%% @see attach/2 +%% @end +%%------------------------------------------------------------------------------ +-spec detach(Port,Ref) -> ok when + Port :: mailbox(), + Ref :: attach_ref(). +detach(Port, {Port,Ref} ) when ?INT_32BIT(Ref) -> + try port_command(Port, <>) of + true -> + receive + {ose_drv_reply,Port,{error,enoent}} -> + %% enoent could mean that it is in the message queue + receive + {mailbox_down,Port,{Port,Ref},_} -> + ok + after 0 -> + ok + end; + {ose_drv_reply,Port,ok} -> + ok + end + catch error:_Error -> + erlang:error(badarg,[Port,{Port,Ref}]) + end; +detach(Port,Ref) -> + erlang:error(badarg,[Port,Ref]). + +%%------------------------------------------------------------------------------ +%% @doc Send an OSE message. +%% +%% The message is sent from the OSE process' own ID that is: `get_id(Port)'. +%% +%% raises: `badarg' +%% +%% @see send/5 +%% @end +%%------------------------------------------------------------------------------ +-spec send(Port,Pid,SigNo,SigData) -> ok when + Port :: mailbox(), + Pid :: mailbox_id(), + SigNo :: message_number(), + SigData :: iodata(). +send(Port, Spid, SigNo, SigData) when ?INT_32BIT(Spid), ?INT_32BIT(SigNo) -> + try erlang:port_command(Port, [<>, SigData]) of + true -> ok + catch error:_Error -> + erlang:error(badarg,[Port,Spid,SigNo,SigData]) + end; +send(Port,Spid,SigNo,SigData) -> + erlang:error(badarg,[Port,Spid,SigNo,SigData]). + + +%%------------------------------------------------------------------------------ +%% @doc Send an OSE message with different sender. +%% +%% As {@link send/4} but the sender will be `SenderPid'. +%% +%% raises: `badarg' +%% +%% @see send/4 +%% @end +%%------------------------------------------------------------------------------ +-spec send(Port,Pid,SenderPid,SigNo,SigData) -> ok when + Port :: mailbox(), + Pid :: mailbox_id(), + SenderPid :: mailbox_id(), + SigNo :: message_number(), + SigData :: iodata(). +send(Port, Spid, SenderPid, SigNo, SigData) + when ?INT_32BIT(Spid), ?INT_32BIT(SenderPid), ?INT_32BIT(SigNo) -> + try erlang:port_command(Port, [<>, SigData]) of + true -> ok + catch error:_Error -> + erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]) + end; +send(Port,Spid,SenderPid,SigNo,SigData) -> + erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]). + +%%------------------------------------------------------------------------------ +%% @doc Start listening for specified OSE signal numbers. +%% +%% The mailbox will send `{message,Port,{FromMboxId,ToMboxId,MsgNo,MsgData}}' +%% to the process that created the mailbox when an OSE message with any +%% of the specified `SigNos' arrives. +%% +%% Repeated calls to listen will replace the current set of signal numbers to +%% listen to. i.e +%% +%% ```1>ose:listen(MsgB,[1234,12345]). +%% ok +%% 2> ose:listen(MsgB,[1234,123456]). +%% ok.''' +%% +%% The above will first listen for signals with numbers 1234 and 12345, and then +%% replace that with only listening to 1234 and 123456. +%% +%% With the current implementation it is not possible to listen to all signal +%% numbers. +%% +%% raises: `badarg' | `enomem' +%% +%% @end +%%------------------------------------------------------------------------------ +-spec listen(Port, SigNos) -> ok when + Port :: mailbox(), + SigNos :: list(message_number()). +listen(Port, SigNos) when is_list(SigNos) -> + USSigNos = lists:usort(SigNos), + BinSigNos = try + << <> || + SigNo <- USSigNos, + ?INT_32BIT(SigNo) orelse erlang:error(badarg) + >> + catch _:_ -> + erlang:error(badarg,[Port,SigNos]) + end, + try port_command(Port, [?LISTEN, BinSigNos]) of + true -> + receive + {ose_drv_reply,Port,{error,Error}} -> + erlang:error(Error,[Port,SigNos]); + {ose_drv_reply,Port,Else} -> + Else + end + catch error:_Error -> + erlang:error(badarg,[Port,SigNos]) + end; +listen(Port, SigNos) -> + erlang:error(badarg,[Port,SigNos]). + + +%%%============================================================================= +%%% Internal functions +%%%============================================================================= diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index f1b8a105ed..ac28d1aae9 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -79,6 +79,10 @@ MODULES= \ loose_node \ sendfile_SUITE +ifeq ($(findstring ose,$(TARGET)),ose) +MODULES+=ose_SUITE +endif + APP_FILES = \ appinc.app \ appinc1.app \ diff --git a/lib/kernel/test/ose_SUITE.erl b/lib/kernel/test/ose_SUITE.erl new file mode 100644 index 0000000000..7e81b19894 --- /dev/null +++ b/lib/kernel/test/ose_SUITE.erl @@ -0,0 +1,765 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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% +%% +-module(ose_SUITE). + +%-compile(export_all). + +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, + init_per_group/2,end_per_group/2,init_per_testcase/2, + end_per_testcase/2]). +-export([ + basic/1,stress/1,multi_msg_numbers/1,multi_mailboxes/1, + hunt/1,multi_hunt/1,dehunt/1,multi_dehunt/1, + attach/1,multi_attach/1,detach/1,multi_detach/1, + open_errors/1,close_errors/1,get_id_errors/1,get_name_errors/1, + hunt_errors/1,dehunt_errors/1,attach_errors/1,detach_errors/1, + send_errors/1,send_w_s_errors/1,listen_errors/1 + ]). + +-define(INTERFACE,ose). + + +init_per_testcase(_Func, Config) -> + Config. +end_per_testcase(_Func, _Config) -> + ok. + +suite() -> [{timeout,{30,seconds}}]. + +all() -> + [ + basic,stress,multi_msg_numbers,multi_mailboxes, + hunt,multi_hunt,dehunt,multi_dehunt, + attach,multi_attach,detach,multi_detach, + + open_errors,close_errors,get_id_errors,get_name_errors, + hunt_errors,dehunt_errors,attach_errors,detach_errors, + send_errors,send_w_s_errors,listen_errors + ]. + +groups() -> + []. + +init_per_suite(Config) -> + case os:type() of + {ose,_} -> + Config; + _Else -> + {skip,"Only run on OSE"} + end. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +basic(_Config) -> + + [P1,P2] = multi_open(2,[42]), + P1Id = ?INTERFACE:get_id(P1), + P2Id = ?INTERFACE:get_id(P2), + + ok = ?INTERFACE:send(P2,P1Id,42,<<"ping">>), + receive + {message,P1,V1} -> + {P2Id,P1Id,42,<<"ping">>} = V1, + ?INTERFACE:send(P1,P2Id,42,<<"pong">>); + Else1 -> + ct:fail({got_wrong_message,Else1}) + end, + + receive + {message,P2,V2} -> + {P1Id,P2Id,42,<<"pong">>} = V2; + Else2 -> + ct:fail({got_wrong_message,Else2}) + end, + + ?INTERFACE:close(P1), + ?INTERFACE:close(P2). + +%% Send 1000 messages and see if we can cope and that msg order is preserved +stress(_Config) -> + + Iterations = 1000, + + [P1,P2] = multi_open(2,[42]), + P1Id = ?INTERFACE:get_id(P1), + P2Id = ?INTERFACE:get_id(P2), + + spawn(fun() -> + n(fun(N) -> + Msg = [<<"ping">>|integer_to_list(N)], + ?INTERFACE:send(P2,P1Id,42,Msg) + end,Iterations) + end), + timer:sleep(100), + n(fun(N) -> + receive + {message,P1,Value} -> + Int = integer_to_binary(N), + {P2Id,P1Id,42,<<"ping",Int/binary>>} = Value, + ok; + Else -> + ct:fail({got_wrong_message,Else}) + end + end,Iterations), + + ?INTERFACE:close(P1), + ?INTERFACE:close(P2). + +%% Listen to 1000 different message numbers and send some random messages +multi_msg_numbers(_Config) -> + + Iterations = 100, + + [P1,P2] = multi_open(2,lists:seq(2000,3000)), + P1Id = ?INTERFACE:get_id(P1), + + n(fun(_) -> + Num = random:uniform(1000)+2000, + ?INTERFACE:send(P2,P1Id,Num,<<"ping",(integer_to_binary(Num))/binary>>) + end,Iterations), + + n(fun(_) -> + receive + {message,P1,{_,_,Id,<<"ping",Num/binary>>}} when Id > 2000; + Id =< 3000 -> + Id = binary_to_integer(Num), + ok; + Else -> + ct:fail({got_wrong_message,Else}) + end + end,Iterations), + + ?INTERFACE:close(P1), + ?INTERFACE:close(P2). + + +%% Create 100 mailboxes and send messages to them +multi_mailboxes(_Config) -> + + Mailboxes = 100, + + [P1|MBs] = multi_open(Mailboxes,[42]), + + [?INTERFACE:send(P1,?INTERFACE:get_id(P),42,[<<"ping">>,?INTERFACE:get_name(P,?INTERFACE:get_id(P))]) || P <- MBs], + + [receive + {message,P,Value} -> + Name = ?INTERFACE:get_name(P,?INTERFACE:get_id(P)), + {_,_,42,<<"ping",Name/binary>>} = Value, + ok + end || P <- MBs], + + [?INTERFACE:close(P) || P <- [P1|MBs]], + ok. + +hunt(_Config) -> + [P1,P2] = multi_open(2,[]), + + Ref = ?INTERFACE:hunt(P1,"p2"), + receive + {mailbox_up,P1,Ref,Pid} -> + Pid = ?INTERFACE:get_id(P2), + ?INTERFACE:close(P1), + ?INTERFACE:close(P2); + Else -> + ct:fail({got_wrong_message,Else,Ref}) + end. + +multi_hunt(_Config) -> + + Iterations = 100, + + P = ?INTERFACE:open("p"), + + Refs = [?INTERFACE:hunt(P,"p"++integer_to_list(N))|| N <- lists:seq(1,Iterations)], + + Pids = [begin + Prt = ?INTERFACE:open("p"++integer_to_list(N)), + Pid = ?INTERFACE:get_id(Prt), + ?INTERFACE:close(Prt), + Pid + end || N <- lists:seq(1,Iterations)], + + [receive + {mailbox_up,P,Ref,Pid} -> + ok + after 10 -> + ct:fail({did_not_get,Pid,Ref}) + end || {Pid,Ref} <- lists:zip(Pids,Refs)], + ?INTERFACE:close(P). + + +dehunt(_Config) -> + [P1] = multi_open(1,[]), + Ref = ?INTERFACE:hunt(P1,"p2"), + receive + _Else -> ct:fail({got,_Else}) + after 1000 -> + ok + end, + P2 = ?INTERFACE:open("p2"), + + % Make sure any messages are sent + receive after 10 -> ok end, + + ok = ?INTERFACE:dehunt(P1,Ref), + + % Make sure no messages are received + receive + _Else2 -> ct:fail({got,_Else2}) + after 1000 -> + ?INTERFACE:close(P1), + ?INTERFACE:close(P2) + end. + +%%% +%%% This testcase basically: +%%% spawn 10 processes that in parallel +%%% adds some hunts for different OSE processes +%%% maybe create hunted OSE process +%%% dehunt half of the hunts +%%% create more hunts +%%% if not created create hunted OSE process +%%% veryify that all expected hunt messages are received +%%% verify that all processes exited correctly +%%% +%%% This complex test is done to make sure that the internal handling +%%% of dehunt works as expected. +%%% +multi_dehunt(_Config) -> + [P1] = multi_open(1,[]), + + Scenario = + fun(Iterations) -> + + Hunted = "p"++integer_to_list(Iterations), + %% Start a couple of hunts + Refs = [?INTERFACE:hunt(P1,Hunted) || _ <- lists:seq(1,Iterations)], + + %% We alternate if the process is opened before or after the dehunt + P2O = if Iterations rem 2 == 0 -> + ?INTERFACE:open(Hunted); + true -> + undefined + end, + + %% Remove half of them + {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 -> + ok = ?INTERFACE:dehunt(P1,Ref), + {[],Acc+1}; + (Ref,Acc) -> + {Ref,Acc+1} + end,0,Refs), + + %% Add some new ones + NewRefs = [?INTERFACE:hunt(P1,Hunted) + || _ <- lists:seq(1,Iterations div 4)] + ++ lists:flatten(RemRefs), + + P2 = if P2O == undefined -> + ?INTERFACE:open(Hunted); + true -> + P2O + end, + P2Id = ?INTERFACE:get_id(P2), + + %% Receive all the expected ones + lists:foreach(fun(Ref) -> + receive + {mailbox_up,P1,Ref,P2Id} -> + ok + after 1000 -> + io:format("Flush: ~p~n",[flush()]), + io:format("~p~n",[{Iterations,{did_not_get, Ref}}]), + ok = Ref + end + end,NewRefs), + + %% Check that no other have arrived + receive + _Else -> + io:format("Flush: ~p~n",[flush()]), + io:format("~p~n",[{Iterations,{got, _Else}}]), + ok = _Else + after 100 -> + ok + end, + ?INTERFACE:close(P2) + end, + + Self = self(), + + n(fun(N) -> + spawn(fun() -> Self ! + Scenario(N*25) + end), + ok + end,10), + + n(fun(_N) -> + receive ok -> ok + after 60000 -> ct:fail(failed) + end + end,10), + ?INTERFACE:close(P1). + +attach(_Config) -> + [P1,P2] = multi_open(2,[]), + + P2Id = ?INTERFACE:get_id(P2), + Ref = ?INTERFACE:attach(P1,P2Id), + ?INTERFACE:close(P2), + receive + {mailbox_down,P1,Ref,P2Id} -> + ?INTERFACE:close(P1); + _Else -> + ct:fail({got,_Else, {P1,Ref,P2Id}}) + after 1000 -> + ct:fail({did_not_get,P1,Ref,P2Id}) + end. + +multi_attach(_Config) -> + + Iterations = 100, + + [P1|Pids] = multi_open(Iterations,[]), + + Refs = [{?INTERFACE:get_id(Pid),?INTERFACE:attach(P1,?INTERFACE:get_id(Pid))} || Pid <- Pids], + + [?INTERFACE:close(Pid) || Pid <- Pids], + + [receive + {mailbox_down,P1,Ref,Pid} -> + ok + after 10000 -> + ct:fail({did_not_get,Pid,Ref}) + end || {Pid,Ref} <- Refs], + ?INTERFACE:close(P1). + +detach(_Config) -> + [P1,P2] = multi_open(2,[]), + P2Id = ?INTERFACE:get_id(P2), + Ref = ?INTERFACE:attach(P1,P2Id), + receive + _Else -> ct:fail({got,_Else}) + after 100 -> + ok + end, + + ?INTERFACE:close(P2), + + % Make sure any messages are sent + receive after 10 -> ok end, + + ?INTERFACE:detach(P1,Ref), + + % Make sure no messages are received + receive + _Else2 -> ct:fail({got,_Else2}) + after 1000 -> + ?INTERFACE:close(P1) + end. + +%%% +%%% This testcase basically: +%%% spawn 10 processes that in parallel +%%% adds some attach for different OSE processes +%%% maybe close OSE process +%%% dehunt half of the hunts +%%% create more hunts +%%% if not closed close attached OSE process +%%% veryify that all expected attach messages are received +%%% verify that all processes exited correctly +%%% +%%% This complex test is done to make sure that the internal handling +%%% of dehunt works as expected. +%%% +multi_detach(_Config) -> + [P1] = multi_open(1,[]), + + Scenario = + fun(Iterations) -> + + Attached = ?INTERFACE:open("p"++integer_to_list(Iterations)), + AttachedId = ?INTERFACE:get_id(Attached), + %% Start a couple of attachs + Refs = [?INTERFACE:attach(P1,AttachedId) || _ <- lists:seq(1,Iterations)], + + %% We alternate if the process is closed before or after the detach + P2O = if Iterations rem 2 == 0 -> + ?INTERFACE:close(Attached); + true -> + undefined + end, + + %% Remove half of them + {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 -> + ok = ?INTERFACE:detach(P1,Ref), + {[],Acc+1}; + (Ref,Acc) -> + {Ref,Acc+1} + end,0,Refs), + + %% Add some new ones + NewRefs = [?INTERFACE:attach(P1,AttachedId) + || _ <- lists:seq(1,Iterations div 4)] + ++ lists:flatten(RemRefs), + + if P2O == undefined -> + ?INTERFACE:close(Attached); + true -> + P2O + end, + + %% Receive all the expected ones + lists:foreach(fun(Ref) -> + receive + {mailbox_down,P1,Ref,AttachedId} -> + ok + after 1000 -> + io:format("Flush: ~p~n",[flush()]), + io:format("~p~n",[{Iterations,{did_not_get, Ref}}]), + ok = Ref + end + end,NewRefs), + + %% Check that no other have arrived + receive + _Else -> + io:format("Flush: ~p~n",[flush()]), + io:format("~p~n",[{Iterations,{got, _Else}}]), + ok = _Else + after 100 -> + ok + end + end, + + Self = self(), + + n(fun(N) -> + spawn(fun() -> Self ! + Scenario(N*5) + end), + ok + end,10), + + n(fun(_N) -> + receive ok -> ok + after 60000 -> ct:fail(failed) + end + end,10), + ?INTERFACE:close(P1). + + +open_errors(_Config) -> + {'EXIT',{badarg,[{?INTERFACE,open,[inval],_}|_]}} = + (catch ?INTERFACE:open(inval)), + {'EXIT',{badarg,[{?INTERFACE,open,[["p"|1]],_}|_]}} = + (catch ?INTERFACE:open(["p"|1])), + {'EXIT',{badarg,[{?INTERFACE,open,[["p",1234]],_}|_]}} = + (catch ?INTERFACE:open(["p",1234])), + + ok. + +close_errors(_Config) -> + {'EXIT',{badarg,[{?INTERFACE,close,[inval],_}|_]}} = + (catch ?INTERFACE:close(inval)), + + P1 = ?INTERFACE:open("p1"), + ok = ?INTERFACE:close(P1), + ok = ?INTERFACE:close(P1). + + +get_id_errors(_Config) -> + {'EXIT',{badarg,[{?INTERFACE,get_id,[inval],_}|_]}} = + (catch ?INTERFACE:get_id(inval)), + + P1 = ?INTERFACE:open("p1"), + ok = ?INTERFACE:close(P1), + {'EXIT',{badarg,[{?INTERFACE,get_id,[P1],_}|_]}} = + (catch ?INTERFACE:get_id(P1)), + + ok. + +get_name_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,inval],_}|_]}} = + (catch ?INTERFACE:get_name(P1,inval)), + + undefined = ?INTERFACE:get_name(P1,1234), + + P2 = ?INTERFACE:open("p2"), + P2Id = ?INTERFACE:get_id(P2), + ok = ?INTERFACE:close(P1), + {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,P2Id],_}|_]}} = + (catch ?INTERFACE:get_name(P1,P2Id)), + ?INTERFACE:close(P2), + + P3 = ?INTERFACE:open([255]), + <<255>> = ?INTERFACE:get_name(P3, ?INTERFACE:get_id(P3)), + ?INTERFACE:close(P3), + + ok. + +hunt_errors(_Config) -> + + {'EXIT',{badarg,[{?INTERFACE,hunt,[inval,"hello"],_}|_]}} = + (catch ?INTERFACE:hunt(inval,"hello")), + + P1 = ?INTERFACE:open("p1"), + {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello",12345]],_}|_]}} = + (catch ?INTERFACE:hunt(P1,["hello",12345])), + + P2 = ?INTERFACE:open(<<255>>), + P2Pid = ?INTERFACE:get_id(P2), + Ref = ?INTERFACE:hunt(P1,[255]), + receive + {mailbox_up,P1,Ref,P2Pid} -> + ok; + Else -> + ct:fail({got,Else,{mailbox_up,P1,Ref,P2Pid}}) + after 150 -> + ct:fail({did_not_get,{mailbox_up,P1,Ref,P2Pid}}) + end, + + ok = ?INTERFACE:close(P1), + ok = ?INTERFACE:close(P2), + {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello"]],_}|_]}} = + (catch ?INTERFACE:hunt(P1,["hello"])), + + ok. + +dehunt_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + Ref = ?INTERFACE:hunt(P1,"p2"), + + {'EXIT',{badarg,[{?INTERFACE,dehunt,[inval,Ref],_}|_]}} = + (catch ?INTERFACE:dehunt(inval,Ref)), + + {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,inval],_}|_]}} = + (catch ?INTERFACE:dehunt(P1,inval)), + + ok = ?INTERFACE:dehunt(P1,Ref), + ok = ?INTERFACE:dehunt(P1,Ref), + + ok = ?INTERFACE:close(P1), + + {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,Ref],_}|_]}} = + (catch ?INTERFACE:dehunt(P1,Ref)), + + case ?INTERFACE of + ose -> ok; + _ -> + P2 = ?INTERFACE:open("p2"), + ok = ?INTERFACE:close(P2) + end, + + receive + Else -> ct:fail({got,Else}) + after 100 -> + ok + end. + +attach_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + P2 = ?INTERFACE:open("p2"), + P2Id = ?INTERFACE:get_id(P2), + + {'EXIT',{badarg,[{?INTERFACE,attach,[inval,P2Id],_}|_]}} = + (catch ?INTERFACE:attach(inval,P2Id)), + + {'EXIT',{badarg,[{?INTERFACE,attach,[P1,[12345]],_}|_]}} = + (catch ?INTERFACE:attach(P1,[12345])), + + ok = ?INTERFACE:close(P1), + ok = ?INTERFACE:close(P2), + {'EXIT',{badarg,[{?INTERFACE,attach,[P1,P2Id],_}|_]}} = + (catch ?INTERFACE:attach(P1,P2Id)), + + ok. + +detach_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + P2 = ?INTERFACE:open("p2"), + P2Id = ?INTERFACE:get_id(P2), + + Ref = ?INTERFACE:attach(P1,P2Id), + + {'EXIT',{badarg,[{?INTERFACE,detach,[inval,Ref],_}|_]}} = + (catch ?INTERFACE:detach(inval,Ref)), + + {'EXIT',{badarg,[{?INTERFACE,detach,[P1,inval],_}|_]}} = + (catch ?INTERFACE:detach(P1,inval)), + + ok = ?INTERFACE:detach(P1,Ref), + ok = ?INTERFACE:detach(P1,Ref), + + case ?INTERFACE of + ose -> ok; + _ -> + ok = ?INTERFACE:close(P1) + end, + + ok = ?INTERFACE:close(P2), + ok = ?INTERFACE:close(P1), + + {'EXIT',{badarg,[{?INTERFACE,detach,[P1,Ref],_}|_]}} = + (catch ?INTERFACE:detach(P1,Ref)), + + receive + Else -> ct:fail({got,Else}) + after 100 -> + ok + end. + +send_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + P2 = ?INTERFACE:open("p2"), + P2Id = ?INTERFACE:get_id(P2), + + {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(inval,P2Id,42,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P1,inval,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P1,inval,42,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,inval,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P1,P2Id,inval,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,inval],_}|_]}} = + (catch ?INTERFACE:send(P1,P2Id,42,inval)), + + ok = ?INTERFACE:close(P2), + ok = ?INTERFACE:send(P1,P2Id,42,"hello"), + ok = ?INTERFACE:close(P1), + + {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P1,P2Id,42,"hello")), + + receive + Else -> ct:fail({got,Else}) + after 100 -> + ok + end. + +send_w_s_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + P1Id = ?INTERFACE:get_id(P1), + P2 = ?INTERFACE:open("p2"), + P2Id = ?INTERFACE:get_id(P2), + P3 = ?INTERFACE:open("p3"), + P3Id = ?INTERFACE:get_id(P3), + + {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,P1Id,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(inval,P2Id,P1Id,42,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P2,-1,P1Id,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P2,-1,P1Id,42,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,1 bsl 32,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P2,P2Id,1 bsl 32,42,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,inval,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P2,P2Id,P1Id,inval,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,42,inval],_}|_]}} = + (catch ?INTERFACE:send(P2,P2Id,P1Id,42,inval)), + + ok = ?INTERFACE:close(P3), + ok = ?INTERFACE:send(P2,P3Id,P1Id,42,"hello"), + + ok = ?INTERFACE:close(P1), + ok = ?INTERFACE:send(P2,P2Id,P1Id,42,"hello"), + ok = ?INTERFACE:close(P2), + + {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,P1Id,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P1,P2Id,P1Id,42,"hello")), + + receive + Else -> ct:fail({got,Else}) + after 100 -> + ok + end. + +listen_errors(_Config) -> + + P1 = ?INTERFACE:open("p1"), + P1Id = ?INTERFACE:get_id(P1), + + {'EXIT',{badarg,[{?INTERFACE,listen,[inval,[42]],_}|_]}} = + (catch ?INTERFACE:listen(inval,[42])), + {'EXIT',{badarg,[{?INTERFACE,listen,[P1,inval],_}|_]}} = + (catch ?INTERFACE:listen(P1,inval)), + {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[1 bsl 33]],_}|_]}} = + (catch ?INTERFACE:listen(P1,[1 bsl 33])), + + ok = ?INTERFACE:listen(P1,[42,42,42,42,42,42,42,42,42,42,42,42,42]), + + case ?INTERFACE of + ose -> ok; + _ -> + ?INTERFACE:send(P1,P1Id,42,"hello"), + timer:sleep(50), + ?INTERFACE:listen(P1,[]), + ?INTERFACE:send(P1,P1Id,42,"hello2"), + + receive + {message,P1,42,"hello"} -> ok + end, + + receive + Else -> ct:fail({got,Else}) + after 100 -> + ok + end + end, + + ok = ?INTERFACE:close(P1), + {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[42]],_}|_]}} = + (catch ?INTERFACE:listen(P1,[42])), + + ok. + +%% +%% Internal functions +%% +multi_open(N,ListenNums) -> + multi_open(N,ListenNums,[]). + +multi_open(0,_,Acc) -> + Acc; +multi_open(N,ListenNums,Acc) -> + P = ?INTERFACE:open("p"++integer_to_list(N)), + ok = ?INTERFACE:listen(P,ListenNums), + multi_open(N-1,ListenNums,[P|Acc]). + +n(_F,0) -> + ok; +n(F,N) -> + ok = F(N), + n(F,N-1). + + +flush() -> + receive + Msg -> + [Msg|flush()] + after 0 -> + [] + end. -- 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 --- lib/erl_interface/aclocal.m4 | 9 ++++++++- lib/megaco/aclocal.m4 | 9 ++++++++- lib/odbc/aclocal.m4 | 9 ++++++++- lib/wx/aclocal.m4 | 9 ++++++++- 4 files changed, 32 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/aclocal.m4 b/lib/erl_interface/aclocal.m4 index 4a3407e0eb..09d0f0194c 100644 --- a/lib/erl_interface/aclocal.m4 +++ b/lib/erl_interface/aclocal.m4 @@ -84,6 +84,8 @@ AC_ARG_VAR(erl_xcomp_ose_LM_SET_CONF, [Sets the configuration for an OSE load mo AC_ARG_VAR(erl_xcomp_ose_LM_ELF_SIZE, [Prints the section size information for an OSE load module (only used when cross compiling for OSE)]) AC_ARG_VAR(erl_xcomp_ose_LM_LCF, [OSE load module linker configuration file (only used when cross compiling for OSE)]) AC_ARG_VAR(erl_xcomp_ose_LM_CONF, [OSE load module default configuration file (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_CONFD, [OSE OSE confd source file]) +AC_ARG_VAR(erl_xcomp_ose_CRT0_LM, [OSE crt0 lm source file]) ]) @@ -1106,7 +1108,12 @@ case "$THR_LIB_NAME" in AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) ;; ose_threads) - AC_DEFINE(ETHR_OSE_THREADS, 1, [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose + AC_DEFINE(ETHR_OSE_THREADS, 1, + [Define if you have OSE style threads]) + ETHR_THR_LIB_BASE_DIR=ose + AC_CHECK_HEADER(ose_spi/ose_spi.h, + AC_DEFINE(HAVE_OSE_SPI, 1, + [Define if you have the "ose_spi/ose_spi.h" header file.])) ;; esac if test "x$THR_LIB_NAME" == "xpthread"; then diff --git a/lib/megaco/aclocal.m4 b/lib/megaco/aclocal.m4 index 4a3407e0eb..09d0f0194c 100644 --- a/lib/megaco/aclocal.m4 +++ b/lib/megaco/aclocal.m4 @@ -84,6 +84,8 @@ AC_ARG_VAR(erl_xcomp_ose_LM_SET_CONF, [Sets the configuration for an OSE load mo AC_ARG_VAR(erl_xcomp_ose_LM_ELF_SIZE, [Prints the section size information for an OSE load module (only used when cross compiling for OSE)]) AC_ARG_VAR(erl_xcomp_ose_LM_LCF, [OSE load module linker configuration file (only used when cross compiling for OSE)]) AC_ARG_VAR(erl_xcomp_ose_LM_CONF, [OSE load module default configuration file (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_CONFD, [OSE OSE confd source file]) +AC_ARG_VAR(erl_xcomp_ose_CRT0_LM, [OSE crt0 lm source file]) ]) @@ -1106,7 +1108,12 @@ case "$THR_LIB_NAME" in AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) ;; ose_threads) - AC_DEFINE(ETHR_OSE_THREADS, 1, [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose + AC_DEFINE(ETHR_OSE_THREADS, 1, + [Define if you have OSE style threads]) + ETHR_THR_LIB_BASE_DIR=ose + AC_CHECK_HEADER(ose_spi/ose_spi.h, + AC_DEFINE(HAVE_OSE_SPI, 1, + [Define if you have the "ose_spi/ose_spi.h" header file.])) ;; esac if test "x$THR_LIB_NAME" == "xpthread"; then diff --git a/lib/odbc/aclocal.m4 b/lib/odbc/aclocal.m4 index 4a3407e0eb..09d0f0194c 100644 --- a/lib/odbc/aclocal.m4 +++ b/lib/odbc/aclocal.m4 @@ -84,6 +84,8 @@ AC_ARG_VAR(erl_xcomp_ose_LM_SET_CONF, [Sets the configuration for an OSE load mo AC_ARG_VAR(erl_xcomp_ose_LM_ELF_SIZE, [Prints the section size information for an OSE load module (only used when cross compiling for OSE)]) AC_ARG_VAR(erl_xcomp_ose_LM_LCF, [OSE load module linker configuration file (only used when cross compiling for OSE)]) AC_ARG_VAR(erl_xcomp_ose_LM_CONF, [OSE load module default configuration file (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_CONFD, [OSE OSE confd source file]) +AC_ARG_VAR(erl_xcomp_ose_CRT0_LM, [OSE crt0 lm source file]) ]) @@ -1106,7 +1108,12 @@ case "$THR_LIB_NAME" in AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) ;; ose_threads) - AC_DEFINE(ETHR_OSE_THREADS, 1, [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose + AC_DEFINE(ETHR_OSE_THREADS, 1, + [Define if you have OSE style threads]) + ETHR_THR_LIB_BASE_DIR=ose + AC_CHECK_HEADER(ose_spi/ose_spi.h, + AC_DEFINE(HAVE_OSE_SPI, 1, + [Define if you have the "ose_spi/ose_spi.h" header file.])) ;; esac if test "x$THR_LIB_NAME" == "xpthread"; then diff --git a/lib/wx/aclocal.m4 b/lib/wx/aclocal.m4 index 4a3407e0eb..09d0f0194c 100644 --- a/lib/wx/aclocal.m4 +++ b/lib/wx/aclocal.m4 @@ -84,6 +84,8 @@ AC_ARG_VAR(erl_xcomp_ose_LM_SET_CONF, [Sets the configuration for an OSE load mo AC_ARG_VAR(erl_xcomp_ose_LM_ELF_SIZE, [Prints the section size information for an OSE load module (only used when cross compiling for OSE)]) AC_ARG_VAR(erl_xcomp_ose_LM_LCF, [OSE load module linker configuration file (only used when cross compiling for OSE)]) AC_ARG_VAR(erl_xcomp_ose_LM_CONF, [OSE load module default configuration file (only used when cross compiling for OSE)]) +AC_ARG_VAR(erl_xcomp_ose_CONFD, [OSE OSE confd source file]) +AC_ARG_VAR(erl_xcomp_ose_CRT0_LM, [OSE crt0 lm source file]) ]) @@ -1106,7 +1108,12 @@ case "$THR_LIB_NAME" in AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) ;; ose_threads) - AC_DEFINE(ETHR_OSE_THREADS, 1, [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose + AC_DEFINE(ETHR_OSE_THREADS, 1, + [Define if you have OSE style threads]) + ETHR_THR_LIB_BASE_DIR=ose + AC_CHECK_HEADER(ose_spi/ose_spi.h, + AC_DEFINE(HAVE_OSE_SPI, 1, + [Define if you have the "ose_spi/ose_spi.h" header file.])) ;; esac if test "x$THR_LIB_NAME" == "xpthread"; then -- cgit v1.2.3 From a0766a4efeefe0ac035d2be04816274aee5751f3 Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Fri, 8 Nov 2013 14:00:36 +0100 Subject: ose: Bugfixes to filesystem related issues. --- lib/kernel/test/file_SUITE.erl | 39 +++++++++++++++++++++++++------------ lib/kernel/test/prim_file_SUITE.erl | 5 ++++- 2 files changed, 31 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index c75639ae7e..15b7016f7d 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -161,7 +161,13 @@ init_per_suite(Config) when is_list(Config) -> ok -> [{sasl,started}] end, - ok = application:start(os_mon), + ok = case os:type() of + {ose,_} -> + ok; + _ -> + application:start(os_mon) + end, + case os:type() of {win32, _} -> Priv = ?config(priv_dir, Config), @@ -185,7 +191,13 @@ end_per_suite(Config) when is_list(Config) -> _ -> ok end, - application:stop(os_mon), + + case os:type() of + {ose,_} -> + ok; + _ -> + application:stop(os_mon) + end, case proplists:get_value(sasl, Config) of started -> application:stop(sasl); @@ -525,11 +537,11 @@ cur_dir_1(Config) when is_list(Config) -> ?line Dog = test_server:timetrap(test_server:seconds(5)), ?line case os:type() of - {unix, _} -> - ?line {error, enotsup} = ?FILE_MODULE:get_cwd("d:"); - {win32, _} -> - win_cur_dir_1(Config) - end, + {win32, _} -> + win_cur_dir_1(Config); + _ -> + ?line {error, enotsup} = ?FILE_MODULE:get_cwd("d:") + end, ?line [] = flush(), ?line test_server:timetrap_cancel(Dog), ok. @@ -712,7 +724,10 @@ open1(Config) when is_list(Config) -> ?line io:format(Fd1,Str,[]), ?line {ok,0} = ?FILE_MODULE:position(Fd1,bof), ?line Str = io:get_line(Fd1,''), - ?line Str = io:get_line(Fd2,''), + ?line case io:get_line(Fd2,'') of + Str -> Str; + eof -> Str + end, ?line ok = ?FILE_MODULE:close(Fd2), ?line {ok,0} = ?FILE_MODULE:position(Fd1,bof), ?line ok = ?FILE_MODULE:truncate(Fd1), @@ -2171,13 +2186,13 @@ e_make_dir(Config) when is_list(Config) -> %% No permission (on Unix only). case os:type() of - {unix, _} -> + {win32, _} -> + ok; + _ -> ?FILE_MODULE:write_file_info(Base, #file_info {mode=0}), {error, eacces} = ?FILE_MODULE:make_dir(filename:join(Base, "xxxx")), ?FILE_MODULE:write_file_info( - Base, #file_info {mode=8#600}); - {win32, _} -> - ok + Base, #file_info {mode=8#600}) end, test_server:timetrap_cancel(Dog), ok. diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index ccf325a493..84618a881e 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -453,7 +453,10 @@ open1(Config) when is_list(Config) -> ?line ?PRIM_FILE:write(Fd1,Str), ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof), ?line {ok, Str} = ?PRIM_FILE:read(Fd1,Length), - ?line {ok, Str} = ?PRIM_FILE:read(Fd2,Length), + ?line case ?PRIM_FILE:read(Fd2,Length) of + Str -> Str; + eof -> Str + end, ?line ok = ?PRIM_FILE:close(Fd2), ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof), ?line ok = ?PRIM_FILE:truncate(Fd1), -- cgit v1.2.3 From 3d24208d607501207af371098c1466758844e667 Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Fri, 22 Nov 2013 09:45:05 +0100 Subject: ose: efile driver updates. --- lib/kernel/test/file_SUITE.erl | 23 +++++++++++++---------- lib/kernel/test/prim_file_SUITE.erl | 9 ++++++--- 2 files changed, 19 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 15b7016f7d..6b52493f46 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -1261,7 +1261,7 @@ file_info_basic_directory(Config) when is_list(Config) -> ?line test_directory("/", read_write), ?line test_directory("c:/", read_write), ?line test_directory("c:\\", read_write); - {unix, _} -> + _ -> ?line test_directory("/", read) end, test_server:timetrap_cancel(Dog). @@ -2045,15 +2045,15 @@ e_delete(Config) when is_list(Config) -> %% No permission. ?line case os:type() of - {unix, _} -> + {win32, _} -> + %% Remove a character device. + ?line {error, eacces} = ?FILE_MODULE:delete("nul"); + _ -> ?line ?FILE_MODULE:write_file_info( Base, #file_info {mode=0}), ?line {error, eacces} = ?FILE_MODULE:delete(Afile), ?line ?FILE_MODULE:write_file_info( - Base, #file_info {mode=8#600}); - {win32, _} -> - %% Remove a character device. - ?line {error, eacces} = ?FILE_MODULE:delete("nul") + Base, #file_info {mode=8#600}) end, ?line [] = flush(), @@ -2155,6 +2155,9 @@ e_rename(Config) when is_list(Config) -> %% At least Windows NT can %% successfully move a file to %% another drive. + ok; + {ose, _} -> + %% disabled for now ok end, [] = flush(), @@ -2235,14 +2238,14 @@ e_del_dir(Config) when is_list(Config) -> %% No permission. case os:type() of - {unix, _} -> + {win32, _} -> + ok; + _ -> ADirectory = filename:join(Base, "no_perm"), ok = ?FILE_MODULE:make_dir(ADirectory), ?FILE_MODULE:write_file_info( Base, #file_info {mode=0}), {error, eacces} = ?FILE_MODULE:del_dir(ADirectory), - ?FILE_MODULE:write_file_info( Base, #file_info {mode=8#600}); - {win32, _} -> - ok + ?FILE_MODULE:write_file_info( Base, #file_info {mode=8#600}) end, [] = flush(), test_server:timetrap_cancel(Dog), diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 84618a881e..3e6a85eadd 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -454,7 +454,7 @@ open1(Config) when is_list(Config) -> ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof), ?line {ok, Str} = ?PRIM_FILE:read(Fd1,Length), ?line case ?PRIM_FILE:read(Fd2,Length) of - Str -> Str; + {ok,Str} -> Str; eof -> Str end, ?line ok = ?PRIM_FILE:close(Fd2), @@ -1664,7 +1664,7 @@ e_rename(Config) when is_list(Config) -> %% successfully move a file to %% another drive. ok; - _ -> + {unix, _ } -> OtherFs = "/tmp", ?line NameOnOtherFs = filename:join(OtherFs, @@ -1688,7 +1688,10 @@ e_rename(Config) when is_list(Config) -> Else -> Else end, - Com + Com; + {ose, _} -> + %% disabled for now + ok end, ?line test_server:timetrap_cancel(Dog), Comment. -- cgit v1.2.3 From b309ad9b4a3e4ff2d6d3a6e6270d37355a798bb1 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 10 Jan 2014 17:16:15 +0100 Subject: ose: Fix check for HAVE_OSE_SPI_H --- lib/erl_interface/aclocal.m4 | 2 +- lib/megaco/aclocal.m4 | 2 +- lib/odbc/aclocal.m4 | 2 +- lib/wx/aclocal.m4 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/aclocal.m4 b/lib/erl_interface/aclocal.m4 index 09d0f0194c..c51c26794a 100644 --- a/lib/erl_interface/aclocal.m4 +++ b/lib/erl_interface/aclocal.m4 @@ -1112,7 +1112,7 @@ case "$THR_LIB_NAME" in [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose AC_CHECK_HEADER(ose_spi/ose_spi.h, - AC_DEFINE(HAVE_OSE_SPI, 1, + AC_DEFINE(HAVE_OSE_SPI_H, 1, [Define if you have the "ose_spi/ose_spi.h" header file.])) ;; esac diff --git a/lib/megaco/aclocal.m4 b/lib/megaco/aclocal.m4 index 09d0f0194c..c51c26794a 100644 --- a/lib/megaco/aclocal.m4 +++ b/lib/megaco/aclocal.m4 @@ -1112,7 +1112,7 @@ case "$THR_LIB_NAME" in [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose AC_CHECK_HEADER(ose_spi/ose_spi.h, - AC_DEFINE(HAVE_OSE_SPI, 1, + AC_DEFINE(HAVE_OSE_SPI_H, 1, [Define if you have the "ose_spi/ose_spi.h" header file.])) ;; esac diff --git a/lib/odbc/aclocal.m4 b/lib/odbc/aclocal.m4 index 09d0f0194c..c51c26794a 100644 --- a/lib/odbc/aclocal.m4 +++ b/lib/odbc/aclocal.m4 @@ -1112,7 +1112,7 @@ case "$THR_LIB_NAME" in [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose AC_CHECK_HEADER(ose_spi/ose_spi.h, - AC_DEFINE(HAVE_OSE_SPI, 1, + AC_DEFINE(HAVE_OSE_SPI_H, 1, [Define if you have the "ose_spi/ose_spi.h" header file.])) ;; esac diff --git a/lib/wx/aclocal.m4 b/lib/wx/aclocal.m4 index 09d0f0194c..c51c26794a 100644 --- a/lib/wx/aclocal.m4 +++ b/lib/wx/aclocal.m4 @@ -1112,7 +1112,7 @@ case "$THR_LIB_NAME" in [Define if you have OSE style threads]) ETHR_THR_LIB_BASE_DIR=ose AC_CHECK_HEADER(ose_spi/ose_spi.h, - AC_DEFINE(HAVE_OSE_SPI, 1, + AC_DEFINE(HAVE_OSE_SPI_H, 1, [Define if you have the "ose_spi/ose_spi.h" header file.])) ;; esac -- cgit v1.2.3 From cd69c2a54201b4e0c4ba86d4248937120e1957e7 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 8 Jan 2014 18:54:15 +0100 Subject: ose: Create OSE application Create an specific OSE application that mainly contains documentation around the OSE specific part of Erlang/OTP. --- lib/Makefile | 2 +- lib/kernel/doc/src/Makefile | 27 +- lib/kernel/doc/src/ref_man.xml | 67 +++ lib/kernel/src/Makefile | 4 - lib/kernel/src/ose.erl | 452 ------------------- lib/kernel/test/Makefile | 4 - lib/kernel/test/ose_SUITE.erl | 765 -------------------------------- lib/ose/Makefile | 36 ++ lib/ose/doc/html/.gitignore | 0 lib/ose/doc/man3/.gitignore | 0 lib/ose/doc/man6/.gitignore | 0 lib/ose/doc/pdf/.gitignore | 0 lib/ose/doc/src/.gitignore | 1 + lib/ose/doc/src/Makefile | 132 ++++++ lib/ose/doc/src/book.xml | 48 ++ lib/ose/doc/src/notes.xml | 33 ++ lib/ose/doc/src/ose_app.xml | 37 ++ lib/ose/doc/src/ose_erl_driver.xml | 109 +++++ lib/ose/doc/src/ose_intro.xml | 48 ++ lib/ose/doc/src/ose_signals_chapter.xml | 197 ++++++++ lib/ose/doc/src/part.xml | 38 ++ lib/ose/doc/src/ref_man.xml | 39 ++ lib/ose/ebin/.gitignore | 0 lib/ose/include/.gitignore | 0 lib/ose/info | 2 + lib/ose/src/Makefile | 106 +++++ lib/ose/src/ose.app.src | 26 ++ lib/ose/src/ose.appup.src | 22 + lib/ose/src/ose.erl | 452 +++++++++++++++++++ lib/ose/test/Makefile | 67 +++ lib/ose/test/ose.cover | 2 + lib/ose/test/ose.spec | 1 + lib/ose/test/ose_SUITE.erl | 765 ++++++++++++++++++++++++++++++++ lib/ose/vsn.mk | 1 + 34 files changed, 2233 insertions(+), 1250 deletions(-) create mode 100644 lib/kernel/doc/src/ref_man.xml delete mode 100644 lib/kernel/src/ose.erl delete mode 100644 lib/kernel/test/ose_SUITE.erl create mode 100644 lib/ose/Makefile create mode 100644 lib/ose/doc/html/.gitignore create mode 100644 lib/ose/doc/man3/.gitignore create mode 100644 lib/ose/doc/man6/.gitignore create mode 100644 lib/ose/doc/pdf/.gitignore create mode 100644 lib/ose/doc/src/.gitignore create mode 100644 lib/ose/doc/src/Makefile create mode 100644 lib/ose/doc/src/book.xml create mode 100644 lib/ose/doc/src/notes.xml create mode 100644 lib/ose/doc/src/ose_app.xml create mode 100644 lib/ose/doc/src/ose_erl_driver.xml create mode 100644 lib/ose/doc/src/ose_intro.xml create mode 100644 lib/ose/doc/src/ose_signals_chapter.xml create mode 100644 lib/ose/doc/src/part.xml create mode 100644 lib/ose/doc/src/ref_man.xml create mode 100644 lib/ose/ebin/.gitignore create mode 100644 lib/ose/include/.gitignore create mode 100644 lib/ose/info create mode 100644 lib/ose/src/Makefile create mode 100644 lib/ose/src/ose.app.src create mode 100644 lib/ose/src/ose.appup.src create mode 100644 lib/ose/src/ose.erl create mode 100644 lib/ose/test/Makefile create mode 100644 lib/ose/test/ose.cover create mode 100644 lib/ose/test/ose.spec create mode 100644 lib/ose/test/ose_SUITE.erl create mode 100644 lib/ose/vsn.mk (limited to 'lib') diff --git a/lib/Makefile b/lib/Makefile index 5128241563..9257d8c7a9 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -34,7 +34,7 @@ ALL_ERLANG_APPLICATIONS = snmp otp_mibs erl_interface asn1 jinterface \ public_key ssl observer odbc diameter \ cosTransactions cosEvent cosTime cosNotification \ cosProperty cosFileTransfer cosEventDomain et megaco webtool \ - eunit ssh typer percept eldap dialyzer hipe + eunit ssh typer percept eldap dialyzer hipe ose ifdef BUILD_ALL ERLANG_APPLICATIONS += $(ALL_ERLANG_APPLICATIONS) diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile index 7f8023aba4..ec5d1f09e4 100644 --- a/lib/kernel/doc/src/Makefile +++ b/lib/kernel/doc/src/Makefile @@ -31,12 +31,6 @@ APPLICATION=kernel # ---------------------------------------------------- RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) -# ---------------------------------------------------- -# Help application directory specification -# ---------------------------------------------------- -EDOC_DIR = $(ERL_TOP)/lib/edoc -SYNTAX_TOOLS_DIR = $(ERL_TOP)/lib/syntax_tools - # ---------------------------------------------------- # Target Specs # ---------------------------------------------------- @@ -71,12 +65,6 @@ XML_REF3_FILES = application.xml \ user.xml \ zlib_stub.xml -ifeq ($(findstring ose,$(TARGET)),ose) -XML_EDOC_FILES = ose.xml -else -XML_EDOC_FILES = -endif - XML_REF4_FILES = app.xml config.xml XML_REF6_FILES = kernel_app.xml @@ -88,8 +76,8 @@ BOOK_FILES = book.xml XML_FILES = \ $(BOOK_FILES) $(XML_CHAPTER_FILES) \ - $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_EDOC_FILES)\ - $(XML_REF4_FILES) $(XML_REF6_FILES) $(XML_APPLICATION_FILES) + $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF4_FILES)\ + $(XML_REF6_FILES) $(XML_APPLICATION_FILES) # ---------------------------------------------------- @@ -115,7 +103,7 @@ TOP_SPECS_FILE = specs.xml # ---------------------------------------------------- XML_FLAGS += -SRC_DIR = ../../src +SPECS_ESRC = ../../src SPECS_FLAGS = -I../../include @@ -160,15 +148,6 @@ $(SPECDIR)/specs_zlib_stub.xml: escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ -o$(dir $@) -module zlib_stub -ose.xml: $(SRC_DIR)/ose.erl - escript $(DOCGEN)/priv/bin/xml_from_edoc.escript $(SRC_DIR)/$(@:%.xml=%.erl) -ref_man.xml: ref_man.xml.src -ifeq ($(findstring ose,$(TARGET)),ose) - sed -e 's:\(os.xml"/>\):\1\n:' $< > $@ -else - cp $< $@ -endif - # ---------------------------------------------------- # Release Target # ---------------------------------------------------- diff --git a/lib/kernel/doc/src/ref_man.xml b/lib/kernel/doc/src/ref_man.xml new file mode 100644 index 0000000000..bd25d1e78d --- /dev/null +++ b/lib/kernel/doc/src/ref_man.xml @@ -0,0 +1,67 @@ + + + + +
+ + 19962013 + Ericsson AB. 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. + + + + Kernel Reference Manual + + + + +
+ +

The Kernel application has all the code necessary to run + the Erlang runtime system itself: file servers and code servers + and so on.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile index 5379006784..cb3c0a49f4 100644 --- a/lib/kernel/src/Makefile +++ b/lib/kernel/src/Makefile @@ -117,10 +117,6 @@ MODULES = \ user_sup \ wrap_log_reader -ifeq ($(findstring ose,$(TARGET)),ose) -MODULES+=ose -endif - HRL_FILES= ../include/file.hrl ../include/inet.hrl ../include/inet_sctp.hrl \ ../include/dist.hrl ../include/dist_util.hrl \ ../include/net_address.hrl diff --git a/lib/kernel/src/ose.erl b/lib/kernel/src/ose.erl deleted file mode 100644 index ff7147233f..0000000000 --- a/lib/kernel/src/ose.erl +++ /dev/null @@ -1,452 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 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% -%% -%% @doc Interface module for OSE messaging and process monitoring from Erlang -%% -%% For each mailbox created through {@link open/1} a OSE phantom process with -%% that name is started. Since phantom processes are used the memory footprint -%% of each mailbox is quite small. -%% -%% To receive messages you first have to subscribe to the specific message -%% numbers that you are interested in with {@link listen/2}. The messages -%% will be sent to the Erlang process that created the mailbox. -%% -%% @end -%% --module(ose). - -%%============================================================================== -%% Exported API -%%============================================================================== --export([open/1, - close/1, - get_id/1, - get_name/2, - hunt/2, - dehunt/2, - attach/2, - detach/2, - send/4, - send/5, - listen/2 - ]). - -%%============================================================================== -%% Types -%%============================================================================== --opaque mailbox() :: port(). -%% Mailbox handle. Implemented as an erlang port. - --opaque mailbox_id() :: integer(). -%% Mailbox ID, this is the same as the process id of an OSE process. -%% An integer. - --type message_number() :: 0..4294967295. -%% OSE Signal number - --opaque hunt_ref() :: {mailbox(),integer()}. -%% Reference from a hunt request. This term will be included -%% in a successful hunt response. - --opaque attach_ref() :: {mailbox(),integer()}. -%% Reference from an attach request. This term will be included -%% in the term returned when the attached mailbox disappears. - --export_type([mailbox_id/0, - message_number/0, - mailbox/0, - hunt_ref/0, - attach_ref/0]). - -%%============================================================================== -%% Defines -%%============================================================================== --define(DRIVER_NAME, "ose_signal_drv"). --define(GET_SPID, 1). --define(GET_NAME, 2). --define(HUNT, 100). --define(DEHUNT, 101). --define(ATTACH, 102). --define(DETACH, 103). --define(SEND, 104). --define(SEND_W_S, 105). --define(LISTEN, 106). --define(OPEN, 200). - --define(INT_32BIT(Int),(is_integer(Int) andalso (Int >= 0) andalso (Int < (1 bsl 32)))). - -%%============================================================================== -%% API functions -%%============================================================================== - -%%------------------------------------------------------------------------------ -%% @doc Create a mailbox with the given name and return a port that handles -%% the mailbox. -%% -%% An OSE phantom process with the given name will be created that will send any -%% messages sent through this mailbox. Any messages sent to the new OSE process -%% will automatically be converted to an Erlang message and sent to the Erlang -%% process that calls this function. See {@link listen/2} for details about the -%% format of the message sent. -%% -%% The caller gets linked to the created mailbox. -%% -%% raises: `badarg' | `system_limit' -%% -%% @see liten/2 -%% @end -%%------------------------------------------------------------------------------ --spec open(Name) -> Port when - Name :: iodata(), - Port :: mailbox(). -open(Name) -> - try open_port({spawn_driver,?DRIVER_NAME}, [binary]) of - Port -> - try port_command(Port,[?OPEN,Name]) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - close(Port), - erlang:error(Error,[Name]); - {ose_drv_reply,Port,ok} -> - Port - end - catch - error:badarg -> close(Port),erlang:error(badarg,[Name]) - end - catch - error:badarg -> erlang:error(badarg,[Name]) - end. - -%%------------------------------------------------------------------------------ -%% @doc Close a mailbox -%% -%% This kills the OSE phantom process associated with this mailbox. -%% -%% Will also consume any ``{'EXIT',Port,_}'' message from the port that comes -%% due to the port closing when the calling process traps exits. -%% -%% raises: `badarg' -%% @end -%%------------------------------------------------------------------------------ --spec close(Port) -> ok when - Port :: mailbox(). -close(Port) when is_port(Port) -> - %% Copied from prim_inet - case erlang:process_info(self(), trap_exit) of - {trap_exit,true} -> - link(Port), - catch erlang:port_close(Port), - receive {'EXIT',Port,_} -> ok end; - {trap_exit,false} -> - catch erlang:port_close(Port), - ok - end; -close(NotPort) -> - erlang:error(badarg,[NotPort]). - -%%------------------------------------------------------------------------------ -%% @doc Get the mailbox id for the given port. -%% -%% The mailbox id is the same as the OSE process id of the OSE phantom process -%% that this mailbox represents. -%% -%% raises: `badarg' -%% @end -%%------------------------------------------------------------------------------ --spec get_id(Port) -> Pid when - Port :: mailbox(), - Pid :: mailbox_id(). -get_id(Port) -> - try port_control(Port, ?GET_SPID, <<>>) of - <> -> Spid - catch error:_Error -> - erlang:error(badarg,[Port]) - end. - -%%------------------------------------------------------------------------------ -%% @doc Get the mailbox name for the given mailbox id. -%% -%% The mailbox name is the name of the OSE process with process id Pid. -%% -%% This call will fail with badarg if the underlying system does not support -%% getting the name from a process id. -%% -%% raises: `badarg' -%% @end -%%------------------------------------------------------------------------------ --spec get_name(Port, Pid) -> Name | undefined when - Port :: mailbox(), - Pid :: mailbox_id(), - Name :: binary(). -get_name(Port, Pid) when ?INT_32BIT(Pid) -> - try port_control(Port, ?GET_NAME, <>) of - [] -> undefined; - Res -> Res - catch error:_Error -> - erlang:error(badarg,[Port,Pid]) - end; -get_name(Port, Pid) -> - erlang:error(badarg,[Port,Pid]). - - -%%------------------------------------------------------------------------------ -%% @doc Hunt for OSE process by name. -%% -%% Will send `{mailbox_up, Port, Ref, MboxId}' -%% to the calling process when the OSE process becomes available. -%% -%% Returns a reference term that can be used to cancel the hunt -%% using {@link dehunt/2}. -%% -%% raises: `badarg' -%% -%% @end -%%------------------------------------------------------------------------------ --spec hunt(Port, HuntPath) -> Ref when - Port :: mailbox(), - HuntPath :: iodata(), - Ref :: hunt_ref(). -hunt(Port, HuntPath) -> - try port_command(Port, [?HUNT,HuntPath]) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - erlang:error(Error,[Port,HuntPath]); - {ose_drv_reply,Port,Ref} -> - Ref - end - catch error:_Error -> - erlang:error(badarg,[Port,HuntPath]) - end. - -%%------------------------------------------------------------------------------ -%% @doc Stop hunting for OSE process. -%% -%% If a message for this hunt has been sent but not received -%% by the calling process, it is removed from the message queue. -%% Note that this only works if the same process that did -%% the hunt does the dehunt. -%% -%% raises: `badarg' -%% -%% @see hunt/2 -%% @end -%%------------------------------------------------------------------------------ --spec dehunt(Port, Ref) -> ok when - Port :: mailbox(), - Ref :: hunt_ref(). -dehunt(Port, {Port,Ref}) when ?INT_32BIT(Ref) -> - try port_command(Port, <>) of - true -> - receive - {ose_drv_reply,Port,{error,enoent}} -> - %% enoent could mean that it is in the message queue - receive - {mailbox_up, Port, {Port,Ref}, _} -> - ok - after 0 -> - ok - end; - {ose_drv_reply,Port,ok} -> - ok - end - catch error:_Error -> - erlang:error(badarg,[Port,{Port,Ref}]) - end; -dehunt(Port,Ref) -> - erlang:error(badarg,[Port,Ref]). - -%%------------------------------------------------------------------------------ -%% @doc Attach to an OSE process. -%% -%% Will send `{mailbox_down, Port, Ref, MboxId}' -%% to the calling process if the OSE process exits. -%% -%% Returns a reference that can be used to cancel the attachment -%% using {@link detach/2}. -%% -%% raises: `badarg' | `enomem' -%% -%% @end -%%------------------------------------------------------------------------------ --spec attach(Port,Pid) -> Ref when - Port :: mailbox(), - Pid :: mailbox_id(), - Ref :: attach_ref(). -attach(Port, Spid) when ?INT_32BIT(Spid) -> - try port_command(Port, <>) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - erlang:error(Error,[Port,Spid]); - {ose_drv_reply,Port,Ref} -> - Ref - end - catch error:_Error -> - erlang:error(badarg,[Port,Spid]) - end; -attach(Port,Spid) -> - erlang:error(badarg,[Port,Spid]). - - -%%------------------------------------------------------------------------------ -%% @doc Remove attachment to an OSE process. -%% -%% If a message for this monitor has been sent but not received -%% by the calling process, it is removed from the message queue. -%% Note that this only works of the same process -%% that did the attach does the detach. -%% -%% raises: `badarg' -%% -%% @see attach/2 -%% @end -%%------------------------------------------------------------------------------ --spec detach(Port,Ref) -> ok when - Port :: mailbox(), - Ref :: attach_ref(). -detach(Port, {Port,Ref} ) when ?INT_32BIT(Ref) -> - try port_command(Port, <>) of - true -> - receive - {ose_drv_reply,Port,{error,enoent}} -> - %% enoent could mean that it is in the message queue - receive - {mailbox_down,Port,{Port,Ref},_} -> - ok - after 0 -> - ok - end; - {ose_drv_reply,Port,ok} -> - ok - end - catch error:_Error -> - erlang:error(badarg,[Port,{Port,Ref}]) - end; -detach(Port,Ref) -> - erlang:error(badarg,[Port,Ref]). - -%%------------------------------------------------------------------------------ -%% @doc Send an OSE message. -%% -%% The message is sent from the OSE process' own ID that is: `get_id(Port)'. -%% -%% raises: `badarg' -%% -%% @see send/5 -%% @end -%%------------------------------------------------------------------------------ --spec send(Port,Pid,SigNo,SigData) -> ok when - Port :: mailbox(), - Pid :: mailbox_id(), - SigNo :: message_number(), - SigData :: iodata(). -send(Port, Spid, SigNo, SigData) when ?INT_32BIT(Spid), ?INT_32BIT(SigNo) -> - try erlang:port_command(Port, [<>, SigData]) of - true -> ok - catch error:_Error -> - erlang:error(badarg,[Port,Spid,SigNo,SigData]) - end; -send(Port,Spid,SigNo,SigData) -> - erlang:error(badarg,[Port,Spid,SigNo,SigData]). - - -%%------------------------------------------------------------------------------ -%% @doc Send an OSE message with different sender. -%% -%% As {@link send/4} but the sender will be `SenderPid'. -%% -%% raises: `badarg' -%% -%% @see send/4 -%% @end -%%------------------------------------------------------------------------------ --spec send(Port,Pid,SenderPid,SigNo,SigData) -> ok when - Port :: mailbox(), - Pid :: mailbox_id(), - SenderPid :: mailbox_id(), - SigNo :: message_number(), - SigData :: iodata(). -send(Port, Spid, SenderPid, SigNo, SigData) - when ?INT_32BIT(Spid), ?INT_32BIT(SenderPid), ?INT_32BIT(SigNo) -> - try erlang:port_command(Port, [<>, SigData]) of - true -> ok - catch error:_Error -> - erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]) - end; -send(Port,Spid,SenderPid,SigNo,SigData) -> - erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]). - -%%------------------------------------------------------------------------------ -%% @doc Start listening for specified OSE signal numbers. -%% -%% The mailbox will send `{message,Port,{FromMboxId,ToMboxId,MsgNo,MsgData}}' -%% to the process that created the mailbox when an OSE message with any -%% of the specified `SigNos' arrives. -%% -%% Repeated calls to listen will replace the current set of signal numbers to -%% listen to. i.e -%% -%% ```1>ose:listen(MsgB,[1234,12345]). -%% ok -%% 2> ose:listen(MsgB,[1234,123456]). -%% ok.''' -%% -%% The above will first listen for signals with numbers 1234 and 12345, and then -%% replace that with only listening to 1234 and 123456. -%% -%% With the current implementation it is not possible to listen to all signal -%% numbers. -%% -%% raises: `badarg' | `enomem' -%% -%% @end -%%------------------------------------------------------------------------------ --spec listen(Port, SigNos) -> ok when - Port :: mailbox(), - SigNos :: list(message_number()). -listen(Port, SigNos) when is_list(SigNos) -> - USSigNos = lists:usort(SigNos), - BinSigNos = try - << <> || - SigNo <- USSigNos, - ?INT_32BIT(SigNo) orelse erlang:error(badarg) - >> - catch _:_ -> - erlang:error(badarg,[Port,SigNos]) - end, - try port_command(Port, [?LISTEN, BinSigNos]) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - erlang:error(Error,[Port,SigNos]); - {ose_drv_reply,Port,Else} -> - Else - end - catch error:_Error -> - erlang:error(badarg,[Port,SigNos]) - end; -listen(Port, SigNos) -> - erlang:error(badarg,[Port,SigNos]). - - -%%%============================================================================= -%%% Internal functions -%%%============================================================================= diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index ac28d1aae9..f1b8a105ed 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -79,10 +79,6 @@ MODULES= \ loose_node \ sendfile_SUITE -ifeq ($(findstring ose,$(TARGET)),ose) -MODULES+=ose_SUITE -endif - APP_FILES = \ appinc.app \ appinc1.app \ diff --git a/lib/kernel/test/ose_SUITE.erl b/lib/kernel/test/ose_SUITE.erl deleted file mode 100644 index 7e81b19894..0000000000 --- a/lib/kernel/test/ose_SUITE.erl +++ /dev/null @@ -1,765 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1998-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% -%% --module(ose_SUITE). - -%-compile(export_all). - --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2,init_per_testcase/2, - end_per_testcase/2]). --export([ - basic/1,stress/1,multi_msg_numbers/1,multi_mailboxes/1, - hunt/1,multi_hunt/1,dehunt/1,multi_dehunt/1, - attach/1,multi_attach/1,detach/1,multi_detach/1, - open_errors/1,close_errors/1,get_id_errors/1,get_name_errors/1, - hunt_errors/1,dehunt_errors/1,attach_errors/1,detach_errors/1, - send_errors/1,send_w_s_errors/1,listen_errors/1 - ]). - --define(INTERFACE,ose). - - -init_per_testcase(_Func, Config) -> - Config. -end_per_testcase(_Func, _Config) -> - ok. - -suite() -> [{timeout,{30,seconds}}]. - -all() -> - [ - basic,stress,multi_msg_numbers,multi_mailboxes, - hunt,multi_hunt,dehunt,multi_dehunt, - attach,multi_attach,detach,multi_detach, - - open_errors,close_errors,get_id_errors,get_name_errors, - hunt_errors,dehunt_errors,attach_errors,detach_errors, - send_errors,send_w_s_errors,listen_errors - ]. - -groups() -> - []. - -init_per_suite(Config) -> - case os:type() of - {ose,_} -> - Config; - _Else -> - {skip,"Only run on OSE"} - end. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - -basic(_Config) -> - - [P1,P2] = multi_open(2,[42]), - P1Id = ?INTERFACE:get_id(P1), - P2Id = ?INTERFACE:get_id(P2), - - ok = ?INTERFACE:send(P2,P1Id,42,<<"ping">>), - receive - {message,P1,V1} -> - {P2Id,P1Id,42,<<"ping">>} = V1, - ?INTERFACE:send(P1,P2Id,42,<<"pong">>); - Else1 -> - ct:fail({got_wrong_message,Else1}) - end, - - receive - {message,P2,V2} -> - {P1Id,P2Id,42,<<"pong">>} = V2; - Else2 -> - ct:fail({got_wrong_message,Else2}) - end, - - ?INTERFACE:close(P1), - ?INTERFACE:close(P2). - -%% Send 1000 messages and see if we can cope and that msg order is preserved -stress(_Config) -> - - Iterations = 1000, - - [P1,P2] = multi_open(2,[42]), - P1Id = ?INTERFACE:get_id(P1), - P2Id = ?INTERFACE:get_id(P2), - - spawn(fun() -> - n(fun(N) -> - Msg = [<<"ping">>|integer_to_list(N)], - ?INTERFACE:send(P2,P1Id,42,Msg) - end,Iterations) - end), - timer:sleep(100), - n(fun(N) -> - receive - {message,P1,Value} -> - Int = integer_to_binary(N), - {P2Id,P1Id,42,<<"ping",Int/binary>>} = Value, - ok; - Else -> - ct:fail({got_wrong_message,Else}) - end - end,Iterations), - - ?INTERFACE:close(P1), - ?INTERFACE:close(P2). - -%% Listen to 1000 different message numbers and send some random messages -multi_msg_numbers(_Config) -> - - Iterations = 100, - - [P1,P2] = multi_open(2,lists:seq(2000,3000)), - P1Id = ?INTERFACE:get_id(P1), - - n(fun(_) -> - Num = random:uniform(1000)+2000, - ?INTERFACE:send(P2,P1Id,Num,<<"ping",(integer_to_binary(Num))/binary>>) - end,Iterations), - - n(fun(_) -> - receive - {message,P1,{_,_,Id,<<"ping",Num/binary>>}} when Id > 2000; - Id =< 3000 -> - Id = binary_to_integer(Num), - ok; - Else -> - ct:fail({got_wrong_message,Else}) - end - end,Iterations), - - ?INTERFACE:close(P1), - ?INTERFACE:close(P2). - - -%% Create 100 mailboxes and send messages to them -multi_mailboxes(_Config) -> - - Mailboxes = 100, - - [P1|MBs] = multi_open(Mailboxes,[42]), - - [?INTERFACE:send(P1,?INTERFACE:get_id(P),42,[<<"ping">>,?INTERFACE:get_name(P,?INTERFACE:get_id(P))]) || P <- MBs], - - [receive - {message,P,Value} -> - Name = ?INTERFACE:get_name(P,?INTERFACE:get_id(P)), - {_,_,42,<<"ping",Name/binary>>} = Value, - ok - end || P <- MBs], - - [?INTERFACE:close(P) || P <- [P1|MBs]], - ok. - -hunt(_Config) -> - [P1,P2] = multi_open(2,[]), - - Ref = ?INTERFACE:hunt(P1,"p2"), - receive - {mailbox_up,P1,Ref,Pid} -> - Pid = ?INTERFACE:get_id(P2), - ?INTERFACE:close(P1), - ?INTERFACE:close(P2); - Else -> - ct:fail({got_wrong_message,Else,Ref}) - end. - -multi_hunt(_Config) -> - - Iterations = 100, - - P = ?INTERFACE:open("p"), - - Refs = [?INTERFACE:hunt(P,"p"++integer_to_list(N))|| N <- lists:seq(1,Iterations)], - - Pids = [begin - Prt = ?INTERFACE:open("p"++integer_to_list(N)), - Pid = ?INTERFACE:get_id(Prt), - ?INTERFACE:close(Prt), - Pid - end || N <- lists:seq(1,Iterations)], - - [receive - {mailbox_up,P,Ref,Pid} -> - ok - after 10 -> - ct:fail({did_not_get,Pid,Ref}) - end || {Pid,Ref} <- lists:zip(Pids,Refs)], - ?INTERFACE:close(P). - - -dehunt(_Config) -> - [P1] = multi_open(1,[]), - Ref = ?INTERFACE:hunt(P1,"p2"), - receive - _Else -> ct:fail({got,_Else}) - after 1000 -> - ok - end, - P2 = ?INTERFACE:open("p2"), - - % Make sure any messages are sent - receive after 10 -> ok end, - - ok = ?INTERFACE:dehunt(P1,Ref), - - % Make sure no messages are received - receive - _Else2 -> ct:fail({got,_Else2}) - after 1000 -> - ?INTERFACE:close(P1), - ?INTERFACE:close(P2) - end. - -%%% -%%% This testcase basically: -%%% spawn 10 processes that in parallel -%%% adds some hunts for different OSE processes -%%% maybe create hunted OSE process -%%% dehunt half of the hunts -%%% create more hunts -%%% if not created create hunted OSE process -%%% veryify that all expected hunt messages are received -%%% verify that all processes exited correctly -%%% -%%% This complex test is done to make sure that the internal handling -%%% of dehunt works as expected. -%%% -multi_dehunt(_Config) -> - [P1] = multi_open(1,[]), - - Scenario = - fun(Iterations) -> - - Hunted = "p"++integer_to_list(Iterations), - %% Start a couple of hunts - Refs = [?INTERFACE:hunt(P1,Hunted) || _ <- lists:seq(1,Iterations)], - - %% We alternate if the process is opened before or after the dehunt - P2O = if Iterations rem 2 == 0 -> - ?INTERFACE:open(Hunted); - true -> - undefined - end, - - %% Remove half of them - {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 -> - ok = ?INTERFACE:dehunt(P1,Ref), - {[],Acc+1}; - (Ref,Acc) -> - {Ref,Acc+1} - end,0,Refs), - - %% Add some new ones - NewRefs = [?INTERFACE:hunt(P1,Hunted) - || _ <- lists:seq(1,Iterations div 4)] - ++ lists:flatten(RemRefs), - - P2 = if P2O == undefined -> - ?INTERFACE:open(Hunted); - true -> - P2O - end, - P2Id = ?INTERFACE:get_id(P2), - - %% Receive all the expected ones - lists:foreach(fun(Ref) -> - receive - {mailbox_up,P1,Ref,P2Id} -> - ok - after 1000 -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{did_not_get, Ref}}]), - ok = Ref - end - end,NewRefs), - - %% Check that no other have arrived - receive - _Else -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{got, _Else}}]), - ok = _Else - after 100 -> - ok - end, - ?INTERFACE:close(P2) - end, - - Self = self(), - - n(fun(N) -> - spawn(fun() -> Self ! - Scenario(N*25) - end), - ok - end,10), - - n(fun(_N) -> - receive ok -> ok - after 60000 -> ct:fail(failed) - end - end,10), - ?INTERFACE:close(P1). - -attach(_Config) -> - [P1,P2] = multi_open(2,[]), - - P2Id = ?INTERFACE:get_id(P2), - Ref = ?INTERFACE:attach(P1,P2Id), - ?INTERFACE:close(P2), - receive - {mailbox_down,P1,Ref,P2Id} -> - ?INTERFACE:close(P1); - _Else -> - ct:fail({got,_Else, {P1,Ref,P2Id}}) - after 1000 -> - ct:fail({did_not_get,P1,Ref,P2Id}) - end. - -multi_attach(_Config) -> - - Iterations = 100, - - [P1|Pids] = multi_open(Iterations,[]), - - Refs = [{?INTERFACE:get_id(Pid),?INTERFACE:attach(P1,?INTERFACE:get_id(Pid))} || Pid <- Pids], - - [?INTERFACE:close(Pid) || Pid <- Pids], - - [receive - {mailbox_down,P1,Ref,Pid} -> - ok - after 10000 -> - ct:fail({did_not_get,Pid,Ref}) - end || {Pid,Ref} <- Refs], - ?INTERFACE:close(P1). - -detach(_Config) -> - [P1,P2] = multi_open(2,[]), - P2Id = ?INTERFACE:get_id(P2), - Ref = ?INTERFACE:attach(P1,P2Id), - receive - _Else -> ct:fail({got,_Else}) - after 100 -> - ok - end, - - ?INTERFACE:close(P2), - - % Make sure any messages are sent - receive after 10 -> ok end, - - ?INTERFACE:detach(P1,Ref), - - % Make sure no messages are received - receive - _Else2 -> ct:fail({got,_Else2}) - after 1000 -> - ?INTERFACE:close(P1) - end. - -%%% -%%% This testcase basically: -%%% spawn 10 processes that in parallel -%%% adds some attach for different OSE processes -%%% maybe close OSE process -%%% dehunt half of the hunts -%%% create more hunts -%%% if not closed close attached OSE process -%%% veryify that all expected attach messages are received -%%% verify that all processes exited correctly -%%% -%%% This complex test is done to make sure that the internal handling -%%% of dehunt works as expected. -%%% -multi_detach(_Config) -> - [P1] = multi_open(1,[]), - - Scenario = - fun(Iterations) -> - - Attached = ?INTERFACE:open("p"++integer_to_list(Iterations)), - AttachedId = ?INTERFACE:get_id(Attached), - %% Start a couple of attachs - Refs = [?INTERFACE:attach(P1,AttachedId) || _ <- lists:seq(1,Iterations)], - - %% We alternate if the process is closed before or after the detach - P2O = if Iterations rem 2 == 0 -> - ?INTERFACE:close(Attached); - true -> - undefined - end, - - %% Remove half of them - {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 -> - ok = ?INTERFACE:detach(P1,Ref), - {[],Acc+1}; - (Ref,Acc) -> - {Ref,Acc+1} - end,0,Refs), - - %% Add some new ones - NewRefs = [?INTERFACE:attach(P1,AttachedId) - || _ <- lists:seq(1,Iterations div 4)] - ++ lists:flatten(RemRefs), - - if P2O == undefined -> - ?INTERFACE:close(Attached); - true -> - P2O - end, - - %% Receive all the expected ones - lists:foreach(fun(Ref) -> - receive - {mailbox_down,P1,Ref,AttachedId} -> - ok - after 1000 -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{did_not_get, Ref}}]), - ok = Ref - end - end,NewRefs), - - %% Check that no other have arrived - receive - _Else -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{got, _Else}}]), - ok = _Else - after 100 -> - ok - end - end, - - Self = self(), - - n(fun(N) -> - spawn(fun() -> Self ! - Scenario(N*5) - end), - ok - end,10), - - n(fun(_N) -> - receive ok -> ok - after 60000 -> ct:fail(failed) - end - end,10), - ?INTERFACE:close(P1). - - -open_errors(_Config) -> - {'EXIT',{badarg,[{?INTERFACE,open,[inval],_}|_]}} = - (catch ?INTERFACE:open(inval)), - {'EXIT',{badarg,[{?INTERFACE,open,[["p"|1]],_}|_]}} = - (catch ?INTERFACE:open(["p"|1])), - {'EXIT',{badarg,[{?INTERFACE,open,[["p",1234]],_}|_]}} = - (catch ?INTERFACE:open(["p",1234])), - - ok. - -close_errors(_Config) -> - {'EXIT',{badarg,[{?INTERFACE,close,[inval],_}|_]}} = - (catch ?INTERFACE:close(inval)), - - P1 = ?INTERFACE:open("p1"), - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:close(P1). - - -get_id_errors(_Config) -> - {'EXIT',{badarg,[{?INTERFACE,get_id,[inval],_}|_]}} = - (catch ?INTERFACE:get_id(inval)), - - P1 = ?INTERFACE:open("p1"), - ok = ?INTERFACE:close(P1), - {'EXIT',{badarg,[{?INTERFACE,get_id,[P1],_}|_]}} = - (catch ?INTERFACE:get_id(P1)), - - ok. - -get_name_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,inval],_}|_]}} = - (catch ?INTERFACE:get_name(P1,inval)), - - undefined = ?INTERFACE:get_name(P1,1234), - - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - ok = ?INTERFACE:close(P1), - {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,P2Id],_}|_]}} = - (catch ?INTERFACE:get_name(P1,P2Id)), - ?INTERFACE:close(P2), - - P3 = ?INTERFACE:open([255]), - <<255>> = ?INTERFACE:get_name(P3, ?INTERFACE:get_id(P3)), - ?INTERFACE:close(P3), - - ok. - -hunt_errors(_Config) -> - - {'EXIT',{badarg,[{?INTERFACE,hunt,[inval,"hello"],_}|_]}} = - (catch ?INTERFACE:hunt(inval,"hello")), - - P1 = ?INTERFACE:open("p1"), - {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello",12345]],_}|_]}} = - (catch ?INTERFACE:hunt(P1,["hello",12345])), - - P2 = ?INTERFACE:open(<<255>>), - P2Pid = ?INTERFACE:get_id(P2), - Ref = ?INTERFACE:hunt(P1,[255]), - receive - {mailbox_up,P1,Ref,P2Pid} -> - ok; - Else -> - ct:fail({got,Else,{mailbox_up,P1,Ref,P2Pid}}) - after 150 -> - ct:fail({did_not_get,{mailbox_up,P1,Ref,P2Pid}}) - end, - - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:close(P2), - {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello"]],_}|_]}} = - (catch ?INTERFACE:hunt(P1,["hello"])), - - ok. - -dehunt_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - Ref = ?INTERFACE:hunt(P1,"p2"), - - {'EXIT',{badarg,[{?INTERFACE,dehunt,[inval,Ref],_}|_]}} = - (catch ?INTERFACE:dehunt(inval,Ref)), - - {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,inval],_}|_]}} = - (catch ?INTERFACE:dehunt(P1,inval)), - - ok = ?INTERFACE:dehunt(P1,Ref), - ok = ?INTERFACE:dehunt(P1,Ref), - - ok = ?INTERFACE:close(P1), - - {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,Ref],_}|_]}} = - (catch ?INTERFACE:dehunt(P1,Ref)), - - case ?INTERFACE of - ose -> ok; - _ -> - P2 = ?INTERFACE:open("p2"), - ok = ?INTERFACE:close(P2) - end, - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -attach_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - - {'EXIT',{badarg,[{?INTERFACE,attach,[inval,P2Id],_}|_]}} = - (catch ?INTERFACE:attach(inval,P2Id)), - - {'EXIT',{badarg,[{?INTERFACE,attach,[P1,[12345]],_}|_]}} = - (catch ?INTERFACE:attach(P1,[12345])), - - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:close(P2), - {'EXIT',{badarg,[{?INTERFACE,attach,[P1,P2Id],_}|_]}} = - (catch ?INTERFACE:attach(P1,P2Id)), - - ok. - -detach_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - - Ref = ?INTERFACE:attach(P1,P2Id), - - {'EXIT',{badarg,[{?INTERFACE,detach,[inval,Ref],_}|_]}} = - (catch ?INTERFACE:detach(inval,Ref)), - - {'EXIT',{badarg,[{?INTERFACE,detach,[P1,inval],_}|_]}} = - (catch ?INTERFACE:detach(P1,inval)), - - ok = ?INTERFACE:detach(P1,Ref), - ok = ?INTERFACE:detach(P1,Ref), - - case ?INTERFACE of - ose -> ok; - _ -> - ok = ?INTERFACE:close(P1) - end, - - ok = ?INTERFACE:close(P2), - ok = ?INTERFACE:close(P1), - - {'EXIT',{badarg,[{?INTERFACE,detach,[P1,Ref],_}|_]}} = - (catch ?INTERFACE:detach(P1,Ref)), - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -send_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - - {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(inval,P2Id,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P1,inval,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,inval,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,inval,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,inval,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,inval],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,42,inval)), - - ok = ?INTERFACE:close(P2), - ok = ?INTERFACE:send(P1,P2Id,42,"hello"), - ok = ?INTERFACE:close(P1), - - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,42,"hello")), - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -send_w_s_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P1Id = ?INTERFACE:get_id(P1), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - P3 = ?INTERFACE:open("p3"), - P3Id = ?INTERFACE:get_id(P3), - - {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,P1Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(inval,P2Id,P1Id,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,-1,P1Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P2,-1,P1Id,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,1 bsl 32,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P2,P2Id,1 bsl 32,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,inval,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P2,P2Id,P1Id,inval,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,42,inval],_}|_]}} = - (catch ?INTERFACE:send(P2,P2Id,P1Id,42,inval)), - - ok = ?INTERFACE:close(P3), - ok = ?INTERFACE:send(P2,P3Id,P1Id,42,"hello"), - - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:send(P2,P2Id,P1Id,42,"hello"), - ok = ?INTERFACE:close(P2), - - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,P1Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,P1Id,42,"hello")), - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -listen_errors(_Config) -> - - P1 = ?INTERFACE:open("p1"), - P1Id = ?INTERFACE:get_id(P1), - - {'EXIT',{badarg,[{?INTERFACE,listen,[inval,[42]],_}|_]}} = - (catch ?INTERFACE:listen(inval,[42])), - {'EXIT',{badarg,[{?INTERFACE,listen,[P1,inval],_}|_]}} = - (catch ?INTERFACE:listen(P1,inval)), - {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[1 bsl 33]],_}|_]}} = - (catch ?INTERFACE:listen(P1,[1 bsl 33])), - - ok = ?INTERFACE:listen(P1,[42,42,42,42,42,42,42,42,42,42,42,42,42]), - - case ?INTERFACE of - ose -> ok; - _ -> - ?INTERFACE:send(P1,P1Id,42,"hello"), - timer:sleep(50), - ?INTERFACE:listen(P1,[]), - ?INTERFACE:send(P1,P1Id,42,"hello2"), - - receive - {message,P1,42,"hello"} -> ok - end, - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end - end, - - ok = ?INTERFACE:close(P1), - {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[42]],_}|_]}} = - (catch ?INTERFACE:listen(P1,[42])), - - ok. - -%% -%% Internal functions -%% -multi_open(N,ListenNums) -> - multi_open(N,ListenNums,[]). - -multi_open(0,_,Acc) -> - Acc; -multi_open(N,ListenNums,Acc) -> - P = ?INTERFACE:open("p"++integer_to_list(N)), - ok = ?INTERFACE:listen(P,ListenNums), - multi_open(N-1,ListenNums,[P|Acc]). - -n(_F,0) -> - ok; -n(F,N) -> - ok = F(N), - n(F,N-1). - - -flush() -> - receive - Msg -> - [Msg|flush()] - after 0 -> - [] - end. diff --git a/lib/ose/Makefile b/lib/ose/Makefile new file mode 100644 index 0000000000..2959f04c3e --- /dev/null +++ b/lib/ose/Makefile @@ -0,0 +1,36 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1996-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% +# +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# +# Macros +# + +SUB_DIRECTORIES = src doc/src + +include vsn.mk +VSN = $(OSE_VSN) + +SPECIAL_TARGETS = + +# +# Default Subdir Targets +# +include $(ERL_TOP)/make/otp_subdir.mk diff --git a/lib/ose/doc/html/.gitignore b/lib/ose/doc/html/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/ose/doc/man3/.gitignore b/lib/ose/doc/man3/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/ose/doc/man6/.gitignore b/lib/ose/doc/man6/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/ose/doc/pdf/.gitignore b/lib/ose/doc/pdf/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/ose/doc/src/.gitignore b/lib/ose/doc/src/.gitignore new file mode 100644 index 0000000000..860e9e703e --- /dev/null +++ b/lib/ose/doc/src/.gitignore @@ -0,0 +1 @@ +ose.xml diff --git a/lib/ose/doc/src/Makefile b/lib/ose/doc/src/Makefile new file mode 100644 index 0000000000..dd58029064 --- /dev/null +++ b/lib/ose/doc/src/Makefile @@ -0,0 +1,132 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-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% +# +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../../vsn.mk +VSN=$(OSE_VSN) +APPLICATION=ose + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) + +# ---------------------------------------------------- +# Help application directory specification +# ---------------------------------------------------- +EDOC_DIR = $(ERL_TOP)/lib/edoc +SYNTAX_TOOLS_DIR = $(ERL_TOP)/lib/syntax_tools + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- +XML_APPLICATION_FILES = ref_man.xml + +XML_REF3_FILES = \ + ose.xml \ + ose_erl_driver.xml + +XML_REF6_FILES = ose_app.xml + +XML_PART_FILES = part.xml +XML_CHAPTER_FILES = notes.xml ose_intro.xml ose_signals_chapter.xml + +BOOK_FILES = book.xml + +XML_FILES = \ + $(BOOK_FILES) $(XML_CHAPTER_FILES) \ + $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES) \ + $(XML_APPLICATION_FILES) + +# ---------------------------------------------------- + +HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ + $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) + +INFO_FILE = ../../info + +MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) +MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6) + +HTML_REF_MAN_FILE = $(HTMLDIR)/index.html + +TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf + +SPECS_FILES = + +TOP_SPECS_FILE = + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +XML_FLAGS += + +SPECS_FLAGS = -I../../include -I../../../kernel/include + +OSE_SRC_DIR = ../../src + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +docs: man pdf html + +$(TOP_PDF_FILE): $(XML_FILES) + +pdf: $(TOP_PDF_FILE) + +html: $(HTML_REF_MAN_FILE) + +man: $(MAN3_FILES) $(MAN6_FILES) + +ose.xml: $(OSE_SRC_DIR)/ose.erl + escript $(DOCGEN)/priv/bin/xml_from_edoc.escript\ + $(OSE_SRC_DIR)/$(@:%.xml=%.erl) + +debug opt: + +clean clean_docs: + rm -rf $(HTMLDIR)/* + rm -f $(MAN3DIR)/* + rm -f $(MAN6DIR)/* + rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) + rm -f $(SPECDIR)/* + rm -f errs core *~ + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_docs_spec: docs + $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf" + $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf" + $(INSTALL_DIR) "$(RELSYSDIR)/doc/html" + $(INSTALL_DATA) $(HTMLDIR)/* \ + "$(RELSYSDIR)/doc/html" + $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)" + $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3" + $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3" + $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6" + $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6" + +release_spec: diff --git a/lib/ose/doc/src/book.xml b/lib/ose/doc/src/book.xml new file mode 100644 index 0000000000..485806e05b --- /dev/null +++ b/lib/ose/doc/src/book.xml @@ -0,0 +1,48 @@ + + + + +
+ + 20142014 + Ericsson AB. 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. + + + + OSE + Lukas Larsson + + 2014-01-08 + 1.0 + book.xml +
+ + + OSE + + + + + + + + + + + + + + +
diff --git a/lib/ose/doc/src/notes.xml b/lib/ose/doc/src/notes.xml new file mode 100644 index 0000000000..760b92feed --- /dev/null +++ b/lib/ose/doc/src/notes.xml @@ -0,0 +1,33 @@ + + + + +
+ + 20142014 + Ericsson AB. 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. + + + + OSE Release Notes + + + + + notes.xml +
+

This document describes the changes made to the OSE application.

+ +
diff --git a/lib/ose/doc/src/ose_app.xml b/lib/ose/doc/src/ose_app.xml new file mode 100644 index 0000000000..e40656fd7b --- /dev/null +++ b/lib/ose/doc/src/ose_app.xml @@ -0,0 +1,37 @@ + + + + +
+ + 20142014 + Ericsson AB. 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. + + + + Enea OSE + + + + +
+ ose + The OSE Application + +

The OSE application contains modules and documentation that only + applies when running Erlang/OTP on Enea OSE.

+
+ +
diff --git a/lib/ose/doc/src/ose_erl_driver.xml b/lib/ose/doc/src/ose_erl_driver.xml new file mode 100644 index 0000000000..6687d78087 --- /dev/null +++ b/lib/ose/doc/src/ose_erl_driver.xml @@ -0,0 +1,109 @@ + + + + +
+ + 20132014 + Ericsson AB. 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. + + + + erl_driver for Enea OSE + Lukas Larsson + + 2014-01-08 + A + ose_erl_driver.xml +
+ ose_erl_driver + Linked-in drivers in Enea OSE + +

Writing Linked-in drivers that also work on Enea OSE is very similar for + how you would do it for Unix. The difference from Unix is that + driver_select, ready_input and ready_output all work with signals + instead of file descriptors. This means that the driver_select is + used to specify which type of signal should trigger calls to + ready_input/ready_output. The functions described below are available + to driver programmers on Enea OSE to facilitate this. +

+
+
+ DATA TYPES + + + union SIGNAL + See the Enea OSE SPI documentation for a description. + SIGSELECT + See the Enea OSE SPI documentation for a description. + ErlDrvEvent + The ErlDrvEvent is a handle to a signal number and id combination. It is passed to driver_select(3). + ErlDrvOseEventId + This is the id used to associate a specific signal to a + certain driver instance. + +
+ + + union SIGNAL *erl_drv_ose_get_signal(ErlDrvEvent drv_event) + + +

Fetch the next signal associated with drv_event. + Signals will be returned in the order which they were received and + when no more signals are available NULL will be returned. + Use this function in the ready_input/ready_output callbacks + to get signals.

+
+
+ + ErlDrvEventerl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id, ErlDrvOseEventId (*resolve_signal)(union SIGNAL* sig)) + + +

Create a new ErlDrvEvent associated with signo, + id and uses the resolve_signal function to extract + the id from a signal with signo. See + + Signals in a Linked-in driver in the OSE User's Guide. +

+
+
+ + voiderl_drv_ose_event_free(ErlDrvEvent drv_event) + + +

Free a ErlDrvEvent. This should always be done in the + stop_select + callback when the event is no longer being used.

+
+
+ + voiderl_drv_ose_event_fetch(ErlDrvEvent drv_event, SIGSELECT *signo, int *id) + + +

Write the signal number and id associated with drv_event + into *signo and *id respectively. NULL can be + also passed as signo or id in order to ignore that field. +

+
+
+
+
+ SEE ALSO +

+ driver_entry(3), + erl_driver(3) +

+
+
diff --git a/lib/ose/doc/src/ose_intro.xml b/lib/ose/doc/src/ose_intro.xml new file mode 100644 index 0000000000..3bab325289 --- /dev/null +++ b/lib/ose/doc/src/ose_intro.xml @@ -0,0 +1,48 @@ + + + + +
+ + 20132014 + Ericsson AB. 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. + + + + Introduction + Lukas Larsson + + 2014-01-08 + A + ose_intro.xml +
+ +
+ Features +
+ +
+ run_erl and to_erl +

+ In OSE run_erl and to_erl are combined into a single load module called + run_erl_lm. Installing and starting the load module will add two new + shell commands called run_erl and to_erl. They work in exactly the same + way as the unix variants of run_erl and to_erl, except that the read + and write pipes have to be placed under the /pipe vm. See also + run_erl for more details. +

+
+ +
diff --git a/lib/ose/doc/src/ose_signals_chapter.xml b/lib/ose/doc/src/ose_signals_chapter.xml new file mode 100644 index 0000000000..2a6ddb5765 --- /dev/null +++ b/lib/ose/doc/src/ose_signals_chapter.xml @@ -0,0 +1,197 @@ + + + + +
+ + 20132014 + Ericsson AB. 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. + + + + Interacting with Enea OSE + Lukas Larsson + + 2014-01-08 + A + ose_signals_chapter.xml +
+ + +
+ Introduction +

The main way which programs on Enea OSE interact is through the + usage of message passing, much the same way as Erlang processes + communicate. There are two ways in which an Erlang programmer can + interact with the signals sent from other Enea OSE processes; either + through the provided ose module, or by writing a custom linked-in + driver. This User's Guide describes and provides examples for both + approaches. +

+
+ + +
+ Signals in Erlang +
+ + +
+ Signals in a Linked-in driver +

+ Writing Linked-in drivers for OSE is very similar to how it is done + for Unix/Windows. It is only the way in which the driver subscribes + and consumed external events that is different. In Unix (and Windows) + file descriptiors (and Event Objects) are used to select on. On OSE + we use signals to deliver the same functionality. There are two large + differences between a signal and an fd. +

+

+ In OSE it is not possible for a signal number to be a unique identifier + for a resource in the same way as an fd is. For example; let's say we + implement a driver that does an asynchronous hunt that uses signal + number 1234 as the hunt_sig. If we want to be able to have multiple + hunt ports running at the same time we have to have someway of routing + the signal to the correct port. This is achieved by supplying a secondary + id that can be retrieved through the meta-data or payload of the signal, + e.g: + ErlDrvEvent event = erl_drv_ose_event_alloc(1234,port,resolver); + The event you get back from + + erl_drv_ose_event_alloc can then be used by + driver_select + to subscribe to signals. The first argument is just the signal number + that we are interested in. The second is the id that we choose to use, + in this case the port id that we got in the + start callback is + used. The third argument is a function pointer to a function that can + be used to figure out the id from a given signal. There is a complete + example of what this could look like in + the next section. + It is very important to issue the driver_select call before + any of the signals you are interested in are sent. If driver_select + is called after the signal is sent, there is a high probability that it + will be lost. +

+

+ The other difference from unix is that in OSE the payload of the event + (i.e. the signal data) is already received when the ready_output/input + callbacks are called. This means that you access the data of a signal + by calling + erl_drv_ose_get_signal. Additionally multiple signals might be + associated with the event, so you should call + + erl_drv_ose_get_signal until NULL is returned. +

+
+ + +
+ Example Linked-in driver +#include "erl_driver.h" +#include "ose.h" + +struct huntsig { + SIGSELECT signo; + ErlDrvPort port; +}; + +union SIGNAL { + SIGSELECT signo; + struct huntsig; +} + +/* Here we have to get the id from the signal. In this case we use the + port id since we have control over the data structure of the signal. + It is however possible to use anything in here. The only restriction + is that the same id has to be used for all signals of the same number.*/ +ErlDrvOseEventId resolver(union SIGNAL *sig) { + return (ErlDrvOseEventId)sig->huntsig.port; +} + +static int drv_init(void) { return 0; }; + +static ErlDrvData drv_start(ErlDrvPort port, char *command) { + return (ErlDrvData)port; +} + +static ErlDrvSSizeT control(ErlDrvData driver_data, unsigned int cmd, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { + ErlDrvPort port = (ErlDrvPort)driver_data; + + /* Create a new event to select on */ + ErlDrvOseEvent evt = erl_drv_ose_event_alloc(1234,port,resolver); + + /* Make sure to do the select call _BEFORE_ the signal arrives. + The signal might get lost if the hunt call is done before the + select. */ + driver_select(port,evt,ERL_DRV_READ|ERL_DRV_USE,1); + + union SIGNAL *sig = alloc(sizeof(union SIGNAL),1234); + sig->huntsig.port = port; + hunt("testprocess",0,NULL,&sig); + return 0; +} + +static void ready_input(ErlDrvData driver_data, ErlDrvEvent evt) { + /* Get the first signal payload from the event */ + union SIGNAL *sig = erl_drv_ose_get_signal(evt); + ErlDrvPort port = (ErlDrvPort)driver_data; + while (sig != NULL) { + if (sig->signo == 1234) { + /* If it is our signal we send a message with the sender of the signal + to the controlling erlang process */ + ErlDrvTermData reply[] = { ERL_DRV_UINT, (ErlDrvUInt)sender(&sig) }; + erl_drv_send_term(port,reply,sizeof(reply) / sizeof(reply[0])); + } + + /* Cleanup the signal and deselect on the event. + Note that the event itself has to be free'd in the stop_select + callback. */ + free_buf(&sig); + driver_select(port,evt,ERL_DRV_READ|ERL_DRV_USE,0); + + /* There could be more than one signal waiting in this event, so + we have to loop until sig == NULL */ + sig = erl_drv_ose_get_signal(evt); + } +} + +static void stop_select(ErlDrvEvent event, void *reserved) +{ + erl_drv_ose_event_free(event); +} + +/** + * Setup the driver entry for the Erlang runtime + **/ +ErlDrvEntry ose_signal_driver_entry = { + .init = drv_init, + .start = drv_start, + .stop = drv_stop, + .ready_input = ready_input, + .driver_name = DRIVER_NAME, + .control = control, + .extended_marker = ERL_DRV_EXTENDED_MARKER, + .major_version = ERL_DRV_EXTENDED_MAJOR_VERSION, + .minor_version = ERL_DRV_EXTENDED_MINOR_VERSION, + .driver_flags = ERL_DRV_FLAG_USE_PORT_LOCKING, + .stop_select = stop_select +}; + +
+ +
diff --git a/lib/ose/doc/src/part.xml b/lib/ose/doc/src/part.xml new file mode 100644 index 0000000000..250bb11f96 --- /dev/null +++ b/lib/ose/doc/src/part.xml @@ -0,0 +1,38 @@ + + + + +
+ + 2014 + 2014 + Ericsson AB, 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. + + The Initial Developer of the Original Code is Ericsson AB. + + + OSE User's Guide + Lukas Larsson + + 2014-01-08 + 1.0 + part.xml +
+ +

OSE.

+
+ + +
diff --git a/lib/ose/doc/src/ref_man.xml b/lib/ose/doc/src/ref_man.xml new file mode 100644 index 0000000000..54c1182fcb --- /dev/null +++ b/lib/ose/doc/src/ref_man.xml @@ -0,0 +1,39 @@ + + + + +
+ + 20142014 + Ericsson AB. 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. + + + + OSE Reference Manual + Lukas Larsson + + 2014-01-08 + 1.0 + ref_man.xml +
+ +

The Standard Erlang Libraries application, STDLIB, + contains modules for manipulating lists, strings and files etc.

+

+
+ + + +
diff --git a/lib/ose/ebin/.gitignore b/lib/ose/ebin/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/ose/include/.gitignore b/lib/ose/include/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/ose/info b/lib/ose/info new file mode 100644 index 0000000000..85c07dbe82 --- /dev/null +++ b/lib/ose/info @@ -0,0 +1,2 @@ +group: misc Miscellaneous Applications +short: Description of Enea OSE specific functionality diff --git a/lib/ose/src/Makefile b/lib/ose/src/Makefile new file mode 100644 index 0000000000..88f89578fb --- /dev/null +++ b/lib/ose/src/Makefile @@ -0,0 +1,106 @@ +# +# %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% +# + +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../vsn.mk +VSN=$(OSE_VSN) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/ose-$(VSN) + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- +MODULES= \ + ose + +HRL_FILES= + +INTERNAL_HRL_FILES= + +ERL_FILES= $(MODULES:%=%.erl) + +TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET) + +APP_FILE= ose.app + +APP_SRC= $(APP_FILE).src +APP_TARGET= $(EBIN)/$(APP_FILE) + +APPUP_FILE= ose.appup + +APPUP_SRC= $(APPUP_FILE).src +APPUP_TARGET= $(EBIN)/$(APPUP_FILE) + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- + +ifeq ($(NATIVE_LIBS_ENABLED),yes) +ERL_COMPILE_FLAGS += +native +endif +ERL_COMPILE_FLAGS += -I../include -I../../kernel/include -Werror + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +debug opt: $(TARGET_FILES) + +clean: + rm -f $(TARGET_FILES) + rm -f core + rm -f erl_parse.erl + +docs: + +# ---------------------------------------------------- +# Special Build Targets +# ---------------------------------------------------- + +$(APP_TARGET): $(APP_SRC) ../vsn.mk + $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ + +$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk + $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + $(INSTALL_DIR) "$(RELSYSDIR)/src" + $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src" + $(INSTALL_DIR) "$(RELSYSDIR)/include" + $(INSTALL_DIR) "$(RELSYSDIR)/ebin" + $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin" + +release_docs_spec: + +# ---------------------------------------------------- +# Dependencies -- alphabetically, please +# ---------------------------------------------------- diff --git a/lib/ose/src/ose.app.src b/lib/ose/src/ose.app.src new file mode 100644 index 0000000000..c39d3f2d05 --- /dev/null +++ b/lib/ose/src/ose.app.src @@ -0,0 +1,26 @@ +%% This is an -*- erlang -*- file. +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-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% +%% +{application, ose, + [{description, "Enea OSE specific modules"}, + {vsn, "%VSN%"}, + {modules, [ose]}, + {registered,[]}, + {applications, [stdlib,kernel]}, + {env, []}]}. diff --git a/lib/ose/src/ose.appup.src b/lib/ose/src/ose.appup.src new file mode 100644 index 0000000000..6654efde16 --- /dev/null +++ b/lib/ose/src/ose.appup.src @@ -0,0 +1,22 @@ +%% -*- erlang -*- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-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% +{"%VSN%", + [ + ], + [ + ]}. diff --git a/lib/ose/src/ose.erl b/lib/ose/src/ose.erl new file mode 100644 index 0000000000..ff7147233f --- /dev/null +++ b/lib/ose/src/ose.erl @@ -0,0 +1,452 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 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% +%% +%% @doc Interface module for OSE messaging and process monitoring from Erlang +%% +%% For each mailbox created through {@link open/1} a OSE phantom process with +%% that name is started. Since phantom processes are used the memory footprint +%% of each mailbox is quite small. +%% +%% To receive messages you first have to subscribe to the specific message +%% numbers that you are interested in with {@link listen/2}. The messages +%% will be sent to the Erlang process that created the mailbox. +%% +%% @end +%% +-module(ose). + +%%============================================================================== +%% Exported API +%%============================================================================== +-export([open/1, + close/1, + get_id/1, + get_name/2, + hunt/2, + dehunt/2, + attach/2, + detach/2, + send/4, + send/5, + listen/2 + ]). + +%%============================================================================== +%% Types +%%============================================================================== +-opaque mailbox() :: port(). +%% Mailbox handle. Implemented as an erlang port. + +-opaque mailbox_id() :: integer(). +%% Mailbox ID, this is the same as the process id of an OSE process. +%% An integer. + +-type message_number() :: 0..4294967295. +%% OSE Signal number + +-opaque hunt_ref() :: {mailbox(),integer()}. +%% Reference from a hunt request. This term will be included +%% in a successful hunt response. + +-opaque attach_ref() :: {mailbox(),integer()}. +%% Reference from an attach request. This term will be included +%% in the term returned when the attached mailbox disappears. + +-export_type([mailbox_id/0, + message_number/0, + mailbox/0, + hunt_ref/0, + attach_ref/0]). + +%%============================================================================== +%% Defines +%%============================================================================== +-define(DRIVER_NAME, "ose_signal_drv"). +-define(GET_SPID, 1). +-define(GET_NAME, 2). +-define(HUNT, 100). +-define(DEHUNT, 101). +-define(ATTACH, 102). +-define(DETACH, 103). +-define(SEND, 104). +-define(SEND_W_S, 105). +-define(LISTEN, 106). +-define(OPEN, 200). + +-define(INT_32BIT(Int),(is_integer(Int) andalso (Int >= 0) andalso (Int < (1 bsl 32)))). + +%%============================================================================== +%% API functions +%%============================================================================== + +%%------------------------------------------------------------------------------ +%% @doc Create a mailbox with the given name and return a port that handles +%% the mailbox. +%% +%% An OSE phantom process with the given name will be created that will send any +%% messages sent through this mailbox. Any messages sent to the new OSE process +%% will automatically be converted to an Erlang message and sent to the Erlang +%% process that calls this function. See {@link listen/2} for details about the +%% format of the message sent. +%% +%% The caller gets linked to the created mailbox. +%% +%% raises: `badarg' | `system_limit' +%% +%% @see liten/2 +%% @end +%%------------------------------------------------------------------------------ +-spec open(Name) -> Port when + Name :: iodata(), + Port :: mailbox(). +open(Name) -> + try open_port({spawn_driver,?DRIVER_NAME}, [binary]) of + Port -> + try port_command(Port,[?OPEN,Name]) of + true -> + receive + {ose_drv_reply,Port,{error,Error}} -> + close(Port), + erlang:error(Error,[Name]); + {ose_drv_reply,Port,ok} -> + Port + end + catch + error:badarg -> close(Port),erlang:error(badarg,[Name]) + end + catch + error:badarg -> erlang:error(badarg,[Name]) + end. + +%%------------------------------------------------------------------------------ +%% @doc Close a mailbox +%% +%% This kills the OSE phantom process associated with this mailbox. +%% +%% Will also consume any ``{'EXIT',Port,_}'' message from the port that comes +%% due to the port closing when the calling process traps exits. +%% +%% raises: `badarg' +%% @end +%%------------------------------------------------------------------------------ +-spec close(Port) -> ok when + Port :: mailbox(). +close(Port) when is_port(Port) -> + %% Copied from prim_inet + case erlang:process_info(self(), trap_exit) of + {trap_exit,true} -> + link(Port), + catch erlang:port_close(Port), + receive {'EXIT',Port,_} -> ok end; + {trap_exit,false} -> + catch erlang:port_close(Port), + ok + end; +close(NotPort) -> + erlang:error(badarg,[NotPort]). + +%%------------------------------------------------------------------------------ +%% @doc Get the mailbox id for the given port. +%% +%% The mailbox id is the same as the OSE process id of the OSE phantom process +%% that this mailbox represents. +%% +%% raises: `badarg' +%% @end +%%------------------------------------------------------------------------------ +-spec get_id(Port) -> Pid when + Port :: mailbox(), + Pid :: mailbox_id(). +get_id(Port) -> + try port_control(Port, ?GET_SPID, <<>>) of + <> -> Spid + catch error:_Error -> + erlang:error(badarg,[Port]) + end. + +%%------------------------------------------------------------------------------ +%% @doc Get the mailbox name for the given mailbox id. +%% +%% The mailbox name is the name of the OSE process with process id Pid. +%% +%% This call will fail with badarg if the underlying system does not support +%% getting the name from a process id. +%% +%% raises: `badarg' +%% @end +%%------------------------------------------------------------------------------ +-spec get_name(Port, Pid) -> Name | undefined when + Port :: mailbox(), + Pid :: mailbox_id(), + Name :: binary(). +get_name(Port, Pid) when ?INT_32BIT(Pid) -> + try port_control(Port, ?GET_NAME, <>) of + [] -> undefined; + Res -> Res + catch error:_Error -> + erlang:error(badarg,[Port,Pid]) + end; +get_name(Port, Pid) -> + erlang:error(badarg,[Port,Pid]). + + +%%------------------------------------------------------------------------------ +%% @doc Hunt for OSE process by name. +%% +%% Will send `{mailbox_up, Port, Ref, MboxId}' +%% to the calling process when the OSE process becomes available. +%% +%% Returns a reference term that can be used to cancel the hunt +%% using {@link dehunt/2}. +%% +%% raises: `badarg' +%% +%% @end +%%------------------------------------------------------------------------------ +-spec hunt(Port, HuntPath) -> Ref when + Port :: mailbox(), + HuntPath :: iodata(), + Ref :: hunt_ref(). +hunt(Port, HuntPath) -> + try port_command(Port, [?HUNT,HuntPath]) of + true -> + receive + {ose_drv_reply,Port,{error,Error}} -> + erlang:error(Error,[Port,HuntPath]); + {ose_drv_reply,Port,Ref} -> + Ref + end + catch error:_Error -> + erlang:error(badarg,[Port,HuntPath]) + end. + +%%------------------------------------------------------------------------------ +%% @doc Stop hunting for OSE process. +%% +%% If a message for this hunt has been sent but not received +%% by the calling process, it is removed from the message queue. +%% Note that this only works if the same process that did +%% the hunt does the dehunt. +%% +%% raises: `badarg' +%% +%% @see hunt/2 +%% @end +%%------------------------------------------------------------------------------ +-spec dehunt(Port, Ref) -> ok when + Port :: mailbox(), + Ref :: hunt_ref(). +dehunt(Port, {Port,Ref}) when ?INT_32BIT(Ref) -> + try port_command(Port, <>) of + true -> + receive + {ose_drv_reply,Port,{error,enoent}} -> + %% enoent could mean that it is in the message queue + receive + {mailbox_up, Port, {Port,Ref}, _} -> + ok + after 0 -> + ok + end; + {ose_drv_reply,Port,ok} -> + ok + end + catch error:_Error -> + erlang:error(badarg,[Port,{Port,Ref}]) + end; +dehunt(Port,Ref) -> + erlang:error(badarg,[Port,Ref]). + +%%------------------------------------------------------------------------------ +%% @doc Attach to an OSE process. +%% +%% Will send `{mailbox_down, Port, Ref, MboxId}' +%% to the calling process if the OSE process exits. +%% +%% Returns a reference that can be used to cancel the attachment +%% using {@link detach/2}. +%% +%% raises: `badarg' | `enomem' +%% +%% @end +%%------------------------------------------------------------------------------ +-spec attach(Port,Pid) -> Ref when + Port :: mailbox(), + Pid :: mailbox_id(), + Ref :: attach_ref(). +attach(Port, Spid) when ?INT_32BIT(Spid) -> + try port_command(Port, <>) of + true -> + receive + {ose_drv_reply,Port,{error,Error}} -> + erlang:error(Error,[Port,Spid]); + {ose_drv_reply,Port,Ref} -> + Ref + end + catch error:_Error -> + erlang:error(badarg,[Port,Spid]) + end; +attach(Port,Spid) -> + erlang:error(badarg,[Port,Spid]). + + +%%------------------------------------------------------------------------------ +%% @doc Remove attachment to an OSE process. +%% +%% If a message for this monitor has been sent but not received +%% by the calling process, it is removed from the message queue. +%% Note that this only works of the same process +%% that did the attach does the detach. +%% +%% raises: `badarg' +%% +%% @see attach/2 +%% @end +%%------------------------------------------------------------------------------ +-spec detach(Port,Ref) -> ok when + Port :: mailbox(), + Ref :: attach_ref(). +detach(Port, {Port,Ref} ) when ?INT_32BIT(Ref) -> + try port_command(Port, <>) of + true -> + receive + {ose_drv_reply,Port,{error,enoent}} -> + %% enoent could mean that it is in the message queue + receive + {mailbox_down,Port,{Port,Ref},_} -> + ok + after 0 -> + ok + end; + {ose_drv_reply,Port,ok} -> + ok + end + catch error:_Error -> + erlang:error(badarg,[Port,{Port,Ref}]) + end; +detach(Port,Ref) -> + erlang:error(badarg,[Port,Ref]). + +%%------------------------------------------------------------------------------ +%% @doc Send an OSE message. +%% +%% The message is sent from the OSE process' own ID that is: `get_id(Port)'. +%% +%% raises: `badarg' +%% +%% @see send/5 +%% @end +%%------------------------------------------------------------------------------ +-spec send(Port,Pid,SigNo,SigData) -> ok when + Port :: mailbox(), + Pid :: mailbox_id(), + SigNo :: message_number(), + SigData :: iodata(). +send(Port, Spid, SigNo, SigData) when ?INT_32BIT(Spid), ?INT_32BIT(SigNo) -> + try erlang:port_command(Port, [<>, SigData]) of + true -> ok + catch error:_Error -> + erlang:error(badarg,[Port,Spid,SigNo,SigData]) + end; +send(Port,Spid,SigNo,SigData) -> + erlang:error(badarg,[Port,Spid,SigNo,SigData]). + + +%%------------------------------------------------------------------------------ +%% @doc Send an OSE message with different sender. +%% +%% As {@link send/4} but the sender will be `SenderPid'. +%% +%% raises: `badarg' +%% +%% @see send/4 +%% @end +%%------------------------------------------------------------------------------ +-spec send(Port,Pid,SenderPid,SigNo,SigData) -> ok when + Port :: mailbox(), + Pid :: mailbox_id(), + SenderPid :: mailbox_id(), + SigNo :: message_number(), + SigData :: iodata(). +send(Port, Spid, SenderPid, SigNo, SigData) + when ?INT_32BIT(Spid), ?INT_32BIT(SenderPid), ?INT_32BIT(SigNo) -> + try erlang:port_command(Port, [<>, SigData]) of + true -> ok + catch error:_Error -> + erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]) + end; +send(Port,Spid,SenderPid,SigNo,SigData) -> + erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]). + +%%------------------------------------------------------------------------------ +%% @doc Start listening for specified OSE signal numbers. +%% +%% The mailbox will send `{message,Port,{FromMboxId,ToMboxId,MsgNo,MsgData}}' +%% to the process that created the mailbox when an OSE message with any +%% of the specified `SigNos' arrives. +%% +%% Repeated calls to listen will replace the current set of signal numbers to +%% listen to. i.e +%% +%% ```1>ose:listen(MsgB,[1234,12345]). +%% ok +%% 2> ose:listen(MsgB,[1234,123456]). +%% ok.''' +%% +%% The above will first listen for signals with numbers 1234 and 12345, and then +%% replace that with only listening to 1234 and 123456. +%% +%% With the current implementation it is not possible to listen to all signal +%% numbers. +%% +%% raises: `badarg' | `enomem' +%% +%% @end +%%------------------------------------------------------------------------------ +-spec listen(Port, SigNos) -> ok when + Port :: mailbox(), + SigNos :: list(message_number()). +listen(Port, SigNos) when is_list(SigNos) -> + USSigNos = lists:usort(SigNos), + BinSigNos = try + << <> || + SigNo <- USSigNos, + ?INT_32BIT(SigNo) orelse erlang:error(badarg) + >> + catch _:_ -> + erlang:error(badarg,[Port,SigNos]) + end, + try port_command(Port, [?LISTEN, BinSigNos]) of + true -> + receive + {ose_drv_reply,Port,{error,Error}} -> + erlang:error(Error,[Port,SigNos]); + {ose_drv_reply,Port,Else} -> + Else + end + catch error:_Error -> + erlang:error(badarg,[Port,SigNos]) + end; +listen(Port, SigNos) -> + erlang:error(badarg,[Port,SigNos]). + + +%%%============================================================================= +%%% Internal functions +%%%============================================================================= diff --git a/lib/ose/test/Makefile b/lib/ose/test/Makefile new file mode 100644 index 0000000000..7e2080ba38 --- /dev/null +++ b/lib/ose/test/Makefile @@ -0,0 +1,67 @@ +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES= \ + ose_SUITE + +ERL_FILES= $(MODULES:%=%.erl) + +TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + +INSTALL_PROGS= $(TARGET_FILES) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/ose_test + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- + +ERL_MAKE_FLAGS += +ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \ + -I$(ERL_TOP)/lib/kernel/include + +EBIN = . + +EMAKEFILE=Emakefile +COVERFILE=ose.cover + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +make_emakefile: + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \ + > $(EMAKEFILE) + +tests debug opt: make_emakefile + erl $(ERL_MAKE_FLAGS) -make + +clean: + rm -f $(EMAKEFILE) + rm -f $(TARGET_FILES) + rm -f core + +docs: + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + +release_tests_spec: make_emakefile + $(INSTALL_DIR) "$(RELSYSDIR)" + $(INSTALL_DATA) ose.spec $(EMAKEFILE) \ + $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)" + chmod -R u+w "$(RELSYSDIR)" + @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) + +release_docs_spec: diff --git a/lib/ose/test/ose.cover b/lib/ose/test/ose.cover new file mode 100644 index 0000000000..7b846cfaf6 --- /dev/null +++ b/lib/ose/test/ose.cover @@ -0,0 +1,2 @@ +%% -*- erlang -*- +{incl_app,ose,details}. diff --git a/lib/ose/test/ose.spec b/lib/ose/test/ose.spec new file mode 100644 index 0000000000..c897e8cd16 --- /dev/null +++ b/lib/ose/test/ose.spec @@ -0,0 +1 @@ +{suites,"../ose_test",all}. diff --git a/lib/ose/test/ose_SUITE.erl b/lib/ose/test/ose_SUITE.erl new file mode 100644 index 0000000000..7e81b19894 --- /dev/null +++ b/lib/ose/test/ose_SUITE.erl @@ -0,0 +1,765 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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% +%% +-module(ose_SUITE). + +%-compile(export_all). + +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, + init_per_group/2,end_per_group/2,init_per_testcase/2, + end_per_testcase/2]). +-export([ + basic/1,stress/1,multi_msg_numbers/1,multi_mailboxes/1, + hunt/1,multi_hunt/1,dehunt/1,multi_dehunt/1, + attach/1,multi_attach/1,detach/1,multi_detach/1, + open_errors/1,close_errors/1,get_id_errors/1,get_name_errors/1, + hunt_errors/1,dehunt_errors/1,attach_errors/1,detach_errors/1, + send_errors/1,send_w_s_errors/1,listen_errors/1 + ]). + +-define(INTERFACE,ose). + + +init_per_testcase(_Func, Config) -> + Config. +end_per_testcase(_Func, _Config) -> + ok. + +suite() -> [{timeout,{30,seconds}}]. + +all() -> + [ + basic,stress,multi_msg_numbers,multi_mailboxes, + hunt,multi_hunt,dehunt,multi_dehunt, + attach,multi_attach,detach,multi_detach, + + open_errors,close_errors,get_id_errors,get_name_errors, + hunt_errors,dehunt_errors,attach_errors,detach_errors, + send_errors,send_w_s_errors,listen_errors + ]. + +groups() -> + []. + +init_per_suite(Config) -> + case os:type() of + {ose,_} -> + Config; + _Else -> + {skip,"Only run on OSE"} + end. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +basic(_Config) -> + + [P1,P2] = multi_open(2,[42]), + P1Id = ?INTERFACE:get_id(P1), + P2Id = ?INTERFACE:get_id(P2), + + ok = ?INTERFACE:send(P2,P1Id,42,<<"ping">>), + receive + {message,P1,V1} -> + {P2Id,P1Id,42,<<"ping">>} = V1, + ?INTERFACE:send(P1,P2Id,42,<<"pong">>); + Else1 -> + ct:fail({got_wrong_message,Else1}) + end, + + receive + {message,P2,V2} -> + {P1Id,P2Id,42,<<"pong">>} = V2; + Else2 -> + ct:fail({got_wrong_message,Else2}) + end, + + ?INTERFACE:close(P1), + ?INTERFACE:close(P2). + +%% Send 1000 messages and see if we can cope and that msg order is preserved +stress(_Config) -> + + Iterations = 1000, + + [P1,P2] = multi_open(2,[42]), + P1Id = ?INTERFACE:get_id(P1), + P2Id = ?INTERFACE:get_id(P2), + + spawn(fun() -> + n(fun(N) -> + Msg = [<<"ping">>|integer_to_list(N)], + ?INTERFACE:send(P2,P1Id,42,Msg) + end,Iterations) + end), + timer:sleep(100), + n(fun(N) -> + receive + {message,P1,Value} -> + Int = integer_to_binary(N), + {P2Id,P1Id,42,<<"ping",Int/binary>>} = Value, + ok; + Else -> + ct:fail({got_wrong_message,Else}) + end + end,Iterations), + + ?INTERFACE:close(P1), + ?INTERFACE:close(P2). + +%% Listen to 1000 different message numbers and send some random messages +multi_msg_numbers(_Config) -> + + Iterations = 100, + + [P1,P2] = multi_open(2,lists:seq(2000,3000)), + P1Id = ?INTERFACE:get_id(P1), + + n(fun(_) -> + Num = random:uniform(1000)+2000, + ?INTERFACE:send(P2,P1Id,Num,<<"ping",(integer_to_binary(Num))/binary>>) + end,Iterations), + + n(fun(_) -> + receive + {message,P1,{_,_,Id,<<"ping",Num/binary>>}} when Id > 2000; + Id =< 3000 -> + Id = binary_to_integer(Num), + ok; + Else -> + ct:fail({got_wrong_message,Else}) + end + end,Iterations), + + ?INTERFACE:close(P1), + ?INTERFACE:close(P2). + + +%% Create 100 mailboxes and send messages to them +multi_mailboxes(_Config) -> + + Mailboxes = 100, + + [P1|MBs] = multi_open(Mailboxes,[42]), + + [?INTERFACE:send(P1,?INTERFACE:get_id(P),42,[<<"ping">>,?INTERFACE:get_name(P,?INTERFACE:get_id(P))]) || P <- MBs], + + [receive + {message,P,Value} -> + Name = ?INTERFACE:get_name(P,?INTERFACE:get_id(P)), + {_,_,42,<<"ping",Name/binary>>} = Value, + ok + end || P <- MBs], + + [?INTERFACE:close(P) || P <- [P1|MBs]], + ok. + +hunt(_Config) -> + [P1,P2] = multi_open(2,[]), + + Ref = ?INTERFACE:hunt(P1,"p2"), + receive + {mailbox_up,P1,Ref,Pid} -> + Pid = ?INTERFACE:get_id(P2), + ?INTERFACE:close(P1), + ?INTERFACE:close(P2); + Else -> + ct:fail({got_wrong_message,Else,Ref}) + end. + +multi_hunt(_Config) -> + + Iterations = 100, + + P = ?INTERFACE:open("p"), + + Refs = [?INTERFACE:hunt(P,"p"++integer_to_list(N))|| N <- lists:seq(1,Iterations)], + + Pids = [begin + Prt = ?INTERFACE:open("p"++integer_to_list(N)), + Pid = ?INTERFACE:get_id(Prt), + ?INTERFACE:close(Prt), + Pid + end || N <- lists:seq(1,Iterations)], + + [receive + {mailbox_up,P,Ref,Pid} -> + ok + after 10 -> + ct:fail({did_not_get,Pid,Ref}) + end || {Pid,Ref} <- lists:zip(Pids,Refs)], + ?INTERFACE:close(P). + + +dehunt(_Config) -> + [P1] = multi_open(1,[]), + Ref = ?INTERFACE:hunt(P1,"p2"), + receive + _Else -> ct:fail({got,_Else}) + after 1000 -> + ok + end, + P2 = ?INTERFACE:open("p2"), + + % Make sure any messages are sent + receive after 10 -> ok end, + + ok = ?INTERFACE:dehunt(P1,Ref), + + % Make sure no messages are received + receive + _Else2 -> ct:fail({got,_Else2}) + after 1000 -> + ?INTERFACE:close(P1), + ?INTERFACE:close(P2) + end. + +%%% +%%% This testcase basically: +%%% spawn 10 processes that in parallel +%%% adds some hunts for different OSE processes +%%% maybe create hunted OSE process +%%% dehunt half of the hunts +%%% create more hunts +%%% if not created create hunted OSE process +%%% veryify that all expected hunt messages are received +%%% verify that all processes exited correctly +%%% +%%% This complex test is done to make sure that the internal handling +%%% of dehunt works as expected. +%%% +multi_dehunt(_Config) -> + [P1] = multi_open(1,[]), + + Scenario = + fun(Iterations) -> + + Hunted = "p"++integer_to_list(Iterations), + %% Start a couple of hunts + Refs = [?INTERFACE:hunt(P1,Hunted) || _ <- lists:seq(1,Iterations)], + + %% We alternate if the process is opened before or after the dehunt + P2O = if Iterations rem 2 == 0 -> + ?INTERFACE:open(Hunted); + true -> + undefined + end, + + %% Remove half of them + {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 -> + ok = ?INTERFACE:dehunt(P1,Ref), + {[],Acc+1}; + (Ref,Acc) -> + {Ref,Acc+1} + end,0,Refs), + + %% Add some new ones + NewRefs = [?INTERFACE:hunt(P1,Hunted) + || _ <- lists:seq(1,Iterations div 4)] + ++ lists:flatten(RemRefs), + + P2 = if P2O == undefined -> + ?INTERFACE:open(Hunted); + true -> + P2O + end, + P2Id = ?INTERFACE:get_id(P2), + + %% Receive all the expected ones + lists:foreach(fun(Ref) -> + receive + {mailbox_up,P1,Ref,P2Id} -> + ok + after 1000 -> + io:format("Flush: ~p~n",[flush()]), + io:format("~p~n",[{Iterations,{did_not_get, Ref}}]), + ok = Ref + end + end,NewRefs), + + %% Check that no other have arrived + receive + _Else -> + io:format("Flush: ~p~n",[flush()]), + io:format("~p~n",[{Iterations,{got, _Else}}]), + ok = _Else + after 100 -> + ok + end, + ?INTERFACE:close(P2) + end, + + Self = self(), + + n(fun(N) -> + spawn(fun() -> Self ! + Scenario(N*25) + end), + ok + end,10), + + n(fun(_N) -> + receive ok -> ok + after 60000 -> ct:fail(failed) + end + end,10), + ?INTERFACE:close(P1). + +attach(_Config) -> + [P1,P2] = multi_open(2,[]), + + P2Id = ?INTERFACE:get_id(P2), + Ref = ?INTERFACE:attach(P1,P2Id), + ?INTERFACE:close(P2), + receive + {mailbox_down,P1,Ref,P2Id} -> + ?INTERFACE:close(P1); + _Else -> + ct:fail({got,_Else, {P1,Ref,P2Id}}) + after 1000 -> + ct:fail({did_not_get,P1,Ref,P2Id}) + end. + +multi_attach(_Config) -> + + Iterations = 100, + + [P1|Pids] = multi_open(Iterations,[]), + + Refs = [{?INTERFACE:get_id(Pid),?INTERFACE:attach(P1,?INTERFACE:get_id(Pid))} || Pid <- Pids], + + [?INTERFACE:close(Pid) || Pid <- Pids], + + [receive + {mailbox_down,P1,Ref,Pid} -> + ok + after 10000 -> + ct:fail({did_not_get,Pid,Ref}) + end || {Pid,Ref} <- Refs], + ?INTERFACE:close(P1). + +detach(_Config) -> + [P1,P2] = multi_open(2,[]), + P2Id = ?INTERFACE:get_id(P2), + Ref = ?INTERFACE:attach(P1,P2Id), + receive + _Else -> ct:fail({got,_Else}) + after 100 -> + ok + end, + + ?INTERFACE:close(P2), + + % Make sure any messages are sent + receive after 10 -> ok end, + + ?INTERFACE:detach(P1,Ref), + + % Make sure no messages are received + receive + _Else2 -> ct:fail({got,_Else2}) + after 1000 -> + ?INTERFACE:close(P1) + end. + +%%% +%%% This testcase basically: +%%% spawn 10 processes that in parallel +%%% adds some attach for different OSE processes +%%% maybe close OSE process +%%% dehunt half of the hunts +%%% create more hunts +%%% if not closed close attached OSE process +%%% veryify that all expected attach messages are received +%%% verify that all processes exited correctly +%%% +%%% This complex test is done to make sure that the internal handling +%%% of dehunt works as expected. +%%% +multi_detach(_Config) -> + [P1] = multi_open(1,[]), + + Scenario = + fun(Iterations) -> + + Attached = ?INTERFACE:open("p"++integer_to_list(Iterations)), + AttachedId = ?INTERFACE:get_id(Attached), + %% Start a couple of attachs + Refs = [?INTERFACE:attach(P1,AttachedId) || _ <- lists:seq(1,Iterations)], + + %% We alternate if the process is closed before or after the detach + P2O = if Iterations rem 2 == 0 -> + ?INTERFACE:close(Attached); + true -> + undefined + end, + + %% Remove half of them + {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 -> + ok = ?INTERFACE:detach(P1,Ref), + {[],Acc+1}; + (Ref,Acc) -> + {Ref,Acc+1} + end,0,Refs), + + %% Add some new ones + NewRefs = [?INTERFACE:attach(P1,AttachedId) + || _ <- lists:seq(1,Iterations div 4)] + ++ lists:flatten(RemRefs), + + if P2O == undefined -> + ?INTERFACE:close(Attached); + true -> + P2O + end, + + %% Receive all the expected ones + lists:foreach(fun(Ref) -> + receive + {mailbox_down,P1,Ref,AttachedId} -> + ok + after 1000 -> + io:format("Flush: ~p~n",[flush()]), + io:format("~p~n",[{Iterations,{did_not_get, Ref}}]), + ok = Ref + end + end,NewRefs), + + %% Check that no other have arrived + receive + _Else -> + io:format("Flush: ~p~n",[flush()]), + io:format("~p~n",[{Iterations,{got, _Else}}]), + ok = _Else + after 100 -> + ok + end + end, + + Self = self(), + + n(fun(N) -> + spawn(fun() -> Self ! + Scenario(N*5) + end), + ok + end,10), + + n(fun(_N) -> + receive ok -> ok + after 60000 -> ct:fail(failed) + end + end,10), + ?INTERFACE:close(P1). + + +open_errors(_Config) -> + {'EXIT',{badarg,[{?INTERFACE,open,[inval],_}|_]}} = + (catch ?INTERFACE:open(inval)), + {'EXIT',{badarg,[{?INTERFACE,open,[["p"|1]],_}|_]}} = + (catch ?INTERFACE:open(["p"|1])), + {'EXIT',{badarg,[{?INTERFACE,open,[["p",1234]],_}|_]}} = + (catch ?INTERFACE:open(["p",1234])), + + ok. + +close_errors(_Config) -> + {'EXIT',{badarg,[{?INTERFACE,close,[inval],_}|_]}} = + (catch ?INTERFACE:close(inval)), + + P1 = ?INTERFACE:open("p1"), + ok = ?INTERFACE:close(P1), + ok = ?INTERFACE:close(P1). + + +get_id_errors(_Config) -> + {'EXIT',{badarg,[{?INTERFACE,get_id,[inval],_}|_]}} = + (catch ?INTERFACE:get_id(inval)), + + P1 = ?INTERFACE:open("p1"), + ok = ?INTERFACE:close(P1), + {'EXIT',{badarg,[{?INTERFACE,get_id,[P1],_}|_]}} = + (catch ?INTERFACE:get_id(P1)), + + ok. + +get_name_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,inval],_}|_]}} = + (catch ?INTERFACE:get_name(P1,inval)), + + undefined = ?INTERFACE:get_name(P1,1234), + + P2 = ?INTERFACE:open("p2"), + P2Id = ?INTERFACE:get_id(P2), + ok = ?INTERFACE:close(P1), + {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,P2Id],_}|_]}} = + (catch ?INTERFACE:get_name(P1,P2Id)), + ?INTERFACE:close(P2), + + P3 = ?INTERFACE:open([255]), + <<255>> = ?INTERFACE:get_name(P3, ?INTERFACE:get_id(P3)), + ?INTERFACE:close(P3), + + ok. + +hunt_errors(_Config) -> + + {'EXIT',{badarg,[{?INTERFACE,hunt,[inval,"hello"],_}|_]}} = + (catch ?INTERFACE:hunt(inval,"hello")), + + P1 = ?INTERFACE:open("p1"), + {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello",12345]],_}|_]}} = + (catch ?INTERFACE:hunt(P1,["hello",12345])), + + P2 = ?INTERFACE:open(<<255>>), + P2Pid = ?INTERFACE:get_id(P2), + Ref = ?INTERFACE:hunt(P1,[255]), + receive + {mailbox_up,P1,Ref,P2Pid} -> + ok; + Else -> + ct:fail({got,Else,{mailbox_up,P1,Ref,P2Pid}}) + after 150 -> + ct:fail({did_not_get,{mailbox_up,P1,Ref,P2Pid}}) + end, + + ok = ?INTERFACE:close(P1), + ok = ?INTERFACE:close(P2), + {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello"]],_}|_]}} = + (catch ?INTERFACE:hunt(P1,["hello"])), + + ok. + +dehunt_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + Ref = ?INTERFACE:hunt(P1,"p2"), + + {'EXIT',{badarg,[{?INTERFACE,dehunt,[inval,Ref],_}|_]}} = + (catch ?INTERFACE:dehunt(inval,Ref)), + + {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,inval],_}|_]}} = + (catch ?INTERFACE:dehunt(P1,inval)), + + ok = ?INTERFACE:dehunt(P1,Ref), + ok = ?INTERFACE:dehunt(P1,Ref), + + ok = ?INTERFACE:close(P1), + + {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,Ref],_}|_]}} = + (catch ?INTERFACE:dehunt(P1,Ref)), + + case ?INTERFACE of + ose -> ok; + _ -> + P2 = ?INTERFACE:open("p2"), + ok = ?INTERFACE:close(P2) + end, + + receive + Else -> ct:fail({got,Else}) + after 100 -> + ok + end. + +attach_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + P2 = ?INTERFACE:open("p2"), + P2Id = ?INTERFACE:get_id(P2), + + {'EXIT',{badarg,[{?INTERFACE,attach,[inval,P2Id],_}|_]}} = + (catch ?INTERFACE:attach(inval,P2Id)), + + {'EXIT',{badarg,[{?INTERFACE,attach,[P1,[12345]],_}|_]}} = + (catch ?INTERFACE:attach(P1,[12345])), + + ok = ?INTERFACE:close(P1), + ok = ?INTERFACE:close(P2), + {'EXIT',{badarg,[{?INTERFACE,attach,[P1,P2Id],_}|_]}} = + (catch ?INTERFACE:attach(P1,P2Id)), + + ok. + +detach_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + P2 = ?INTERFACE:open("p2"), + P2Id = ?INTERFACE:get_id(P2), + + Ref = ?INTERFACE:attach(P1,P2Id), + + {'EXIT',{badarg,[{?INTERFACE,detach,[inval,Ref],_}|_]}} = + (catch ?INTERFACE:detach(inval,Ref)), + + {'EXIT',{badarg,[{?INTERFACE,detach,[P1,inval],_}|_]}} = + (catch ?INTERFACE:detach(P1,inval)), + + ok = ?INTERFACE:detach(P1,Ref), + ok = ?INTERFACE:detach(P1,Ref), + + case ?INTERFACE of + ose -> ok; + _ -> + ok = ?INTERFACE:close(P1) + end, + + ok = ?INTERFACE:close(P2), + ok = ?INTERFACE:close(P1), + + {'EXIT',{badarg,[{?INTERFACE,detach,[P1,Ref],_}|_]}} = + (catch ?INTERFACE:detach(P1,Ref)), + + receive + Else -> ct:fail({got,Else}) + after 100 -> + ok + end. + +send_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + P2 = ?INTERFACE:open("p2"), + P2Id = ?INTERFACE:get_id(P2), + + {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(inval,P2Id,42,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P1,inval,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P1,inval,42,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,inval,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P1,P2Id,inval,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,inval],_}|_]}} = + (catch ?INTERFACE:send(P1,P2Id,42,inval)), + + ok = ?INTERFACE:close(P2), + ok = ?INTERFACE:send(P1,P2Id,42,"hello"), + ok = ?INTERFACE:close(P1), + + {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P1,P2Id,42,"hello")), + + receive + Else -> ct:fail({got,Else}) + after 100 -> + ok + end. + +send_w_s_errors(_Config) -> + P1 = ?INTERFACE:open("p1"), + P1Id = ?INTERFACE:get_id(P1), + P2 = ?INTERFACE:open("p2"), + P2Id = ?INTERFACE:get_id(P2), + P3 = ?INTERFACE:open("p3"), + P3Id = ?INTERFACE:get_id(P3), + + {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,P1Id,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(inval,P2Id,P1Id,42,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P2,-1,P1Id,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P2,-1,P1Id,42,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,1 bsl 32,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P2,P2Id,1 bsl 32,42,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,inval,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P2,P2Id,P1Id,inval,"hello")), + {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,42,inval],_}|_]}} = + (catch ?INTERFACE:send(P2,P2Id,P1Id,42,inval)), + + ok = ?INTERFACE:close(P3), + ok = ?INTERFACE:send(P2,P3Id,P1Id,42,"hello"), + + ok = ?INTERFACE:close(P1), + ok = ?INTERFACE:send(P2,P2Id,P1Id,42,"hello"), + ok = ?INTERFACE:close(P2), + + {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,P1Id,42,"hello"],_}|_]}} = + (catch ?INTERFACE:send(P1,P2Id,P1Id,42,"hello")), + + receive + Else -> ct:fail({got,Else}) + after 100 -> + ok + end. + +listen_errors(_Config) -> + + P1 = ?INTERFACE:open("p1"), + P1Id = ?INTERFACE:get_id(P1), + + {'EXIT',{badarg,[{?INTERFACE,listen,[inval,[42]],_}|_]}} = + (catch ?INTERFACE:listen(inval,[42])), + {'EXIT',{badarg,[{?INTERFACE,listen,[P1,inval],_}|_]}} = + (catch ?INTERFACE:listen(P1,inval)), + {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[1 bsl 33]],_}|_]}} = + (catch ?INTERFACE:listen(P1,[1 bsl 33])), + + ok = ?INTERFACE:listen(P1,[42,42,42,42,42,42,42,42,42,42,42,42,42]), + + case ?INTERFACE of + ose -> ok; + _ -> + ?INTERFACE:send(P1,P1Id,42,"hello"), + timer:sleep(50), + ?INTERFACE:listen(P1,[]), + ?INTERFACE:send(P1,P1Id,42,"hello2"), + + receive + {message,P1,42,"hello"} -> ok + end, + + receive + Else -> ct:fail({got,Else}) + after 100 -> + ok + end + end, + + ok = ?INTERFACE:close(P1), + {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[42]],_}|_]}} = + (catch ?INTERFACE:listen(P1,[42])), + + ok. + +%% +%% Internal functions +%% +multi_open(N,ListenNums) -> + multi_open(N,ListenNums,[]). + +multi_open(0,_,Acc) -> + Acc; +multi_open(N,ListenNums,Acc) -> + P = ?INTERFACE:open("p"++integer_to_list(N)), + ok = ?INTERFACE:listen(P,ListenNums), + multi_open(N-1,ListenNums,[P|Acc]). + +n(_F,0) -> + ok; +n(F,N) -> + ok = F(N), + n(F,N-1). + + +flush() -> + receive + Msg -> + [Msg|flush()] + after 0 -> + [] + end. diff --git a/lib/ose/vsn.mk b/lib/ose/vsn.mk new file mode 100644 index 0000000000..78ffa4d496 --- /dev/null +++ b/lib/ose/vsn.mk @@ -0,0 +1 @@ +OSE_VSN = 1.0 -- cgit v1.2.3 From 31c4876582acf42f77f65f0d822d4d224d642364 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 27 Jan 2014 17:13:53 +0100 Subject: ose: Add -block option to run_erl ose docs --- lib/ose/doc/src/ose_intro.xml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ose/doc/src/ose_intro.xml b/lib/ose/doc/src/ose_intro.xml index 3bab325289..8fe723ba83 100644 --- a/lib/ose/doc/src/ose_intro.xml +++ b/lib/ose/doc/src/ose_intro.xml @@ -40,7 +40,19 @@ run_erl_lm. Installing and starting the load module will add two new shell commands called run_erl and to_erl. They work in exactly the same way as the unix variants of run_erl and to_erl, except that the read - and write pipes have to be placed under the /pipe vm. See also + and write pipes have to be placed under the /pipe vm. One additional + option also exists to run_erl on ose: + + -block Name + The name of the install handle and block that will be created/used by + installing and exectuting the first part of the command. If nothing + if given the basename of the load module will be used for this value. + Example: + pm_install erlang /path/to/erlang/vm +run_erl -daemon -block erlang /pipe/ /mst/erlang_logs/ "erl -A 10" + + + See also run_erl for more details.

-- cgit v1.2.3 From d58602adef3412b354fd521bbd4bda24a0b1a789 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 13 Feb 2014 18:14:10 +0100 Subject: crypto: Add rand_seed function This function is needed on OSs that do not automatically initialize the PRNG seed. --- lib/crypto/c_src/crypto.c | 15 ++++++++++++++- lib/crypto/doc/src/crypto.xml | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 925ad0c091..bf8107d10b 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -254,6 +254,8 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); + /* helpers */ static void init_algorithms_types(ErlNifEnv*); @@ -381,7 +383,9 @@ static ErlNifFunc nif_funcs[] = { {"ec_key_generate", 1, ec_key_generate}, {"ecdsa_sign_nif", 4, ecdsa_sign_nif}, {"ecdsa_verify_nif", 5, ecdsa_verify_nif}, - {"ecdh_compute_key_nif", 3, ecdh_compute_key_nif} + {"ecdh_compute_key_nif", 3, ecdh_compute_key_nif}, + + {"rand_seed_nif", 1, rand_seed_nif} }; ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload) @@ -3374,6 +3378,15 @@ out_err: #endif } +static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifBinary seed_bin; + if (!enif_inspect_binary(env, argv[0], &seed_bin)) + return enif_make_badarg(env); + RAND_seed(seed_bin.data,seed_bin.size); + return atom_ok; +} + /* HMAC */ diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 40f829e704..952808d9db 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -552,6 +552,21 @@ + + rand_seed(Seed) -> ok + Set the seed for random bytes generation + + Seed = binary() + + +

Set the seed for PRNG to the given binary. This calls the + RAND_seed function from openssl. Only use this if the system + you are running on does not have enough "randomness" built in. + Normally this is when + stong_rand_bytes/1 returns low_entropy

+
+
+ rand_uniform(Lo, Hi) -> N Generate a random number -- cgit v1.2.3 From 6c4ee8337dff6e9b680dbff0796038948d718b5a Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 13 Feb 2014 17:16:42 +0100 Subject: ose: Fix support for crypto To enable it you have to modify the OSESSL variable in the ose xcomp file. --- lib/crypto/Makefile | 4 + lib/crypto/c_src/crypto.c | 205 +++++++++++++++++++++++++++++++++++---- lib/crypto/src/crypto.erl | 7 ++ lib/crypto/test/crypto_SUITE.erl | 16 ++- 4 files changed, 211 insertions(+), 21 deletions(-) (limited to 'lib') diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 2adcfd7f31..e893c914e6 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -23,7 +23,11 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk # Macros # +ifneq ($(findstring ose,$(TARGET)),ose) SUB_DIRECTORIES = src c_src doc/src +else +SUB_DIRECTORIES = src doc/src +endif static_lib: SUB_DIRECTORIES = c_src include vsn.mk diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index bf8107d10b..bd027cf1ba 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -455,6 +455,46 @@ static ERL_NIF_TERM atom_onbasis; #define PRINTF_ERR0(FMT) #define PRINTF_ERR1(FMT,A1) +#ifdef __OSE__ + +/* For crypto on OSE we have to initialize the crypto library on each + process that uses it. So since we do not know which scheduler is going + to execute the nif we have to check before each nif call that we have + initialized crypto in that process. */ + +#include "ose.h" +#include "openssl/osessl.h" + +static ErlNifTSDKey crypto_init_key; +static int check_ose_crypto(void); +static int init_ose_crypto(void); + +static int check_ose_crypto() { + int key = (int)enif_tsd_get(crypto_init_key); + if (!key) { + if (!CRYPTO_OSE5_init()) { + PRINTF_ERR0("CRYPTO: Call to CRYPTO_OSE5_init failed"); + return 0; + } + enif_tsd_set(crypto_init_key,1); + } + return 1; +} + +static int init_ose_crypto() { + /* Crypto nif upgrade does not work on OSE so no need to + destroy this key */ + enif_tsd_key_create("crypto_init_key", &crypto_init_key); + return check_ose_crypto(); +} + +#define INIT_OSE_CRYPTO() init_ose_crypto() +#define CHECK_OSE_CRYPTO() check_ose_crypto() +#else +#define INIT_OSE_CRYPTO() 1 +#define CHECK_OSE_CRYPTO() +#endif + #ifdef HAVE_DYNAMIC_CRYPTO_LIB static int change_basename(ErlNifBinary* bin, char* buf, int bufsz, const char* newfile) { @@ -491,6 +531,9 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) ErlNifBinary lib_bin; char lib_buf[1000]; + if (!INIT_OSE_CRYPTO()) + return 0; + /* load_info: {301, <<"/full/path/of/this/library">>} */ if (!enif_get_tuple(env, load_info, &tpl_arity, &tpl_array) || tpl_arity != 2 @@ -714,7 +757,7 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -726,6 +769,7 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); MD5_Init((MD5_CTX *) enif_make_new_binary(env, MD5_CTX_LEN, &ret)); return ret; } @@ -734,6 +778,7 @@ static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv MD5_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { @@ -750,6 +795,7 @@ static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary ctx_bin; MD5_CTX ctx_clone; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN) { return enif_make_badarg(env); } @@ -762,7 +808,7 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -774,6 +820,7 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); RIPEMD160_Init((RIPEMD160_CTX *) enif_make_new_binary(env, RIPEMD160_CTX_LEN, &ret)); return ret; } @@ -782,6 +829,7 @@ static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TER RIPEMD160_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { @@ -798,6 +846,7 @@ static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary ctx_bin; RIPEMD160_CTX ctx_clone; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) { return enif_make_badarg(env); } @@ -811,7 +860,7 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -823,6 +872,7 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); SHA1_Init((SHA_CTX *) enif_make_new_binary(env, SHA_CTX_LEN, &ret)); return ret; } @@ -831,6 +881,7 @@ static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv SHA_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -846,6 +897,7 @@ static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary ctx_bin; SHA_CTX ctx_clone; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN) { return enif_make_badarg(env); } @@ -859,7 +911,7 @@ static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA224 ErlNifBinary ibin; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -875,6 +927,7 @@ static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM {/* () */ #ifdef HAVE_SHA224 ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); SHA224_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret)); return ret; #else @@ -887,6 +940,7 @@ static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA256_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -906,6 +960,7 @@ static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA256_CTX ctx_clone; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) { return enif_make_badarg(env); } @@ -922,7 +977,7 @@ static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA256 ErlNifBinary ibin; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -938,6 +993,7 @@ static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM {/* () */ #ifdef HAVE_SHA256 ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); SHA256_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret)); return ret; #else @@ -950,6 +1006,7 @@ static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA256_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -969,6 +1026,7 @@ static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA256_CTX ctx_clone; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) { return enif_make_badarg(env); } @@ -985,7 +1043,7 @@ static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA384 ErlNifBinary ibin; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1001,6 +1059,7 @@ static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM {/* () */ #ifdef HAVE_SHA384 ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); SHA384_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret)); return ret; #else @@ -1013,6 +1072,7 @@ static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA512_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1032,6 +1092,7 @@ static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA512_CTX ctx_clone; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) { return enif_make_badarg(env); } @@ -1048,7 +1109,7 @@ static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA512 ErlNifBinary ibin; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1076,6 +1137,7 @@ static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA512_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1095,6 +1157,7 @@ static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA512_CTX ctx_clone; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) { return enif_make_badarg(env); } @@ -1111,7 +1174,7 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1123,6 +1186,7 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); MD4_Init((MD4_CTX *) enif_make_new_binary(env, MD4_CTX_LEN, &ret)); return ret; } @@ -1131,6 +1195,7 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv MD4_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1146,6 +1211,7 @@ static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary ctx_bin; MD4_CTX ctx_clone; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN) { return enif_make_badarg(env); } @@ -1160,7 +1226,7 @@ static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > MD5_LEN) { @@ -1178,7 +1244,7 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA_LEN) { @@ -1198,7 +1264,7 @@ static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA224_DIGEST_LENGTH) { @@ -1221,7 +1287,7 @@ static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA256_DIGEST_LENGTH) { @@ -1244,7 +1310,7 @@ static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA384_DIGEST_LENGTH) { @@ -1268,7 +1334,7 @@ static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA512_DIGEST_LENGTH) { @@ -1291,6 +1357,8 @@ static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ unsigned char * ctx_buf; const EVP_MD *md; + CHECK_OSE_CRYPTO(); + if (argv[0] == atom_sha) md = EVP_sha1(); #ifdef HAVE_SHA224 else if (argv[0] == atom_sha224) md = EVP_sha224(); @@ -1326,6 +1394,8 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg ERL_NIF_TERM ret; unsigned char * ctx_buf; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_binary(env, argv[0], &context) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || context.size != sizeof(HMAC_CTX)) { @@ -1349,7 +1419,9 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv unsigned char * mac_bin; unsigned int req_len = 0; unsigned int mac_len; - + + CHECK_OSE_CRYPTO(); + if (!enif_inspect_binary(env, argv[0], &context)) { return enif_make_badarg(env); } @@ -1382,6 +1454,8 @@ static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8 || !enif_inspect_iolist_as_binary(env, argv[2], &text) @@ -1403,6 +1477,8 @@ static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8 || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { @@ -1421,6 +1497,7 @@ static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ErlNifBinary key, text; DES_key_schedule schedule; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 || !enif_inspect_iolist_as_binary(env, argv[1], &text) || text.size != 8) { return enif_make_badarg(env); @@ -1440,6 +1517,8 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8 || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8 || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8 @@ -1468,6 +1547,8 @@ static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_N DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8 || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8 || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8 @@ -1498,6 +1579,8 @@ static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE int new_ivlen = 0; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 16 || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16 || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { @@ -1525,6 +1608,8 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned int num = 0; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16 @@ -1556,6 +1641,8 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N unsigned char * ivec2_buf; unsigned char * ecount2_buf; + CHECK_OSE_CRYPTO(); + if (!enif_get_tuple(env, argv[0], &state_arity, &state_term) || state_arity != 4 || !enif_inspect_iolist_as_binary(env, state_term[0], &key_bin) @@ -1589,6 +1676,7 @@ static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned bytes; unsigned char* data; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bytes)) { return enif_make_badarg(env); } @@ -1602,6 +1690,7 @@ static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NI unsigned bytes; unsigned char* data; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bytes)) { return enif_make_badarg(env); } @@ -1619,6 +1708,7 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned char* data; unsigned top_mask, bot_mask; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bytes) || !enif_get_uint(env, argv[1], &top_mask) || !enif_get_uint(env, argv[2], &bot_mask)) { @@ -1641,6 +1731,9 @@ static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NI unsigned char* data; unsigned dlen; ERL_NIF_TERM ret; + + CHECK_OSE_CRYPTO(); + if (!enif_get_uint(env, argv[0], &bits) || !enif_get_int(env, argv[1], &top) || !enif_get_int(env, argv[2], &bottom)) { @@ -1708,6 +1801,9 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER unsigned char* data; unsigned dlen; ERL_NIF_TERM ret; + + CHECK_OSE_CRYPTO(); + if (!get_bn_from_mpint(env, argv[0], &bn_from) || !get_bn_from_mpint(env, argv[1], &bn_rand)) { if (bn_from) BN_free(bn_from); @@ -1739,6 +1835,8 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg unsigned extra_byte; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!get_bn_from_bin(env, argv[0], &bn_base) || !get_bn_from_bin(env, argv[1], &bn_exponent) || !get_bn_from_bin(env, argv[2], &bn_modulo) @@ -1781,6 +1879,8 @@ static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM DSA *dsa; int i; + CHECK_OSE_CRYPTO(); + if (argv[0] == atom_sha) { if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { if (tpl_arity != 2 || tpl_terms[0] != atom_digest @@ -1948,6 +2048,8 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM struct digest_type_t* digp = NULL; unsigned char* digest = NULL; + CHECK_OSE_CRYPTO(); + digp = get_digest_type(type); if (!digp) { return enif_make_badarg(env); @@ -2007,6 +2109,8 @@ static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a unsigned char* ret_ptr; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 16 && key_bin.size != 32) || !enif_inspect_binary(env, argv[1], &ivec_bin) @@ -2043,6 +2147,8 @@ static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE unsigned char* ret_ptr; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 16 && key_bin.size != 32) || !enif_inspect_binary(env, argv[1], &ivec_bin) @@ -2079,6 +2185,8 @@ static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) int i; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env,argv[0], &d1) || !enif_inspect_iolist_as_binary(env,argv[1], &d2) || d1.size != d2.size) { @@ -2099,6 +2207,8 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg RC4_KEY rc4_key; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env,argv[0], &key) || !enif_inspect_iolist_as_binary(env,argv[1], &data)) { return enif_make_badarg(env); @@ -2115,6 +2225,8 @@ static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg ErlNifBinary key; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env,argv[0], &key)) { return enif_make_badarg(env); } @@ -2130,6 +2242,8 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N RC4_KEY* rc4_key; ERL_NIF_TERM new_state, new_data; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env,argv[0], &state) || state.size != sizeof(RC4_KEY) || !enif_inspect_iolist_as_binary(env,argv[1], &data)) { @@ -2149,6 +2263,8 @@ static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a RC2_KEY rc2_key; ERL_NIF_TERM ret; unsigned char iv_copy[8]; + + CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16) @@ -2210,6 +2326,8 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar struct digest_type_t *digp; unsigned char* digest; + CHECK_OSE_CRYPTO(); + digp = get_digest_type(argv[0]); if (!digp) { return enif_make_badarg(env); @@ -2276,6 +2394,8 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar DSA* dsa; int i; + CHECK_OSE_CRYPTO(); + if (argv[0] == atom_sha) { if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { if (tpl_arity != 2 || tpl_terms[0] != atom_digest @@ -2358,7 +2478,11 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary data_bin, ret_bin; ERL_NIF_TERM head, tail; int padding, i; - RSA* rsa = RSA_new(); + RSA* rsa; + + CHECK_OSE_CRYPTO(); + + rsa = RSA_new(); if (!enif_inspect_binary(env, argv[0], &data_bin) || !enif_get_list_cell(env, argv[1], &head, &tail) @@ -2404,7 +2528,11 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE {/* (Data, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C], Padding, IsEncrypt) */ ErlNifBinary data_bin, ret_bin; int padding, i; - RSA* rsa = RSA_new(); + RSA* rsa; + + CHECK_OSE_CRYPTO(); + + rsa = RSA_new(); if (!enif_inspect_binary(env, argv[0], &data_bin) || !get_rsa_private_key(env, argv[1], rsa) @@ -2450,6 +2578,8 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E unsigned char *p_ptr, *g_ptr; ERL_NIF_TERM ret_p, ret_g; + CHECK_OSE_CRYPTO(); + if (!enif_get_int(env, argv[0], &prime_len) || !enif_get_int(env, argv[1], &generator)) { @@ -2473,10 +2603,14 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* ([PrimeLen, Generator]) */ - DH* dh_params = DH_new(); + DH* dh_params; int i; ERL_NIF_TERM ret, head, tail; + CHECK_OSE_CRYPTO(); + + dh_params = DH_new(); + if (!enif_get_list_cell(env, argv[0], &head, &tail) || !get_bn_from_bin(env, head, &dh_params->p) || !enif_get_list_cell(env, tail, &head, &tail) @@ -2503,12 +2637,16 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (PrivKey, DHParams=[P,G], Mpint) */ - DH* dh_params = DH_new(); + DH* dh_params; int pub_len, prv_len; unsigned char *pub_ptr, *prv_ptr; ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail; int mpint; /* 0 or 4 */ + CHECK_OSE_CRYPTO(); + + dh_params = DH_new(); + if (!(get_bn_from_bin(env, argv[0], &dh_params->priv_key) || argv[0] == atom_undefined) || !enif_get_list_cell(env, argv[1], &head, &tail) @@ -2545,12 +2683,16 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */ - DH* dh_params = DH_new(); + DH* dh_params; BIGNUM* pubkey = NULL; int i; ErlNifBinary ret_bin; ERL_NIF_TERM ret, head, tail; + CHECK_OSE_CRYPTO(); + + dh_params = DH_new(); + if (!get_bn_from_bin(env, argv[0], &pubkey) || !get_bn_from_bin(env, argv[1], &dh_params->priv_key) || !enif_get_list_cell(env, argv[2], &head, &tail) @@ -2588,6 +2730,8 @@ static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned dlen; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!get_bn_from_bin(env, argv[0], &bn_multiplier) || !get_bn_from_bin(env, argv[1], &bn_verifier) || !get_bn_from_bin(env, argv[2], &bn_generator) @@ -2648,6 +2792,8 @@ static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_ unsigned dlen; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!get_bn_from_bin(env, argv[0], &bn_a) || !get_bn_from_bin(env, argv[1], &bn_u) || !get_bn_from_bin(env, argv[2], &bn_B) @@ -2727,6 +2873,8 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_ unsigned dlen; ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!get_bn_from_bin(env, argv[0], &bn_verifier) || !get_bn_from_bin(env, argv[1], &bn_b) || !get_bn_from_bin(env, argv[2], &bn_u) @@ -2787,6 +2935,8 @@ static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM int bf_n = 0; /* blowfish ivec pos */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_binary(env, argv[1], &ivec_bin) || ivec_bin.size != 8 @@ -2810,6 +2960,8 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned char bf_tkey[8]; /* blowfish ivec */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_binary(env, argv[1], &ivec_bin) || ivec_bin.size != 8 @@ -2833,6 +2985,8 @@ static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar BF_KEY bf_key; /* blowfish key 8 */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin) || data_bin.size < 8) { @@ -2853,6 +3007,8 @@ static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_N int bf_n = 0; /* blowfish ivec pos */ ERL_NIF_TERM ret; + CHECK_OSE_CRYPTO(); + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_binary(env, argv[1], &ivec_bin) || ivec_bin.size != 8 @@ -3171,6 +3327,8 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM #if defined(HAVE_EC) EC_KEY *key = ec_key_new(env, argv[0]); + CHECK_OSE_CRYPTO(); + if (key && EC_KEY_generate_key(key)) { const EC_GROUP *group; const EC_POINT *public_key; @@ -3208,6 +3366,8 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM struct digest_type_t *digp; unsigned char* digest; + CHECK_OSE_CRYPTO(); + digp = get_digest_type(argv[0]); if (!digp) { return enif_make_badarg(env); @@ -3275,6 +3435,8 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER struct digest_type_t* digp = NULL; unsigned char* digest = NULL; + CHECK_OSE_CRYPTO(); + digp = get_digest_type(type); if (!digp) { return enif_make_badarg(env); @@ -3338,6 +3500,8 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF EC_POINT *my_ecpoint; EC_KEY *other_ecdh = NULL; + CHECK_OSE_CRYPTO(); + if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key)) return enif_make_badarg(env); @@ -3381,6 +3545,7 @@ out_err: static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary seed_bin; + CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &seed_bin)) return enif_make_badarg(env); RAND_seed(seed_bin.data,seed_bin.size); diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index d953bd3bca..5bf52fc8a4 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -35,6 +35,7 @@ -export([private_encrypt/4, public_decrypt/4]). -export([dh_generate_parameters/2, dh_check/1]). %% Testing see -export([ec_curve/1, ec_curves/0]). +-export([rand_seed/1]). %% DEPRECATED %% Replaced by hash_* @@ -437,6 +438,11 @@ rand_uniform_pos(_,_) -> rand_uniform_nif(_From,_To) -> ?nif_stub. +-spec rand_seed(binary()) -> ok. +rand_seed(Seed) -> + rand_seed_nif(Seed). + +rand_seed_nif(_Seed) -> ?nif_stub. -spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error. mod_pow(Base, Exponent, Prime) -> @@ -1774,6 +1780,7 @@ mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub. rand_bytes, strong_rand_bytes, rand_uniform, + rand_seed, mod_pow, exor, %% deprecated diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index d1be7cea68..d05277390a 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -104,7 +104,21 @@ groups() -> init_per_suite(Config) -> try crypto:start() of ok -> - Config + try crypto:strong_rand_bytes(1) of + _ -> + Config + catch error:low_entropy -> + %% Make sure we are on OSE, otherwise we want to crash + {ose,_} = os:type(), + + %% This is NOT how you want to seed this, it is just here + %% to make the tests pass. Check your OS manual for how you + %% really want to seed. + {H,M,L} = erlang:now(), + Bin = <>, + crypto:rand_seed(<< <> || _ <- lists:seq(1,16) >>), + Config + end catch _:_ -> {skip, "Crypto did not start"} end. -- cgit v1.2.3 From ff77d5049cca221e82d1b28e862512069c399eb7 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 14 Feb 2014 15:29:43 +0100 Subject: ose: Fix broken doc links --- lib/ose/doc/src/ose_erl_driver.xml | 2 +- lib/ose/doc/src/ose_signals_chapter.xml | 2 +- lib/ose/src/ose.erl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ose/doc/src/ose_erl_driver.xml b/lib/ose/doc/src/ose_erl_driver.xml index 6687d78087..93cbd91be7 100644 --- a/lib/ose/doc/src/ose_erl_driver.xml +++ b/lib/ose/doc/src/ose_erl_driver.xml @@ -74,7 +74,7 @@

Create a new ErlDrvEvent associated with signo, id and uses the resolve_signal function to extract the id from a signal with signo. See - + Signals in a Linked-in driver in the OSE User's Guide.

diff --git a/lib/ose/doc/src/ose_signals_chapter.xml b/lib/ose/doc/src/ose_signals_chapter.xml index 2a6ddb5765..85849e1a39 100644 --- a/lib/ose/doc/src/ose_signals_chapter.xml +++ b/lib/ose/doc/src/ose_signals_chapter.xml @@ -79,7 +79,7 @@ used. The third argument is a function pointer to a function that can be used to figure out the id from a given signal. There is a complete example of what this could look like in - the next section. + the next section. It is very important to issue the driver_select call before any of the signals you are interested in are sent. If driver_select is called after the signal is sent, there is a high probability that it diff --git a/lib/ose/src/ose.erl b/lib/ose/src/ose.erl index ff7147233f..77f11addf9 100644 --- a/lib/ose/src/ose.erl +++ b/lib/ose/src/ose.erl @@ -108,7 +108,7 @@ %% %% raises: `badarg' | `system_limit' %% -%% @see liten/2 +%% @see listen/2 %% @end %%------------------------------------------------------------------------------ -spec open(Name) -> Port when -- 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 --- lib/ose/doc/src/ose_erl_driver.xml | 9 +++++---- lib/ose/doc/src/ose_signals_chapter.xml | 23 +++++++++++++++++++++-- 2 files changed, 26 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ose/doc/src/ose_erl_driver.xml b/lib/ose/doc/src/ose_erl_driver.xml index 93cbd91be7..1d89d7aeea 100644 --- a/lib/ose/doc/src/ose_erl_driver.xml +++ b/lib/ose/doc/src/ose_erl_driver.xml @@ -68,12 +68,13 @@
- ErlDrvEventerl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id, ErlDrvOseEventId (*resolve_signal)(union SIGNAL* sig)) + ErlDrvEventerl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id, ErlDrvOseEventId (*resolve_signal)(union SIGNAL* sig), void *extra)

Create a new ErlDrvEvent associated with signo, id and uses the resolve_signal function to extract - the id from a signal with signo. See + the id from a signal with signo. The extra + parameter can be used for additional data. See Signals in a Linked-in driver in the OSE User's Guide.

@@ -89,10 +90,10 @@
- voiderl_drv_ose_event_fetch(ErlDrvEvent drv_event, SIGSELECT *signo, int *id) + voiderl_drv_ose_event_fetch(ErlDrvEvent drv_event, SIGSELECT *signo, ErlDrvOseEventId *id, void **extra) -

Write the signal number and id associated with drv_event +

Write the signal number, id and any extra data associated with drv_event into *signo and *id respectively. NULL can be also passed as signo or id in order to ignore that field.

diff --git a/lib/ose/doc/src/ose_signals_chapter.xml b/lib/ose/doc/src/ose_signals_chapter.xml index 85849e1a39..c8d98f4099 100644 --- a/lib/ose/doc/src/ose_signals_chapter.xml +++ b/lib/ose/doc/src/ose_signals_chapter.xml @@ -77,7 +77,12 @@ in this case the port id that we got in the start callback is used. The third argument is a function pointer to a function that can - be used to figure out the id from a given signal. There is a complete + be used to figure out the id from a given signal. The fourth argument can + point to any additional data you might want to associate with the event. + There is a complete. You can examine the data contained in the event with + erl_drv_ose_event_fetch + , eg: + erl_drv_ose_event_fetch(event, &signal, &port, (void **)&extra); example of what this could look like in the next section. It is very important to issue the driver_select call before @@ -132,8 +137,12 @@ static ErlDrvSSizeT control(ErlDrvData driver_data, unsigned int cmd, char **rbuf, ErlDrvSizeT rlen) { ErlDrvPort port = (ErlDrvPort)driver_data; + /* An example of extra data to associate with the event */ + char *extra_data = driver_alloc(80); + snprintf("extra_data, "Event, sig_no: 1234, and port: %d", port); + /* Create a new event to select on */ - ErlDrvOseEvent evt = erl_drv_ose_event_alloc(1234,port,resolver); + ErlDrvOseEvent evt = erl_drv_ose_event_alloc(1234,port,resolver, extra_data); /* Make sure to do the select call _BEFORE_ the signal arrives. The signal might get lost if the hunt call is done before the @@ -147,11 +156,16 @@ static ErlDrvSSizeT control(ErlDrvData driver_data, unsigned int cmd, } static void ready_input(ErlDrvData driver_data, ErlDrvEvent evt) { + char *extra_data; /* Get the first signal payload from the event */ union SIGNAL *sig = erl_drv_ose_get_signal(evt); ErlDrvPort port = (ErlDrvPort)driver_data; while (sig != NULL) { if (sig->signo == 1234) { + /* Print out the string we added as the extra parameter */ + erl_drv_ose_event_fetch(evt, NULL, NULL, (void **)&extra_data); + printf("We've received: %s\n", extra_data); + /* If it is our signal we send a message with the sender of the signal to the controlling erlang process */ ErlDrvTermData reply[] = { ERL_DRV_UINT, (ErlDrvUInt)sender(&sig) }; @@ -172,6 +186,11 @@ static void ready_input(ErlDrvData driver_data, ErlDrvEvent evt) { static void stop_select(ErlDrvEvent event, void *reserved) { + /* Free the extra_data */ + erl_drv_ose_event_fetch(evt, NULL, NULL, (void **)&extra_data); + driver_free(extra_data); + + /* Free the event itself */ erl_drv_ose_event_free(event); } -- cgit v1.2.3 From 13ed57745c639f72be8ae1f25fbd206f6e7307f3 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 21 Feb 2014 15:19:53 +0100 Subject: ose: Expand OSE docs --- lib/ose/doc/src/ose_intro.xml | 97 ++++++++++++++++++++++++++++++++- lib/ose/doc/src/ose_signals_chapter.xml | 23 ++++++++ 2 files changed, 118 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ose/doc/src/ose_intro.xml b/lib/ose/doc/src/ose_intro.xml index 8fe723ba83..0dd3ec409e 100644 --- a/lib/ose/doc/src/ose_intro.xml +++ b/lib/ose/doc/src/ose_intro.xml @@ -33,6 +33,62 @@ Features +
+ Starting Erlang/OTP +

+ Starting Erlang/OTP on OSE is not as simple as on Unix/Windows (yet). + First of all you have to explicitly use the beam (or beam.smp) executables + found in erts-X.Y.Z/bin as the load module that you run. This in turn + means that you have to supply the raw beam arguments to the emulator + when starting. Fortunately erl on Unix/Windows has a + undocumented flag called -emu_args_exit that can be used to + figure out what the arguments to beam look like. For example:

+ # erl +Mut false +A 10 +S 4:4 +Muycs256 +P 2096 +Q 2096 -emu_args_exit +-Mut +false +-A +10 +-S +4:4 +-Muycs256 +-P +2096 +-Q +2096 +-- +-root +/usr/local/lib/erlang +-progname +erl +-- +-home +/home/erlang +-- +

+ The arguments are printed on seperate lines to make it possible to know + what has to be quoted with ". Each line is one quotable unit. + So taking the arguments above you can supply them to pm_create or + just execute directly on the command line. For example:

+ rtose@acp3400> pm_install erlang /mst/erlang/erts-6.0/bin/beam.smp +rtose@acp3400> pm_create -c ARGV="-Mut false -A 10 -S 4:4 -Muycs256 -P 2096 -Q 2099 -- -root /mst/erlang -progname erl -- -home /mst/erlang --" erlang +pid: 0x110059 +rtose@acp3400> pm_start 0x110059 +

+ Also note that since we are running erl to figure out the arguments on a + seperate machine the paths have to be updated. In the example above + /usr/local/lib/erlang was replaced by /mst/erlang/. The + goal is to in future releases not have to do the special argument handling + but for now (17.0-rc2) you have to do it. +

+ + Because of a limitation in the way the OSE handles stdio when starting + load modules using pm_install/create the Erlang shell only reads every + other command from stdin. However if you start Erlang using run_erl + you do not have this problem. So it is highly recommended that you + start Erlang using run_erl. + +
+
run_erl and to_erl

@@ -48,13 +104,50 @@ installing and exectuting the first part of the command. If nothing if given the basename of the load module will be used for this value. Example: - pm_install erlang /path/to/erlang/vm -run_erl -daemon -block erlang /pipe/ /mst/erlang_logs/ "erl -A 10" + pm_install erlang /path/to/erlang/vm/beam.smp +run_erl -daemon -block erlang /pipe/ /mst/erlang_logs/ "beam.smp -A 1 -- -root /mst/erlang -- -home /mst --" + The same argument munching as when starting Erlang/OTP without run_erl + has to be done. If -daemon is given then all error printouts + are sent to the ramlog. See also run_erl for more details.

+

+ Below is an example of how to get started with run_erl_lm. + rtose@acp3400> pm_install run_erl_lm /mst/erlang/erts-6.0/bin/run_erl_lm +rtose@acp3400> pm_create run_erl_lm +pid: 0x1c005d +rtose@acp3400> pm_start 0x1c005d +rtose@acp3400> mkdir /mst/erlang_log +rtose@acp3400> run_erl -daemon /pipe/ /mst/erlang_log/ "/mst/erlang/erts-6.0/bin/beam.smp -A 1 -- -root /mst/erlang -- -home /mst --" +rtose@acp3400> to_erl +Attaching to /pipe/erlang.pipe.1 (^C to exit) +os:type(). +{ose,release} +2> +'to_erl' terminated. + Note that Ctrl-C is used instead of Ctrl-D to exit the to_erl shell. +

+
+ +
+ epmd +

+ In OSE epmd will not be started automatically so if you want to use + Erlang distribution you have to manually start epmd. +

+
+ +
+ VM Process Priorities +

+ It is possible to set the priorities you want for the OSE processes that + thr emulator creates in the lmconf. An example of how to do it can be + found in the default lmconf file in + $ERL_TOP/erts/emulator/sys/ose/default.lmconf. +

diff --git a/lib/ose/doc/src/ose_signals_chapter.xml b/lib/ose/doc/src/ose_signals_chapter.xml index c8d98f4099..ff501777cc 100644 --- a/lib/ose/doc/src/ose_signals_chapter.xml +++ b/lib/ose/doc/src/ose_signals_chapter.xml @@ -45,6 +45,29 @@
Signals in Erlang +

Erlang/OTP on OSE provides a erlang module called + ose that can be used to interact + with other OSE processes using message passing. The api in the module + is very similar to the native OSE api, so for details of how the + functions work please refer to the official OSE documenation. Below + is an example usage of the API. +

+ 1> P1 = ose:open("p1"). +#Port>0.344> +2> ose:hunt(P1,"p2"). +{#Port>0.344>,1} +3> P2 = ose:open("p2"). +#Port>0.355> +4> flush(). +Shell got {mailbox_up,#Port>0.344>,{#Port>0.344>,1},852189} +ok +5> ose:listen(P1,[1234]). +ok +6> ose:send(P2,ose:get_id(P1),1234,>>"hello">>). +ok +7> flush(). +Shell got {message,#Port>0.344>,{852189,1245316,1234,>>"hello">>}} +ok
-- cgit v1.2.3