diff options
Diffstat (limited to 'erts')
37 files changed, 1046 insertions, 583 deletions
diff --git a/erts/Makefile.in b/erts/Makefile.in index 6e259c1772..1979c50781 100644 --- a/erts/Makefile.in +++ b/erts/Makefile.in @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2006-2011. All Rights Reserved. +# Copyright Ericsson AB 2006-2012. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -25,7 +25,7 @@ include vsn.mk # ---------------------------------------------------------------------- # Other erts dirs than the emulator dir... -ERTSDIRS = doc/src etc epmd lib_src +ERTSDIRS = etc epmd lib_src XINSTDIRS = preloaded ifeq ($(NO_START_SCRIPTS),) ERTSDIRS += start_scripts @@ -40,42 +40,36 @@ ifeq ($(BUILD_HYBRID_EMU),yes) EXTRA_FLAVORS += hybrid endif -# -# Some byggy 'make's get confused when a directory is created and used -# for storing files which other files depend on during the same "make -# session". As a workaround we do a 'make generate' (which creates -# all directories) before doing 'make opt', etc... -# - +.PHONY: all ifneq ($(BUILD_HYBRID_EMU),yes) all: smp opt else all: hybrid smp opt endif -debug opt docs clean: - @ case $@ in \ - docs|clean) ;; \ - *) ( cd emulator && $(MAKE) generate TYPE=$@ FLAVOR=$(FLAVOR)) ;; \ - esac - @ ( cd emulator && $(MAKE) $@ FLAVOR=$(FLAVOR)) - @for d in $(ERTSDIRS); do \ +.PHONY: docs +docs: + ( cd doc/src && $(MAKE) $@ ) + +.PHONY: debug opt clean +debug opt clean: + for d in emulator $(ERTSDIRS); do \ if test -d $$d; then \ - ( cd $$d && $(MAKE) $@ ) || exit $$? ; \ + ( cd $$d && $(MAKE) $@ FLAVOR=$(FLAVOR) ) || exit $$? ; \ fi ; \ - done + done # ---------------------------------------------------------------------- # These are "convenience targets", provided as shortcuts for developers # - don't use them in scripts or assume they will always stay like this! # +.PHONY: $(EXTRA_FLAVORS) $(EXTRA_FLAVORS): - @ ( cd emulator \ - && $(MAKE) generate TYPE=opt FLAVOR=$@ \ - && $(MAKE) opt FLAVOR=$@ ) + ( cd emulator && $(MAKE) opt FLAVOR=$@ ) ifneq ($(BUILD_HYBRID_EMU),yes) +.PHONY: hybrid hybrid: @echo '*** Omitted build of hybrid heap emulator' @echo '*** since target is $(TARGET)' @@ -88,6 +82,7 @@ endif # The copying of beam.dll should be removed when the beam dll need no longer be # in the same directory... +.PHONY: local_setup local_setup: @cd start_scripts && $(MAKE) @echo `ls $(ERL_TOP)/bin/` @@ -134,11 +129,13 @@ local_setup: $(ERL_TOP)/bin/start_clean.script # Run the configure script +.PHONY: configure configure: @set -e ; cd autoconf && $(MAKE) # Remake the makefiles, if you already have configured but you have edited # a "Makefile.in". +.PHONY: makefiles makefiles: @set -e ; cd autoconf && $(MAKE) $@ @@ -146,21 +143,17 @@ makefiles: # Release targets # -release release_docs: -ifeq ($(BUILD_HYBRID_EMU),yes) - @if test $@ = release; then ( cd emulator && $(MAKE) $@ FLAVOR=hybrid) fi -else - @if test $@ = release; then ( $(MAKE) hybrid ) fi -endif - @if test $@ = release; then ( cd emulator && $(MAKE) $@ FLAVOR=smp) fi - @ (cd emulator && $(MAKE) $@ FLAVOR=plain) - @for d in $(ERTSDIRS) $(XINSTDIRS); do \ +.PHONY: release +release: + for f in plain $(EXTRA_FLAVORS) ; do \ + ( cd emulator && $(MAKE) release FLAVOR=$$f ) \ + done + for d in $(ERTSDIRS) $(XINSTDIRS); do \ if test -d $$d; then \ ( cd $$d && $(MAKE) $@ ) || exit $$? ; \ fi ; \ done -# ---------------------------------------------------------------------- - -.PHONY: debug opt docs clean local_setup configure release \ - release_docs run_test_cases hybrid smp +.PHONY: release_docs +release_docs: + ( cd doc/src && $(MAKE) $@ ) diff --git a/erts/configure.in b/erts/configure.in index 50f8908f7a..b801994e14 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. -*-m4-*- dnl %CopyrightBegin% dnl -dnl Copyright Ericsson AB 1997-2011. All Rights Reserved. +dnl Copyright Ericsson AB 1997-2012. All Rights Reserved. dnl dnl The contents of this file are subject to the Erlang Public License, dnl Version 1.1, (the "License"); you may not use this file except in @@ -4373,7 +4373,6 @@ dnl Note that the output files are relative to $srcdir AC_OUTPUT( emulator/$host/Makefile:emulator/Makefile.in - emulator/zlib/$host/Makefile:emulator/zlib/Makefile.in epmd/src/$host/Makefile:epmd/src/Makefile.in etc/common/$host/Makefile:etc/common/Makefile.in include/internal/$host/ethread.mk:include/internal/ethread.mk.in diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 8c01d77721..fbe7b36163 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2011</year> + <year>1996</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -215,9 +215,9 @@ representation of <c>Atom</c>. If <c>Encoding</c> is <c>latin1</c>, there will be one byte for each character in the text representation. If <c>Encoding</c> is <c>utf8</c> or - <c>unicode</c>, the characters will encoded using UTF-8 + <c>unicode</c>, the characters will be encoded using UTF-8 (meaning that characters from 16#80 up to 0xFF will be - encode in two bytes).</p> + encoded in two bytes).</p> <note><p>Currently, <c>atom_to_binary(Atom, latin1)</c> can never fail because the text representation of an atom can only contain @@ -268,7 +268,7 @@ <p>If <c>PosLen</c> in any way references outside the binary, a <c>badarg</c> exception is raised.</p> - <p><c>Start</c> is zero-based, i.e:</p> + <p><c>Start</c> is zero-based, i.e.:</p> <code> 1> Bin = <<1,2,3>> 2> binary_part(Bin,{0,2}). @@ -773,9 +773,9 @@ false</pre> turned off, nothing happens.</p> <p>Once <c>demonitor(MonitorRef)</c> has returned it is guaranteed that no <c>{'DOWN', MonitorRef, _, _, _}</c> message - due to the monitor will be placed in the callers message queue + due to the monitor will be placed in the caller's message queue in the future. A <c>{'DOWN', MonitorRef, _, _, _}</c> message - might have been placed in the callers message queue prior to + might have been placed in the caller's message queue prior to the call, though. Therefore, in most cases, it is advisable to remove such a <c>'DOWN'</c> message from the message queue after monitoring has been stopped. @@ -818,7 +818,7 @@ false</pre> <tag><c>flush</c></tag> <item> <p>Remove (one) <c>{_, MonitorRef, _, _, _}</c> message, - if there is one, from the callers message queue after + if there is one, from the caller's message queue after monitoring has been stopped.</p> <p>Calling <c>demonitor(MonitorRef, [flush])</c> is equivalent to the following, but more efficient:</p> @@ -847,7 +847,7 @@ false</pre> <item><p>The monitor was not found and could not be removed. This probably because someone already has placed a <c>'DOWN'</c> message corresponding to this monitor - in the callers message queue. + in the caller's message queue. </p> </item> </taglist> @@ -4933,6 +4933,21 @@ true</pre> threads in the Erlang run-time system and may therefore be greater than the wall-clock time.</p> </item> + <tag><marker id="statistics_scheduler_wall_time"><c>scheduler_wall_time</c></marker></tag> + <item> + <p>Returns + <c>[{Scheduler_Id, Scheduler_Worked_Time, Scheduler_Total_Time}]</c>, time lapses are since the + the system flag <seealso marker="#system_flag_scheduler_wall_time">scheduler_wall_time</seealso> + was set to true. + Returns <c>undefined</c> if the system flag <seealso marker="#system_flag_scheduler_wall_time"> + scheduler_wall_time</seealso> is set to false. + </p> + <p>The list of scheduler information is unsorted and may come in different order + between calls. The time unit is undefined and may be changed and should only be used + to calculate relative utilization. + </p> + </item> + <tag><c>wall_clock</c></tag> <item> <p>Returns @@ -5305,6 +5320,14 @@ true</pre> flags. </p> </item> + <tag><marker id="system_flag_scheduler_wall_time"><c>erlang:system_flag(scheduler_wall_time, Boolean)</c></marker></tag> + <item> + <p>Turns on/off scheduler wall time measurements. </p> + <p>For more information see, + <seealso marker="#statistics_scheduler_wall_time">erlang:statistics(scheduler_wall_time)</seealso>. + </p> + </item> + <tag><marker id="system_flag_schedulers_online"><c>erlang:system_flag(schedulers_online, SchedulersOnline)</c></marker></tag> <item> <p>Sets the amount of schedulers online. Valid range is @@ -5316,6 +5339,7 @@ true</pre> <seealso marker="#system_info_schedulers_online">erlang:system_info(schedulers_online)</seealso>. </p> </item> + <tag><c>erlang:system_flag(trace_control_word, TCW)</c></tag> <item> <p>Sets the value of the node's trace control word to @@ -7090,7 +7114,7 @@ true</pre> <c>Id</c> has no effect on the caller in the future (unless the link is setup again). If caller is trapping exits, an <c>{'EXIT', Id, _}</c> message due to the link might have - been placed in the callers message queue prior to the call, + been placed in the caller's message queue prior to the call, though. Note, the <c>{'EXIT', Id, _}</c> message can be the result of the link, but can also be the result of <c>Id</c> calling <c>exit/2</c>. Therefore, it <em>may</em> be diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml index f0390c9db8..cd2b3abc1e 100644 --- a/erts/doc/src/match_spec.xml +++ b/erts/doc/src/match_spec.xml @@ -75,7 +75,7 @@ <item>MatchCondition ::= { GuardFunction } | { GuardFunction, ConditionExpression, ... } </item> - <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_constant]]></c> | + <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | <c><![CDATA[is_list]]></c> | <c><![CDATA[is_number]]></c> | <c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> | <c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> | <c><![CDATA[is_binary]]></c> | @@ -133,7 +133,7 @@ <item>MatchCondition ::= { GuardFunction } | { GuardFunction, ConditionExpression, ... } </item> - <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_constant]]></c> | + <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | <c><![CDATA[is_list]]></c> | <c><![CDATA[is_number]]></c> | <c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> | <c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> | <c><![CDATA[is_binary]]></c> | @@ -172,7 +172,7 @@ <title>Functions allowed in all types of match specifications</title> <p>The different functions allowed in <c><![CDATA[match_spec]]></c> work like this: </p> - <p><em>is_atom, is_constant, is_float, is_integer, is_list, is_number, is_pid, is_port, is_reference, is_tuple, is_binary, is_function: </em> Like the corresponding guard tests in + <p><em>is_atom, is_float, is_integer, is_list, is_number, is_pid, is_port, is_reference, is_tuple, is_binary, is_function: </em> Like the corresponding guard tests in Erlang, return <c><![CDATA[true]]></c> or <c><![CDATA[false]]></c>. </p> <p><em>is_record: </em>Takes an additional parameter, which SHALL diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index a5d8217545..2bd7297231 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1996-2011. All Rights Reserved. +# Copyright Ericsson AB 1996-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 @@ -28,21 +28,26 @@ Z_LIB=@Z_LIB@ NO_INLINE_FUNCTIONS=false OPCODE_TABLES = $(ERL_TOP)/lib/compiler/src/genop.tab beam/ops.tab +DEBUG_CFLAGS = @DEBUG_CFLAGS@ +CONFIGURE_CFLAGS = @CFLAGS@ + # # Run this make file with TYPE set to the type of emulator you want. # Different versions of the emulator for different uses. The default # is "debug". For a normal version use "opt". # +DEFS=@DEFS@ THR_DEFS=@EMU_THR_DEFS@ M4FLAGS= CREATE_DIRS= LDFLAGS=@LDFLAGS@ +ARFLAGS=rc ifeq ($(TYPE),debug) PURIFY = TYPEMARKER = .debug -TYPE_FLAGS = @DEBUG_CFLAGS@ -DDEBUG +TYPE_FLAGS = $(DEBUG_CFLAGS) -DDEBUG ENABLE_ALLOC_TYPE_VARS += debug ifeq ($(TARGET),win32) TYPE_FLAGS += -DNO_JUMP_TABLE @@ -53,7 +58,7 @@ else ifeq ($(TYPE),purify) PURIFY = purify $(PURIFY_BUILD_OPTIONS) TYPEMARKER = .purify -TYPE_FLAGS = @DEBUG_CFLAGS@ -DPURIFY -DNO_JUMP_TABLE -DERTS_MSEG_FAKE_SEGMENTS +TYPE_FLAGS = $(DEBUG_CFLAGS) -DPURIFY -DNO_JUMP_TABLE -DERTS_MSEG_FAKE_SEGMENTS ENABLE_ALLOC_TYPE_VARS += purify else @@ -67,14 +72,14 @@ else ifeq ($(TYPE),purecov) PURIFY = purecov --follow-child-processes=yes $(PURECOV_BUILD_OPTIONS) TYPEMARKER = .purecov -TYPE_FLAGS = @DEBUG_CFLAGS@ -DPURECOV -DNO_JUMP_TABLE +TYPE_FLAGS = $(DEBUG_CFLAGS) -DPURECOV -DNO_JUMP_TABLE ENABLE_ALLOC_TYPE_VARS += purecov else ifeq ($(TYPE),gcov) PURIFY = TYPEMARKER = .gcov -TYPE_FLAGS = @DEBUG_CFLAGS@ -DERTS_GCOV -DNO_JUMP_TABLE -fprofile-arcs -ftest-coverage -O0 -DERTS_CAN_INLINE=0 -DERTS_INLINE= +TYPE_FLAGS = $(DEBUG_CFLAGS) -DERTS_GCOV -DNO_JUMP_TABLE -fprofile-arcs -ftest-coverage -O0 -DERTS_CAN_INLINE=0 -DERTS_INLINE= ifneq ($(findstring solaris,$(TARGET)),solaris) LIBS += -lgcov endif @@ -84,7 +89,7 @@ else ifeq ($(TYPE),valgrind) PURIFY = TYPEMARKER = .valgrind -TYPE_FLAGS = @DEBUG_CFLAGS@ -DVALGRIND -DNO_JUMP_TABLE -DERTS_MSEG_FAKE_SEGMENTS +TYPE_FLAGS = $(DEBUG_CFLAGS) -DVALGRIND -DNO_JUMP_TABLE -DERTS_MSEG_FAKE_SEGMENTS ENABLE_ALLOC_TYPE_VARS += valgrind else @@ -147,6 +152,15 @@ endif TF_MARKER=$(TYPEMARKER)$(FLAVOR_MARKER) +ifeq ($(FLAVOR)-@ERTS_BUILD_SMP_EMU@,smp-no) +VOID_EMULATOR = '*** SMP emulator disabled by configure' +else +ifeq ($(TYPE)-@HAVE_VALGRIND@,valgrind-no) +VOID_EMULATOR = '*** valgrind emulator disabled by configure' +else +VOID_EMULATOR = +endif +endif OPSYS=@OPSYS@ sol2CFLAGS= @@ -187,7 +201,7 @@ else EMU_CC = @EMU_CC@ endif WFLAGS = @WFLAGS@ -CFLAGS = @STATIC_CFLAGS@ $(TYPE_FLAGS) $(FLAVOR_FLAGS) @DEFS@ $(WFLAGS) $(THR_DEFS) $(ARCHCFLAGS) +CFLAGS = @STATIC_CFLAGS@ $(TYPE_FLAGS) $(FLAVOR_FLAGS) $(DEFS) $(WFLAGS) $(THR_DEFS) $(ARCHCFLAGS) HCC = @HCC@ LD = @LD@ DEXPORT = @DEXPORT@ @@ -263,30 +277,29 @@ CS_PURIFY = CS_TYPE_FLAGS = $(subst QUANTIFY,FAKE_QUANTIFY, \ $(subst PURIFY,FAKE_PURIFY, $(TYPE_FLAGS))) endif -CS_CFLAGS_ = $(CS_TYPE_FLAGS) @DEFS@ $(WFLAGS) +CS_CFLAGS_ = $(CS_TYPE_FLAGS) $(DEFS) $(WFLAGS) ifeq ($(GCC),yes) CS_CFLAGS = $(subst -O2, $(GEN_OPT_FLGS) $(UNROLL_FLG), $(CS_CFLAGS_)) else CS_CFLAGS = $(CS_CFLAGS_) endif CS_LDFLAGS = $(LDFLAGS) -CS_LIBS = -L../lib/internal/$(TARGET) -lerts_internal @ERTS_INTERNAL_X_LIBS@ +CS_LIBS = -L../lib/internal/$(TARGET) -lerts_internal$(TYPEMARKER) @ERTS_INTERNAL_X_LIBS@ LIBS += @TERMCAP_LIB@ -L../lib/internal/$(TARGET) @ERTS_INTERNAL_X_LIBS@ ifdef Z_LIB # Use shared zlib library LIBS += $(Z_LIB) +DEPLIBS = else +DEPLIBS=$(ZLIB_LIBRARY) ifeq ($(TARGET),win32) -LIBS += -L$(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE) -lz -DEPLIBS = $(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE)/z.lib +LIBS += -L$(ZLIB_OBJDIR) -lz else # Build on darwin fails if -lz is used -LIBS += $(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE)/libz.a -DEPLIBS = $(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE)/libz.a +LIBS += $(ZLIB_LIBRARY) endif - endif ifeq ($(TARGET),win32) @@ -313,12 +326,9 @@ LIBSCTP = @LIBSCTP@ ORG_THR_LIBS=@EMU_THR_LIBS@ THR_LIB_NAME=@EMU_THR_LIB_NAME@ -ifneq ($(strip $(THR_LIB_NAME)),) -DEPLIBS += $(ERL_TOP)/erts/lib/internal/$(TARGET)/$(LIB_PREFIX)erts_internal_r$(TYPEMARKER)$(LIB_SUFFIX) \ - $(ERL_TOP)/erts/lib/internal/$(TARGET)/$(LIB_PREFIX)ethread$(TYPEMARKER)$(LIB_SUFFIX) -else -DEPLIBS += $(ERL_TOP)/erts/lib/internal/$(TARGET)/$(LIB_PREFIX)erts_internal$(TYPEMARKER)$(LIB_SUFFIX) -endif +ERTS_LIB_DIR = $(ERL_TOP)/erts/lib_src +ERTS_LIB = $(ERTS_LIB_DIR)/obj/$(TARGET)/$(TYPE)/MADE +DEPLIBS += $(ERTS_LIB) THR_LIBS=$(subst -l$(THR_LIB_NAME),-l$(THR_LIB_NAME)$(TYPEMARKER), \ $(subst -lerts_internal_r,-lerts_internal_r$(TYPEMARKER),$(ORG_THR_LIBS))) @@ -354,8 +364,7 @@ OBJDIR = obj/$(TTF_DIR) CREATE_DIRS += $(OBJDIR) \ pcre/obj/$(TARGET)/$(TYPE) \ - zlib/obj/$(TARGET)/$(TYPE) - + $(ZLIB_OBJDIR) BINDIR = $(ERL_TOP)/bin/$(TARGET) @@ -378,15 +387,12 @@ else UNIX_ONLY_BUILDS = endif -ifeq ($(TYPE)-@HAVE_VALGRIND@,valgrind-no) -all: - @echo '*** valgrind not found by configure' -else -ifeq ($(FLAVOR)-@ERTS_BUILD_SMP_EMU@,smp-no) +.PHONY: all +ifdef VOID_EMULATOR all: - @echo '*** Omitted build of emulator with smp support' + @echo $(VOID_EMULATOR)' - omitted target all' else -all: generate erts_lib zlib $(BINDIR)/$(EMULATOR_EXECUTABLE) $(UNIX_ONLY_BUILDS) +all: $(BINDIR)/$(EMULATOR_EXECUTABLE) $(UNIX_ONLY_BUILDS) ifeq ($(OMIT_OMIT_FP),yes) @echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *' @echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *' @@ -397,37 +403,25 @@ ifeq ($(OMIT_OMIT_FP),yes) @echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *' endif endif -endif - -ifdef Z_LIB -zlib: - @echo 'Skip zlib directory, use shared library' -else -zlib: - @set -e ; cd zlib && $(MAKE) TYPE=$(TYPE) $(TYPE) -endif - +include zlib/zlib.mk include pcre/pcre.mk -erts_lib: - cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE) +$(ERTS_LIB): + cd $(ERTS_LIB_DIR) && $(MAKE) $(TYPE) +.PHONY: clean clean: -ifeq ($(TARGET),win32) - $(RM) -f $(TARGET)/beams.rc -endif - $(RM) -f $(TARGET)/*.c $(TARGET)/*.h $(TARGET)/depend.mk - $(RM) -f $(TARGET)/*/*/*.c $(TARGET)/*/*/*.h $(TARGET)/*/*/*.S - $(RM) -f $(ERL_TOP)/erts/emulator/obj/$(TARGET)/*/*/*.o - $(RM) -f $(BINDIR)/beam $(BINDIR)/beam.* - $(RM) -rf $(BINDIR)/child_setup $(BINDIR)/child_setup.* - $(RM) -f $(BINDIR)/hipe_mkliterals $(BINDIR)/hipe_mkliterals.* - @set -e ; cd zlib && $(MAKE) clean - rm -f $(OBJS) $(OBJDIR)/libepcre.a - -.PHONY: all zlib clean - + $(RM) -f $(GENERATE) + $(RM) -rf $(TARGET)/*.c $(TARGET)/*.h $(TARGET)/*-GENERATED + $(RM) -rf $(TARGET)/*/* + $(RM) -rf obj/$(TARGET) + $(RM) -rf pcre/obj/$(TARGET) $(PCRE_GENINC) + $(RM) -rf zlib/obj/$(TARGET) + $(RM) -rf bin/$(TARGET) + cd $(ERTS_LIB_DIR) && $(MAKE) clean + +.PHONY: docs docs: # ---------------------------------------------------------------------- @@ -440,13 +434,11 @@ ifeq ($(TARGET),win32) RELEASE_INCLUDES += sys/$(ERLANG_OSTYPE)/erl_win_dyn_driver.h endif -ifeq ($(TYPE)-@HAVE_VALGRIND@,valgrind-no) -release_spec: - @echo '*** valgrind not found by configure' -else -ifeq ($(FLAVOR)-@ERTS_BUILD_SMP_EMU@,smp-no) + +.PHONY: release_spec +ifdef VOID_EMULATOR release_spec: - @echo '*** No emulator with smp support to install' + @echo $(VOID_EMULATOR)' - omitted target release_spec (install)' else release_spec: all $(INSTALL_DIR) $(RELSYSDIR) @@ -463,8 +455,8 @@ ifeq ($(ERLANG_OSTYPE), unix) $(INSTALL_PROGRAM) $(BINDIR)/$(CS_EXECUTABLE) $(RELSYSDIR)/bin endif endif -endif +.PHONY: release_docs_spec release_docs_spec: # ---------------------------------------------------------------------- @@ -473,48 +465,41 @@ release_docs_spec: _create_dirs := $(shell mkdir -p $(CREATE_DIRS)) -.PHONY : generate - -GENERATE= $(TTF_DIR)/beam_opcodes.h \ - $(TARGET)/erl_bif_table.c \ - $(TARGET)/erl_version.h \ - $(TTF_DIR)/driver_tab.c \ - $(TTF_DIR)/erl_alloc_types.h - -ifeq ($(TARGET),win32) -GENERATE += $(TARGET)/beams.rc -else -GENERATE += $(TARGET)/preload.c -endif +GENERATE = +HIPE_ASM = ifeq ($(findstring vxworks,$(TARGET)),vxworks) else ifdef HIPE_ENABLED -GENERATE += $(TTF_DIR)/hipe_x86_asm.h \ +HIPE_ASM += $(TTF_DIR)/hipe_x86_asm.h \ $(TTF_DIR)/hipe_amd64_asm.h \ $(TTF_DIR)/hipe_sparc_asm.h \ $(TTF_DIR)/hipe_ppc_asm.h \ - $(TTF_DIR)/hipe_arm_asm.h \ + $(TTF_DIR)/hipe_arm_asm.h + +GENERATE += $(HIPE_ASM) \ $(TTF_DIR)/hipe_literals.h \ $(BINDIR)/hipe_mkliterals$(TF_MARKER) endif endif -ifeq ($(FLAVOR)-@ERTS_BUILD_SMP_EMU@,smp-no) -GENERATE= -endif - -generate: $(GENERATE) - ifdef HIPE_ENABLED OPCODE_TABLES += hipe/hipe_ops.tab endif -$(TTF_DIR)/beam_opcodes.h $(TTF_DIR)/beam_opcodes.c: $(OPCODE_TABLES) utils/beam_makeops +$(TTF_DIR)/beam_cold.h \ +$(TTF_DIR)/beam_hot.h \ +$(TTF_DIR)/beam_opcodes.c \ +$(TTF_DIR)/beam_opcodes.h \ +$(TTF_DIR)/beam_pred_funcs.h \ +$(TTF_DIR)/beam_tr_funcs.h \ + : $(TTF_DIR)/OPCODES-GENERATED +$(TTF_DIR)/OPCODES-GENERATED: $(OPCODE_TABLES) utils/beam_makeops LANG=C $(PERL) utils/beam_makeops \ -wordsize @EXTERNAL_WORD_SIZE@ \ -outdir $(TTF_DIR) \ - -emulator $(OPCODE_TABLES) + -emulator $(OPCODE_TABLES) && echo $? >$(TTF_DIR)/OPCODES-GENERATED +GENERATE += $(TTF_DIR)/OPCODES-GENERATED # bif and atom table ATOMS= beam/atom.names @@ -534,25 +519,32 @@ BIFS += hipe/hipe_perfctr.tab endif endif -TABLES= $(TARGET)/erl_bif_table.c $(TARGET)/erl_bif_table.h \ - $(TARGET)/erl_bif_wrap.c $(TARGET)/erl_bif_list.h \ - $(TARGET)/erl_atom_table.c $(TARGET)/erl_atom_table.h \ - $(TARGET)/erl_pbifs.c - -$(TABLES): $(ATOMS) $(BIFS) utils/make_tables +$(TARGET)/erl_bif_table.c \ +$(TARGET)/erl_bif_table.h \ +$(TARGET)/erl_bif_wrap.c \ +$(TARGET)/erl_bif_list.h \ +$(TARGET)/erl_atom_table.c \ +$(TARGET)/erl_atom_table.h \ +$(TARGET)/erl_pbifs.c \ + : $(TARGET)/TABLES-GENERATED +$(TARGET)/TABLES-GENERATED: $(ATOMS) $(BIFS) utils/make_tables LANG=C $(PERL) utils/make_tables -src $(TARGET) -include $(TARGET)\ - $(ATOMS) $(BIFS) + $(ATOMS) $(BIFS) && echo $? >$(TARGET)/TABLES-GENERATED +GENERATE += $(TARGET)/TABLES-GENERATED $(TTF_DIR)/erl_alloc_types.h: beam/erl_alloc.types utils/make_alloc_types LANG=C $(PERL) utils/make_alloc_types -src $< -dst $@ $(ENABLE_ALLOC_TYPE_VARS) +GENERATE += $(TTF_DIR)/erl_alloc_types.h # version include file $(TARGET)/erl_version.h: ../vsn.mk LANG=C $(PERL) utils/make_version -o $@ $(SYSTEM_VSN) $(VSN)$(SERIALNO) $(TARGET) +GENERATE += $(TARGET)/erl_version.h # driver table $(TTF_DIR)/driver_tab.c: Makefile.in LANG=C $(PERL) utils/make_driver_tab -o $@ $(DRV_OBJS) +GENERATE += $(TTF_DIR)/driver_tab.c # Preloaded code. # @@ -568,6 +560,7 @@ $(TARGET)/beams.rc: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \ $(ERL_TOP)/erts/preloaded/ebin/erl_prim_loader.beam \ $(ERL_TOP)/erts/preloaded/ebin/erlang.beam LANG=C $(PERL) utils/make_preload $(MAKE_PRELOAD_EXTRA) -rc $^ > $@ +GENERATE += $(TARGET)/beams.rc else $(TARGET)/preload.c: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \ $(ERL_TOP)/erts/preloaded/ebin/init.beam \ @@ -578,6 +571,17 @@ $(TARGET)/preload.c: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \ $(ERL_TOP)/erts/preloaded/ebin/erl_prim_loader.beam \ $(ERL_TOP)/erts/preloaded/ebin/erlang.beam LANG=C $(PERL) utils/make_preload -old $^ > $@ +GENERATE += $(TARGET)/preload.c +endif + +.PHONY : generate +ifdef VOID_EMULATOR +generate: + @echo $(VOID_EMULATOR)' - omitted target generate' +else +generate: $(TTF_DIR)/GENERATED +$(TTF_DIR)/GENERATED: $(GENERATE) + echo $? >$(TTF_DIR)/GENERATED endif # ---------------------------------------------------------------------- @@ -656,7 +660,7 @@ endif # CS_SRC = sys/$(ERLANG_OSTYPE)/erl_child_setup.c -$(BINDIR)/$(CS_EXECUTABLE): $(CS_SRC) +$(BINDIR)/$(CS_EXECUTABLE): $(TTF_DIR)/GENERATED $(CS_SRC) $(ERTS_LIB) $(CS_PURIFY) $(CC) $(CS_LDFLAGS) -o $(BINDIR)/$(CS_EXECUTABLE) \ $(CS_CFLAGS) $(COMMON_INCLUDES) $(CS_SRC) $(CS_LIBS) @@ -834,6 +838,9 @@ BASE_OBJS = $(RUN_OBJS) $(EMU_OBJS) $(OS_OBJS) $(EXTRA_BASE_OBJS) OBJS = $(BASE_OBJS) $(DRV_OBJS) +$(INIT_OBJS): $(TTF_DIR)/GENERATED +$(OBJS): $(TTF_DIR)/GENERATED + ######################################## # HiPE section @@ -857,30 +864,49 @@ $(OBJDIR)/%.o: hipe/%.c $(BINDIR)/hipe_mkliterals$(TF_MARKER): $(OBJDIR)/hipe_mkliterals.o $(CC) $(CFLAGS) $(INCLUDES) -o $@ $< -$(OBJDIR)/hipe_mkliterals.o: $(TTF_DIR)/hipe_x86_asm.h $(TTF_DIR)/hipe_ppc_asm.h $(TTF_DIR)/beam_opcodes.h +$(OBJDIR)/hipe_mkliterals.o: $(HIPE_ASM) $(TTF_DIR)/erl_alloc_types.h \ + $(TTF_DIR)/OPCODES-GENERATED $(TARGET)/TABLES-GENERATED $(TTF_DIR)/hipe_literals.h: $(BINDIR)/hipe_mkliterals$(TF_MARKER) $(BINDIR)/hipe_mkliterals$(TF_MARKER) -c > $@ -$(OBJDIR)/hipe_x86_glue.o: hipe/hipe_x86_glue.S $(TTF_DIR)/hipe_x86_asm.h $(TTF_DIR)/hipe_literals.h hipe/hipe_mode_switch.h -$(TTF_DIR)/hipe_x86_bifs.S: hipe/hipe_x86_bifs.m4 hipe/hipe_x86_asm.m4 hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h -$(OBJDIR)/hipe_x86_bifs.o: $(TTF_DIR)/hipe_x86_bifs.S $(TTF_DIR)/hipe_literals.h - -$(OBJDIR)/hipe_amd64_glue.o: hipe/hipe_amd64_glue.S $(TTF_DIR)/hipe_amd64_asm.h $(TTF_DIR)/hipe_literals.h hipe/hipe_mode_switch.h -$(TTF_DIR)/hipe_amd64_bifs.S: hipe/hipe_amd64_bifs.m4 hipe/hipe_amd64_asm.m4 hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h -$(OBJDIR)/hipe_amd64_bifs.o: $(TTF_DIR)/hipe_amd64_bifs.S $(TTF_DIR)/hipe_literals.h - -$(OBJDIR)/hipe_sparc_glue.o: hipe/hipe_sparc_glue.S $(TTF_DIR)/hipe_sparc_asm.h hipe/hipe_mode_switch.h $(TTF_DIR)/hipe_literals.h -$(TTF_DIR)/hipe_sparc_bifs.S: hipe/hipe_sparc_bifs.m4 hipe/hipe_sparc_asm.m4 hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h -$(OBJDIR)/hipe_sparc_bifs.o: $(TTF_DIR)/hipe_sparc_bifs.S $(TTF_DIR)/hipe_literals.h - -$(OBJDIR)/hipe_ppc_glue.o: hipe/hipe_ppc_glue.S $(TTF_DIR)/hipe_ppc_asm.h hipe/hipe_mode_switch.h $(TTF_DIR)/hipe_literals.h -$(TTF_DIR)/hipe_ppc_bifs.S: hipe/hipe_ppc_bifs.m4 hipe/hipe_ppc_asm.m4 hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h -$(OBJDIR)/hipe_ppc_bifs.o: $(TTF_DIR)/hipe_ppc_bifs.S $(TTF_DIR)/hipe_literals.h - -$(OBJDIR)/hipe_arm_glue.o: hipe/hipe_arm_glue.S $(TTF_DIR)/hipe_arm_asm.h hipe/hipe_mode_switch.h $(TTF_DIR)/hipe_literals.h -$(TTF_DIR)/hipe_arm_bifs.S: hipe/hipe_arm_bifs.m4 hipe/hipe_arm_asm.m4 hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h -$(OBJDIR)/hipe_arm_bifs.o: $(TTF_DIR)/hipe_arm_bifs.S $(TTF_DIR)/hipe_literals.h +$(OBJDIR)/hipe_x86_glue.o: hipe/hipe_x86_glue.S \ + $(TTF_DIR)/hipe_x86_asm.h $(TTF_DIR)/hipe_literals.h \ + hipe/hipe_mode_switch.h +$(TTF_DIR)/hipe_x86_bifs.S: hipe/hipe_x86_bifs.m4 hipe/hipe_x86_asm.m4 \ + hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h +$(OBJDIR)/hipe_x86_bifs.o: $(TTF_DIR)/hipe_x86_bifs.S \ + $(TTF_DIR)/hipe_literals.h + +$(OBJDIR)/hipe_amd64_glue.o: hipe/hipe_amd64_glue.S \ + $(TTF_DIR)/hipe_amd64_asm.h $(TTF_DIR)/hipe_literals.h \ + hipe/hipe_mode_switch.h +$(TTF_DIR)/hipe_amd64_bifs.S: hipe/hipe_amd64_bifs.m4 hipe/hipe_amd64_asm.m4 \ + hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h +$(OBJDIR)/hipe_amd64_bifs.o: $(TTF_DIR)/hipe_amd64_bifs.S \ + $(TTF_DIR)/hipe_literals.h + +$(OBJDIR)/hipe_sparc_glue.o: hipe/hipe_sparc_glue.S \ + $(TTF_DIR)/hipe_sparc_asm.h hipe/hipe_mode_switch.h \ + $(TTF_DIR)/hipe_literals.h +$(TTF_DIR)/hipe_sparc_bifs.S: hipe/hipe_sparc_bifs.m4 hipe/hipe_sparc_asm.m4 \ + hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h +$(OBJDIR)/hipe_sparc_bifs.o: $(TTF_DIR)/hipe_sparc_bifs.S \ + $(TTF_DIR)/hipe_literals.h + +$(OBJDIR)/hipe_ppc_glue.o: hipe/hipe_ppc_glue.S $(TTF_DIR)/hipe_ppc_asm.h \ + hipe/hipe_mode_switch.h $(TTF_DIR)/hipe_literals.h +$(TTF_DIR)/hipe_ppc_bifs.S: hipe/hipe_ppc_bifs.m4 hipe/hipe_ppc_asm.m4 \ + hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h +$(OBJDIR)/hipe_ppc_bifs.o: $(TTF_DIR)/hipe_ppc_bifs.S \ + $(TTF_DIR)/hipe_literals.h + +$(OBJDIR)/hipe_arm_glue.o: hipe/hipe_arm_glue.S $(TTF_DIR)/hipe_arm_asm.h \ + hipe/hipe_mode_switch.h $(TTF_DIR)/hipe_literals.h +$(TTF_DIR)/hipe_arm_bifs.S: hipe/hipe_arm_bifs.m4 hipe/hipe_arm_asm.m4 \ + hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h +$(OBJDIR)/hipe_arm_bifs.o: $(TTF_DIR)/hipe_arm_bifs.S \ + $(TTF_DIR)/hipe_literals.h # end of HiPE section ######################################## @@ -927,13 +953,6 @@ $(BINDIR)/$(EMULATOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS) endif -# -# Create directories -# - -$(CREATE_DIRS): - $(MKDIR) -p $@ - # ---------------------------------------------------------------------- # Dependencies # @@ -945,6 +964,7 @@ $(TARGET)/Makefile: Makefile.in #SED_REPL_WIN_DRIVE=s|\([ ]\)\([A-Za-z]\):|\1/cygdrive/\2|g;s|^\([A-Za-z]\):|/cygdrive/\1|g SED_REPL_O=s|^\([^:]*:\)|$$(OBJDIR)/\1|g +SED_REPL_O_ZLIB=s|^\([^:]*:\)|$$(ZLIB_OBJDIR)/\1|g SED_REPL_TTF_DIR=s|$(TTF_DIR)/|$$(TTF_DIR)/|g SED_REPL_ERL_TOP=s|\([ ]\)$(ERL_TOP)/|\1$$(ERL_TOP)/|g;s|^$(ERL_TOP)/|$$(ERL_TOP)/|g SED_REPL_POLL=s|$$(OBJDIR)/erl_poll.o|$$(OBJDIR)/erl_poll.kp.o $$(OBJDIR)/erl_poll.nkp.o|g @@ -964,6 +984,7 @@ SED_SUFFIX= endif SED_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_O);$(SED_REPL_TTF_DIR);$(SED_REPL_ERL_TOP)$(SED_SUFFIX)' +SED_DEPEND_ZLIB=sed '$(SED_PREFIX)$(SED_REPL_O_ZLIB)' ifdef HIPE_ENABLED HIPE_SRC=$(wildcard hipe/*.c) @@ -1008,22 +1029,36 @@ DEP_FLAGS=-MM $(MG_FLAG) $(CFLAGS) $(INCLUDES) -Idrivers/common -Idrivers/$(ERLA SYS_SRC=$(ALL_SYS_SRC) endif +.PHONY: depend +ifdef VOID_EMULATOR depend: + @echo $(VOID_EMULATOR)' - omitted target depend' +else +depend: $(TTF_DIR)/depend.mk +$(TTF_DIR)/depend.mk: $(TTF_DIR)/GENERATED $(DEP_CC) $(DEP_FLAGS) $(BEAM_SRC) \ - | $(SED_DEPEND) > $(TARGET)/depend.mk + | $(SED_DEPEND) > $(TTF_DIR)/depend.mk $(DEP_CC) $(DEP_FLAGS) -DLIBSCTP=$(LIBSCTP) $(DRV_COMMON_SRC) \ - | $(SED_DEPEND) >> $(TARGET)/depend.mk + | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk $(DEP_CC) $(DEP_FLAGS) -I../etc/$(ERLANG_OSTYPE) $(DRV_OSTYPE_SRC) \ - | $(SED_DEPEND) >> $(TARGET)/depend.mk + | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk $(DEP_CC) $(DEP_FLAGS) $(SYS_SRC) \ - | $(SED_DEPEND) >> $(TARGET)/depend.mk + | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk $(DEP_CC) $(DEP_FLAGS) $(TARGET_SRC) \ - | $(SED_DEPEND) >> $(TARGET)/depend.mk + | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk + $(DEP_CC) $(DEP_FLAGS) $(ZLIB_SRC) \ + | $(SED_DEPEND_ZLIB) >> $(TTF_DIR)/depend.mk ifdef HIPE_ENABLED $(DEP_CC) $(DEP_FLAGS) $(HIPE_SRC) \ - | $(SED_DEPEND) >> $(TARGET)/depend.mk + | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk +endif + cd $(ERTS_LIB_DIR) && $(MAKE) depend endif --include $(TARGET)/depend.mk - - +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(MAKECMDGOALS),generate) +ifndef VOID_EMULATOR +-include $(TTF_DIR)/depend.mk +endif +endif +endif diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index 71454b3e57..7be40976f6 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -95,6 +95,7 @@ atom atom atom atom_used atom attributes atom await_proc_exit +atom await_sched_wall_time_modifications atom awaiting_load atom awaiting_unload atom backtrace backtrace_depth @@ -239,6 +240,7 @@ atom generational atom get_seq_token atom get_tcw atom getenv +atom gather_sched_wall_time_result atom getting_linked atom getting_unlinked atom global @@ -554,6 +556,7 @@ atom waiting atom wall_clock atom warning atom warning_msg +atom scheduler_wall_time atom wordsize atom write_concurrency atom xor diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index 692fa61fe8..dd13cd179a 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -1329,10 +1329,14 @@ static BpData *get_break(Process *p, BeamInstr *pc, BeamInstr break_op) { } static BpData *is_break(BeamInstr *pc, BeamInstr break_op) { - BpData **rs = (BpData **) pc[-4]; + BpData **rs; BpData *bd = NULL, *ebd = NULL; ASSERT(pc[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); + if (erts_is_native_break(pc)) { + return NULL; + } + rs = (BpData **) pc[-4]; if (! rs) { return NULL; } diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 55f4798892..f8305944a4 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -43,6 +43,9 @@ static Export* set_cpu_topology_trap = NULL; static Export* await_proc_exit_trap = NULL; Export* erts_format_cpu_topology_trap = NULL; +static Export *await_sched_wall_time_mod_trap; +static erts_smp_atomic32_t sched_wall_time; + #define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1) /* @@ -4160,6 +4163,18 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2) erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); BIF_RET(am_true); + } else if (BIF_ARG_1 == am_scheduler_wall_time) { + if (BIF_ARG_2 == am_true || BIF_ARG_2 == am_false) { + erts_aint32_t new = BIF_ARG_2 == am_true ? 1 : 0; + erts_aint32_t old = erts_smp_atomic32_xchg_nob(&sched_wall_time, + new); + Eterm ref = erts_sched_wall_time_request(BIF_P, 1, new); + ASSERT(is_value(ref)); + BIF_TRAP2(await_sched_wall_time_mod_trap, + BIF_P, + ref, + old ? am_true : am_false); + } } else if (ERTS_IS_ATOM_STR("scheduling_statistics", BIF_ARG_1)) { int what; if (ERTS_IS_ATOM_STR("disable", BIF_ARG_2)) @@ -4457,6 +4472,9 @@ void erts_init_bif(void) am_format_cpu_topology, 1); await_proc_exit_trap = erts_export_put(am_erlang,am_await_proc_exit,3); + await_sched_wall_time_mod_trap + = erts_export_put(am_erlang, am_await_sched_wall_time_modifications, 2); + erts_smp_atomic32_init_nob(&sched_wall_time, 0); } #ifdef HARDDEBUG diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types index 962db8b831..90a6c0cbee 100644 --- a/erts/emulator/beam/erl_alloc.types +++ b/erts/emulator/beam/erl_alloc.types @@ -367,6 +367,7 @@ type EXPORT LONG_LIVED_LOW CODE export_entry type MONITOR_SH STANDARD_LOW PROCESSES monitor_sh type NLINK_SH STANDARD_LOW PROCESSES nlink_sh type AINFO_REQ STANDARD_LOW SYSTEM alloc_info_request +type SCHED_WTIME_REQ STANDARD_LOW SYSTEM sched_wall_time_request +else # "fullword" @@ -383,6 +384,7 @@ type EXPORT LONG_LIVED CODE export_entry type MONITOR_SH FIXED_SIZE PROCESSES monitor_sh type NLINK_SH FIXED_SIZE PROCESSES nlink_sh type AINFO_REQ SHORT_LIVED SYSTEM alloc_info_request +type SCHED_WTIME_REQ SHORT_LIVED SYSTEM sched_wall_time_request +endif diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c index c32938bdff..2e1a92f61d 100644 --- a/erts/emulator/beam/erl_alloc_util.c +++ b/erts/emulator/beam/erl_alloc_util.c @@ -3956,7 +3956,8 @@ realloc_thr_pref(ErtsAlcType_t type, void *extra, void *p, Uint size, if (used_allctr->thread_safe && (!force_move || used_allctr != pref_allctr)) erts_mtx_lock(&used_allctr->mutex); - ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&used_allctr->mutex)); + ERTS_SMP_LC_ASSERT(!used_allctr->thread_safe || + erts_lc_mtx_is_locked(&used_allctr->mutex)); cpy_size = BLK_SZ(blk); if (used_allctr->thread_safe && (!force_move || used_allctr != pref_allctr)) diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 5a806777fe..ebd475f73a 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -57,6 +57,8 @@ static Export* alloc_info_trap = NULL; static Export* alloc_sizes_trap = NULL; +static Export *gather_sched_wall_time_res_trap; + #define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1) /* Keep erts_system_version as a global variable for easy access from a core */ @@ -3180,7 +3182,12 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1) Eterm res; Eterm* hp; - if (BIF_ARG_1 == am_context_switches) { + if (BIF_ARG_1 == am_scheduler_wall_time) { + res = erts_sched_wall_time_request(BIF_P, 0, 0); + if (is_non_value(res)) + BIF_RET(am_undefined); + BIF_TRAP1(gather_sched_wall_time_res_trap, BIF_P, res); + } else if (BIF_ARG_1 == am_context_switches) { Eterm cs = erts_make_integer(erts_get_total_context_switches(), BIF_P); hp = HAlloc(BIF_P, 3); res = TUPLE2(hp, cs, SMALL_ZERO); @@ -4160,6 +4167,8 @@ erts_bif_info_init(void) alloc_info_trap = erts_export_put(am_erlang, am_alloc_info, 1); alloc_sizes_trap = erts_export_put(am_erlang, am_alloc_sizes, 1); + gather_sched_wall_time_res_trap + = erts_export_put(am_erlang, am_gather_sched_wall_time_result, 1); process_info_init(); os_info_init(); } diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index eb2b945877..bde87b8346 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -357,10 +357,11 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj) erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS); p->gcstatus = p->status; p->status = P_GARBING; + erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS); + if (erts_system_monitor_long_gc != 0) { get_now(&ms1, &s1, &us1); } - erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS); ERTS_CHK_OFFHEAP(p); @@ -910,7 +911,18 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl) * XXX: WARNING: If HiPE starts storing other non-Erlang values on the * nstack, such as floats, then this will have to be changed. */ -#define offset_nstack(p,offs,area,area_size) offset_heap_ptr(hipe_nstack_start((p)),hipe_nstack_used((p)),(offs),(area),(area_size)) +static ERTS_INLINE void offset_nstack(Process* p, Sint offs, + char* area, Uint area_size) +{ + if (p->hipe.nstack) { + ASSERT(p->hipe.nsp && p->hipe.nstend); + offset_heap_ptr(hipe_nstack_start(p), hipe_nstack_used(p), + offs, area, area_size); + } + else { + ASSERT(!p->hipe.nsp && !p->hipe.nstend); + } +} #else /* !HIPE */ diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 5469a59d8c..30c91af630 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -537,6 +537,209 @@ erts_late_init_process(void) } +static void +init_sched_wall_time(ErtsSchedWallTime *swtp) +{ + swtp->enabled = 0; + swtp->start = 0; + swtp->working.total = 0; + swtp->working.start = 0; + swtp->working.currently = 0; +} + +static ERTS_INLINE Uint64 +sched_wall_time_ts(void) +{ +#ifdef HAVE_GETHRTIME + return (Uint64) sys_gethrtime(); +#else + Uint64 res; + SysTimeval tv; + sys_gettimeofday(&tv); + res = (Uint64) tv.tv_sec*1000000; + res += (Uint64) tv.tv_usec; + return res; +#endif +} + +static ERTS_INLINE void +sched_wall_time_change(ErtsSchedulerData *esdp, int working) +{ + if (esdp->sched_wall_time.enabled) { + Uint64 ts = sched_wall_time_ts(); + if (working) { +#ifdef DEBUG + ASSERT(!esdp->sched_wall_time.working.currently); + esdp->sched_wall_time.working.currently = 1; +#endif + ts -= esdp->sched_wall_time.start; + esdp->sched_wall_time.working.start = ts; + } + else { +#ifdef DEBUG + ASSERT(esdp->sched_wall_time.working.currently); + esdp->sched_wall_time.working.currently = 0; +#endif + ts -= esdp->sched_wall_time.start; + ts -= esdp->sched_wall_time.working.start; + esdp->sched_wall_time.working.total += ts; + } + } +} + +typedef struct { + int set; + int enable; + Process *proc; + Eterm ref; + Eterm ref_heap[REF_THING_SIZE]; + Uint req_sched; + erts_smp_atomic32_t refc; +} ErtsSchedWallTimeReq; + +#if !HALFWORD_HEAP +ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(swtreq, + ErtsSchedWallTimeReq, + 5, + ERTS_ALC_T_SCHED_WTIME_REQ) +#else +static ERTS_INLINE ErtsSchedWallTimeReq * +swtreq_alloc(void) +{ + return erts_alloc(ERTS_ALC_T_SCHED_WTIME_REQ, + sizeof(ErtsSchedWallTimeReq)); +} + +static ERTS_INLINE void +swtreq_free(ErtsSchedWallTimeReq *ptr) +{ + erts_free(ERTS_ALC_T_SCHED_WTIME_REQ, ptr); +} +#endif + +static void +reply_sched_wall_time(void *vswtrp) +{ + Uint64 working = 0, total = 0; + ErtsSchedulerData *esdp = erts_get_scheduler_data(); + ErtsSchedWallTimeReq *swtrp = (ErtsSchedWallTimeReq *) vswtrp; + ErtsProcLocks rp_locks = (swtrp->req_sched == esdp->no + ? ERTS_PROC_LOCK_MAIN + : 0); + Process *rp = swtrp->proc; + Eterm ref_copy = NIL, msg; + Eterm *hp = NULL; + Eterm **hpp; + Uint sz, *szp; + ErlOffHeap *ohp = NULL; + ErlHeapFragment *bp = NULL; + + ASSERT(esdp); + + if (swtrp->set) { + if (!swtrp->enable && esdp->sched_wall_time.enabled) + esdp->sched_wall_time.enabled = 0; + else if (swtrp->enable && !esdp->sched_wall_time.enabled) { + Uint64 ts = sched_wall_time_ts(); + esdp->sched_wall_time.enabled = 1; + esdp->sched_wall_time.start = ts; + esdp->sched_wall_time.working.total = 0; + esdp->sched_wall_time.working.start = 0; + esdp->sched_wall_time.working.currently = 1; + } + } + + if (esdp->sched_wall_time.enabled) { + Uint64 ts = sched_wall_time_ts(); + ASSERT(esdp->sched_wall_time.working.currently); + ts -= esdp->sched_wall_time.start; + total = ts; + ts -= esdp->sched_wall_time.working.start; + working = esdp->sched_wall_time.working.total + ts; + } + + sz = 0; + hpp = NULL; + szp = &sz; + + while (1) { + if (hpp) + ref_copy = STORE_NC(hpp, ohp, swtrp->ref); + else + *szp += REF_THING_SIZE; + + if (swtrp->set) + msg = ref_copy; + else { + msg = (!esdp->sched_wall_time.enabled + ? am_notsup + : erts_bld_tuple(hpp, szp, 3, + make_small(esdp->no), + erts_bld_uint64(hpp, szp, working), + erts_bld_uint64(hpp, szp, total))); + + msg = erts_bld_tuple(hpp, szp, 2, ref_copy, msg); + } + if (hpp) + break; + + hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks); + szp = NULL; + hpp = &hp; + } + + erts_queue_message(rp, &rp_locks, bp, msg, NIL); + + if (swtrp->req_sched == esdp->no) + rp_locks &= ~ERTS_PROC_LOCK_MAIN; + + if (rp_locks) + erts_smp_proc_unlock(rp, rp_locks); + + erts_smp_proc_dec_refc(rp); + + if (erts_smp_atomic32_dec_read_nob(&swtrp->refc) == 0) + swtreq_free(vswtrp); +} + +Eterm +erts_sched_wall_time_request(Process *c_p, int set, int enable) +{ + ErtsSchedulerData *esdp = ERTS_PROC_GET_SCHDATA(c_p); + Eterm ref; + ErtsSchedWallTimeReq *swtrp; + Eterm *hp; + + if (!set && !esdp->sched_wall_time.enabled) + return THE_NON_VALUE; + + swtrp = swtreq_alloc(); + ref = erts_make_ref(c_p); + hp = &swtrp->ref_heap[0]; + + swtrp->set = set; + swtrp->enable = enable; + swtrp->proc = c_p; + swtrp->ref = STORE_NC(&hp, NULL, ref); + swtrp->req_sched = esdp->no; + erts_smp_atomic32_init_nob(&swtrp->refc, + (erts_aint32_t) erts_no_schedulers); + + erts_smp_proc_add_refc(c_p, (Sint32) erts_no_schedulers); + +#ifdef ERTS_SMP + if (erts_no_schedulers > 1) + erts_schedule_multi_misc_aux_work(1, + erts_no_schedulers, + reply_sched_wall_time, + (void *) swtrp); +#endif + + reply_sched_wall_time((void *) swtrp); + + return ref; +} + static ERTS_INLINE ErtsProcList * proclist_create(Process *p) { @@ -1707,6 +1910,7 @@ aux_thread(void *unused) static void scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) { + int working = 1; ErtsSchedulerSleepInfo *ssi = esdp->ssi; int spincount; erts_aint32_t aux_work = 0; @@ -1737,12 +1941,17 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) tse_wait: + if (thr_prgr_active != working) + sched_wall_time_change(esdp, thr_prgr_active); + while (1) { aux_work = erts_atomic32_read_acqb(&ssi->aux_work); if (aux_work) { - if (!thr_prgr_active) + if (!thr_prgr_active) { erts_thr_progress_active(esdp, thr_prgr_active = 1); + sched_wall_time_change(esdp, 1); + } aux_work = handle_aux_work(&esdp->aux_work_data, aux_work); if (aux_work && erts_thr_progress_update(esdp)) erts_thr_progress_leader_update(esdp); @@ -1751,8 +1960,10 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) if (aux_work) flgs = erts_smp_atomic32_read_acqb(&ssi->flags); else { - if (thr_prgr_active) + if (thr_prgr_active) { erts_thr_progress_active(esdp, thr_prgr_active = 0); + sched_wall_time_change(esdp, 0); + } erts_thr_progress_prepare_wait(esdp); flgs = sched_spin_wait(ssi, spincount); @@ -1789,8 +2000,10 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) if (flgs & ~ERTS_SSI_FLG_SUSPENDED) erts_smp_atomic32_read_band_nob(&ssi->flags, ERTS_SSI_FLG_SUSPENDED); - if (!thr_prgr_active) + if (!thr_prgr_active) { erts_thr_progress_active(esdp, thr_prgr_active = 1); + sched_wall_time_change(esdp, 1); + } erts_smp_runq_lock(rq); sched_active(esdp->no, rq); @@ -1806,14 +2019,21 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) sched_waiting_sys(esdp->no, rq); + erts_smp_runq_unlock(rq); + ASSERT(working); + sched_wall_time_change(esdp, working = 0); + spincount = ERTS_SCHED_SYS_SLEEP_SPINCOUNT; while (spincount-- > 0) { sys_poll_aux_work: + if (working) + sched_wall_time_change(esdp, working = 0); + ASSERT(!erts_port_task_have_outstanding_io_tasks()); erl_sys_schedule(1); /* Might give us something to do */ @@ -1828,6 +2048,8 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) aux_work = erts_atomic32_read_acqb(&ssi->aux_work); if (aux_work) { + if (!working) + sched_wall_time_change(esdp, working = 1); #ifdef ERTS_SMP if (!thr_prgr_active) erts_thr_progress_active(esdp, thr_prgr_active = 1); @@ -1920,6 +2142,9 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) erts_smp_runq_unlock(rq); + if (working) + sched_wall_time_change(esdp, working = 0); + #ifdef ERTS_SMP if (thr_prgr_active) erts_thr_progress_active(esdp, thr_prgr_active = 0); @@ -1955,6 +2180,8 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) if (flgs & ~ERTS_SSI_FLG_SUSPENDED) erts_smp_atomic32_read_band_nob(&ssi->flags, ERTS_SSI_FLG_SUSPENDED); #endif + if (!working) + sched_wall_time_change(esdp, working = 1); sched_active_sys(esdp->no, rq); } @@ -3430,9 +3657,14 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online) esdp->run_queue->scheduler = esdp; init_aux_work_data(&esdp->aux_work_data, esdp); + init_sched_wall_time(&esdp->sched_wall_time); } init_misc_aux_work(); +#if !HALFWORD_HEAP + init_swtreq_alloc(); +#endif + #ifdef ERTS_SMP @@ -3755,6 +3987,8 @@ suspend_scheduler(ErtsSchedulerData *esdp) if (erts_system_profile_flags.scheduler) profile_scheduler(make_small(esdp->no), am_inactive); + sched_wall_time_change(esdp, 0); + erts_smp_mtx_lock(&schdlr_sspnd.mtx); flgs = sched_prep_spin_suspended(ssi, ERTS_SSI_FLG_SUSPENDED); @@ -3813,16 +4047,20 @@ suspend_scheduler(ErtsSchedulerData *esdp) aux_work = erts_atomic32_read_acqb(&ssi->aux_work); if (aux_work) { - if (!thr_prgr_active) + if (!thr_prgr_active) { erts_thr_progress_active(esdp, thr_prgr_active = 1); + sched_wall_time_change(esdp, 1); + } aux_work = handle_aux_work(&esdp->aux_work_data, aux_work); if (aux_work && erts_thr_progress_update(esdp)) erts_thr_progress_leader_update(esdp); } if (!aux_work) { - if (thr_prgr_active) + if (thr_prgr_active) { erts_thr_progress_active(esdp, thr_prgr_active = 0); + sched_wall_time_change(esdp, 0); + } erts_thr_progress_prepare_wait(esdp); flgs = sched_spin_suspended(ssi, ERTS_SCHED_SUSPEND_SLEEP_SPINCOUNT); @@ -3877,8 +4115,10 @@ suspend_scheduler(ErtsSchedulerData *esdp) if (erts_system_profile_flags.scheduler) profile_scheduler(make_small(esdp->no), am_active); - if (!thr_prgr_active) + if (!thr_prgr_active) { erts_thr_progress_active(esdp, thr_prgr_active = 1); + sched_wall_time_change(esdp, 1); + } erts_smp_runq_lock(esdp->run_queue); non_empty_runq(esdp->run_queue); diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index a51b380bb0..173b7df69d 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -394,6 +394,16 @@ do { \ } while (0) typedef struct { + int enabled; + Uint64 start; + struct { + Uint64 total; + Uint64 start; + int currently; + } working; +} ErtsSchedWallTime; + +typedef struct { int sched_id; ErtsSchedulerData *esdp; ErtsSchedulerSleepInfo *ssi; @@ -457,6 +467,8 @@ struct ErtsSchedulerData_ { ErtsSchedAllocData alloc_data; + ErtsSchedWallTime sched_wall_time; + #ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC erts_alloc_verify_func_t verify_unused_temp_alloc; Allctr_t *verify_unused_temp_alloc_data; @@ -1064,6 +1076,8 @@ void erts_late_init_process(void); void erts_early_init_scheduling(int); void erts_init_scheduling(int, int); +Eterm erts_sched_wall_time_request(Process *c_p, int set, int enable); + ErtsProcList *erts_proclist_create(Process *); void erts_proclist_destroy(ErtsProcList *); int erts_proclist_same(ErtsProcList *, Process *); diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index 70c3e7612f..b1d1e1d9b0 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -544,7 +544,7 @@ send_to_port(Process *c_p, Eterm message, */ static void -profile_send(Eterm profiler, Eterm message) { +profile_send(Eterm from, Eterm message) { Uint sz = 0; ErlHeapFragment *bp = NULL; Uint *hp = NULL; @@ -552,6 +552,11 @@ profile_send(Eterm profiler, Eterm message) { Process *profile_p = NULL; ErlOffHeap *off_heap = NULL; + Eterm profiler = erts_get_system_profile(); + + /* do not profile profiler pid */ + if (from == profiler) return; + if (is_internal_port(profiler)) { Port *profiler_port = NULL; @@ -2581,7 +2586,6 @@ profile_scheduler(Eterm scheduler_id, Eterm state) { Uint Ms, s, us; #ifndef ERTS_SMP - Eterm profiler; #define LOCAL_HEAP_SIZE (4 + 7) DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); UseTmpHeapNoproc(LOCAL_HEAP_SIZE); @@ -2616,8 +2620,7 @@ profile_scheduler(Eterm scheduler_id, Eterm state) { make_small(active_sched), timestamp); hp += 7; #ifndef ERTS_SMP - profiler = erts_get_system_profile(); - profile_send(profiler, msg); + profile_send(NIL, msg); UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); #undef LOCAL_HEAP_SIZE #else @@ -2632,7 +2635,6 @@ profile_scheduler_q(Eterm scheduler_id, Eterm state, Eterm no_schedulers, Uint M Eterm *hp, msg, timestamp; #ifndef ERTS_SMP - Eterm profiler; #define LOCAL_HEAP_SIZE (4 + 7) DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); UseTmpHeapNoproc(LOCAL_HEAP_SIZE); @@ -2653,8 +2655,7 @@ profile_scheduler_q(Eterm scheduler_id, Eterm state, Eterm no_schedulers, Uint M timestamp = TUPLE3(hp, make_small(Ms), make_small(s), make_small(us)); hp += 4; msg = TUPLE6(hp, am_profile, am_scheduler, scheduler_id, state, no_schedulers, timestamp); hp += 7; #ifndef ERTS_SMP - profiler = erts_get_system_profile(); - profile_send(profiler, msg); + profile_send(NIL, msg); UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); #undef LOCAL_HEAP_SIZE #else @@ -2897,7 +2898,6 @@ profile_runnable_port(Port *p, Eterm status) { Eterm count = make_small(0); #ifndef ERTS_SMP - Eterm profiler; #define LOCAL_HEAP_SIZE (4 + 6) DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); @@ -2922,12 +2922,11 @@ profile_runnable_port(Port *p, Eterm status) { msg = TUPLE5(hp, am_profile, p->id, status, count, timestamp); hp += 6; #ifndef ERTS_SMP - profiler = erts_get_system_profile(); - profile_send(profiler, msg); + profile_send(p->id, msg); UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); #undef LOCAL_HEAP_SIZE #else - enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp); + enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, p->id, NIL, msg, bp); #endif erts_smp_mtx_unlock(&smq_mtx); } @@ -2938,7 +2937,6 @@ profile_runnable_proc(Process *p, Eterm status){ Uint Ms, s, us; Eterm *hp, msg, timestamp; Eterm where = am_undefined; - Eterm profiler; #ifndef ERTS_SMP #define LOCAL_HEAP_SIZE (4 + 6 + 4) @@ -2951,12 +2949,6 @@ profile_runnable_proc(Process *p, Eterm status){ ErlHeapFragment *bp; Uint hsz = 4 + 6 + 4; #endif - profiler = erts_get_system_profile(); - - /* Do not profile profiler pid */ - if (profiler == p->id) { - return; - } if (!p->current) { p->current = find_function_from_pc(p->i); @@ -2983,11 +2975,11 @@ profile_runnable_proc(Process *p, Eterm status){ timestamp = TUPLE3(hp, make_small(Ms), make_small(s), make_small(us)); hp += 4; msg = TUPLE5(hp, am_profile, p->id, status, where, timestamp); hp += 6; #ifndef ERTS_SMP - profile_send(profiler, msg); + profile_send(p->id, msg); UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); #undef LOCAL_HEAP_SIZE #else - enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp); + enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, p->id, NIL, msg, bp); #endif erts_smp_mtx_unlock(&smq_mtx); } diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 49cd0e5f53..b23b1f628d 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1996-2011. All Rights Reserved. + * Copyright Ericsson AB 1996-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 @@ -818,6 +818,11 @@ erts_smp_xports_unlock(Port *prt) #define SET_VEC(iov, bv, bin, ptr, len, vlen) do { \ (iov)->iov_base = (ptr); \ (iov)->iov_len = (len); \ + if (sizeof((iov)->iov_len) < sizeof(len) \ + /* Check if (len) overflowed (iov)->iov_len */ \ + && ((len) >> (sizeof((iov)->iov_len)*CHAR_BIT)) != 0) { \ + goto L_overflow; \ + } \ *(bv)++ = (bin); \ (iov)++; \ (vlen)++; \ @@ -1146,11 +1151,21 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list) ivp[0].iov_len = 0; bvp[0] = NULL; ev.vsize = io_list_to_vec(list, ivp+1, bvp+1, cbin, blimit); + if (ev.vsize < 0) { + if (ivp != iv) { + erts_free(ERTS_ALC_T_TMP, (void *) ivp); + } + if (bvp != bv) { + erts_free(ERTS_ALC_T_TMP, (void *) bvp); + } + driver_free_binary(cbin); + goto bad_value; + } ev.vsize++; #if 0 /* This assertion may say something useful, but it can be falsified during the emulator test suites. */ - ASSERT((ev.vsize >= 0) && (ev.vsize == vsize)); + ASSERT(ev.vsize == vsize); #endif ev.size = size; /* total size */ ev.iov = ivp; @@ -3912,7 +3927,7 @@ int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, ErlDrvSizeT skip) ErlDrvSizeT driver_deq(ErlDrvPort ix, ErlDrvSizeT size) { ErlIOQueue* q = drvport2ioq(ix); - int len; + ErlDrvSizeT len; if ((q == NULL) || (q->size < size)) return -1; diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index b132991a3b..36ed108b76 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -1385,7 +1385,11 @@ static void invoke_writev(void *data) { size = d->c.writev.size; } - /* Copy the io vector to avoid locking the port que while writing */ + /* Copy the io vector to avoid locking the port que while writing, + * also, both we and efile_writev might/will change the SysIOVec + * when segmenting or due to partial write and we do not want to + * tamper with the actual queue that we get from driver_peekq + */ MUTEX_LOCK(d->c.writev.q_mtx); /* Lock before accessing the port queue */ iov0 = driver_peekq(d->c.writev.port, &iovlen); @@ -1424,7 +1428,7 @@ static void invoke_writev(void *data) { } else { d->result_ok = efile_writev(&d->errInfo, d->flags, (int) d->fd, - iov, iovcnt, size); + iov, iovcnt); } } else if (iovlen == 0) { d->result_ok = 1; diff --git a/erts/emulator/drivers/common/erl_efile.h b/erts/emulator/drivers/common/erl_efile.h index 3868b38137..69ad02633c 100644 --- a/erts/emulator/drivers/common/erl_efile.h +++ b/erts/emulator/drivers/common/erl_efile.h @@ -162,7 +162,7 @@ int efile_write_info(Efile_error* errInfo, Efile_info* pInfo, char *name); int efile_write(Efile_error* errInfo, int flags, int fd, char* buf, size_t count); int efile_writev(Efile_error* errInfo, int flags, int fd, - SysIOVec* iov, int iovcnt, size_t size); + SysIOVec* iov, int iovcnt); int efile_read(Efile_error* errInfo, int flags, int fd, char* buf, size_t count, size_t* pBytesRead); int efile_seek(Efile_error* errInfo, int fd, diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index eeaa4d24ea..47a99fdbe6 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -6194,6 +6194,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) type = SCTP_DEFAULT_SEND_PARAM; arg_ptr = (char*) (&arg.sri); arg_sz = sizeof ( arg.sri); + VALGRIND_MAKE_MEM_DEFINED(arg_ptr, arg_sz); /*suppress "uninitialised bytes"*/ break; } case SCTP_OPT_EVENTS: @@ -10299,7 +10300,6 @@ static void packet_inet_command(ErlDrvData e, char* buf, ErlDrvSizeT len) cmsg.hdr.cmsg_level = IPPROTO_SCTP; cmsg.hdr.cmsg_type = SCTP_SNDRCV; cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(*sri)); - VALGRIND_MAKE_MEM_DEFINED(&cmsg, (char*)sri - (char*)&cmsg); /*suppress padding as "uninitialised bytes"*/ data_len = (buf + len) - ptr; /* The whole msg. @@ -10313,6 +10313,7 @@ static void packet_inet_command(ErlDrvData e, char* buf, ErlDrvSizeT len) mhdr.msg_iovlen = 1; mhdr.msg_control = cmsg.ancd; /* For ancilary data */ mhdr.msg_controllen = cmsg.hdr.cmsg_len; + VALGRIND_MAKE_MEM_DEFINED(mhdr.msg_control, mhdr.msg_controllen); /*suppress "uninitialised bytes"*/ mhdr.msg_flags = 0; /* Not used with "sendmsg" */ /* Now do the actual sending. NB: "flags" in "sendmsg" itself are NOT diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 7cf0a712ce..796843a735 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -1004,13 +1004,11 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */ * opened */ int fd, /* File descriptor to write to */ SysIOVec* iov, /* Vector of buffer structs. - * The structs are unchanged - * after the call */ - int iovcnt, /* Number of structs in vector */ - size_t size) /* Number of bytes to write */ + * The structs may be changed i.e. + * due to incomplete writes */ + int iovcnt) /* Number of structs in vector */ { int cnt = 0; /* Buffers so far written */ - int p = 0; /* Position in next buffer */ ASSERT(iovcnt >= 0); @@ -1021,66 +1019,47 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */ #endif while (cnt < iovcnt) { + if ((! iov[cnt].iov_base) || (iov[cnt].iov_len <= 0)) { + /* Empty buffer - skip */ + cnt++; + } else { /* Non-empty buffer */ + ssize_t w; /* Bytes written in this call */ #ifdef HAVE_WRITEV - int w; /* Bytes written in this call */ - int b = iovcnt - cnt; /* Buffers to write */ - if (b > MAXIOV) - b = MAXIOV; - if (iov[cnt].iov_base && iov[cnt].iov_len > 0) { - if (b == 1) { - /* Degenerated io vector */ - do { - w = write(fd, iov[cnt].iov_base + p, iov[cnt].iov_len - p); - } while (w < 0 && errno == EINTR); - } else { - /* Non-empty vector first. - * Adjust pos in first buffer in case of - * previous incomplete writev */ - iov[cnt].iov_base += p; - iov[cnt].iov_len -= p; + int b = iovcnt - cnt; /* Buffers to write */ + /* Use as many buffers as MAXIOV allows */ + if (b > MAXIOV) + b = MAXIOV; + if (b > 1) { do { w = writev(fd, &iov[cnt], b); } while (w < 0 && errno == EINTR); - iov[cnt].iov_base -= p; - iov[cnt].iov_len += p; - } - if (w < 0) - return check_error(-1, errInfo); - } else { - /* Empty vector first - skip */ - cnt++; - continue; - } - ASSERT(w >= 0); - /* Move forward to next vector to write */ - for (; cnt < iovcnt; cnt++) { - if (iov[cnt].iov_base && iov[cnt].iov_len > 0) { - if (w < iov[cnt].iov_len) - break; - else - w -= iov[cnt].iov_len; - } - } - ASSERT(w >= 0); - p = w > 0 ? w : 0; /* Skip p bytes next writev */ -#else /* #ifdef HAVE_WRITEV */ - if (iov[cnt].iov_base && iov[cnt].iov_len > 0) { - /* Non-empty vector */ - int w; /* Bytes written in this call */ - while (p < iov[cnt].iov_len) { - do { - w = write(fd, iov[cnt].iov_base + p, iov[cnt].iov_len - p); - } while (w < 0 && errno == EINTR); - if (w < 0) - return check_error(-1, errInfo); - p += w; + } else + /* Degenerated io vector - use regular write */ +#endif + { + do { + w = write(fd, iov[cnt].iov_base, iov[cnt].iov_len); + } while (w < 0 && errno == EINTR); + ASSERT(w <= iov[cnt].iov_len); + } + if (w < 0) return check_error(-1, errInfo); + /* Move forward to next buffer to write */ + for (; cnt < iovcnt && w > 0; cnt++) { + if (iov[cnt].iov_base && iov[cnt].iov_len > 0) { + if (w < iov[cnt].iov_len) { + /* Adjust the buffer for next write */ + iov[cnt].iov_len -= w; + iov[cnt].iov_base += w; + w = 0; + break; + } else { + w -= iov[cnt].iov_len; + } + } } - } - cnt++; - p = 0; -#endif /* #ifdef HAVE_WRITEV */ + ASSERT(w == 0); + } /* else Non-empty buffer */ } /* while (cnt< iovcnt) */ - size = 0; /* Avoid compiler warning */ return 1; } @@ -1427,10 +1406,9 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, } #ifdef HAVE_SENDFILE - // For some reason the maximum size_t cannot be used as the max size // 3GB seems to work on all platforms -#define SENDFILE_CHUNK_SIZE ((1 << 30) -1) +#define SENDFILE_CHUNK_SIZE ((1UL << 30) -1) /* * sendfile: The implementation of the sendfile system call varies @@ -1467,7 +1445,7 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, written += retval; *nbytes -= retval; } - } while (retval != -1 && retval == SENDFILE_CHUNK_SIZE); + } while (retval == SENDFILE_CHUNK_SIZE); *nbytes = written; return check_error(retval == -1 ? -1 : 0, errInfo); #elif defined(__sun) && defined(__SVR4) && defined(HAVE_SENDFILEV) diff --git a/erts/emulator/drivers/win32/win_efile.c b/erts/emulator/drivers/win32/win_efile.c index 0d3d334154..606fa1d7de 100644 --- a/erts/emulator/drivers/win32/win_efile.c +++ b/erts/emulator/drivers/win32/win_efile.c @@ -1115,8 +1115,7 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */ SysIOVec* iov, /* Vector of buffer structs. * The structs are unchanged * after the call */ - int iovcnt, /* Number of structs in vector */ - size_t size) /* Number of bytes to write */ + int iovcnt) /* Number of structs in vector */ { int cnt; /* Buffers so far written */ OVERLAPPED overlapped; diff --git a/erts/emulator/hipe/hipe_gc.c b/erts/emulator/hipe/hipe_gc.c index 0199dea99e..e0575c35ff 100644 --- a/erts/emulator/hipe/hipe_gc.c +++ b/erts/emulator/hipe/hipe_gc.c @@ -46,9 +46,14 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop) char *src, *oh; Uint src_size, oh_size; + if (!p->hipe.nstack) { + ASSERT(!p->hipe.nsp && !p->hipe.nstend); + return n_htop; + } if (!nstack_walk_init_check(p)) return n_htop; + ASSERT(p->hipe.nsp && p->hipe.nstend); nsp = nstack_walk_nsp_begin(p); nsp_end = p->hipe.nstgraylim; if (nsp_end) @@ -136,9 +141,14 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop) char *heap; Uint heap_size, mature_size; + if (!p->hipe.nstack) { + ASSERT(!p->hipe.nsp && !p->hipe.nstend); + return; + } if (!nstack_walk_init_check(p)) return; + ASSERT(p->hipe.nsp && p->hipe.nstend); nsp = nstack_walk_nsp_begin(p); nsp_end = p->hipe.nstgraylim; if (nsp_end) { diff --git a/erts/emulator/pcre/pcre.mk b/erts/emulator/pcre/pcre.mk index b752c11459..352137b341 100644 --- a/erts/emulator/pcre/pcre.mk +++ b/erts/emulator/pcre/pcre.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2011. All Rights Reserved. +# Copyright Ericsson AB 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 @@ -17,8 +17,6 @@ # %CopyrightEnd% # -ARFLAGS = rc - PCRE_O = \ pcre_latin_1_table.o \ pcre_compile.o \ @@ -43,7 +41,7 @@ pcre_xclass.o PCRE_OBJS = $(PCRE_O:%=$(PCRE_OBJDIR)/%) -GENINC = pcre/pcre_exec_loop_break_cases.inc +PCRE_GENINC = $(ERL_TOP)/erts/emulator/pcre/pcre_exec_loop_break_cases.inc PCRE_OBJDIR = $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE) @@ -61,12 +59,12 @@ endif $(PCRE_OBJDIR)/%.o: pcre/%.c $(CC) -c $(PCRE_CFLAGS) -o $@ $< -$(GENINC): pcre/pcre_exec.c +$(PCRE_GENINC): pcre/pcre_exec.c for x in `grep -n COST_CHK pcre/pcre_exec.c | grep -v 'COST_CHK(N)' | awk -F: '{print $$1}'`; \ do \ N=`expr $$x + 100`; \ echo "case $$N: goto L_LOOP_COUNT_$${x};"; \ - done > $(GENINC) + done > $(PCRE_GENINC) # Dependencies. @@ -79,7 +77,7 @@ $(PCRE_OBJDIR)/pcre_config.o: pcre/pcre_config.c pcre/pcre_internal.h \ $(PCRE_OBJDIR)/pcre_dfa_exec.o: pcre/pcre_dfa_exec.c pcre/pcre_internal.h \ pcre/local_config.h pcre/pcre.h pcre/ucp.h $(PCRE_OBJDIR)/pcre_exec.o: pcre/pcre_exec.c pcre/pcre_internal.h \ - pcre/local_config.h pcre/pcre.h pcre/ucp.h $(GENINC) + pcre/local_config.h pcre/pcre.h pcre/ucp.h $(PCRE_GENINC) $(PCRE_OBJDIR)/pcre_fullinfo.o: pcre/pcre_fullinfo.c pcre/pcre_internal.h \ pcre/local_config.h pcre/pcre.h pcre/ucp.h $(PCRE_OBJDIR)/pcre_get.o: pcre/pcre_get.c pcre/pcre_internal.h \ diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index 3e2bee06d1..7030ebed3f 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -165,10 +165,14 @@ worker_loop() -> worker_foo(_Arg) -> ok. -basic(doc) -> - "Basic test of the call tracing (we trace one process)."; -basic(suite) -> []; -basic(Config) when is_list(Config) -> +%% Basic test of the call tracing (we trace one process). +basic(_Config) -> + case test_server:is_native(lists) of + true -> {skip,"lists is native"}; + false -> basic() + end. + +basic() -> ?line start_tracer(), ?line trace_info(self(), flags), ?line trace_info(self(), tracer), @@ -263,9 +267,15 @@ foo() -> foo0. foo(X) -> X+1. foo(X, Y) -> X+Y. -flags(doc) -> "Test flags (arity, timestamp) for call_trace/3. " - "Also, test the '{tracer,Pid}' option."; -flags(Config) when is_list(Config) -> +%% Test flags (arity, timestamp) for call_trace/3. +%% Also, test the '{tracer,Pid}' option. +flags(_Config) -> + case test_server:is_native(filename) of + true -> {skip,"filename is native"}; + false -> flags() + end. + +flags() -> ?line Tracer = start_tracer_loop(), ?line trace_pid(self(), true, [call,{tracer,Tracer}]), @@ -428,9 +438,14 @@ pam_foo(A, B) -> {ok,A,B}. -change_pam(doc) -> "Test changing PAM programs for a function."; -change_pam(suite) -> []; -change_pam(Config) when is_list(Config) -> +%% Test changing PAM programs for a function. +change_pam(_Config) -> + case test_server:is_native(lists) of + true -> {skip,"lists is native"}; + false -> change_pam() + end. + +change_pam() -> ?line start_tracer(), ?line Self = self(), @@ -468,10 +483,11 @@ change_pam_trace(Prog) -> {match_spec,Prog} = trace_info({erlang,process_info,2}, match_spec), ok. -return_trace(doc) -> "Test the new return trace."; -return_trace(suite) -> []; -return_trace(Config) when is_list(Config) -> - return_trace(). +return_trace(_Config) -> + case test_server:is_native(lists) of + true -> {skip,"lists is native"}; + false -> return_trace() + end. return_trace() -> X = {save,me}, @@ -521,7 +537,7 @@ return_trace() -> ?line {match_spec,Prog2} = trace_info({erlang,atom_to_list,1}, match_spec), ?line lists:seq(2, 7), - ?line atom_to_list(non_literal(nisse)), + ?line _ = atom_to_list(non_literal(nisse)), ?line expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}), ?line expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}), @@ -539,10 +555,11 @@ return_trace() -> nasty() -> exit(good_bye). -exception_trace(doc) -> "Test the new exception trace."; -exception_trace(suite) -> []; -exception_trace(Config) when is_list(Config) -> - exception_trace(). +exception_trace(_Config) -> + case test_server:is_native(lists) of + true -> {skip,"lists is native"}; + false -> exception_trace() + end. exception_trace() -> X = {save,me}, @@ -600,7 +617,7 @@ exception_trace() -> trace_info({erlang,atom_to_list,1}, match_spec), ?line lists:seq(2, 7), - ?line atom_to_list(non_literal(nisse)), + ?line _ = atom_to_list(non_literal(nisse)), ?line expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}), ?line expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}), diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 370363bf9e..6bd7361612 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -859,7 +859,13 @@ resource_holder(Pid,Reply,List) -> threading(doc) -> ["Test the threading API functions (reuse tests from driver API)"]; -threading(Config) when is_list(Config) -> +threading(Config) when is_list(Config) -> + case erlang:system_info(threads) of + true -> threading_do(Config); + false -> {skipped,"No thread support"} + end. + +threading_do(Config) -> ?line Data = ?config(data_dir, Config), ?line File = filename:join(Data, "tester"), ?line {ok,tester,ModBin} = compile:file(File, [binary,return_errors]), diff --git a/erts/emulator/test/nif_SUITE_data/tester.c b/erts/emulator/test/nif_SUITE_data/tester.c index 08466d0f18..257b116322 100644 --- a/erts/emulator/test/nif_SUITE_data/tester.c +++ b/erts/emulator/test/nif_SUITE_data/tester.c @@ -61,6 +61,7 @@ static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) static ERL_NIF_TERM run(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { testcase_run(NULL); + testcase_cleanup(NULL); return enif_make_atom(env, "ok"); } diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl index 0392312a6f..a93dd309c1 100644 --- a/erts/emulator/test/statistics_SUITE.erl +++ b/erts/emulator/test/statistics_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% 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 @@ -29,6 +29,7 @@ runtime_zero_diff/1, runtime_update/1, runtime_diff/1, run_queue_one/1, + scheduler_wall_time/1, reductions/1, reductions_big/1, garbage_collection/1, io/1, badarg/1]). @@ -51,8 +52,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [{group, wall_clock}, {group, runtime}, reductions, - reductions_big, {group, run_queue}, garbage_collection, - io, badarg]. + reductions_big, {group, run_queue}, scheduler_wall_time, + garbage_collection, io, badarg]. groups() -> [{wall_clock, [], @@ -266,11 +267,10 @@ run_queue_one(Config) when is_list(Config) -> run_queue_one_test(Config) when is_list(Config) -> - ?line Hog = spawn_link(?MODULE, hog, [self()]), + ?line _Hog = spawn_link(?MODULE, hog, [self()]), ?line receive - hog_started -> - Hog ! go - end, + hog_started -> ok + end, ?line receive after 100 -> ok end, % Give hog a head start. ?line case statistics(run_queue) of N when N >= 1 -> ok; @@ -280,18 +280,88 @@ run_queue_one_test(Config) when is_list(Config) -> %% CPU-bound process, going at low priority. It will always be ready %% to run. - + hog(Pid) -> ?line process_flag(priority, low), ?line Pid ! hog_started, - ?line receive - go -> hog_iter(0) + ?line Mon = erlang:monitor(process, Pid), + ?line hog_iter(0, Mon). + +hog_iter(N, Mon) when N > 0 -> + receive + {'DOWN', Mon, _, _, _} -> ok + after 0 -> + ?line hog_iter(N-1, Mon) + end; +hog_iter(0, Mon) -> + ?line hog_iter(10000, Mon). + +%%% Tests of statistics(scheduler_wall_time). + +scheduler_wall_time(doc) -> + "Tests that statistics(scheduler_wall_time) works as intended"; +scheduler_wall_time(Config) when is_list(Config) -> + %% Should return undefined if system_flag is not turned on yet + undefined = statistics(scheduler_wall_time), + %% Turn on statistics + false = erlang:system_flag(scheduler_wall_time, true), + try + Schedulers = erlang:system_info(schedulers_online), + %% Let testserver and everyone else finish their work + timer:sleep(500), + %% Empty load + EmptyLoad = get_load(), + {false, _} = {lists:any(fun(Load) -> Load > 50 end, EmptyLoad),EmptyLoad}, + MeMySelfAndI = self(), + StartHog = fun() -> + Pid = spawn(?MODULE, hog, [self()]), + receive hog_started -> MeMySelfAndI ! go end, + Pid + end, + P1 = StartHog(), + %% Max on one, the other schedulers empty (hopefully) + %% Be generous the process can jump between schedulers + %% which is ok and we don't want the test to fail for wrong reasons + _L1 = [S1Load|EmptyScheds1] = get_load(), + {true,_} = {S1Load > 50,S1Load}, + {false,_} = {lists:any(fun(Load) -> Load > 50 end, EmptyScheds1),EmptyScheds1}, + {true,_} = {lists:sum(EmptyScheds1) < 60,EmptyScheds1}, + + %% 50% load + HalfHogs = [StartHog() || _ <- lists:seq(1, (Schedulers-1) div 2)], + HalfLoad = lists:sum(get_load()) div Schedulers, + if Schedulers < 2, HalfLoad > 80 -> ok; %% Ok only one scheduler online and one hog + %% We want roughly 50% load + HalfLoad > 40, HalfLoad < 60 -> ok; + true -> exit({halfload, HalfLoad}) + end, + + %% 100% load + LastHogs = [StartHog() || _ <- lists:seq(1, Schedulers div 2)], + FullScheds = get_load(), + {false,_} = {lists:any(fun(Load) -> Load < 80 end, FullScheds),FullScheds}, + FullLoad = lists:sum(FullScheds) div Schedulers, + if FullLoad > 90 -> ok; + true -> exit({fullload, FullLoad}) + end, + + [exit(Pid, kill) || Pid <- [P1|HalfHogs++LastHogs]], + AfterLoad = get_load(), + {false,_} = {lists:any(fun(Load) -> Load > 5 end, AfterLoad),AfterLoad}, + true = erlang:system_flag(scheduler_wall_time, false) + after + erlang:system_flag(scheduler_wall_time, false) end. -hog_iter(N) when N > 0 -> - ?line hog_iter(N-1); -hog_iter(0) -> - ?line hog_iter(10000). +get_load() -> + Start = erlang:statistics(scheduler_wall_time), + timer:sleep(500), + End = erlang:statistics(scheduler_wall_time), + lists:reverse(lists:sort(load_percentage(lists:sort(Start),lists:sort(End)))). + +load_percentage([{Id, WN, TN}|Ss], [{Id, WP, TP}|Ps]) -> + [100*(WN-WP) div (TN-TP)|load_percentage(Ss, Ps)]; +load_percentage([], []) -> []. garbage_collection(doc) -> diff --git a/erts/emulator/test/trace_port_SUITE.erl b/erts/emulator/test/trace_port_SUITE.erl index 0026da4979..b0ce6f81db 100644 --- a/erts/emulator/test/trace_port_SUITE.erl +++ b/erts/emulator/test/trace_port_SUITE.erl @@ -77,7 +77,8 @@ end_per_testcase(_Func, Config) -> call_trace(doc) -> "Test sending call trace messages to a port."; call_trace(Config) when is_list(Config) -> - case test_server:is_native(?MODULE) of + case test_server:is_native(?MODULE) orelse + test_server:is_native(lists) of true -> {skip,"Native code"}; false -> @@ -128,7 +129,8 @@ bs_sum_c(<<>>, Acc) -> Acc. return_trace(doc) -> "Test the new return trace."; return_trace(Config) when is_list(Config) -> - case test_server:is_native(?MODULE) of + case test_server:is_native(?MODULE) orelse + test_server:is_native(lists) of true -> {skip,"Native code"}; false -> diff --git a/erts/emulator/zlib/Makefile b/erts/emulator/zlib/Makefile deleted file mode 100644 index def8e1aa47..0000000000 --- a/erts/emulator/zlib/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2009. All Rights Reserved. -# -# The contents of this file are subject to the Erlang Public License, -# Version 1.1, (the "License"); you may not use this file except in -# compliance with the License. You should have received a copy of the -# Erlang Public License along with this software. If not, it can be -# retrieved online at http://www.erlang.org/. -# -# Software distributed under the License is distributed on an "AS IS" -# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -# the License for the specific language governing rights and limitations -# under the License. -# -# %CopyrightEnd% -# -# -# Invoke with GNU make or clearmake -C gnu. -# - -include $(ERL_TOP)/make/run_make.mk diff --git a/erts/emulator/zlib/Makefile.in b/erts/emulator/zlib/Makefile.in deleted file mode 100644 index b44a87551d..0000000000 --- a/erts/emulator/zlib/Makefile.in +++ /dev/null @@ -1,102 +0,0 @@ -# Makefile for zlib -# Copyright (C) 1995-1996 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# %ExternalCopyright% - -# To compile and test, type: -# ./configure; make test -# The call of configure is optional if you don't have special requirements - -# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: -# make install -# To install in $HOME instead of /usr/local, use: -# make install prefix=$HOME - -ARFLAGS = rc -CFLAGS = $(subst -O2, -O3, @CFLAGS@ @DEFS@ @EMU_THR_DEFS@) -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-g -DDEBUG -#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -# -Wstrict-prototypes -Wmissing-prototypes - -VER=1.0.4 - -O = adler32.o compress.o crc32.o uncompr.o deflate.o trees.o \ - zutil.o inflate.o inftrees.o inffast.o -OBJS = $(O:%=$(OBJDIR)/%) - - -#### Begin OTP targets - -include $(ERL_TOP)/make/target.mk - -ifeq ($(TYPE),gcov) -CFLAGS = -O0 -fprofile-arcs -ftest-coverage @DEBUG_CFLAGS@ @DEFS@ @EMU_THR_DEFS@ -else # gcov -ifeq ($(TYPE),debug) -CFLAGS = @DEBUG_CFLAGS@ @DEFS@ @EMU_THR_DEFS@ -endif # debug -endif # gcov - -# On windows we *need* a separate zlib during debug build -OBJDIR= $(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE) - -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -ifeq ($(TARGET), win32) -LIBRARY=$(OBJDIR)/z.lib -else -LIBRARY=$(OBJDIR)/libz.a -endif - -all: $(LIBRARY) - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - -tests release_tests: - -docs release_docs release_docs_spec: - -clean: - rm -f $(OBJS) $(OBJDIR)/libz.a - -#### end OTP targets - -ifeq ($(TARGET), win32) -$(LIBRARY): $(OBJS) - $(AR) -out:$@ $(OBJS) -else -$(LIBRARY): $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) - -@ ($(RANLIB) $@ || true) 2>/dev/null -endif - -$(OBJDIR)/%.o: %.c - $(CC) -c $(CFLAGS) -o $@ $< - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -adler32.o: zlib.h zconf.h -compress.o: zlib.h zconf.h -crc32.o: zlib.h zconf.h -deflate.o: deflate.h zutil.h zlib.h zconf.h -example.o: zlib.h zconf.h -gzio.o: zutil.h zlib.h zconf.h -infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h -infcodes.o: zutil.h zlib.h zconf.h -infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h -inffast.o: zutil.h zlib.h zconf.h inftrees.h -inffast.o: infblock.h infcodes.h infutil.h inffast.h -inflate.o: zutil.h zlib.h zconf.h infblock.h -inftrees.o: zutil.h zlib.h zconf.h inftrees.h -infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h -minigzip.o: zlib.h zconf.h -trees.o: deflate.h zutil.h zlib.h zconf.h -uncompr.o: zlib.h zconf.h -zutil.o: zutil.h zlib.h zconf.h diff --git a/erts/emulator/zlib/zlib.mk b/erts/emulator/zlib/zlib.mk new file mode 100644 index 0000000000..fa1f159fae --- /dev/null +++ b/erts/emulator/zlib/zlib.mk @@ -0,0 +1,74 @@ +#-*-makefile-*- ; force emacs to enter makefile-mode +# ---------------------------------------------------- +# Make include file for zlib +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2011-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% +# +# ---------------------------------------------------- +# Copyright for zlib itself see copyright notice in zlib.h + +ZLIB_FILES = \ + adler32 \ + compress \ + crc32 \ + uncompr \ + deflate \ + trees \ + zutil \ + inflate \ + inftrees \ + inffast + +# On windows we *need* a separate zlib during debug build +ZLIB_OBJDIR = $(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE) + +ZLIB_OBJS = $(ZLIB_FILES:%=$(ZLIB_OBJDIR)/%.o) +ZLIB_SRC = $(ZLIB_FILES:%=zlib/%.c) + +ifeq ($(TARGET), win32) +ZLIB_LIBRARY = $(ZLIB_OBJDIR)/z.lib +else +ZLIB_LIBRARY = $(ZLIB_OBJDIR)/libz.a +endif + + +ifeq ($(TYPE),gcov) +ZLIB_CFLAGS = -O0 -fprofile-arcs -ftest-coverage $(DEBUG_CFLAGS) $(DEFS) $(THR_DEFS) +else # gcov +ifeq ($(TYPE),debug) +ZLIB_CFLAGS = $(DEBUG_CFLAGS) $(DEFS) $(THR_DEFS) +else # debug +ZLIB_CFLAGS = $(subst -O2, -O3, $(CONFIGURE_CFLAGS) $(DEFS) $(THR_DEFS)) +#ZLIB_CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#ZLIB_CFLAGS=-g -DDEBUG +#ZLIB_CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes +endif # debug +endif # gcov + +ifeq ($(TARGET), win32) +$(ZLIB_LIBRARY): $(ZLIB_OBJS) + $(AR) -out:$@ $(ZLIB_OBJS) +else +$(ZLIB_LIBRARY): $(ZLIB_OBJS) + $(AR) $(ARFLAGS) $@ $(ZLIB_OBJS) + -@ ($(RANLIB) $@ || true) 2>/dev/null +endif + +$(ZLIB_OBJDIR)/%.o: zlib/%.c + $(CC) -c $(ZLIB_CFLAGS) -o $@ $< diff --git a/erts/epmd/src/Makefile.in b/erts/epmd/src/Makefile.in index 2f5296a5e8..5767edc346 100644 --- a/erts/epmd/src/Makefile.in +++ b/erts/epmd/src/Makefile.in @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1998-2010. All Rights Reserved. +# Copyright Ericsson AB 1998-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 @@ -24,6 +24,7 @@ PURIFY = TYPEMARKER = .debug TYPE_FLAGS = -DDEBUG @DEBUG_FLAGS@ else + ifeq ($(TYPE),purify) PURIFY = purify TYPEMARKER = @@ -33,6 +34,8 @@ else TYPE_FLAGS = -O2 -DPURIFY endif else + +override TYPE = opt PURIFY = TYPEMARKER = ifeq ($(findstring ose,$(TARGET)),ose) @@ -65,6 +68,8 @@ ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPE endif endif +ERTS_LIB = $(ERL_TOP)/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE + CC = @CC@ WFLAGS = @WFLAGS@ CFLAGS = @CFLAGS@ @DEFS@ $(TYPE_FLAGS) $(WFLAGS) $(ERTS_INCL) @@ -106,7 +111,7 @@ EPMD_OBJS = $(OBJDIR)/epmd.o \ #--------------------------------- -all: erts_lib $(BINDIR)/$(EPMD) +all: $(BINDIR)/$(EPMD) docs: @@ -122,13 +127,13 @@ clean: # Objects & executables # -$(BINDIR)/$(EPMD): $(EPMD_OBJS) +$(BINDIR)/$(EPMD): $(EPMD_OBJS) $(ERTS_LIB) $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(EPMD_OBJS) $(LIBS) $(OBJDIR)/%.o: %.c epmd.h epmd_int.h $(CC) $(CFLAGS) $(EPMD_FLAGS) -o $@ -c $< -erts_lib: +$(ERTS_LIB): cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE) include $(ERL_TOP)/make/otp_release_targets.mk @@ -139,4 +144,3 @@ release_spec: all release_docs_spec: - diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in index c3c242b87c..28c5e5ccad 100644 --- a/erts/etc/common/Makefile.in +++ b/erts/etc/common/Makefile.in @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1996-2011. All Rights Reserved. +# Copyright Ericsson AB 1996-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 @@ -29,6 +29,7 @@ PURIFY = TYPEMARKER = .debug TYPE_FLAGS = -DDEBUG @DEBUG_FLAGS@ else + ifeq ($(TYPE),purify) PURIFY = purify TYPEMARKER = @@ -38,6 +39,8 @@ else TYPE_FLAGS = -g -O2 -DPURIFY endif else + +override TYPE=opt PURIFY = TYPEMARKER = ERTS_LIB_TYPEMARKER= @@ -101,6 +104,8 @@ else ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@ -lm endif +ERTS_LIB = $(ERL_TOP)/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE + # ---------------------------------------------------- # Release directory specification # ---------------------------------------------------- @@ -161,9 +166,8 @@ ERLSRV_OBJECTS= \ $(OBJDIR)/erlsrv_main.o \ $(OBJDIR)/erlsrv_util.o \ $(OBJDIR)/erlsrv_logmess.res -MC_OUTPUTS= \ - $(OBJDIR)/erlsrv_logmess.h $(OBJDIR)/erlsrv_logmess.rc - MT_FLAG="-MT" +MC_OUTPUTS=$(OBJDIR)/erlsrv_logmess.h $(OBJDIR)/erlsrv_logmess.rc +MT_FLAG="-MT" else ERLRES_OBJ=erl_res.o ERLSRV_OBJECTS= \ @@ -173,9 +177,8 @@ ERLSRV_OBJECTS= \ $(OBJDIR)/erlsrv_main.o \ $(OBJDIR)/erlsrv_util.o \ $(OBJDIR)/erlsrv_logmess.o -MC_OUTPUTS= \ - $(OBJDIR)/erlsrv_logmess.h $(OBJDIR)/erlsrv_logmess.res - MT_FLAG="-MD" +MC_OUTPUTS=$(OBJDIR)/erlsrv_logmess.h $(OBJDIR)/erlsrv_logmess.res +MT_FLAG="-MD" endif INET_GETHOST = $(BINDIR)/inet_gethost.exe INSTALL_EMBEDDED_PROGS += $(BINDIR)/typer.exe $(BINDIR)/dialyzer.exe $(BINDIR)/erlc.exe $(BINDIR)/start_erl.exe $(BINDIR)/escript.exe $(BINDIR)/ct_run.exe @@ -232,14 +235,17 @@ endif endif endif -etc: erts_lib $(ENTRY_OBJ) $(INSTALL_PROGS) $(INSTALL_LIBS) $(TEXTFILES) $(INSTALL_TOP_BIN) +.PHONY: etc +etc: $(ENTRY_OBJ) $(INSTALL_PROGS) $(INSTALL_LIBS) $(TEXTFILES) $(INSTALL_TOP_BIN) # erlexec needs the erts_internal library... -erts_lib: +$(ERTS_LIB): cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE) +.PHONY: docs docs: +.PHONY: clean clean: ifneq ($(INSTALL_PROGS),) rm -f $(INSTALL_PROGS) @@ -278,85 +284,9 @@ endif rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/vxcall.o rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/erl.o rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/werl.o + rm -f $(TEXTFILES) rm -f *~ core -# -# Objects & executables -# -#$(OBJDIR)/%.o: %.c -# $(CC) $(CFLAGS) -o $@ -c $< -# -#$(OBJDIR)/%.o: ../unix/%.c -# $(CC) $(CFLAGS) -o $@ -c $< -# -#$(BINDIR)/%: $(OBJDIR)/%.o -# $(PURIFY) $(LD) $(LDFLAGS) -o $@ $< $(LIBS) - -$(OBJDIR)/inet_gethost.o: inet_gethost.c - $(CC) $(CFLAGS) -o $@ -c inet_gethost.c - -$(BINDIR)/inet_gethost@EXEEXT@: $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) - $(PURIFY) $(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(LIBS) $(ERTS_INTERNAL_LIBS) - -$(BINDIR)/run_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o - $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(LIBS) - -$(OBJDIR)/run_erl.o: ../unix/run_erl.c - $(CC) $(CFLAGS) -o $@ -c ../unix/run_erl.c - -$(BINDIR)/to_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o - $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o - -$(OBJDIR)/to_erl.o: ../unix/to_erl.c - $(CC) $(CFLAGS) -o $@ -c ../unix/to_erl.c - -$(BINDIR)/dyn_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o - $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o - -$(OBJDIR)/dyn_erl.o: ../unix/dyn_erl.c - $(CC) $(CFLAGS) -o $@ -c ../unix/dyn_erl.c - -$(OBJDIR)/safe_string.o: ../unix/safe_string.c - $(CC) $(CFLAGS) -o $@ -c ../unix/safe_string.c - -ifneq ($(TARGET),win32) -$(BINDIR)/$(ERLEXEC): $(OBJDIR)/$(ERLEXEC).o - $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/$(ERLEXEC).o $(ERTS_INTERNAL_LIBS) - -$(OBJDIR)/$(ERLEXEC).o: $(ERLEXECDIR)/$(ERLEXEC).c - $(CC) -I$(EMUDIR) $(CFLAGS) -o $@ -c $(ERLEXECDIR)/$(ERLEXEC).c -endif -$(BINDIR)/erlc@EXEEXT@: $(OBJDIR)/erlc.o - $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/erlc.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS) - -$(OBJDIR)/erlc.o: erlc.c - $(CC) $(CFLAGS) -o $@ -c erlc.c - -$(BINDIR)/dialyzer@EXEEXT@: $(OBJDIR)/dialyzer.o - $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/dialyzer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS) - -$(OBJDIR)/dialyzer.o: dialyzer.c - $(CC) $(CFLAGS) -o $@ -c dialyzer.c - -$(BINDIR)/typer@EXEEXT@: $(OBJDIR)/typer.o - $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/typer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS) - -$(OBJDIR)/typer.o: typer.c - $(CC) $(CFLAGS) -o $@ -c typer.c - -$(BINDIR)/escript@EXEEXT@: $(OBJDIR)/escript.o - $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/escript.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS) - -$(OBJDIR)/escript.o: escript.c - $(CC) $(CFLAGS) -o $@ -c escript.c - -$(BINDIR)/ct_run@EXEEXT@: $(OBJDIR)/ct_run.o - $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/ct_run.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS) - -$(OBJDIR)/ct_run.o: ct_run.c - $(CC) $(CFLAGS) -o $@ -c ct_run.c - - #------------------------------------------------------------------------ # Windows specific targets # The windows platform is quite different from the others. erl/werl are small C programs @@ -367,7 +297,7 @@ $(OBJDIR)/ct_run.o: ct_run.c ifeq ($(TARGET),win32) -$(BINDIR)/$(ERLEXEC): $(OBJDIR)/erlexec.o $(OBJDIR)/win_erlexec.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ) +$(BINDIR)/$(ERLEXEC): $(OBJDIR)/erlexec.o $(OBJDIR)/win_erlexec.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ) $(ERTS_LIB) $(LD) -dll $(LDFLAGS) -o $@ $(OBJDIR)/erlexec.o $(OBJDIR)/win_erlexec.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ) $(ERTS_INTERNAL_LIBS) $(BINDIR)/erl@EXEEXT@: $(OBJDIR)/erl.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ) @@ -382,58 +312,75 @@ $(BINDIR)/start_erl@EXEEXT@: $(OBJDIR)/start_erl.o $(BINDIR)/Install@EXEEXT@: $(OBJDIR)/Install.o $(OBJDIR)/init_file.o $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/Install.o $(OBJDIR)/init_file.o +# The service expects to be compiled with $(MT_FLAG) flag. $(BINDIR)/erlsrv@EXEEXT@: $(ERLSRV_OBJECTS) $(LD) $(LDFLAGS) $(MT_FLAG) -o $@ $(ERLSRV_OBJECTS) -# The service expects to be compiled with $(MT_FLAG) flag. - -$(OBJDIR)/%.o: $(WINETC)/erlsrv/%.c $(ERLSRV_HEADERS) - $(CC) $(CFLAGS) $(MT_FLAG) -o $@ -c $< - -$(OBJDIR)/erlsrv_util.o: $(WINETC)/erlsrv/erlsrv_util.c $(ERLSRV_HEADERS) \ -$(OBJDIR)/erlsrv_logmess.h - $(CC) $(CFLAGS) -I$(OBJDIR) $(MT_FLAG) -o $@ -c $< +# To fix a spooky parallel make build problem on Windows there are some +# false dependencies on the $(MC), $(RC) and .o rules. The theory behind +# is that the $(MC) and/or $(RC) compilers seems to temporarily create and +# destroy a toplevel file vc100.pdb that simultaneous ordinary compilations +# (that have been by flags explicitly ordered to not use .pdb files) +# gets upset when that file vanishes from under their feet. +# +# The false dependencies are targeted to make make (pun intended) run +# the $(MC) and $(RC) compilations to completion before all others. + +LOGMESS_GENERATED = $(OBJDIR)/LOGMESS-GENERATED +$(MC_OUTPUTS): $(LOGMESS_GENERATED) +$(LOGMESS_GENERATED): $(WINETC)/erlsrv/erlsrv_logmess.mc + $(MC) -o $(OBJDIR) $(WINETC)/erlsrv/erlsrv_logmess.mc && \ + echo $? >$(LOGMESS_GENERATED) + +$(OBJDIR)/$(ERLRES_OBJ): $(WINETC)/erl.rc $(WINETC)/erlang.ico \ + $(WINETC)/erl_icon.ico $(WINETC)/hrl_icon.ico \ + $(WINETC)/beam_icon.ico $(LOGMESS_GENERATED) + $(RC) -o $@ -I$(WINETC) $(WINETC)/erl.rc ifeq ($(USING_VC), yes) -$(OBJDIR)/erlsrv_logmess.res: $(OBJDIR)/erlsrv_logmess.rc +RC_GENERATED = $(OBJDIR)/erlsrv_logmess.res +$(RC_GENERATED): $(OBJDIR)/erlsrv_logmess.rc $(OBJDIR)/$(ERLRES_OBJ) $(RC) -o $(OBJDIR)/erlsrv_logmess.res -I$(OBJDIR) $(OBJDIR)/erlsrv_logmess.rc else -$(OBJDIR)/erlsrv_logmess.o: $(OBJDIR)/erlsrv_logmess.res +RC_GENERATED = $(OBJDIR)/erlsrv_logmess.o +$(RC_GENERATED): $(OBJDIR)/erlsrv_logmess.res $(OBJDIR)/$(ERLRES_OBJ) $(RC) -o $(OBJDIR)/erlsrv_logmess.o -I$(OBJDIR) $(OBJDIR)/erlsrv_logmess.res endif -$(MC_OUTPUTS): $(WINETC)/erlsrv/erlsrv_logmess.mc - $(MC) -o $(OBJDIR) $(WINETC)/erlsrv/erlsrv_logmess.mc +# The service expects to be compiled with $(MT_FLAG) flag. +$(OBJDIR)/%.o: $(WINETC)/erlsrv/%.c $(ERLSRV_HEADERS) $(RC_GENERATED) + $(CC) $(CFLAGS) $(MT_FLAG) -o $@ -c $< -$(OBJDIR)/werl.o: $(WINETC)/erl.c +$(OBJDIR)/erlsrv_util.o: $(WINETC)/erlsrv/erlsrv_util.c $(ERLSRV_HEADERS) \ + $(OBJDIR)/erlsrv_logmess.h $(RC_GENERATED) + $(CC) $(CFLAGS) -I$(OBJDIR) $(MT_FLAG) -o $@ -c $< + +$(OBJDIR)/werl.o: $(WINETC)/erl.c $(WINETC)/init_file.h $(RC_GENERATED) $(CC) $(CFLAGS) -DBUILD_TYPE=\"-$(TYPE)\" -DERL_RUN_SHARED_LIB=1 \ -DWIN32_WERL -o $@ -c $(WINETC)/erl.c -$(OBJDIR)/erl.o: $(WINETC)/erl.c +$(OBJDIR)/erl.o: $(WINETC)/erl.c $(WINETC)/init_file.h $(RC_GENERATED) $(CC) $(CFLAGS) -DBUILD_TYPE=\"-$(TYPE)\" -DERL_RUN_SHARED_LIB=1 \ -o $@ -c $(WINETC)/erl.c -$(OBJDIR)/erlexec.o: $(ERLEXECDIR)/erlexec.c +$(OBJDIR)/erlexec.o: $(ERLEXECDIR)/erlexec.c $(RC_GENERATED) $(CC) $(CFLAGS) -DBUILD_TYPE=\"-$(TYPE)\" -DERL_RUN_SHARED_LIB=1 \ -o $@ -c $(ERLEXECDIR)/erlexec.c -$(OBJDIR)/win_erlexec.o: $(WINETC)/win_erlexec.c +$(OBJDIR)/win_erlexec.o: $(WINETC)/win_erlexec.c $(RC_GENERATED) $(CC) $(CFLAGS) -DBUILD_TYPE=\"-$(TYPE)\" -DERL_RUN_SHARED_LIB=1 \ -o $@ -c $(WINETC)/win_erlexec.c -$(OBJDIR)/init_file.o: $(WINETC)/init_file.c $(WINETC)/init_file.h +$(OBJDIR)/init_file.o: $(WINETC)/init_file.c $(WINETC)/init_file.h $(RC_GENERATED) $(CC) $(CFLAGS) -o $@ -c $(WINETC)/init_file.c -$(OBJDIR)/Install.o: $(WINETC)/Install.c $(WINETC)/init_file.h +$(OBJDIR)/Install.o: $(WINETC)/Install.c $(WINETC)/init_file.h $(RC_GENERATED) $(CC) $(CFLAGS) -o $@ -c $(WINETC)/Install.c -$(OBJDIR)/$(ERLRES_OBJ): $(WINETC)/erl.rc $(WINETC)/erlang.ico $(WINETC)/erl_icon.ico $(WINETC)/hrl_icon.ico $(WINETC)/beam_icon.ico - $(RC) -o $@ -I$(WINETC) $(WINETC)/erl.rc - -$(OBJDIR)/start_erl.o: $(WINETC)/start_erl.c +$(OBJDIR)/start_erl.o: $(WINETC)/start_erl.c $(RC_GENERATED) $(CC) $(CFLAGS) -o $@ -c $(WINETC)/start_erl.c -$(ENTRY_OBJ): $(ENTRY_SRC) +$(ENTRY_OBJ): $(ENTRY_SRC) $(RC_GENERATED) $(CC) $(CFLAGS) -o $@ -c $(ENTRY_SRC) Install.ini: ../$(TARGET)/Install.src ../../vsn.mk $(TARGET)/Makefile @@ -442,6 +389,8 @@ Install.ini: ../$(TARGET)/Install.src ../../vsn.mk $(TARGET)/Makefile ../$(TARGET)/Install.src > Install.ini +else +RC_GENERATED = endif #--------------------------------------------------------- # End of windows specific targets. @@ -469,7 +418,7 @@ $(BINDIR)/heart@EXEEXT@: $(OBJDIR)/heart.o $(ENTRY_OBJ) $(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/heart.o \ $(ENTRY_OBJ) $(WINDSOCK) -$(OBJDIR)/heart.o: heart.c +$(OBJDIR)/heart.o: heart.c $(RC_GENERATED) $(CC) $(CFLAGS) -o $@ -c heart.c endif @@ -497,6 +446,84 @@ $(OBJDIR)/vxcall.o: $(VXETC)/vxcall.c +# +# Objects & executables +# +#$(OBJDIR)/%.o: %.c +# $(CC) $(CFLAGS) -o $@ -c $< +# +#$(OBJDIR)/%.o: ../unix/%.c +# $(CC) $(CFLAGS) -o $@ -c $< +# +#$(BINDIR)/%: $(OBJDIR)/%.o +# $(PURIFY) $(LD) $(LDFLAGS) -o $@ $< $(LIBS) + +$(OBJDIR)/inet_gethost.o: inet_gethost.c $(RC_GENERATED) + $(CC) $(CFLAGS) -o $@ -c inet_gethost.c + +$(BINDIR)/inet_gethost@EXEEXT@: $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(ERTS_LIB) + $(PURIFY) $(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(LIBS) $(ERTS_INTERNAL_LIBS) + +$(BINDIR)/run_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o + $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(LIBS) + +$(OBJDIR)/run_erl.o: ../unix/run_erl.c $(RC_GENERATED) + $(CC) $(CFLAGS) -o $@ -c ../unix/run_erl.c + +$(BINDIR)/to_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o + $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o + +$(OBJDIR)/to_erl.o: ../unix/to_erl.c $(RC_GENERATED) + $(CC) $(CFLAGS) -o $@ -c ../unix/to_erl.c + +$(BINDIR)/dyn_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o + $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o + +$(OBJDIR)/dyn_erl.o: ../unix/dyn_erl.c $(RC_GENERATED) + $(CC) $(CFLAGS) -o $@ -c ../unix/dyn_erl.c + +$(OBJDIR)/safe_string.o: ../unix/safe_string.c $(RC_GENERATED) + $(CC) $(CFLAGS) -o $@ -c ../unix/safe_string.c + +ifneq ($(TARGET),win32) +$(BINDIR)/$(ERLEXEC): $(OBJDIR)/$(ERLEXEC).o $(ERTS_LIB) + $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/$(ERLEXEC).o $(ERTS_INTERNAL_LIBS) + +$(OBJDIR)/$(ERLEXEC).o: $(ERLEXECDIR)/$(ERLEXEC).c $(RC_GENERATED) + $(CC) -I$(EMUDIR) $(CFLAGS) -o $@ -c $(ERLEXECDIR)/$(ERLEXEC).c +endif +$(BINDIR)/erlc@EXEEXT@: $(OBJDIR)/erlc.o $(ERTS_LIB) + $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/erlc.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS) + +$(OBJDIR)/erlc.o: erlc.c $(RC_GENERATED) + $(CC) $(CFLAGS) -o $@ -c erlc.c + +$(BINDIR)/dialyzer@EXEEXT@: $(OBJDIR)/dialyzer.o $(ERTS_LIB) + $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/dialyzer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS) + +$(OBJDIR)/dialyzer.o: dialyzer.c $(RC_GENERATED) + $(CC) $(CFLAGS) -o $@ -c dialyzer.c + +$(BINDIR)/typer@EXEEXT@: $(OBJDIR)/typer.o $(ERTS_LIB) + $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/typer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS) + +$(OBJDIR)/typer.o: typer.c $(RC_GENERATED) + $(CC) $(CFLAGS) -o $@ -c typer.c + +$(BINDIR)/escript@EXEEXT@: $(OBJDIR)/escript.o $(ERTS_LIB) + $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/escript.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS) + +$(OBJDIR)/escript.o: escript.c $(RC_GENERATED) + $(CC) $(CFLAGS) -o $@ -c escript.c + +$(BINDIR)/ct_run@EXEEXT@: $(OBJDIR)/ct_run.o $(ERTS_LIB) + $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/ct_run.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS) + +$(OBJDIR)/ct_run.o: ct_run.c $(RC_GENERATED) + $(CC) $(CFLAGS) -o $@ -c ct_run.c + + + Install: ../unix/Install.src ../../vsn.mk $(TARGET)/Makefile sed -e 's;%I_VSN%;$(VSN);' \ -e 's;%EMULATOR%;$(EMULATOR);' \ @@ -515,6 +542,7 @@ erl.src: ../unix/erl.src.src ../../vsn.mk $(TARGET)/Makefile # ---------------------------------------------------- include $(ERL_TOP)/make/otp_release_targets.mk +.PHONY: release_spec release_spec: etc ifneq ($(INSTALL_OBJS),) $(INSTALL_DIR) $(RELEASE_PATH)/erts-$(VSN)/obj @@ -561,9 +589,5 @@ ifneq ($(INSTALL_INCLUDES),) $(INSTALL_DATA) $(INSTALL_INCLUDES) $(RELEASE_PATH)/erts-$(VSN)/include endif +.PHONY: release_docs_spec release_docs_spec: - - - - - diff --git a/erts/lib_src/Makefile.in b/erts/lib_src/Makefile.in index 54ee7410fd..ea80e74100 100644 --- a/erts/lib_src/Makefile.in +++ b/erts/lib_src/Makefile.in @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2011. All Rights Reserved. +# Copyright Ericsson AB 2004-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 @@ -318,10 +318,14 @@ ETHREAD_LIB= endif +_create_dirs := $(shell mkdir -p $(CREATE_DIRS)) # # Everything to build # -all: $(CREATE_DIRS) $(ETHREAD_LIB) $(ERTS_LIBS) $(ERTS_INTERNAL_LIBS) +.PHONY: all +all: $(OBJ_DIR)/MADE + +$(OBJ_DIR)/MADE: $(ETHREAD_LIB) $(ERTS_LIBS) $(ERTS_INTERNAL_LIBS) ifeq ($(OMIT_OMIT_FP),yes) @echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *' @echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *' @@ -331,6 +335,8 @@ ifeq ($(OMIT_OMIT_FP),yes) @echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *' @echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *' endif + echo $? > $(OBJ_DIR)/MADE + # # The libs ... # @@ -428,13 +434,6 @@ $(MTd_OBJ_DIR)/%.o: $(ETHR_THR_LIB_BASE_DIR)/%.c $(CC) $(THR_DEFS) $(CFLAGS) -MTd $(INCLUDES) -c $< -o $@ # -# Create directories -# - -$(CREATE_DIRS): - $(MKDIR) -p $@ - -# # Install # @@ -471,6 +470,7 @@ INTERNAL_RELEASE_LIBS= \ $(ETHREAD_LIB) \ $(ERTS_INTERNAL_LIBS) +.PHONY: release_spec release_spec: all ifneq ($(strip $(RELEASE_INCLUDES)),) $(INSTALL_DIR) $(RELSYSDIR)/include @@ -500,19 +500,20 @@ ifneq ($(strip $(INTERNAL_RELEASE_LIBS)),) $(INSTALL_DATA) $(INTERNAL_RELEASE_LIBS) $(RELSYSDIR)/lib/internal endif +.PHONY: docs docs: +.PHONY: release_docs_spec release_docs_spec: - # # Cleanup # +.PHONY: clean clean: $(RM) -rf ../lib/internal/$(TARGET)/* $(RM) -rf ../lib/$(TARGET)/* $(RM) -rf obj/$(TARGET)/* - $(RM) -f $(TARGET)/depend.mk # # Make dependencies @@ -554,9 +555,11 @@ SED_MDd_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_MDd_O);$(SED_REPL_TT_DIR);$(SED_REPL SED_MT_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_MT_O);$(SED_REPL_TT_DIR);$(SED_REPL_TARGET)' SED_MTd_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_MTd_O);$(SED_REPL_TT_DIR);$(SED_REPL_TARGET)' -DEPEND_MK=$(TARGET)/depend.mk +DEPEND_MK=$(OBJ_DIR)/depend.mk -depend: +.PHONY: depend +depend: $(DEPEND_MK) +$(DEPEND_MK): @echo "Generating dependency file $(DEPEND_MK)..." @echo "# Generated dependency rules" > $(DEPEND_MK); @echo "# " >> $(DEPEND_MK); @@ -629,6 +632,8 @@ endif endif @echo "# EOF" >> $(DEPEND_MK); +ifneq ($(MAKECMDGOALS),clean) -include $(DEPEND_MK) +endif # eof diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex 9e369d5348..b78747bc84 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 4affc9bffe..4cbff3f36e 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -43,6 +43,9 @@ -export([memory/0, memory/1]). -export([alloc_info/1, alloc_sizes/1]). +-export([gather_sched_wall_time_result/1, + await_sched_wall_time_modifications/2]). + -deprecated([hash/2]). % Get rid of autoimports of spawn to avoid clashes with ourselves. @@ -1202,3 +1205,34 @@ receive_allocator(Ref, N, Acc) -> {Ref, _, InfoList} -> receive_allocator(Ref, N-1, insert_info(InfoList, Acc)) end. + +-spec await_sched_wall_time_modifications(Ref, Result) -> boolean() when + Ref :: reference(), + Result :: boolean(). + +await_sched_wall_time_modifications(Ref, Result) -> + sched_wall_time(Ref, erlang:system_info(schedulers)), + Result. + +-spec gather_sched_wall_time_result(Ref) -> [{pos_integer(), + non_neg_integer(), + non_neg_integer()}] when + Ref :: reference(). + +gather_sched_wall_time_result(Ref) when is_reference(Ref) -> + sched_wall_time(Ref, erlang:system_info(schedulers), []). + +sched_wall_time(_Ref, 0) -> + ok; +sched_wall_time(Ref, N) -> + receive Ref -> sched_wall_time(Ref, N-1) end. + +sched_wall_time(_Ref, 0, Acc) -> + Acc; +sched_wall_time(Ref, N, undefined) -> + receive {Ref, _} -> sched_wall_time(Ref, N-1, undefined) end; +sched_wall_time(Ref, N, Acc) -> + receive + {Ref, undefined} -> sched_wall_time(Ref, N-1, undefined); + {Ref, SWT} -> sched_wall_time(Ref, N-1, [SWT|Acc]) + end. diff --git a/erts/vsn.mk b/erts/vsn.mk index 053c0e9f52..bbf77b1a68 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2011. All Rights Reserved. +# 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 |