diff options
Diffstat (limited to 'erts')
66 files changed, 833 insertions, 1164 deletions
diff --git a/erts/configure.in b/erts/configure.in index 7257751068..b9c9a76ef6 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -1082,8 +1082,26 @@ fi AC_SUBST(ERTS_BUILD_SMP_EMU) -AC_CHECK_FUNCS([posix_fadvise, fallocate]) +AC_CHECK_FUNCS([posix_fadvise]) AC_CHECK_HEADERS([linux/falloc.h]) +dnl * Old glibcs have broken fallocate64(). Make sure not to use it. +AC_CACHE_CHECK([whether fallocate() works],i_cv_fallocate_works,[ + AC_TRY_LINK([ + #include <stdio.h> + #include <stdlib.h> + #include <fcntl.h> + #include <unistd.h> + #include <fcntl.h> + #include <linux/falloc.h> + ], + [ + int fd = creat("conftest.temp", 0600); + fallocate(fd, FALLOC_FL_KEEP_SIZE,(off_t) 1024,(off_t) 1024); + ], i_cv_fallocate_works=yes, i_cv_fallocate_works=no) +]) +if test $i_cv_fallocate_works = yes; then + AC_DEFINE(HAVE_FALLOCATE, 1, Define if you have a working fallocate()) +fi dnl * Old glibcs have broken posix_fallocate(). Make sure not to use it. dnl * It may also be broken in AIX. @@ -1324,6 +1342,17 @@ if test "x$TERMCAP_LIB" != "x"; then AC_DEFINE(HAVE_TERMCAP, 1, [Define if termcap functions exists]) fi +if test "X$host" != "Xwin32"; then + AC_MSG_CHECKING(for wcwidth) + AC_TRY_LINK([#include <wchar.h>], [wcwidth(0);], + have_wcwidth=yes, have_wcwidth=no) + if test $have_wcwidth = yes; then + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_WCWIDTH, [1], + [Define to 1 if you have a `wcwidth' function.]) + fi +fi + dnl ------------- dnl zlib dnl ------------- @@ -3558,10 +3587,7 @@ DED_EXT=so case $host_os in win32) DED_EXT=dll;; darwin*) - DED_CFLAGS="$DED_CFLAGS -fno-common" - if test "X$STATIC_CFLAGS" = "X"; then - STATIC_CFLAGS="-mdynamic-no-pic" - fi;; + DED_CFLAGS="$DED_CFLAGS -fno-common";; *) ;; esac diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index bb81330fec..a68e62d051 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -536,15 +536,35 @@ <tag><marker id="file_name_encoding"></marker><c><![CDATA[+fnl]]></c></tag> <item> <p>The VM works with file names as if they are encoded using the ISO-latin-1 encoding, disallowing Unicode characters with codepoints beyond 255. This is default on operating systems that have transparent file naming, i.e. all Unixes except MacOSX.</p> + <p>See <seealso marker="stdlib:unicode_usage#unicode_file_names">STDLIB User's Guide</seealso> for more infomation about unicode file names.</p> </item> - <tag><c><![CDATA[+fnu]]></c></tag> + <tag><c><![CDATA[+fnu[{w|i|e}]]]></c></tag> <item> <p>The VM works with file names as if they are encoded using UTF-8 (or some other system specific Unicode encoding). This is the default on operating systems that enforce Unicode encoding, i.e. Windows and MacOSX.</p> - <p>By enabling Unicode file name translation on systems where this is not default, you open up to the possibility that some file names can not be interpreted by the VM and therefore will be returned to the program as raw binaries. The option is therefore considered experimental.</p> - </item> - <tag><c><![CDATA[+fna]]></c></tag> - <item> - <p>Selection between <c>+fnl</c> and <c>+fnu</c> is done based on the current locale settings in the OS, meaning that if you have set your terminal for UTF-8 encoding, the filesystem is expected to use the same encoding for filenames (use with care).</p> + <p>The <c>+fnu</c> switch can be followed by <c>w</c>, + <c>i</c>, or <c>e</c> to control the way wrongly encoded file + names are to be reported. <c>w</c> means that a warning is + sent to the <c>error_logger</c> whenever a wrongly encoded + file name is "skipped" in directory listings, <c>i</c> means + that those wrongly encoded file names are silently ignored and + <c>e</c> means that the API function will return an error + whenever a wrongly encoded file (or directory) name is + encountered. <c>w</c> is the default. Note that + <c>file:read_link/1</c> will always return an error if the + link points to an invalid file name.</p> + <p>See <seealso marker="stdlib:unicode_usage#unicode_file_names">STDLIB User's Guide</seealso> for more infomation about unicode file names.</p> + </item> + <tag><c><![CDATA[+fna[{w|i|e}]]]></c></tag> + <item> + <p>Selection between <c>+fnl</c> and <c>+fnu</c> is done based on the current locale settings in the OS, meaning that if you have set your terminal for UTF-8 encoding, the filesystem is expected to use the same encoding for file names (use with care).</p> + <p>The <c>+fna</c> switch can be followed by <c>w</c>, + <c>i</c>, or <c>e</c>. This will have effect if the locale + settings cause the behavior of <c>+fnu</c> to be selected. + See the description of <c>+fnu</c> above. If the locale + settings cause the behavior of <c>+fnl</c> to be selected, + then <c>w</c>, <c>i</c>, or <c>e</c> will not have any + effect.</p> + <p>See <seealso marker="stdlib:unicode_usage#unicode_file_names">STDLIB User's Guide</seealso> for more infomation about unicode file names.</p> </item> <tag><c><![CDATA[+hms Size]]></c></tag> <item> @@ -571,9 +591,9 @@ </item> <tag><c><![CDATA[+L]]></c></tag> <item> - <p>Don't load information about source filenames and line numbers. + <p>Don't load information about source file names and line numbers. This will save some memory, but exceptions will not contain - information about the filenames and line numbers. + information about the file names and line numbers. </p> </item> <tag><marker id="erts_alloc"><c><![CDATA[+MFlag Value]]></c></marker></tag> @@ -615,7 +635,7 @@ debugging.</item> </taglist> </item> - <tag><marker id="+pc"/><marker id="max_processes"><c><![CDATA[+pc Range]]></c></marker></tag> + <tag><marker id="+pc"/><marker id="printable_character_range"><c><![CDATA[+pc Range]]></c></marker></tag> <item> <p>Sets the range of characters that the system will consider printable in heuristic detection of strings. This typically affects the shell, debugger and io:format functions (when ~tp is used in the format string).</p> <p>Currently two values for the <c>Range</c> are supported: @@ -1009,6 +1029,20 @@ documentation of the <seealso marker="#+sbt">+sbt</seealso> flag. </p> </item> + <tag><marker id="+swct"><c>+sws very_eager|eager|medium|lazy|very_lazy</c></marker></tag> + <item> + <p> + Set scheduler wake cleanup threshold. Default is <c>medium</c>. + This flag controls how eager schedulers should be requesting + wake up due to certain cleanup operations. When a lazy setting + is used, more outstanding cleanup operations can be left undone + while a scheduler is idling. When an eager setting is used, + schedulers will more frequently be woken, potentially increasing + CPU-utilization. + </p> + <p><em>NOTE:</em> This flag may be removed or changed at any time without prior notice. + </p> + </item> <tag><marker id="+sws"><c>+sws default|legacy</c></marker></tag> <item> <p> diff --git a/erts/doc/src/erl_ext_fig.ps b/erts/doc/src/erl_ext_fig.ps deleted file mode 100644 index 2501dc3c05..0000000000 --- a/erts/doc/src/erl_ext_fig.ps +++ /dev/null @@ -1,153 +0,0 @@ -%!PS-Adobe-3.0 EPSF-2.0 -%%BoundingBox: 0 0 600 520 -%%Creator: mscgen 1 -%%EndComments -0.70 0.70 scale -0 0 moveto -0 520 lineto -600 520 lineto -600 0 lineto -closepath -clip -%PageTrailer -%Page: 1 1 -/Helvetica findfont -10 scalefont -setfont -0 520 translate -/mtrx matrix def -/ellipse - { /endangle exch def - /startangle exch def - /ydia exch def - /xdia exch def - /y exch def - /x exch def - /savematrix mtrx currentmatrix def - x y translate - xdia 2 div ydia 2 div scale - 0 0 1 startangle endangle arc - savematrix setmatrix -} def -150 -12 moveto (Client (or Node)) dup stringwidth pop 2 div neg 0 rmoveto show -450 -12 moveto (EPMD) dup stringwidth pop 2 div neg 0 rmoveto show -newpath 150 -20 moveto 150 -45 lineto stroke -newpath 450 -20 moveto 450 -45 lineto stroke -newpath 150 -32 moveto 450 -32 lineto stroke -newpath 450 -32 moveto 440 -38 lineto 440 -26 lineto closepath fill -270 -30 moveto (ALIVE2_REQ) show -newpath 150 -45 moveto 150 -70 lineto stroke -newpath 450 -45 moveto 450 -70 lineto stroke -[2] 0 setdash -newpath 450 -57 moveto 150 -57 lineto stroke -[] 0 setdash -newpath 150 -57 moveto 160 -63 lineto 160 -51 lineto closepath fill -267 -55 moveto (ALIVE2_RESP) show -[2] 0 setdash -newpath 150 -70 moveto 150 -95 lineto stroke -[] 0 setdash -[2] 0 setdash -newpath 450 -70 moveto 450 -95 lineto stroke -[] 0 setdash -newpath 150 -95 moveto 150 -120 lineto stroke -newpath 450 -95 moveto 450 -120 lineto stroke -newpath 150 -107 moveto 450 -107 lineto stroke -newpath 450 -107 moveto 440 -113 lineto 440 -101 lineto closepath fill -253 -105 moveto (ALIVE_CLOSE_REQ) show -[2] 0 setdash -newpath 150 -120 moveto 150 -145 lineto stroke -[] 0 setdash -[2] 0 setdash -newpath 450 -120 moveto 450 -145 lineto stroke -[] 0 setdash -newpath 150 -145 moveto 150 -170 lineto stroke -newpath 450 -145 moveto 450 -170 lineto stroke -newpath 150 -157 moveto 450 -157 lineto stroke -newpath 450 -157 moveto 440 -163 lineto 440 -151 lineto closepath fill -248 -155 moveto (PORT_PLEASE2_REQ) show -newpath 150 -170 moveto 150 -195 lineto stroke -newpath 450 -170 moveto 450 -195 lineto stroke -[2] 0 setdash -newpath 450 -182 moveto 150 -182 lineto stroke -[] 0 setdash -newpath 150 -182 moveto 160 -188 lineto 160 -176 lineto closepath fill -267 -180 moveto (PORT2_RESP) show -[2] 0 setdash -newpath 150 -195 moveto 150 -220 lineto stroke -[] 0 setdash -[2] 0 setdash -newpath 450 -195 moveto 450 -220 lineto stroke -[] 0 setdash -newpath 150 -220 moveto 150 -245 lineto stroke -newpath 450 -220 moveto 450 -245 lineto stroke -newpath 150 -232 moveto 450 -232 lineto stroke -newpath 450 -232 moveto 440 -238 lineto 440 -226 lineto closepath fill -269 -230 moveto (NAMES_REQ) show -newpath 150 -245 moveto 150 -270 lineto stroke -newpath 450 -245 moveto 450 -270 lineto stroke -[2] 0 setdash -newpath 450 -257 moveto 150 -257 lineto stroke -[] 0 setdash -newpath 150 -257 moveto 160 -263 lineto 160 -251 lineto closepath fill -266 -255 moveto (NAMES_RESP) show -[2] 0 setdash -newpath 150 -270 moveto 150 -295 lineto stroke -[] 0 setdash -[2] 0 setdash -newpath 450 -270 moveto 450 -295 lineto stroke -[] 0 setdash -newpath 150 -295 moveto 150 -320 lineto stroke -newpath 450 -295 moveto 450 -320 lineto stroke -newpath 150 -307 moveto 450 -307 lineto stroke -newpath 450 -307 moveto 440 -313 lineto 440 -301 lineto closepath fill -272 -305 moveto (DUMP_REQ) show -newpath 150 -320 moveto 150 -345 lineto stroke -newpath 450 -320 moveto 450 -345 lineto stroke -[2] 0 setdash -newpath 450 -332 moveto 150 -332 lineto stroke -[] 0 setdash -newpath 150 -332 moveto 160 -338 lineto 160 -326 lineto closepath fill -269 -330 moveto (DUMP_RESP) show -[2] 0 setdash -newpath 150 -345 moveto 150 -370 lineto stroke -[] 0 setdash -[2] 0 setdash -newpath 450 -345 moveto 450 -370 lineto stroke -[] 0 setdash -newpath 150 -370 moveto 150 -395 lineto stroke -newpath 450 -370 moveto 450 -395 lineto stroke -newpath 150 -382 moveto 450 -382 lineto stroke -newpath 450 -382 moveto 440 -388 lineto 440 -376 lineto closepath fill -277 -380 moveto (KILL_REQ) show -newpath 150 -395 moveto 150 -420 lineto stroke -newpath 450 -395 moveto 450 -420 lineto stroke -[2] 0 setdash -newpath 450 -407 moveto 150 -407 lineto stroke -[] 0 setdash -newpath 150 -407 moveto 160 -413 lineto 160 -401 lineto closepath fill -274 -405 moveto (KILL_RESP) show -[2] 0 setdash -newpath 150 -420 moveto 150 -445 lineto stroke -[] 0 setdash -[2] 0 setdash -newpath 450 -420 moveto 450 -445 lineto stroke -[] 0 setdash -newpath 150 -445 moveto 150 -470 lineto stroke -newpath 450 -445 moveto 450 -470 lineto stroke -newpath 150 -457 moveto 450 -457 lineto stroke -newpath 450 -457 moveto 440 -463 lineto 440 -451 lineto closepath fill -273 -455 moveto (STOP_REQ) show -newpath 150 -470 moveto 150 -495 lineto stroke -newpath 450 -470 moveto 450 -495 lineto stroke -[2] 0 setdash -newpath 450 -482 moveto 150 -482 lineto stroke -[] 0 setdash -newpath 150 -482 moveto 160 -488 lineto 160 -476 lineto closepath fill -260 -480 moveto (STOP_OK_RESP) show -newpath 150 -495 moveto 150 -520 lineto stroke -newpath 450 -495 moveto 450 -520 lineto stroke -[2] 0 setdash -newpath 450 -507 moveto 150 -507 lineto stroke -[] 0 setdash -newpath 150 -507 moveto 160 -513 lineto 160 -501 lineto closepath fill -250 -505 moveto (STOP_NOTOK_RESP) show diff --git a/erts/doc/src/erl_fix_alloc.ps b/erts/doc/src/erl_fix_alloc.ps deleted file mode 100644 index bf65d1556c..0000000000 --- a/erts/doc/src/erl_fix_alloc.ps +++ /dev/null @@ -1,646 +0,0 @@ -%!PS-Adobe-2.0 EPSF-2.0 -%%Title: erl_fix_alloc.fig -%%Creator: fig2dev Version 3.1 Patchlevel 2 -%%CreationDate: Tue May 20 11:10:33 1997 -%%For: jocke@akvavit (Joakim Greben|,ETX/B/DUP) -%Magnification: 1.00 -%%Orientation: Portrait -%%BoundingBox: 0 0 506 462 -%%Pages: 0 -%%BeginSetup -%%IncludeFeature: *PageSize A4 -%%EndSetup -%%EndComments -/MyAppDict 100 dict dup begin def -/$F2psDict 200 dict def -$F2psDict begin -$F2psDict /mtrx matrix put -/col-1 {0 setgray} bind def -/col0 {0.000 0.000 0.000 srgb} bind def -/col1 {0.000 0.000 1.000 srgb} bind def -/col2 {0.000 1.000 0.000 srgb} bind def -/col3 {0.000 1.000 1.000 srgb} bind def -/col4 {1.000 0.000 0.000 srgb} bind def -/col5 {1.000 0.000 1.000 srgb} bind def -/col6 {1.000 1.000 0.000 srgb} bind def -/col7 {1.000 1.000 1.000 srgb} bind def -/col8 {0.000 0.000 0.560 srgb} bind def -/col9 {0.000 0.000 0.690 srgb} bind def -/col10 {0.000 0.000 0.820 srgb} bind def -/col11 {0.530 0.810 1.000 srgb} bind def -/col12 {0.000 0.560 0.000 srgb} bind def -/col13 {0.000 0.690 0.000 srgb} bind def -/col14 {0.000 0.820 0.000 srgb} bind def -/col15 {0.000 0.560 0.560 srgb} bind def -/col16 {0.000 0.690 0.690 srgb} bind def -/col17 {0.000 0.820 0.820 srgb} bind def -/col18 {0.560 0.000 0.000 srgb} bind def -/col19 {0.690 0.000 0.000 srgb} bind def -/col20 {0.820 0.000 0.000 srgb} bind def -/col21 {0.560 0.000 0.560 srgb} bind def -/col22 {0.690 0.000 0.690 srgb} bind def -/col23 {0.820 0.000 0.820 srgb} bind def -/col24 {0.500 0.190 0.000 srgb} bind def -/col25 {0.630 0.250 0.000 srgb} bind def -/col26 {0.750 0.380 0.000 srgb} bind def -/col27 {1.000 0.500 0.500 srgb} bind def -/col28 {1.000 0.630 0.630 srgb} bind def -/col29 {1.000 0.750 0.750 srgb} bind def -/col30 {1.000 0.880 0.880 srgb} bind def -/col31 {1.000 0.840 0.000 srgb} bind def - -end -save --18.0 481.0 translate -1 -1 scale -.9 .9 scale % to make patterns same scale as in xfig - -% This junk string is used by the show operators -/PATsstr 1 string def -/PATawidthshow { % cx cy cchar rx ry string - % Loop over each character in the string - { % cx cy cchar rx ry char - % Show the character - dup % cx cy cchar rx ry char char - PATsstr dup 0 4 -1 roll put % cx cy cchar rx ry char (char) - false charpath % cx cy cchar rx ry char - /clip load PATdraw - % Move past the character (charpath modified the - % current point) - currentpoint % cx cy cchar rx ry char x y - newpath - moveto % cx cy cchar rx ry char - % Reposition by cx,cy if the character in the string is cchar - 3 index eq { % cx cy cchar rx ry - 4 index 4 index rmoveto - } if - % Reposition all characters by rx ry - 2 copy rmoveto % cx cy cchar rx ry - } forall - pop pop pop pop pop % - - currentpoint - newpath - moveto -} bind def -/PATcg { - 7 dict dup begin - /lw currentlinewidth def - /lc currentlinecap def - /lj currentlinejoin def - /ml currentmiterlimit def - /ds [ currentdash ] def - /cc [ currentrgbcolor ] def - /cm matrix currentmatrix def - end -} bind def -% PATdraw - calculates the boundaries of the object and -% fills it with the current pattern -/PATdraw { % proc - save exch - PATpcalc % proc nw nh px py - 5 -1 roll exec % nw nh px py - newpath - PATfill % - - restore -} bind def -% PATfill - performs the tiling for the shape -/PATfill { % nw nh px py PATfill - - PATDict /CurrentPattern get dup begin - setfont - % Set the coordinate system to Pattern Space - PatternGState PATsg - % Set the color for uncolored pattezns - PaintType 2 eq { PATDict /PColor get PATsc } if - % Create the string for showing - 3 index string % nw nh px py str - % Loop for each of the pattern sources - 0 1 Multi 1 sub { % nw nh px py str source - % Move to the starting location - 3 index 3 index % nw nh px py str source px py - moveto % nw nh px py str source - % For multiple sources, set the appropriate color - Multi 1 ne { dup PC exch get PATsc } if - % Set the appropriate string for the source - 0 1 7 index 1 sub { 2 index exch 2 index put } for pop - % Loop over the number of vertical cells - 3 index % nw nh px py str nh - { % nw nh px py str - currentpoint % nw nh px py str cx cy - 2 index show % nw nh px py str cx cy - YStep add moveto % nw nh px py str - } repeat % nw nh px py str - } for - 5 { pop } repeat - end -} bind def - -% PATkshow - kshow with the current pattezn -/PATkshow { % proc string - exch bind % string proc - 1 index 0 get % string proc char - % Loop over all but the last character in the string - 0 1 4 index length 2 sub { - % string proc char idx - % Find the n+1th character in the string - 3 index exch 1 add get % string proe char char+1 - exch 2 copy % strinq proc char+1 char char+1 char - % Now show the nth character - PATsstr dup 0 4 -1 roll put % string proc chr+1 chr chr+1 (chr) - false charpath % string proc char+1 char char+1 - /clip load PATdraw - % Move past the character (charpath modified the current point) - currentpoint newpath moveto - % Execute the user proc (should consume char and char+1) - mark 3 1 roll % string proc char+1 mark char char+1 - 4 index exec % string proc char+1 mark... - cleartomark % string proc char+1 - } for - % Now display the last character - PATsstr dup 0 4 -1 roll put % string proc (char+1) - false charpath % string proc - /clip load PATdraw - neewath - pop pop % - -} bind def -% PATmp - the makepattern equivalent -/PATmp { % patdict patmtx PATmp patinstance - exch dup length 7 add % We will add 6 new entries plus 1 FID - dict copy % Create a new dictionary - begin - % Matrix to install when painting the pattern - TilingType PATtcalc - /PatternGState PATcg def - PatternGState /cm 3 -1 roll put - % Check for multi pattern sources (Level 1 fast color patterns) - currentdict /Multi known not { /Multi 1 def } if - % Font dictionary definitions - /FontType 3 def - % Create a dummy encoding vector - /Encoding 256 array def - 3 string 0 1 255 { - Encoding exch dup 3 index cvs cvn put } for pop - /FontMatrix matrix def - /FontBBox BBox def - /BuildChar { - mark 3 1 roll % mark dict char - exch begin - Multi 1 ne {PaintData exch get}{pop} ifelse % mark [paintdata] - PaintType 2 eq Multi 1 ne or - { XStep 0 FontBBox aload pop setcachedevice } - { XStep 0 setcharwidth } ifelse - currentdict % mark [paintdata] dict - /PaintProc load % mark [paintdata] dict paintproc - end - gsave - false PATredef exec true PATredef - grestore - cleartomark % - - } bind def - currentdict - end % newdict - /foo exch % /foo newlict - definefont % newfont -} bind def -% PATpcalc - calculates the starting point and width/height -% of the tile fill for the shape -/PATpcalc { % - PATpcalc nw nh px py - PATDict /CurrentPattern get begin - gsave - % Set up the coordinate system to Pattern Space - % and lock down pattern - PatternGState /cm get setmatrix - BBox aload pop pop pop translate - % Determine the bounding box of the shape - pathbbox % llx lly urx ury - grestore - % Determine (nw, nh) the # of cells to paint width and height - PatHeight div ceiling % llx lly urx qh - 4 1 roll % qh llx lly urx - PatWidth div ceiling % qh llx lly qw - 4 1 roll % qw qh llx lly - PatHeight div floor % qw qh llx ph - 4 1 roll % ph qw qh llx - PatWidth div floor % ph qw qh pw - 4 1 roll % pw ph qw qh - 2 index sub cvi abs % pw ph qs qh-ph - exch 3 index sub cvi abs exch % pw ph nw=qw-pw nh=qh-ph - % Determine the starting point of the pattern fill - %(px, py) - 4 2 roll % nw nh pw ph - PatHeight mul % nw nh pw py - exch % nw nh py pw - PatWidth mul exch % nw nh px py - end -} bind def - -% Save the original routines so that we can use them later on -/oldfill /fill load def -/oldeofill /eofill load def -/oldstroke /stroke load def -/oldshow /show load def -/oldashow /ashow load def -/oldwidthshow /widthshow load def -/oldawidthshow /awidthshow load def -/oldkshow /kshow load def - -% These defs are necessary so that subsequent procs don't bind in -% the originals -/fill { oldfill } bind def -/eofill { oldeofill } bind def -/stroke { oldstroke } bind def -/show { oldshow } bind def -/ashow { oldashow } bind def -/widthshow { oldwidthshow } bind def -/awidthshow { oldawidthshow } bind def -/kshow { oldkshow } bind def -/PATredef { - MyAppDict begin - { - /fill { /clip load PATdraw newpath } bind def - /eofill { /eoclip load PATdraw newpath } bind def - /stroke { PATstroke } bind def - /show { 0 0 null 0 0 6 -1 roll PATawidthshow } bind def - /ashow { 0 0 null 6 3 roll PATawidthshow } - bind def - /widthshow { 0 0 3 -1 roll PATawidthshow } - bind def - /awidthshow { PATawidthshow } bind def - /kshow { PATkshow } bind def - } { - /fill { oldfill } bind def - /eofill { oldeofill } bind def - /stroke { oldstroke } bind def - /show { oldshow } bind def - /ashow { oldashow } bind def - /widthshow { oldwidthshow } bind def - /awidthshow { oldawidthshow } bind def - /kshow { oldkshow } bind def - } ifelse - end -} bind def -false PATredef -% Conditionally define setcmykcolor if not available -/setcmykcolor where { pop } { - /setcmykcolor { - 1 sub 4 1 roll - 3 { - 3 index add neg dup 0 lt { pop 0 } if 3 1 roll - } repeat - setrgbcolor - pop - } bind def -} ifelse -/PATsc { % colorarray - aload length % c1 ... cn length - dup 1 eq { pop setgray } { 3 eq { setrgbcolor } { setcmykcolor - } ifelse } ifelse -} bind def -/PATsg { % dict - begin - lw setlinewidth - lc setlinecap - lj setlinejoin - ml setmiterlimit - ds aload pop setdash - cc aload pop setrgbcolor - cm setmatrix - end -} bind def - -/PATDict 3 dict def -/PATsp { - true PATredef - PATDict begin - /CurrentPattern exch def - % If it's an uncolored pattern, save the color - CurrentPattern /PaintType get 2 eq { - /PColor exch def - } if - /CColor [ currentrgbcolor ] def - end -} bind def -% PATstroke - stroke with the current pattern -/PATstroke { - countdictstack - save - mark - { - currentpoint strokepath moveto - PATpcalc % proc nw nh px py - clip newpath PATfill - } stopped { - (*** PATstroke Warning: Path is too complex, stroking - with gray) = - cleartomark - restore - countdictstack exch sub dup 0 gt - { { end } repeat } { pop } ifelse - gsave 0.5 setgray oldstroke grestore - } { pop restore pop } ifelse - newpath -} bind def -/PATtcalc { % modmtx tilingtype PATtcalc tilematrix - % Note: tiling types 2 and 3 are not supported - gsave - exch concat % tilingtype - matrix currentmatrix exch % cmtx tilingtype - % Tiling type 1 and 3: constant spacing - 2 ne { - % Distort the pattern so that it occupies - % an integral number of device pixels - dup 4 get exch dup 5 get exch % tx ty cmtx - XStep 0 dtransform - round exch round exch % tx ty cmtx dx.x dx.y - XStep div exch XStep div exch % tx ty cmtx a b - 0 YStep dtransform - round exch round exch % tx ty cmtx a b dy.x dy.y - YStep div exch YStep div exch % tx ty cmtx a b c d - 7 -3 roll astore % { a b c d tx ty } - } if - grestore -} bind def -/PATusp { - false PATredef - PATDict begin - CColor PATsc - end -} bind def - -% right30 -11 dict begin -/PaintType 1 def -/PatternType 1 def -/TilingType 1 def -/BBox [0 0 1 1] def -/XStep 1 def -/YStep 1 def -/PatWidth 1 def -/PatHeight 1 def -/Multi 2 def -/PaintData [ - { clippath } bind - { 32 16 true [ 32 0 0 -16 0 16 ] - {<00030003000c000c0030003000c000c0030003000c000c00 - 30003000c000c00000030003000c000c0030003000c000c0 - 030003000c000c0030003000c000c000>} - imagemask } bind -] def -/PaintProc { - pop - exec fill -} def -currentdict -end -/P2 exch def -1.1111 1.1111 scale %restore scale - -/cp {closepath} bind def -/ef {eofill} bind def -/gr {grestore} bind def -/gs {gsave} bind def -/sa {save} bind def -/rs {restore} bind def -/l {lineto} bind def -/m {moveto} bind def -/rm {rmoveto} bind def -/n {newpath} bind def -/s {stroke} bind def -/sh {show} bind def -/slc {setlinecap} bind def -/slj {setlinejoin} bind def -/slw {setlinewidth} bind def -/srgb {setrgbcolor} bind def -/rot {rotate} bind def -/sc {scale} bind def -/sd {setdash} bind def -/ff {findfont} bind def -/sf {setfont} bind def -/scf {scalefont} bind def -/sw {stringwidth} bind def -/tr {translate} bind def -/tnt {dup dup currentrgbcolor - 4 -2 roll dup 1 exch sub 3 -1 roll mul add - 4 -2 roll dup 1 exch sub 3 -1 roll mul add - 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} - bind def -/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul - 4 -2 roll mul srgb} bind def - /DrawSplineSection { - /y3 exch def - /x3 exch def - /y2 exch def - /x2 exch def - /y1 exch def - /x1 exch def - /xa x1 x2 x1 sub 0.666667 mul add def - /ya y1 y2 y1 sub 0.666667 mul add def - /xb x3 x2 x3 sub 0.666667 mul add def - /yb y3 y2 y3 sub 0.666667 mul add def - x1 y1 lineto - xa ya xb yb x3 y3 curveto - } def - -/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def -/$F2psEnd {$F2psEnteredState restore end} def -%%EndProlog - -$F2psBegin -10 setmiterlimit -n 0 842 m 0 0 l 595 0 l 595 842 l cp clip - 0.06000 0.06000 sc -7.500 slw -% Polyline -n 750 3600 m 750 1200 l 2325 1200 l 2325 3600 l gs col-1 s gr -% Polyline -n 750 1500 m 2325 1500 l gs col-1 s gr -% Polyline -n 750 1800 m 2325 1800 l gs col-1 s gr -15.000 slw -% Polyline -n 375 2100 m 2775 2100 l gs col-1 s gr -/Times-Roman ff 180.00 scf sf -900 2025 m -gs 1 -1 sc (allocated_blocks) col-1 sh gr -/Times-Roman ff 180.00 scf sf -1200 1725 m -gs 1 -1 sc (free_list) col-1 sh gr -/Times-Roman ff 180.00 scf sf -1200 1425 m -gs 1 -1 sc (item_size) col-1 sh gr -7.500 slw -% Polyline -n 3525 1200 m 5025 1200 l 5025 1800 l 3525 1800 l cp gs col-1 s gr -% Polyline -n 3525 1500 m 5025 1500 l gs col-1 s gr -/Times-Roman ff 180.00 scf sf -4050 1425 m -gs 1 -1 sc (next) col-1 sh gr -/Times-Roman ff 180.00 scf sf -4050 1725 m -gs 1 -1 sc (block) col-1 sh gr -% Polyline -n 5850 1200 m 7350 1200 l 7350 1800 l 5850 1800 l cp gs col-1 s gr -% Polyline -n 5850 1500 m 7350 1500 l gs col-1 s gr -/Times-Roman ff 180.00 scf sf -6375 1425 m -gs 1 -1 sc (next) col-1 sh gr -/Times-Roman ff 180.00 scf sf -6375 1725 m -gs 1 -1 sc (block) col-1 sh gr -15.000 slw -% Polyline - [100.0] 0 sd -n 3450 5700 m 5400 5700 l gs col-1 s gr [] 0 sd -7.500 slw -% Polyline -n 3600 8000 m 3600 3450 l 5175 3450 l 5175 8000 l gs col-1 s gr -15.000 slw -% Polyline - [100.0] 0 sd -n 3525 6900 m 5325 6900 l gs col-1 s gr [] 0 sd -0.000 slw -% Polyline - [33.3] 0 sd -n 3675 3525 m 5100 3525 l 5100 4425 l 3675 4425 l cp gs /PC [[1.00 1.00 1.00] [0.00 0.00 0.00]] def -15.00 15.00 sc P2 [16 0 0 -8 245.00 235.00] PATmp PATsp ef gr PATusp [] 0 sd -% Polyline - [33.3] 0 sd -n 3675 5775 m 5100 5775 l 5100 6825 l 3675 6825 l cp gs /PC [[1.00 1.00 1.00] [0.00 0.00 0.00]] def -15.00 15.00 sc P2 [16 0 0 -8 245.00 385.00] PATmp PATsp ef gr PATusp [] 0 sd -7.500 slw -% Polyline - [15 50.0] 50.0 sd -n 3600 4725 m 5250 4725 l gs col-1 s gr [] 0 sd -% Polyline - [15 50.0] 50.0 sd -n 3600 4950 m 5175 4950 l gs col-1 s gr [] 0 sd -0.000 slw -% Polyline - [15 25.0] 25.0 sd -n 6375 3750 m 6675 3750 l 6675 4050 l 6375 4050 l cp gs /PC [[1.00 1.00 1.00] [0.00 0.00 0.00]] def -15.00 15.00 sc P2 [16 0 0 -8 425.00 250.00] PATmp PATsp ef gr PATusp [] 0 sd -7.500 slw -% Polyline -gs clippath -4305 3253 m 4275 3373 l 4245 3253 l 4245 3415 l 4305 3415 l cp clip -n 4275 1800 m 4275 3400 l gs col-1 s gr gr - -% arrowhead -n 4305 3253 m 4275 3373 l 4245 3253 l 4275 3253 l 4305 3253 l cp gs 0.00 setgray ef gr col-1 s -15.000 slw -% Polyline - [100.0] 0 sd -n 3450 4500 m 5325 4500 l gs col-1 s gr [] 0 sd -7.500 slw -% Polyline -gs clippath -6630 2778 m 6600 2898 l 6570 2778 l 6570 2940 l 6630 2940 l cp clip -n 6600 1800 m 6600 2925 l gs col-1 s gr gr - -% arrowhead -n 6630 2778 m 6600 2898 l 6570 2778 l 6600 2778 l 6630 2778 l cp gs 0.00 setgray ef gr col-1 s -15.000 slw -% Polyline -gs clippath -656 840 m 723 1078 l 552 900 l 713 1181 l 817 1121 l cp clip -n 450 600 m 750 1125 l gs col-1 s gr gr - -% arrowhead -n 656 840 m 723 1078 l 552 900 l 604 870 l 656 840 l cp gs 0.00 setgray ef gr col-1 s -% Open spline -gs clippath -5627 1227 m 5749 1210 l 5650 1282 l 5800 1222 l 5778 1167 l cp clip -7.500 slw -n 4875.0 1350.0 m 5137.5 1350.0 l - 5137.5 1350.0 5400.0 1350.0 5587.5 1275.0 DrawSplineSection - 5775.0 1200.0 l gs col-1 s gr - gr - -% arrowhead -n 5627 1227 m 5749 1210 l 5650 1282 l 5639 1255 l 5627 1227 l cp gs 0.00 setgray ef gr col-1 s -% Open spline -gs clippath -7877 1227 m 7999 1210 l 7900 1282 l 8050 1222 l 8028 1167 l cp clip -n 7125.0 1350.0 m 7387.5 1350.0 l - 7387.5 1350.0 7650.0 1350.0 7837.5 1275.0 DrawSplineSection - 8025.0 1200.0 l gs col-1 s gr - gr - -% arrowhead -n 7877 1227 m 7999 1210 l 7900 1282 l 7889 1255 l 7877 1227 l cp gs 0.00 setgray ef gr col-1 s -% Interp Spline -gs clippath -3308 4453 m 3423 4496 l 3300 4512 l 3461 4532 l 3468 4472 l cp clip -n 2175 1650 m - 2346.9 1637.5 2421.9 1637.5 2475 1650 curveto - 2514.6 1659.3 2593.0 1702.0 2625 1725 curveto - 2665.4 1754.1 2753.1 1822.2 2775 1875 curveto - 2790.5 1912.4 2775.0 1990.8 2775 2025 curveto - 2775.0 2537.6 2542.8 3714.4 2775 4275 curveto - 2785.9 4301.4 2829.8 4335.4 2850 4350 curveto - 2882.0 4373.0 2962.7 4412.9 3000 4425 curveto - 3076.1 4449.8 3188.6 4468.5 3450 4500 curveto - gs col-1 s gr - gr - -% arrowhead -n 3308 4453 m 3423 4496 l 3300 4512 l 3304 4483 l 3308 4453 l cp gs 0.00 setgray ef gr col-1 s -% Interp Spline -gs clippath -5325 6973 m 5201 6969 l 5312 6914 l 5154 6949 l 5167 7007 l cp clip -n 5100 4575 m - 5270.9 4558.6 5345.9 4558.6 5400 4575 curveto - 5465.1 4594.7 5582.7 4669.6 5625 4725 curveto - 5662.1 4773.6 5691.1 4895.0 5700 4950 curveto - 5764.9 5350.0 5796.1 6267.8 5700 6675 curveto - 5690.7 6714.6 5655.4 6794.6 5625 6825 curveto - 5594.6 6855.4 5511.4 6886.6 5475 6900 curveto - 5424.7 6918.6 5349.7 6937.4 5175 6975 curveto - gs col-1 s gr - gr - -% arrowhead -n 5325 6973 m 5201 6969 l 5312 6914 l 5319 6944 l 5325 6973 l cp gs 0.00 setgray ef gr col-1 s -% Interp Spline -gs clippath -3300 1202 m 3423 1205 l 3313 1261 l 3471 1226 l 3458 1168 l cp clip -n 2250 1950 m - 2378.9 1959.4 2435.2 1959.4 2475 1950 curveto - 2514.6 1940.7 2593.0 1898.0 2625 1875 curveto - 2665.4 1845.9 2745.9 1765.4 2775 1725 curveto - 2821.1 1661.1 2878.9 1488.9 2925 1425 curveto - 2939.6 1404.8 2979.8 1364.6 3000 1350 curveto - 3032.0 1327.0 3113.7 1288.5 3150 1275 curveto - 3200.3 1256.4 3275.3 1237.7 3450 1200 curveto - gs col-1 s gr - gr - -% arrowhead -n 3300 1202 m 3423 1205 l 3313 1261 l 3306 1231 l 3300 1202 l cp gs 0.00 setgray ef gr col-1 s -/Times-Roman ff 180.00 scf sf -3975 4650 m -gs 1 -1 sc (next_free) col-1 sh gr -/Times-Roman ff 180.00 scf sf -4050 4875 m -gs 1 -1 sc (magic) col-1 sh gr -/Times-Bold ff 210.00 scf sf -6825 3975 m -gs 1 -1 sc (= allocated memory) col-1 sh gr -/Helvetica-Bold ff 180.00 scf sf -3675 1125 m -gs 1 -1 sc (AllocatedBlock) col-1 sh gr -/Helvetica-Bold ff 180.00 scf sf -1575 1125 m -gs 1 -1 sc (FixItem) col-1 sh gr -/Helvetica-Bold ff 180.00 scf sf -2400 4650 m -gs 1 -1 sc (FreeHeader) col-1 sh gr -/Times-Bold ff 180.00 scf sf -5250 3600 m -gs 1 -1 sc 270.0 rot (item_size) col-1 sh gr -/Times-Bold ff 270.00 scf sf -300 525 m -gs 1 -1 sc (fix_array) col-1 sh gr -$F2psEnd -rs -end diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 06fefa8efb..7dc59ea954 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -4477,6 +4477,7 @@ true</pre> </func> <func> <name name="spawn_opt" arity="2"/> + <type name="priority_level" /> <fsummary>Create a new process with a fun as entry point</fsummary> <desc> <p>Returns the pid of a new process started by the application @@ -4490,6 +4491,7 @@ true</pre> </func> <func> <name name="spawn_opt" arity="3"/> + <type name="priority_level" /> <fsummary>Create a new process with a fun as entry point on a given node</fsummary> <desc> <p>Returns the pid of a new process started by the application @@ -4501,6 +4503,7 @@ true</pre> </func> <func> <name name="spawn_opt" arity="4"/> + <type name="priority_level" /> <fsummary>Create a new process with a function as entry point</fsummary> <desc> <p>Works exactly like @@ -4602,6 +4605,7 @@ true</pre> </func> <func> <name name="spawn_opt" arity="5"/> + <type name="priority_level" /> <fsummary>Create a new process with a function as entry point on a given node</fsummary> <desc> <p>Returns the pid of a new process started by the application diff --git a/erts/doc/src/escript.xml b/erts/doc/src/escript.xml index 66e904f64f..9e2a87dde6 100644 --- a/erts/doc/src/escript.xml +++ b/erts/doc/src/escript.xml @@ -4,7 +4,7 @@ <comref> <header> <copyright> - <year>2007</year><year>2011</year> + <year>2007</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -85,6 +85,11 @@ $ <input>escript factorial 5</input> </pre> enter the major mode for editing Erlang source files. If the directive is present it must be located on the second line.</p> + + <p>If there is a comment selecting the <seealso + marker="stdlib:epp#encoding">encoding</seealso> it can be + located on the second line.</p> + <p>On the third line (or second line depending on the presence of the Emacs directive), it is possible to give arguments to the emulator, such as </p> @@ -133,7 +138,9 @@ halt(1).</pre> <pre> -include_lib("kernel/include/file.hrl").</pre> <p>to include the record definitions for the records used by the - <c>file:read_link_info/1</c> function.</p> + <c>file:read_link_info/1</c> function. You can also select + encoding here, but if there is a valid encoding comment on + the second line it takes precedence.</p> <p>The script will be checked for syntactic and semantic correctness before being run. If there are warnings (such as diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index 7fc61517a8..3a2c644ff7 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -30,6 +30,84 @@ </header> <p>This document describes the changes made to the ERTS application.</p> +<section><title>Erts 5.10.1.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A bug in the implementation of offline schedulers has + been fixed. The bug was introduced in OTP-R16A/ERTS-5.10, + and caused work-stealing between schedulers to fail. This + in turn, caused work to accumulate in some run-queues. + The bug was only triggered when there were offline + schedulers in the system, i.e., when the amount of online + schedulers was less than the total amount of schedulers. + The effect of the bug got more severe the larger amount + of offline schedulers the system had.</p> + <p> + Own Id: OTP-11022 Aux Id: OTP-9892 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.10.1.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The BIF <seealso + marker="erlang#is_process_alive/1"><c>is_process_alive/1</c></seealso> + could prematurely return <c>false</c> while the process + being inspected was terminating. This bug was introduced + in ERTS-5.10.</p> + <p> + Own Id: OTP-10926</p> + </item> + <item> + <p>Fix a problem in <c>erlang:delete_element/2</c> where + the call could corrupt one word of stack if the heap and + stack met during call.</p> + <p> + Own Id: OTP-10932</p> + </item> + <item> + <p> + The <seealso + marker="erl#+sws"><c>+sws<value></c></seealso> and + <seealso + marker="erl#+swt"><c>+swt<value></c></seealso> + system flags failed if no white space were passed between + the parameter and value parts of the flags. Upon failure, + the runtime system refused to start.</p> + <p> + Own Id: OTP-11000</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Scheduler threads will now by default be less eager + requesting wakeup due to certain cleanup operations. This + can also be controlled using the <seealso + marker="erl#+swct"><c>+swct</c></seealso> command line + argument of <seealso + marker="erl"><c>erl(1)</c></seealso>.</p> + <p> + Own Id: OTP-10994</p> + </item> + </list> + </section> + +</section> + <section><title>Erts 5.10.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index 133ecd69e4..4f2f647742 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -476,8 +476,10 @@ endif ifdef DTRACE_ENABLED # global.h causes problems by including dtrace-wrapper.h which includes # the autogenerated erlang_dtrace.h ... so make erlang_dtrace.h very early. -generate: $(TARGET)/erlang_dtrace.h $(GENERATE) +DTRACE_HEADERS = $(TARGET)/erlang_dtrace.h +generate: $(DTRACE_HEADERS) $(GENERATE) else +DTRACE_HEADERS = generate: $(GENERATE) endif @@ -863,7 +865,7 @@ $(OBJDIR)/%.o: hipe/%.c $(BINDIR)/hipe_mkliterals$(TF_MARKER): $(OBJDIR)/hipe_mkliterals.o $(ld_verbose)$(CC) $(CFLAGS) $(INCLUDES) -o $@ $< -$(OBJDIR)/hipe_mkliterals.o: $(HIPE_ASM) $(TTF_DIR)/erl_alloc_types.h \ +$(OBJDIR)/hipe_mkliterals.o: $(HIPE_ASM) $(TTF_DIR)/erl_alloc_types.h $(DTRACE_HEADERS) \ $(TTF_DIR)/OPCODES-GENERATED $(TARGET)/TABLES-GENERATED $(TTF_DIR)/hipe_literals.h: $(BINDIR)/hipe_mkliterals$(TF_MARKER) diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index 9b17de34ec..ce025c9b6d 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -1580,6 +1580,7 @@ clear_function_break(BeamInstr *pc, Uint break_flags) } if (common & ERTS_BPF_META_TRACE) { MatchSetUnref(bp->meta_ms); + bp_meta_unref(bp->meta_pid); } if (common & ERTS_BPF_COUNT) { ASSERT((bp->flags & ERTS_BPF_COUNT_ACTIVE) == 0); diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index bd4e5a52d0..4193eb4f3f 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -2964,19 +2964,19 @@ gen_put_integer(LoaderState* stp, GenOpArg Fail, GenOpArg Size, NEW_GENOP(stp, op); NATIVE_ENDIAN(Flags); - if (Size.type == TAG_i && Size.val < 0) { - error: /* Negative size must fail */ - op->op = genop_badarg_1; - op->arity = 1; - op->a[0] = Fail; - } else if (Size.type == TAG_i) { + if (Size.type == TAG_i) { op->op = genop_i_new_bs_put_integer_imm_4; op->arity = 4; op->a[0] = Fail; op->a[1].type = TAG_u; if (!safe_mul(Size.val, Unit.val, &op->a[1].val)) { - goto error; + error: + op->op = genop_badarg_1; + op->arity = 1; + op->a[0] = Fail; + op->next = NULL; + return op; } op->a[1].val = Size.val * Unit.val; op->a[2].type = Flags.type; diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 9c438679ea..ff237b6a78 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -2543,7 +2543,7 @@ BIF_RETTYPE insert_element_3(BIF_ALIST_3) Eterm* hp; Uint arity; Eterm res; - Sint ix; + Sint ix, c1, c2; if (is_not_tuple(BIF_ARG_2) || is_not_small(BIF_ARG_1)) { BIF_ERROR(BIF_P, BADARG); @@ -2561,14 +2561,12 @@ BIF_RETTYPE insert_element_3(BIF_ALIST_3) res = make_tuple(hp); *hp = make_arityval(arity + 1); - ix--; - arity -= ix; - - while (ix--) { *++hp = *++ptr; } + c1 = ix - 1; + c2 = arity - ix + 1; + while (c1--) { *++hp = *++ptr; } *++hp = BIF_ARG_3; - - while(arity--) { *++hp = *++ptr; } + while (c2--) { *++hp = *++ptr; } BIF_RET(res); } @@ -2579,7 +2577,7 @@ BIF_RETTYPE delete_element_2(BIF_ALIST_3) Eterm* hp; Uint arity; Eterm res; - Sint ix; + Sint ix, c1, c2; if (is_not_tuple(BIF_ARG_2) || is_not_small(BIF_ARG_1)) { BIF_ERROR(BIF_P, BADARG); @@ -2597,14 +2595,12 @@ BIF_RETTYPE delete_element_2(BIF_ALIST_3) res = make_tuple(hp); *hp = make_arityval(arity - 1); - ix--; - arity -= ix; - - while (ix--) { *++hp = *++ptr; } + c1 = ix - 1; + c2 = arity - ix; + while (c1--) { *++hp = *++ptr; } ++ptr; - - while(arity--) { *++hp = *++ptr; } + while (c2--) { *++hp = *++ptr; } BIF_RET(res); } diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c index acfcc845e4..6f9b171224 100644 --- a/erts/emulator/beam/big.c +++ b/erts/emulator/beam/big.c @@ -150,14 +150,14 @@ #define D2GTE(a1,a0,b1,b0) (!D2LT(a1,a0,b1,b0)) #define D2LTE(a1,a0,b1,b0) (!D2GT(a1,a0,b1,b0)) -// Add (A+B), A=(a1B+a0) B=(b1B+b0) +/* Add (A+B), A=(a1B+a0) B=(b1B+b0) */ #define D2ADD(a1,a0,b1,b0,c1,c0) do { \ ErtsDigit __ci = 0; \ DSUM(a0,b0,__ci,c0); \ DSUMc(a1,b1,__ci,c1); \ } while(0) -// Subtract (A-B), A=(a1B+a0), B=(b1B+b0) (A>=B) +/* Subtract (A-B), A=(a1B+a0), B=(b1B+b0) (A>=B) */ #define D2SUB(a1,a0,b1,b0,c1,c0) do { \ ErtsDigit __bi; \ DSUB(a0,b0,__bi,c0); \ @@ -1337,7 +1337,7 @@ static dsize_t I_lshift(ErtsDigit* x, dsize_t xl, Sint y, while(bw--) *r++ = 0; - if (sw) { // NOTE! x >> 32 is not = 0! + if (sw) { /* NOTE! x >> 32 is not = 0! */ while(xl--) { a0 = (*x << sw) | a1; a1 = (*x >> (D_EXP - sw)); @@ -1384,7 +1384,7 @@ static dsize_t I_lshift(ErtsDigit* x, dsize_t xl, Sint y, x += (xl-1); r += (rl-1); xl -= bw; - if (sw) { // NOTE! x >> 32 is not = 0! + if (sw) { /* NOTE! x >> 32 is not = 0! */ while(xl--) { a1 = (*x >> sw) | a0; a0 = (*x << (D_EXP-sw)); @@ -2468,7 +2468,7 @@ int term_equals_2pow32(Eterm x) if (!is_big(x)) return 0; bp = big_val(x); -#if D_EXP == 16 // 16 bit platfrom not really supported!!! +#if D_EXP == 16 /* 16 bit platfrom not really supported!!! */ return (BIG_SIZE(bp) == 3) && !BIG_DIGIT(bp,0) && !BIG_DIGIT(bp,1) && BIG_DIGIT(bp,2) == 1; #elif D_EXP == 32 @@ -2528,17 +2528,18 @@ const byte d_base_exp_lookup[] = { 31, 19, 15, 13, 11, 11, 10, 9, 9, 8, 8, 8, 8, * end * How much can the characters which fit in 31 bit represent */ -const Uint d_base_base_lookup[] = { 2147483648, 1162261467, 1073741824, - 1220703125, 362797056, 1977326743, 1073741824, 387420489, 1000000000, - 214358881, 429981696, 815730721, 1475789056, 170859375, 268435456, - 410338673, 612220032, 893871739, 1280000000, 1801088541, 113379904, - 148035889, 191102976, 244140625, 308915776, 387420489, 481890304, - 594823321, 729000000, 887503681, 1073741824, 1291467969, 1544804416, - 1838265625, 60466176, 69343957, 79235168, 90224199, 102400000, - 115856201, 130691232, 147008443, 164916224, 184528125, 205962976, - 229345007, 254803968, 282475249, 312500000, 345025251, 380204032, - 418195493, 459165024, 503284375, 550731776, 601692057, 656356768, - 714924299, 777600000, 844596301, 916132832, 992436543, 1073741824 }; +const Uint d_base_base_lookup[] = { 2147483648u, 1162261467u, 1073741824u, + 1220703125u, 362797056u, 1977326743u, 1073741824u, 387420489u, + 1000000000u, 214358881u, 429981696u, 815730721u, 1475789056u, + 170859375u, 268435456u, 410338673u, 612220032u, 893871739u, 1280000000u, + 1801088541u, 113379904u, 148035889u, 191102976u, 244140625u, 308915776u, + 387420489u, 481890304u, 594823321u, 729000000u, 887503681u, 1073741824u, + 1291467969u, 1544804416u, 1838265625u, 60466176u, 69343957u, 79235168u, + 90224199u, 102400000u, 115856201u, 130691232u, 147008443u, 164916224u, + 184528125u, 205962976u, 229345007u, 254803968u, 282475249u, 312500000u, + 345025251u, 380204032u, 418195493u, 459165024u, 503284375u, 550731776u, + 601692057u, 656356768u, 714924299u, 777600000u, 844596301u, 916132832u, + 992436543u, 1073741824u }; Eterm erts_chars_to_integer(Process *BIF_P, char *bytes, Uint size, const int base) { diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index d748f86d75..c19a2647e4 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -495,6 +495,38 @@ refuse_af_strategy(struct au_init *init) static void hdbg_init(void); #endif +static void adjust_fix_alloc_sizes(UWord extra_block_size) +{ + + if (extra_block_size && erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled) { + int j; + +#ifdef ERTS_SMP + if (erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].thr_spec) { + int i; + ErtsAllocatorThrSpec_t* tspec; + + tspec = &erts_allctr_thr_spec[ERTS_ALC_A_FIXED_SIZE]; + ASSERT(tspec->enabled); + + for (i=0; i < tspec->size; i++) { + Allctr_t* allctr = tspec->allctr[i]; + for (j=0; j < ERTS_ALC_NO_FIXED_SIZES; ++j) { + allctr->fix[j].type_size += extra_block_size; + } + } + } + else +#endif + { + Allctr_t* allctr = erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra; + for (j=0; j < ERTS_ALC_NO_FIXED_SIZES; ++j) { + allctr->fix[j].type_size += extra_block_size; + } + } + } +} + void erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) { @@ -515,9 +547,9 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) = sizeof(Process); #if !HALFWORD_HEAP fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MONITOR_SH)] - = ERTS_MONITOR_SH_SIZE; + = ERTS_MONITOR_SH_SIZE * sizeof(Uint); fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_NLINK_SH)] - = ERTS_LINK_SH_SIZE; + = ERTS_LINK_SH_SIZE * sizeof(Uint); #endif fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_EV_D_STATE)] = sizeof(ErtsDrvEventDataState); @@ -538,6 +570,8 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) if (ncpu < 1) ncpu = 1; + erts_tsd_key_create(&erts_allctr_prelock_tsd_key); + erts_sys_alloc_init(); erts_init_utils_mem(); @@ -768,7 +802,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) #ifdef DEBUG extra_block_size += install_debug_functions(); #endif - + adjust_fix_alloc_sizes(extra_block_size); } void @@ -3107,6 +3141,55 @@ erts_request_alloc_info(struct process *c_p, return 1; } +/* + * The allocator wrapper prelocking stuff below is about the locking order. + * It only affects wrappers (erl_mtrace.c and erl_instrument.c) that keep locks + * during alloc/realloc/free. + * + * Some query functions in erl_alloc_util.c lock the allocator mutex and then + * use erts_printf that in turn may call the sys allocator through the wrappers. + * To avoid breaking locking order these query functions first "pre-locks" all + * allocator wrappers. + */ +ErtsAllocatorWrapper_t *erts_allctr_wrappers; +int erts_allctr_wrapper_prelocked = 0; +erts_tsd_key_t erts_allctr_prelock_tsd_key; + +void erts_allctr_wrapper_prelock_init(ErtsAllocatorWrapper_t* wrapper) +{ + ASSERT(wrapper->lock && wrapper->unlock); + wrapper->next = erts_allctr_wrappers; + erts_allctr_wrappers = wrapper; +} + +void erts_allctr_wrapper_pre_lock(void) +{ + if (erts_allctr_wrappers) { + ErtsAllocatorWrapper_t* wrapper = erts_allctr_wrappers; + for ( ; wrapper; wrapper = wrapper->next) { + wrapper->lock(); + } + ASSERT(!erts_allctr_wrapper_prelocked); + erts_allctr_wrapper_prelocked = 1; + erts_tsd_set(erts_allctr_prelock_tsd_key, (void*)1); + } +} + +void erts_allctr_wrapper_pre_unlock(void) +{ + if (erts_allctr_wrappers) { + ErtsAllocatorWrapper_t* wrapper = erts_allctr_wrappers; + + erts_allctr_wrapper_prelocked = 0; + erts_tsd_set(erts_allctr_prelock_tsd_key, (void*)0); + for ( ; wrapper; wrapper = wrapper->next) { + wrapper->unlock(); + } + } +} + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Deprecated functions * * * diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h index ba5ec9c367..9cafd8ddc8 100644 --- a/erts/emulator/beam/erl_alloc.h +++ b/erts/emulator/beam/erl_alloc.h @@ -135,6 +135,18 @@ typedef struct { extern ErtsAllocatorThrSpec_t erts_allctr_thr_spec[ERTS_ALC_A_MAX+1]; +typedef struct ErtsAllocatorWrapper_t_ { + void (*lock)(void); + void (*unlock)(void); + struct ErtsAllocatorWrapper_t_* next; +}ErtsAllocatorWrapper_t; +ErtsAllocatorWrapper_t *erts_allctr_wrappers; +extern int erts_allctr_wrapper_prelocked; +extern erts_tsd_key_t erts_allctr_prelock_tsd_key; +void erts_allctr_wrapper_prelock_init(ErtsAllocatorWrapper_t* wrapper); +void erts_allctr_wrapper_pre_lock(void); +void erts_allctr_wrapper_pre_unlock(void); + void erts_alloc_register_scheduler(void *vesdp); #ifdef ERTS_SMP void erts_alloc_scheduler_handle_delayed_dealloc(void *vesdp, @@ -188,6 +200,7 @@ void *erts_realloc(ErtsAlcType_t type, void *ptr, Uint size); void erts_free(ErtsAlcType_t type, void *ptr); void *erts_alloc_fnf(ErtsAlcType_t type, Uint size); void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size); +int erts_is_allctr_wrapper_prelocked(void); #endif /* #if !ERTS_ALC_DO_INLINE */ @@ -258,6 +271,13 @@ void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size) size); } +ERTS_ALC_INLINE +int erts_is_allctr_wrapper_prelocked(void) +{ + return erts_allctr_wrapper_prelocked /* locked */ + && !!erts_tsd_get(erts_allctr_prelock_tsd_key); /* by me */ +} + #endif /* #if ERTS_ALC_DO_INLINE || defined(ERTS_ALC_INTERNAL__) */ #define ERTS_ALC_GET_THR_IX() ((int) erts_get_scheduler_id()) diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c index ac7f420708..cbeb2c1e3a 100644 --- a/erts/emulator/beam/erl_alloc_util.c +++ b/erts/emulator/beam/erl_alloc_util.c @@ -588,17 +588,21 @@ do { \ #ifdef DEBUG #ifdef USE_THREADS +# ifdef ERTS_SMP +# define IS_ACTUALLY_BLOCKING (erts_thr_progress_is_blocking()) +# else +# define IS_ACTUALLY_BLOCKING 0 +# endif #define ERTS_ALCU_DBG_CHK_THR_ACCESS(A) \ do { \ - if (!(A)->thread_safe) { \ - if (!(A)->debug.saved_tid) { \ + if (!(A)->thread_safe && !IS_ACTUALLY_BLOCKING) { \ + if (!(A)->debug.saved_tid) { \ (A)->debug.tid = erts_thr_self(); \ (A)->debug.saved_tid = 1; \ } \ else { \ ERTS_SMP_LC_ASSERT( \ - ethr_equal_tids((A)->debug.tid, erts_thr_self()) \ - || erts_thr_progress_is_blocking()); \ + ethr_equal_tids((A)->debug.tid, erts_thr_self())); \ } \ } \ } while (0) @@ -878,8 +882,10 @@ erts_alcu_fix_alloc_shrink(Allctr_t *allctr, erts_aint32_t flgs) #ifdef ERTS_SMP -#define ERTS_ALCU_DD_FIX_TYPE_OFFS \ - ((sizeof(ErtsAllctrDDBlock_t)-1)/sizeof(UWord) + 1) +typedef struct { + ErtsAllctrDDBlock_t ddblock__; /* must be first */ + ErtsAlcType_t fix_type; +}ErtsAllctrFixDDBlock_t; static ERTS_INLINE Allctr_t* @@ -1180,7 +1186,7 @@ handle_delayed_dealloc(Allctr_t *allctr, if (fix) { ErtsAlcType_t type; - type = (ErtsAlcType_t) ((UWord *) ptr)[ERTS_ALCU_DD_FIX_TYPE_OFFS]; + type = ((ErtsAllctrFixDDBlock_t*) ptr)->fix_type; ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE; ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1); fix[ix].used--; @@ -1242,7 +1248,7 @@ enqueue_dealloc_other_instance(ErtsAlcType_t type, int cinit) { if (allctr->fix) - ((UWord *) ptr)[ERTS_ALCU_DD_FIX_TYPE_OFFS] = (UWord) type; + ((ErtsAllctrFixDDBlock_t*) ptr)->fix_type = type; if (ddq_enqueue(type, &allctr->dd.q, ptr, cinit)) erts_alloc_notify_delayed_dealloc(allctr->ix); @@ -2508,12 +2514,6 @@ static erts_mtx_t init_atoms_mtx; static void init_atoms(Allctr_t *allctr) { - -#ifdef USE_THREADS - if (allctr && allctr->thread_safe) - erts_mtx_unlock(&allctr->mutex); -#endif - erts_mtx_lock(&init_atoms_mtx); if (!atoms_initialized) { @@ -2604,18 +2604,13 @@ init_atoms(Allctr_t *allctr) fix_type_atoms[ix] = am_atom_put(name, len); } } - - if (allctr) { + if (allctr && !allctr->atoms_initialized) { make_name_atoms(allctr); (*allctr->init_atoms)(); -#ifdef USE_THREADS - if (allctr->thread_safe) - erts_mtx_lock(&allctr->mutex); -#endif allctr->atoms_initialized = 1; } @@ -3243,17 +3238,21 @@ erts_alcu_info_options(Allctr_t *allctr, { Eterm res; + if (hpp || szp) + ensure_atoms_initialized(allctr); #ifdef USE_THREADS - if (allctr->thread_safe) + if (allctr->thread_safe) { + erts_allctr_wrapper_pre_lock(); erts_mtx_lock(&allctr->mutex); + } #endif - if (hpp || szp) - ensure_atoms_initialized(allctr); res = info_options(allctr, print_to_p, print_to_arg, hpp, szp); #ifdef USE_THREADS - if (allctr->thread_safe) + if (allctr->thread_safe) { erts_mtx_unlock(&allctr->mutex); + erts_allctr_wrapper_pre_unlock(); + } #endif return res; } @@ -3280,16 +3279,18 @@ erts_alcu_sz_info(Allctr_t *allctr, return am_false; } + if (hpp || szp) + ensure_atoms_initialized(allctr); + #ifdef USE_THREADS - if (allctr->thread_safe) + if (allctr->thread_safe) { + erts_allctr_wrapper_pre_lock(); erts_mtx_lock(&allctr->mutex); + } #endif ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr); - if (hpp || szp) - ensure_atoms_initialized(allctr); - /* Update sbc values not continously updated */ allctr->sbcs.blocks.curr.no = allctr->sbcs.curr.norm.mseg.no + allctr->sbcs.curr.norm.sys_alloc.no; @@ -3325,13 +3326,16 @@ erts_alcu_sz_info(Allctr_t *allctr, #ifdef USE_THREADS - if (allctr->thread_safe) + if (allctr->thread_safe) { erts_mtx_unlock(&allctr->mutex); + erts_allctr_wrapper_pre_unlock(); + } #endif return res; } + Eterm erts_alcu_info(Allctr_t *allctr, int begin_max_period, @@ -3352,16 +3356,18 @@ erts_alcu_info(Allctr_t *allctr, return am_false; } + if (hpp || szp) + ensure_atoms_initialized(allctr); + #ifdef USE_THREADS - if (allctr->thread_safe) + if (allctr->thread_safe) { + erts_allctr_wrapper_pre_lock(); erts_mtx_lock(&allctr->mutex); + } #endif ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr); - if (hpp || szp) - ensure_atoms_initialized(allctr); - /* Update sbc values not continously updated */ allctr->sbcs.blocks.curr.no = allctr->sbcs.curr.norm.mseg.no + allctr->sbcs.curr.norm.sys_alloc.no; @@ -3414,8 +3420,10 @@ erts_alcu_info(Allctr_t *allctr, #ifdef USE_THREADS - if (allctr->thread_safe) + if (allctr->thread_safe) { erts_mtx_unlock(&allctr->mutex); + erts_allctr_wrapper_pre_unlock(); + } #endif return res; @@ -3487,7 +3495,9 @@ do_erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size) fix = allctr->fix; if (fix) { int ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE; + ASSERT((unsigned)ix < ERTS_ALC_NO_FIXED_SIZES); ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1); + ASSERT(size <= fix[ix].type_size); fix[ix].used++; res = fix[ix].list; if (res) { @@ -3508,8 +3518,7 @@ do_erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size) ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0); return res; } - if (size < 2*sizeof(UWord)) - size += sizeof(UWord); + size = fix[ix].type_size; if (fix[ix].limit < fix[ix].used) fix[ix].limit = fix[ix].used; if (fix[ix].max_used < fix[ix].used) @@ -4198,9 +4207,8 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init) #if ERTS_SMP if (init->tpref) { Uint sz = ABLK_HDR_SZ; - sz += ERTS_ALCU_DD_FIX_TYPE_OFFS*sizeof(UWord); - if (init->fix) - sz += sizeof(UWord); + sz += (init->fix ? + sizeof(ErtsAllctrFixDDBlock_t) : sizeof(ErtsAllctrDDBlock_t)); sz = UNIT_CEILING(sz); if (sz > allctr->min_block_size) allctr->min_block_size = sz; @@ -4325,6 +4333,9 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init) allctr->fix[i].list = NULL; allctr->fix[i].allocated = 0; allctr->fix[i].used = 0; +#ifdef ERTS_SMP + ASSERT(allctr->fix[i].type_size >= sizeof(ErtsAllctrFixDDBlock_t)); +#endif } } diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 8582a8954b..379d3eecc6 100755 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -3077,7 +3077,7 @@ BIF_RETTYPE is_process_alive_1(BIF_ALIST_1) if (BIF_ARG_1 == BIF_P->common.id) BIF_RET(am_true); - rp = erts_proc_lookup(BIF_ARG_1); + rp = erts_proc_lookup_raw(BIF_ARG_1); if (!rp) { BIF_RET(am_false); } diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c index 41c98bbffb..559cb3efa1 100644 --- a/erts/emulator/beam/erl_bif_trace.c +++ b/erts/emulator/beam/erl_bif_trace.c @@ -1224,9 +1224,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key) match_spec_meta = NIL; } if (r & FUNC_TRACE_COUNT_TRACE) { - c = count < 0 ? - erts_make_integer(-count-1, p) : - erts_make_integer(count, p); + c = erts_make_integer(count, p); } if (r & FUNC_TRACE_TIME_TRACE) { ct = call_time; diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index d0afc8ed8d..98c2988323 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -264,9 +264,10 @@ static void schedule_free_dbtable(DbTable* tb) * function has returned). */ ASSERT(erts_refc_read(&tb->common.ref, 0) == 0); - erts_schedule_thr_prgr_later_op(free_dbtable, - (void *) tb, - &tb->release.data); + erts_schedule_thr_prgr_later_cleanup_op(free_dbtable, + (void *) tb, + &tb->release.data, + sizeof(DbTable)); } static ERTS_INLINE void db_init_lock(DbTable* tb, int use_frequent_read_lock, diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index e7e4030900..e6a96d427f 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -532,6 +532,8 @@ void erts_usage(void) erts_fprintf(stderr, " see the erl(1) documentation for more info.\n"); erts_fprintf(stderr, "-sws val set scheduler wakeup strategy, valid values are:\n"); erts_fprintf(stderr, " default|legacy.\n"); + erts_fprintf(stderr, "-swct val set scheduler wake cleanup threshold, valid values are:\n"); + erts_fprintf(stderr, " very_lazy|lazy|medium|eager|very_eager.\n"); erts_fprintf(stderr, "-swt val set scheduler wakeup threshold, valid values are:\n"); erts_fprintf(stderr, " very_low|low|medium|high|very_high.\n"); erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n"); @@ -1413,7 +1415,17 @@ erl_start(int argc, char **argv) erts_usage(); } } - else if (sys_strcmp("wt", sub_param) == 0) { + else if (has_prefix("wct", sub_param)) { + arg = get_arg(sub_param+3, argv[i+1], &i); + if (erts_sched_set_wake_cleanup_threshold(arg) != 0) { + erts_fprintf(stderr, "scheduler wake cleanup threshold: %s\n", + arg); + erts_usage(); + } + VERBOSE(DEBUG_SYSTEM, + ("scheduler wake cleanup threshold: %s\n", arg)); + } + else if (has_prefix("wt", sub_param)) { arg = get_arg(sub_param+2, argv[i+1], &i); if (erts_sched_set_wakeup_other_thresold(arg) != 0) { erts_fprintf(stderr, "scheduler wakeup threshold: %s\n", @@ -1423,7 +1435,7 @@ erl_start(int argc, char **argv) VERBOSE(DEBUG_SYSTEM, ("scheduler wakeup threshold: %s\n", arg)); } - else if (sys_strcmp("ws", sub_param) == 0) { + else if (has_prefix("ws", sub_param)) { arg = get_arg(sub_param+2, argv[i+1], &i); if (erts_sched_set_wakeup_other_type(arg) != 0) { erts_fprintf(stderr, "scheduler wakeup strategy: %s\n", diff --git a/erts/emulator/beam/erl_instrument.c b/erts/emulator/beam/erl_instrument.c index b5b245288b..1aea3f65bc 100644 --- a/erts/emulator/beam/erl_instrument.c +++ b/erts/emulator/beam/erl_instrument.c @@ -271,6 +271,18 @@ stat_upd_realloc(ErtsAlcType_t n, Uint size, Uint old_size) * stat instrumentation callback functions */ +static void stat_pre_lock(void) +{ + erts_mtx_lock(&instr_mutex); +} + +static void stat_pre_unlock(void) +{ + erts_mtx_unlock(&instr_mutex); +} + +static ErtsAllocatorWrapper_t instr_wrapper; + static void * stat_alloc(ErtsAlcType_t n, void *extra, Uint size) { @@ -278,7 +290,9 @@ stat_alloc(ErtsAlcType_t n, void *extra, Uint size) Uint ssize; void *res; - erts_mtx_lock(&instr_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_lock(&instr_mutex); + } ssize = size + STAT_BLOCK_HEADER_SIZE; res = (*real_af->alloc)(n, real_af->extra, ssize); @@ -293,7 +307,9 @@ stat_alloc(ErtsAlcType_t n, void *extra, Uint size) res = (void *) ((StatBlock_t *) res)->mem; } - erts_mtx_unlock(&instr_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_unlock(&instr_mutex); + } return res; } @@ -307,7 +323,9 @@ stat_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size) void *sptr; void *res; - erts_mtx_lock(&instr_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_lock(&instr_mutex); + } if (ptr) { sptr = (void *) (((char *) ptr) - STAT_BLOCK_HEADER_SIZE); @@ -329,7 +347,9 @@ stat_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size) res = (void *) ((StatBlock_t *) res)->mem; } - erts_mtx_unlock(&instr_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_unlock(&instr_mutex); + } return res; } @@ -340,7 +360,9 @@ stat_free(ErtsAlcType_t n, void *extra, void *ptr) ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; void *sptr; - erts_mtx_lock(&instr_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_lock(&instr_mutex); + } if (ptr) { sptr = (void *) (((char *) ptr) - STAT_BLOCK_HEADER_SIZE); @@ -352,7 +374,9 @@ stat_free(ErtsAlcType_t n, void *extra, void *ptr) (*real_af->free)(n, real_af->extra, sptr); - erts_mtx_unlock(&instr_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_unlock(&instr_mutex); + } } @@ -360,6 +384,18 @@ stat_free(ErtsAlcType_t n, void *extra, void *ptr) * map stat instrumentation callback functions */ +static void map_stat_pre_lock(void) +{ + erts_mtx_lock(&instr_x_mutex); + erts_mtx_lock(&instr_mutex); +} + +static void map_stat_pre_unlock(void) +{ + erts_mtx_unlock(&instr_mutex); + erts_mtx_unlock(&instr_x_mutex); +} + static void * map_stat_alloc(ErtsAlcType_t n, void *extra, Uint size) { @@ -367,7 +403,9 @@ map_stat_alloc(ErtsAlcType_t n, void *extra, Uint size) Uint msize; void *res; - erts_mtx_lock(&instr_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_lock(&instr_mutex); + } msize = size + MAP_STAT_BLOCK_HEADER_SIZE; res = (*real_af->alloc)(n, real_af->extra, msize); @@ -388,7 +426,9 @@ map_stat_alloc(ErtsAlcType_t n, void *extra, Uint size) res = (void *) mb->mem; } - erts_mtx_unlock(&instr_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_unlock(&instr_mutex); + } return res; } @@ -402,8 +442,10 @@ map_stat_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size) void *mptr; void *res; - erts_mtx_lock(&instr_x_mutex); - erts_mtx_lock(&instr_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_lock(&instr_x_mutex); + erts_mtx_lock(&instr_mutex); + } if (ptr) { mptr = (void *) (((char *) ptr) - MAP_STAT_BLOCK_HEADER_SIZE); @@ -449,9 +491,10 @@ map_stat_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size) res = (void *) mb->mem; } - - erts_mtx_unlock(&instr_mutex); - erts_mtx_unlock(&instr_x_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_unlock(&instr_mutex); + erts_mtx_unlock(&instr_x_mutex); + } return res; } @@ -462,8 +505,10 @@ map_stat_free(ErtsAlcType_t n, void *extra, void *ptr) ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; void *mptr; - erts_mtx_lock(&instr_x_mutex); - erts_mtx_lock(&instr_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_lock(&instr_x_mutex); + erts_mtx_lock(&instr_mutex); + } if (ptr) { MapStatBlock_t *mb; @@ -486,8 +531,10 @@ map_stat_free(ErtsAlcType_t n, void *extra, void *ptr) (*real_af->free)(n, real_af->extra, mptr); - erts_mtx_unlock(&instr_mutex); - erts_mtx_unlock(&instr_x_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_unlock(&instr_mutex); + erts_mtx_unlock(&instr_x_mutex); + } } @@ -496,8 +543,10 @@ static void dump_memory_map_to_stream(FILE *fp) ErtsAlcType_t n; MapStatBlock_t *bp; int lock = !ERTS_IS_CRASH_DUMPING; - if (lock) + if (lock) { + ASSERT(!erts_is_allctr_wrapper_prelocked()); erts_mtx_lock(&instr_mutex); + } /* Write header */ @@ -1155,6 +1204,7 @@ erts_instr_get_type_info(Process *proc) Uint erts_instr_init(int stat, int map_stat) { + Uint extra_sz; int i; am_tot = NULL; @@ -1208,7 +1258,9 @@ erts_instr_init(int stat, int map_stat) erts_allctrs[i].free = map_stat_free; erts_allctrs[i].extra = (void *) &real_allctrs[i]; } - return MAP_STAT_BLOCK_HEADER_SIZE; + instr_wrapper.lock = map_stat_pre_lock; + instr_wrapper.unlock = map_stat_pre_unlock; + extra_sz = MAP_STAT_BLOCK_HEADER_SIZE; } else { erts_instr_stat = 1; @@ -1220,8 +1272,11 @@ erts_instr_init(int stat, int map_stat) erts_allctrs[i].free = stat_free; erts_allctrs[i].extra = (void *) &real_allctrs[i]; } - return STAT_BLOCK_HEADER_SIZE; + instr_wrapper.lock = stat_pre_lock; + instr_wrapper.unlock = stat_pre_unlock; + extra_sz = STAT_BLOCK_HEADER_SIZE; } - + erts_allctr_wrapper_prelock_init(&instr_wrapper); + return extra_sz; } diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c index 69bb4be717..a1d270adba 100644 --- a/erts/emulator/beam/erl_lock_check.c +++ b/erts/emulator/beam/erl_lock_check.c @@ -143,6 +143,8 @@ static erts_lc_lock_order_t erts_lock_order[] = { { "ptimer_pre_alloc_lock", "address", }, { "btm_pre_alloc_lock", NULL, }, { "dist_entry_out_queue", "address" }, + { "port_sched_lock", "port_id" }, + { "port_table", NULL }, #endif { "mtrace_op", NULL }, { "instr_x", NULL }, @@ -154,10 +156,8 @@ static erts_lc_lock_order_t erts_lock_order[] = { { "pmmap", NULL }, #endif #ifdef ERTS_SMP - { "port_sched_lock", "port_id" }, { "port_task_pre_alloc_lock", "address" }, { "proclist_pre_alloc_lock", "address" }, - { "port_table", NULL }, { "xports_list_pre_alloc_lock", "address" }, { "inet_buffer_stack_lock", NULL }, { "gc_info", NULL }, diff --git a/erts/emulator/beam/erl_mtrace.c b/erts/emulator/beam/erl_mtrace.c index e538ba30c2..c8bb126687 100644 --- a/erts/emulator/beam/erl_mtrace.c +++ b/erts/emulator/beam/erl_mtrace.c @@ -222,6 +222,8 @@ static byte *tracep; static byte *endp; static SysTimeval last_tv; +static ErtsAllocatorWrapper_t mtrace_wrapper; + #if ERTS_MTRACE_SEGMENT_ID >= ERTS_ALC_A_MIN || ERTS_MTRACE_SEGMENT_ID < 0 #error ERTS_MTRACE_SEGMENT_ID >= ERTS_ALC_A_MIN || ERTS_MTRACE_SEGMENT_ID < 0 #endif @@ -555,6 +557,8 @@ write_trace_header(char *nodename, char *pid, char *hostname) return 1; } +static void mtrace_pre_lock(void); +static void mtrace_pre_unlock(void); static void *mtrace_alloc(ErtsAlcType_t, void *, Uint); static void *mtrace_realloc(ErtsAlcType_t, void *, void *, Uint); static void mtrace_free(ErtsAlcType_t, void *, void *); @@ -635,12 +639,16 @@ erts_mtrace_install_wrapper_functions(void) erts_allctrs[i].free = mtrace_free; erts_allctrs[i].extra = (void *) &real_allctrs[i]; } + mtrace_wrapper.lock = mtrace_pre_lock; + mtrace_wrapper.unlock = mtrace_pre_unlock; + erts_allctr_wrapper_prelock_init(&mtrace_wrapper); } } void erts_mtrace_stop(void) { + ASSERT(!erts_is_allctr_wrapper_prelocked()); erts_mtx_lock(&mtrace_op_mutex); erts_mtx_lock(&mtrace_buf_mutex); if (erts_mtrace_enabled) { @@ -677,6 +685,7 @@ erts_mtrace_stop(void) void erts_mtrace_exit(Uint32 exit_value) { + ASSERT(!erts_is_allctr_wrapper_prelocked()); erts_mtx_lock(&mtrace_op_mutex); erts_mtx_lock(&mtrace_buf_mutex); if (erts_mtrace_enabled) { @@ -935,18 +944,33 @@ write_free_entry(byte tag, erts_mtx_unlock(&mtrace_buf_mutex); } +static void mtrace_pre_lock(void) +{ + erts_mtx_lock(&mtrace_op_mutex); +} + +static void mtrace_pre_unlock(void) +{ + erts_mtx_unlock(&mtrace_op_mutex); +} + + static void * mtrace_alloc(ErtsAlcType_t n, void *extra, Uint size) { ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; void *res; - erts_mtx_lock(&mtrace_op_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_lock(&mtrace_op_mutex); + } res = (*real_af->alloc)(n, real_af->extra, size); write_alloc_entry(ERTS_MT_ALLOC_BDY_TAG, res, n, 0, size); - erts_mtx_unlock(&mtrace_op_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_unlock(&mtrace_op_mutex); + } return res; } @@ -957,12 +981,16 @@ mtrace_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size) ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; void *res; - erts_mtx_lock(&mtrace_op_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_lock(&mtrace_op_mutex); + } res = (*real_af->realloc)(n, real_af->extra, ptr, size); write_realloc_entry(ERTS_MT_REALLOC_BDY_TAG, res, n, 0, ptr, size); - erts_mtx_unlock(&mtrace_op_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_unlock(&mtrace_op_mutex); + } return res; @@ -973,10 +1001,14 @@ mtrace_free(ErtsAlcType_t n, void *extra, void *ptr) { ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra; - erts_mtx_lock(&mtrace_op_mutex); + if (!erts_is_allctr_wrapper_prelocked()) { + erts_mtx_lock(&mtrace_op_mutex); + } (*real_af->free)(n, real_af->extra, ptr); - write_free_entry(ERTS_MT_FREE_BDY_TAG, n, 0, ptr); + if (!erts_is_allctr_wrapper_prelocked()) { + write_free_entry(ERTS_MT_FREE_BDY_TAG, n, 0, ptr); + } erts_mtx_unlock(&mtrace_op_mutex); } diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index ce045ec94e..0ed08bee01 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -151,9 +151,10 @@ static ERTS_INLINE void schedule_port_task_free(ErtsPortTask *ptp) { #ifdef ERTS_SMP - erts_schedule_thr_prgr_later_op(call_port_task_free, - (void *) ptp, - &ptp->u.release); + erts_schedule_thr_prgr_later_cleanup_op(call_port_task_free, + (void *) ptp, + &ptp->u.release, + sizeof(ErtsPortTask)); #else port_task_free(ptp); #endif @@ -772,9 +773,10 @@ static void schedule_port_task_handle_list_free(ErtsPortTaskHandleList *pthlp) { #ifdef ERTS_SMP - erts_schedule_thr_prgr_later_op(free_port_task_handle_list, - (void *) pthlp, - &pthlp->u.release); + erts_schedule_thr_prgr_later_cleanup_op(free_port_task_handle_list, + (void *) pthlp, + &pthlp->u.release, + sizeof(ErtsPortTaskHandleList)); #else erts_free(ERTS_ALC_T_PT_HNDL_LIST, pthlp); #endif @@ -1999,6 +2001,7 @@ begin_port_cleanup(Port *pp, ErtsPortTask **execqp, int *processing_busy_q_p) * Schedule cleanup of port structure... */ #ifdef ERTS_SMP + /* Has to be more or less immediate to release any driver */ erts_schedule_thr_prgr_later_op(release_port, (void *) pp, &pp->common.u.release); diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 00247b387a..5d9c5af55f 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -146,6 +146,14 @@ extern BeamInstr beam_continue_exit[]; int erts_sched_compact_load; Uint erts_no_schedulers; +#define ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_VERY_LAZY (4*1024*1024) +#define ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_LAZY (512*1024) +#define ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_MEDIUM (64*1024) +#define ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_EAGER (16*1024) +#define ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_VERY_EAGER (1024) + +static UWord thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_MEDIUM; + ErtsPTab erts_proc erts_align_attribute(ERTS_CACHE_LINE_SIZE); int erts_sched_thread_suggested_stack_size = -1; @@ -496,6 +504,7 @@ erts_init_process(int ncpu, int proc_tab_size) #endif (ErtsPTabElementCommon *) &erts_invalid_process.common, proc_tab_size, + sizeof(Process), "process_table"); last_reductions = 0; @@ -909,6 +918,53 @@ unset_aux_work_flags(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flgs) #ifdef ERTS_SMP static ERTS_INLINE void +haw_chk_later_cleanup_op_wakeup(ErtsAuxWorkData *awdp, ErtsThrPrgrVal val) +{ + if (awdp->later_op.first + && erts_thr_progress_cmp(val, awdp->later_op.thr_prgr) >= 0) { + awdp->later_op.size = thr_prgr_later_cleanup_op_threshold; + } +} + +static ERTS_INLINE void +haw_thr_prgr_wakeup(ErtsAuxWorkData *awdp, ErtsThrPrgrVal val) +{ + int cmp = erts_thr_progress_cmp(val, awdp->latest_wakeup); + if (cmp != 0) { + if (cmp > 0) { + awdp->latest_wakeup = val; + haw_chk_later_cleanup_op_wakeup(awdp, val); + } + erts_thr_progress_wakeup(awdp->esdp, val); + } +} + +static ERTS_INLINE void +haw_thr_prgr_soft_wakeup(ErtsAuxWorkData *awdp, ErtsThrPrgrVal val) +{ + if (erts_thr_progress_cmp(val, awdp->latest_wakeup) > 0) { + awdp->latest_wakeup = val; + haw_chk_later_cleanup_op_wakeup(awdp, val); + erts_thr_progress_wakeup(awdp->esdp, val); + } +} + +static ERTS_INLINE void +haw_thr_prgr_later_cleanup_op_wakeup(ErtsAuxWorkData *awdp, ErtsThrPrgrVal val, UWord size) +{ + if (erts_thr_progress_cmp(val, awdp->latest_wakeup) > 0) { + awdp->later_op.thr_prgr = val; + if (awdp->later_op.size > size) + awdp->later_op.size -= size; + else { + awdp->latest_wakeup = val; + awdp->later_op.size = thr_prgr_later_cleanup_op_threshold; + erts_thr_progress_wakeup(awdp->esdp, val); + } + } +} + +static ERTS_INLINE void haw_thr_prgr_current_reset(ErtsAuxWorkData *awdp) { awdp->current_thr_prgr = ERTS_THR_PRGR_INVALID; @@ -1066,8 +1122,7 @@ misc_aux_work_clean(ErtsThrQ_t *q, case ERTS_THR_Q_NEED_THR_PRGR: #ifdef ERTS_SMP set_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC_THR_PRGR); - erts_thr_progress_wakeup(awdp->esdp, - erts_thr_q_need_thr_progress(q)); + haw_thr_prgr_soft_wakeup(awdp, erts_thr_q_need_thr_progress(q)); #endif case ERTS_THR_Q_CLEAN: break; @@ -1225,8 +1280,7 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp, return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN; #ifdef ERTS_SMP case ERTS_ASYNC_READY_NEED_THR_PRGR: - erts_thr_progress_wakeup(awdp->esdp, - awdp->async_ready.thr_prgr); + haw_thr_prgr_soft_wakeup(awdp, awdp->async_ready.thr_prgr); awdp->async_ready.need_thr_prgr = 1; return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN; #endif @@ -1300,7 +1354,7 @@ handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waitin awdp->dd.thr_prgr = wakeup; set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR); awdp->dd.thr_prgr = wakeup; - erts_thr_progress_wakeup(awdp->esdp, wakeup); + haw_thr_prgr_soft_wakeup(awdp, wakeup); } else if (awdp->dd.completed_callback) { awdp->dd.completed_callback(awdp->dd.completed_arg); @@ -1341,7 +1395,7 @@ handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, i if (wakeup == ERTS_THR_PRGR_INVALID) wakeup = erts_thr_progress_later(awdp->esdp); awdp->dd.thr_prgr = wakeup; - erts_thr_progress_wakeup(awdp->esdp, wakeup); + haw_thr_prgr_soft_wakeup(awdp, wakeup); } else { unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR); @@ -1376,6 +1430,7 @@ handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int wait } lop->func(lop->data); if (!awdp->later_op.first) { + awdp->later_op.size = thr_prgr_later_cleanup_op_threshold; awdp->later_op.last = NULL; unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP); @@ -1386,6 +1441,29 @@ handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int wait return aux_work; } +static ERTS_INLINE ErtsThrPrgrVal +enqueue_later_op(ErtsSchedulerData *esdp, + void (*later_func)(void *), + void *later_data, + ErtsThrPrgrLaterOp *lop) +{ + ErtsThrPrgrVal later = erts_thr_progress_later(esdp); + ASSERT(esdp); + + lop->func = later_func; + lop->data = later_data; + lop->later = later; + lop->next = NULL; + if (!esdp->aux_work_data.later_op.last) + esdp->aux_work_data.later_op.first = lop; + else + esdp->aux_work_data.later_op.last->next = lop; + esdp->aux_work_data.later_op.last = lop; + set_aux_work_flags_wakeup_nob(esdp->ssi, + ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP); + return later; +} + #endif /* ERTS_SMP */ void @@ -1396,31 +1474,24 @@ erts_schedule_thr_prgr_later_op(void (*later_func)(void *), #ifndef ERTS_SMP later_func(later_data); #else - ErtsSchedulerData *esdp; - ErtsAuxWorkData *awdp; - int request_wakeup = 1; - - esdp = erts_get_scheduler_data(); - ASSERT(esdp); - awdp = &esdp->aux_work_data; + ErtsSchedulerData *esdp = erts_get_scheduler_data(); + ErtsThrPrgrVal later = enqueue_later_op(esdp, later_func, later_data, lop); + haw_thr_prgr_wakeup(&esdp->aux_work_data, later); +#endif +} - lop->func = later_func; - lop->data = later_data; - lop->later = erts_thr_progress_later(esdp); - lop->next = NULL; - if (!awdp->later_op.last) - awdp->later_op.first = lop; - else { - ErtsThrPrgrLaterOp *last = awdp->later_op.last; - last->next = lop; - if (erts_thr_progress_equal(last->later, lop->later)) - request_wakeup = 0; - } - awdp->later_op.last = lop; - set_aux_work_flags_wakeup_nob(awdp->ssi, - ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP); - if (request_wakeup) - erts_thr_progress_wakeup(esdp, lop->later); +void +erts_schedule_thr_prgr_later_cleanup_op(void (*later_func)(void *), + void *later_data, + ErtsThrPrgrLaterOp *lop, + UWord size) +{ +#ifndef ERTS_SMP + later_func(later_data); +#else + ErtsSchedulerData *esdp = erts_get_scheduler_data(); + ErtsThrPrgrVal later = enqueue_later_op(esdp, later_func, later_data, lop); + haw_thr_prgr_later_cleanup_op_wakeup(&esdp->aux_work_data, later, size); #endif } @@ -1811,7 +1882,7 @@ erts_set_aux_work_timeout(int ix, erts_aint32_t type, int enable) ERTS_DBG_CHK_AUX_WORK_VAL(type); ERTS_DBG_CHK_AUX_WORK_VAL(erts_atomic32_read_nob(&aux_work_tmo->type[ix])); -// erts_fprintf(stderr, "t(%d, 0x%x, %d)\n", ix, type, enable); + /* erts_fprintf(stderr, "t(%d, 0x%x, %d)\n", ix, type, enable); */ if (!enable) { old = erts_atomic32_read_band_mb(&aux_work_tmo->type[ix], ~type); @@ -2554,6 +2625,8 @@ set_no_active_runqs(int active) erts_aint32_t exp = erts_smp_atomic32_read_nob(&balance_info.no_runqs); while (1) { erts_aint32_t act, new; + if ((exp & ERTS_NO_RUNQS_MASK) == active) + break; new = exp & (ERTS_NO_RUNQS_MASK << ERTS_NO_USED_RUNQS_SHIFT); new |= active & ERTS_NO_RUNQS_MASK; act = erts_smp_atomic32_cmpxchg_nob(&balance_info.no_runqs, new, exp); @@ -3100,9 +3173,6 @@ evacuate_run_queue(ErtsRunQueue *rq, if (notify) smp_notify_inc_runq(to_rq); } - - if (ERTS_EMPTY_RUNQ(rq)) - empty_runq(rq); } static int @@ -3996,9 +4066,8 @@ static void change_no_used_runqs(int used) { ErtsMigrationPaths *new_mpaths, *old_mpaths; - int active, qix; + int qix; erts_smp_mtx_lock(&balance_info.update_mtx); - get_no_runqs(&active, NULL); set_no_used_runqs(used); old_mpaths = erts_get_migration_paths_managed(); @@ -4358,6 +4427,25 @@ erts_sched_set_busy_wait_threshold(char *str) return 0; } + +int +erts_sched_set_wake_cleanup_threshold(char *str) +{ + if (sys_strcmp(str, "very_lazy") == 0) + thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_VERY_LAZY; + else if (sys_strcmp(str, "lazy") == 0) + thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_LAZY; + else if (sys_strcmp(str, "medium") == 0) + thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_MEDIUM; + else if (sys_strcmp(str, "eager") == 0) + thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_EAGER; + else if (sys_strcmp(str, "very_eager") == 0) + thr_prgr_later_cleanup_op_threshold = ERTS_THR_PRGR_LATER_CLEANUP_OP_THRESHOLD_VERY_EAGER; + else + return EINVAL; + return 0; +} + static void init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp) { @@ -4365,10 +4453,13 @@ init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp) awdp->esdp = esdp; awdp->ssi = esdp ? esdp->ssi : NULL; #ifdef ERTS_SMP + awdp->latest_wakeup = ERTS_THR_PRGR_VAL_FIRST; awdp->misc.thr_prgr = ERTS_THR_PRGR_VAL_WAITING; awdp->dd.thr_prgr = ERTS_THR_PRGR_VAL_WAITING; awdp->dd.completed_callback = NULL; awdp->dd.completed_arg = NULL; + awdp->later_op.thr_prgr = ERTS_THR_PRGR_VAL_FIRST; + awdp->later_op.size = 0; awdp->later_op.first = NULL; awdp->later_op.last = NULL; #endif @@ -4604,7 +4695,7 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online) schdlr_sspnd.msb.ongoing = 0; erts_smp_atomic32_init_nob(&schdlr_sspnd.active, no_schedulers); schdlr_sspnd.msb.procs = NULL; - init_no_runqs(no_schedulers, no_schedulers_online); + init_no_runqs(no_schedulers_online, no_schedulers_online); balance_info.last_active_runqs = no_schedulers; erts_smp_mtx_init(&balance_info.update_mtx, "migration_info_update"); balance_info.forced_check_balance = 0; diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 6d1032c292..3d3579fa7e 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -430,6 +430,7 @@ typedef struct { ErtsSchedulerSleepInfo *ssi; #ifdef ERTS_SMP ErtsThrPrgrVal current_thr_prgr; + ErtsThrPrgrVal latest_wakeup; #endif struct { int ix; @@ -444,6 +445,8 @@ typedef struct { void (*completed_arg)(void *); } dd; struct { + ErtsThrPrgrVal thr_prgr; + UWord size; ErtsThrPrgrLaterOp *first; ErtsThrPrgrLaterOp *last; } later_op; @@ -1298,10 +1301,15 @@ ERTS_GLB_INLINE int erts_proclist_is_last(ErtsProcList *list, int erts_sched_set_wakeup_other_thresold(char *str); int erts_sched_set_wakeup_other_type(char *str); int erts_sched_set_busy_wait_threshold(char *str); +int erts_sched_set_wake_cleanup_threshold(char *); void erts_schedule_thr_prgr_later_op(void (*)(void *), void *, ErtsThrPrgrLaterOp *); +void erts_schedule_thr_prgr_later_cleanup_op(void (*)(void *), + void *, + ErtsThrPrgrLaterOp *, + UWord); #if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK) int erts_dbg_check_halloc_lock(Process *p); diff --git a/erts/emulator/beam/erl_ptab.c b/erts/emulator/beam/erl_ptab.c index 87beeafa1a..5bbc71c659 100644 --- a/erts/emulator/beam/erl_ptab.c +++ b/erts/emulator/beam/erl_ptab.c @@ -421,6 +421,7 @@ erts_ptab_init_table(ErtsPTab *ptab, void (*release_element)(void *), ErtsPTabElementCommon *invalid_element, int size, + UWord element_size, char *name) { size_t tab_sz; @@ -443,6 +444,7 @@ erts_ptab_init_table(ErtsPTab *ptab, bits = erts_fit_in_bits_int32((Sint32) size - 1); } + ptab->r.o.element_size = element_size; ptab->r.o.max = size; tab_sz = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(size*sizeof(erts_smp_atomic_t)); @@ -670,9 +672,10 @@ erts_ptab_delete_element(ErtsPTab *ptab, } if (ptab->r.o.release_element) - erts_schedule_thr_prgr_later_op(ptab->r.o.release_element, - (void *) ptab_el, - &ptab_el->u.release); + erts_schedule_thr_prgr_later_cleanup_op(ptab->r.o.release_element, + (void *) ptab_el, + &ptab_el->u.release, + ptab->r.o.element_size); } /* diff --git a/erts/emulator/beam/erl_ptab.h b/erts/emulator/beam/erl_ptab.h index 8a130f42a3..7fa1251900 100644 --- a/erts/emulator/beam/erl_ptab.h +++ b/erts/emulator/beam/erl_ptab.h @@ -109,6 +109,7 @@ typedef struct { ErtsPTabElementCommon *invalid_element; Eterm invalid_data; void (*release_element)(void *); + UWord element_size; } ErtsPTabReadOnlyData; typedef struct { @@ -177,6 +178,7 @@ void erts_ptab_init_table(ErtsPTab *ptab, void (*release_element)(void *), ErtsPTabElementCommon *invalid_element, int size, + UWord element_size, char *name); int erts_ptab_new_element(ErtsPTab *ptab, ErtsPTabElementCommon *ptab_el, diff --git a/erts/emulator/beam/erl_thr_progress.c b/erts/emulator/beam/erl_thr_progress.c index 1292cb0678..cf5e3dc012 100644 --- a/erts/emulator/beam/erl_thr_progress.c +++ b/erts/emulator/beam/erl_thr_progress.c @@ -418,7 +418,7 @@ erts_thr_progress_pre_init(void) { intrnl = NULL; erts_tsd_key_create(&erts_thr_prgr_data_key__); - init_nob(&erts_thr_prgr__.current, 0); + init_nob(&erts_thr_prgr__.current, ERTS_THR_PRGR_VAL_FIRST); } void diff --git a/erts/emulator/beam/erl_thr_progress.h b/erts/emulator/beam/erl_thr_progress.h index 1416aa6166..1aeecf2b06 100644 --- a/erts/emulator/beam/erl_thr_progress.h +++ b/erts/emulator/beam/erl_thr_progress.h @@ -108,6 +108,8 @@ struct ErtsThrPrgrLaterOp_ { #ifdef ERTS_SMP +/* ERTS_THR_PRGR_VAL_FIRST should only be used when initializing... */ +#define ERTS_THR_PRGR_VAL_FIRST ((ErtsThrPrgrVal) 0) #define ERTS_THR_PRGR_VAL_WAITING (~((ErtsThrPrgrVal) 0)) #define ERTS_THR_PRGR_INVALID (~((ErtsThrPrgrVal) 0)) diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c index fa53fd0937..ad6f8b993a 100644 --- a/erts/emulator/beam/erl_unicode.c +++ b/erts/emulator/beam/erl_unicode.c @@ -724,7 +724,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */ hp = HAlloc(p, 2); obj = CDR(objp); ioterm = CONS(hp, rest_term, obj); - //(*left) = 0; + /* (*left) = 0; */ goto done; } if (rest_term != NIL) { diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index 5ce0d97c74..8420cfae24 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -3147,17 +3147,6 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags) return result; } -static int is_valid_utf8_atom(byte* bytes, Uint nbytes) -{ - byte* err_pos; - Uint num_chars; - - /*SVERK Do we really need to validate correct utf8? */ - return nbytes <= MAX_ATOM_SZ_LIMIT - && erts_analyze_utf8(bytes, nbytes, &err_pos, &num_chars, NULL) == ERTS_UTF8_OK - && num_chars <= MAX_ATOM_CHARACTERS; -} - static Sint decoded_size(byte *ep, byte* endp, int internal_tags) { @@ -3235,7 +3224,7 @@ decoded_size(byte *ep, byte* endp, int internal_tags) CHKSIZE(2); n = get_int16(ep); ep += 2; - if (!is_valid_utf8_atom(ep, n)) { + if (n > MAX_ATOM_SZ_LIMIT) { return -1; } SKIP(n+atom_extra_skip); @@ -3254,7 +3243,7 @@ decoded_size(byte *ep, byte* endp, int internal_tags) CHKSIZE(1); n = get_int8(ep); ep++; - if (!is_valid_utf8_atom(ep, n)) { + if (n > MAX_ATOM_SZ_LIMIT) { return -1; } SKIP(n+atom_extra_skip); diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 8c67f731f4..f93b599632 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -2651,11 +2651,17 @@ void erts_init_io(int port_tab_size, int port_tab_size_ignore_files) { ErlDrvEntry** dp; + UWord common_element_size; erts_smp_rwmtx_opt_t drv_list_rwmtx_opts = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER; drv_list_rwmtx_opts.type = ERTS_SMP_RWMTX_TYPE_EXTREMELY_FREQUENT_READ; drv_list_rwmtx_opts.lived = ERTS_SMP_RWMTX_LONG_LIVED; + common_element_size = ERTS_ALC_DATA_ALIGN_SIZE(sizeof(Port)); + common_element_size += ERTS_ALC_DATA_ALIGN_SIZE(sizeof(ErtsPortTaskBusyPortQ)); + common_element_size += 10; /* name */ #ifdef ERTS_SMP + common_element_size += sizeof(erts_mtx_t); + init_xports_list_alloc(); #endif @@ -2684,6 +2690,7 @@ void erts_init_io(int port_tab_size, NULL, (ErtsPTabElementCommon *) &erts_invalid_port.common, port_tab_size, + common_element_size, /* Doesn't need to be excact */ "port_table"); erts_smp_atomic_init_nob(&erts_bytes_out, 0); @@ -4140,7 +4147,7 @@ port_sig_call(Port *prt, ErlOffHeap *ohp; Process *rp; ErtsProcLocks rp_locks = 0; - Uint hsz; + Sint hsz; rp = erts_proc_lookup_raw(sigdp->caller); if (!rp) @@ -4257,7 +4264,7 @@ erts_port_call(Process* c_p, switch (try_call_res) { case ERTS_TRY_IMM_DRV_CALL_OK: { Eterm *hp, *hp_end; - Uint hsz; + Sint hsz; unsigned ret_flags = 0U; Eterm term; @@ -5934,10 +5941,6 @@ int driver_outputv(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen, return driver_output2(ix, hbuf, hlen, NULL, 0); size = vec->size - skip; /* Size of remaining bytes in vector */ - ASSERT(hlen >= 0); /* debug only */ - if (hlen < 0) - hlen = 0; - prt = erts_drvport2port_state(ix, &state); if (prt == ERTS_INVALID_ERL_DRV_PORT) return -1; @@ -5960,7 +5963,7 @@ int driver_outputv(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen, binv++; n--; } else { - iov->iov_base += skip; + iov->iov_base = ((char *)(iov->iov_base)) + skip; iov->iov_len -= skip; skip = 0; } @@ -6405,7 +6408,7 @@ int driver_enqv(ErlDrvPort ix, ErlIOVec* vec, ErlDrvSizeT skip) n--; } else { - iov->iov_base += skip; + iov->iov_base = ((char *)(iov->iov_base)) + skip; iov->iov_len -= skip; skip = 0; } @@ -6470,7 +6473,7 @@ int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, ErlDrvSizeT skip) n--; } else { - iov->iov_base += skip; + iov->iov_base = ((char *)(iov->iov_base)) + skip; iov->iov_len -= skip; skip = 0; } @@ -6529,7 +6532,7 @@ ErlDrvSizeT driver_deq(ErlDrvPort ix, ErlDrvSizeT size) q->v_head++; } else { - q->v_head->iov_base += size; + q->v_head->iov_base = ((char *)(q->v_head->iov_base)) + size; q->v_head->iov_len -= size; size = 0; } diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index a8f15fdc38..d5d97d748a 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -2713,25 +2713,26 @@ tailrecur_ne: case SMALL_FLOAT: GET_DOUBLE(bw, f2); if (f2.fd < MAX_LOSSLESS_FLOAT && f2.fd > MIN_LOSSLESS_FLOAT) { - // Float is within the no loss limit + /* Float is within the no loss limit */ f1.fd = signed_val(aw); j = float_comp(f1.fd, f2.fd); #if ERTS_SIZEOF_ETERM == 8 } else if (f2.fd > (double) (MAX_SMALL + 1)) { - // Float is a positive bignum, i.e. bigger + /* Float is a positive bignum, i.e. bigger */ j = -1; } else if (f2.fd < (double) (MIN_SMALL - 1)) { - // Float is a negative bignum, i.e. smaller + /* Float is a negative bignum, i.e. smaller */ j = 1; - } else { // Float is a Sint but less precise + } else { + /* Float is a Sint but less precise */ j = signed_val(aw) - (Sint) f2.fd; } #else } else { - // If float is positive it is bigger than small + /* If float is positive it is bigger than small */ j = (f2.fd > 0.0) ? -1 : 1; } -#endif // ERTS_SIZEOF_ETERM == 8 +#endif /* ERTS_SIZEOF_ETERM == 8 */ break; case FLOAT_BIG: { @@ -2743,18 +2744,18 @@ tailrecur_ne: GET_DOUBLE(bw, f2); if ((f2.fd < (double) (MAX_SMALL + 1)) && (f2.fd > (double) (MIN_SMALL - 1))) { - // Float is a Sint + /* Float is a Sint */ j = big_sign(aw) ? -1 : 1; } else if (big_arity(aw) > BIG_ARITY_FLOAT_MAX || pow(2.0,(big_arity(aw)-1)*D_EXP) > fabs(f2.fd)) { - // If bignum size shows that it is bigger than the abs float + /* If bignum size shows that it is bigger than the abs float */ j = big_sign(aw) ? -1 : 1; } else if (big_arity(aw) < BIG_ARITY_FLOAT_MAX && (pow(2.0,(big_arity(aw))*D_EXP)-1.0) < fabs(f2.fd)) { - // If bignum size shows that it is smaller than the abs float + /* If bignum size shows that it is smaller than the abs float */ j = f2.fd < 0 ? 1 : -1; } else if (f2.fd < MAX_LOSSLESS_FLOAT && f2.fd > MIN_LOSSLESS_FLOAT) { - // Float is within the no loss limit + /* Float is within the no loss limit */ if (big_to_double(aw, &f1.fd) < 0) { j = big_sign(aw) ? -1 : 1; } else { @@ -2771,25 +2772,26 @@ tailrecur_ne: case FLOAT_SMALL: GET_DOUBLE(aw, f1); if (f1.fd < MAX_LOSSLESS_FLOAT && f1.fd > MIN_LOSSLESS_FLOAT) { - // Float is within the no loss limit + /* Float is within the no loss limit */ f2.fd = signed_val(bw); j = float_comp(f1.fd, f2.fd); #if ERTS_SIZEOF_ETERM == 8 } else if (f1.fd > (double) (MAX_SMALL + 1)) { - // Float is a positive bignum, i.e. bigger + /* Float is a positive bignum, i.e. bigger */ j = 1; } else if (f1.fd < (double) (MIN_SMALL - 1)) { - // Float is a negative bignum, i.e. smaller + /* Float is a negative bignum, i.e. smaller */ j = -1; - } else { // Float is a Sint but less precise it + } else { + /* Float is a Sint but less precise it */ j = (Sint) f1.fd - signed_val(bw); } #else } else { - // If float is positive it is bigger than small + /* If float is positive it is bigger than small */ j = (f1.fd > 0.0) ? 1 : -1; } -#endif // ERTS_SIZEOF_ETERM == 8 +#endif /* ERTS_SIZEOF_ETERM == 8 */ break; default: j = b_tag - a_tag; diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 69acfc9dfd..6cc1295973 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -397,7 +397,6 @@ struct t_pwritev { ErlDrvPort port; ErlDrvPDL q_mtx; size_t size; - size_t free_size; unsigned cnt; unsigned n; struct t_pbuf_spec specs[1]; @@ -462,7 +461,6 @@ struct t_data ErlDrvPort port; ErlDrvPDL q_mtx; size_t size; - size_t free_size; size_t reply_size; } writev; struct t_pwritev pwritev; @@ -1346,7 +1344,7 @@ static void invoke_preadv(void *data) = efile_pread(&d->errInfo, (int) d->fd, c->offsets[c->cnt] + c->size, - ev->iov[1 + c->cnt].iov_base + c->size, + ((char *)ev->iov[1 + c->cnt].iov_base) + c->size, read_size, &bytes_read))) { bytes_read_so_far += bytes_read; @@ -1532,26 +1530,24 @@ static void invoke_writev(void *data) { } EF_FREE(iov); - d->c.writev.free_size = size; - d->c.writev.size -= size; if (! d->result_ok) { d->again = 0; + MUTEX_LOCK(d->c.writev.q_mtx); + driver_deq(d->c.writev.port, d->c.writev.size); + MUTEX_UNLOCK(d->c.writev.q_mtx); } else { if (! segment) { d->again = 0; } + d->c.writev.size -= size; TRACE_F(("w%lu", (unsigned long)size)); - + MUTEX_LOCK(d->c.writev.q_mtx); + driver_deq(d->c.writev.port, size); + MUTEX_UNLOCK(d->c.writev.q_mtx); } - DTRACE_INVOKE_RETURN(FILE_WRITE); -} -static void free_writev(void *data) { - struct t_data *d = data; - MUTEX_LOCK(d->c.writev.q_mtx); - driver_deq(d->c.writev.port, d->c.writev.size + d->c.writev.free_size); - MUTEX_UNLOCK(d->c.writev.q_mtx); - EF_FREE(d); + + DTRACE_INVOKE_RETURN(FILE_WRITE); } static void invoke_pwd(void *data) @@ -1602,7 +1598,7 @@ static void invoke_pwritev(void *data) { struct t_pwritev *c = &d->c.pwritev; size_t p; int segment; - size_t size, write_size; + size_t size, write_size, written; DTRACE_INVOKE_SETUP(FILE_PWRITEV); segment = d->again && c->size >= 2*FILE_SEGMENT_WRITE; @@ -1622,39 +1618,35 @@ static void invoke_pwritev(void *data) { if (iovlen < 0) goto error; /* Port terminated */ - for (iovcnt = 0, c->free_size = 0; - c->cnt < c->n && iovcnt < iovlen && c->free_size < size; + for (iovcnt = 0, written = 0; + c->cnt < c->n && iovcnt < iovlen && written < size; c->cnt++) { int chop; write_size = c->specs[c->cnt].size; if (iov[iovcnt].iov_len - p < write_size) { - /* Mismatch between pos/size spec and what is queued */ - d->errInfo.posix_errno = EINVAL; - d->result_ok = 0; - d->again = 0; - goto done; + goto error; } - chop = segment && c->free_size + write_size >= 2*FILE_SEGMENT_WRITE; + chop = segment && written + write_size >= 2*FILE_SEGMENT_WRITE; if (chop) { - ASSERT(c->free_size < FILE_SEGMENT_WRITE); + ASSERT(written < FILE_SEGMENT_WRITE); write_size = FILE_SEGMENT_WRITE + FILE_SEGMENT_WRITE/2 - - c->free_size; + - written; } d->result_ok = efile_pwrite(&d->errInfo, (int) d->fd, - iov[iovcnt].iov_base + p, + (char *)(iov[iovcnt].iov_base) + p, write_size, c->specs[c->cnt].offset); if (! d->result_ok) { d->again = 0; - goto done; + goto deq_error; } - c->free_size += write_size; + written += write_size; c->size -= write_size; if (chop) { c->specs[c->cnt].offset += write_size; c->specs[c->cnt].size -= write_size; /* Schedule out (d->again != 0) */ - goto done; + break; } /* Move forward in buffer */ p += write_size; @@ -1676,25 +1668,28 @@ static void invoke_pwritev(void *data) { d->errInfo.posix_errno = EINVAL; d->result_ok = 0; d->again = 0; + deq_error: + MUTEX_LOCK(d->c.writev.q_mtx); + driver_deq(d->c.pwritev.port, c->size); + MUTEX_UNLOCK(d->c.writev.q_mtx); + + goto done; } else { - ASSERT(c->free_size == size); + ASSERT(written == size); d->again = 0; } - } + } else + ASSERT(written == FILE_SEGMENT_WRITE); + + MUTEX_LOCK(d->c.writev.q_mtx); + driver_deq(d->c.pwritev.port, size); + MUTEX_UNLOCK(d->c.writev.q_mtx); done: EF_FREE(iov); /* Free our copy of the vector, nothing to restore */ + DTRACE_INVOKE_RETURN(FILE_PWRITEV); } -static void free_pwritev(void *data) { - struct t_data *d = data; - - MUTEX_LOCK(d->c.writev.q_mtx); - driver_deq(d->c.pwritev.port, d->c.pwritev.free_size + d->c.pwritev.size); - MUTEX_UNLOCK(d->c.writev.q_mtx); - EF_FREE(d); -} - static void invoke_flstat(void *data) { struct t_data *d = (struct t_data *) data; @@ -2008,21 +2003,8 @@ static void try_free_read_bin(file_descriptor *desc) { static int try_again(file_descriptor *desc, struct t_data *d) { - if (! d->again) { + if (! d->again) return 0; - } - switch (d->command) { - case FILE_WRITE: - MUTEX_LOCK(d->c.writev.q_mtx); - driver_deq(d->c.writev.port, d->c.writev.free_size); - MUTEX_UNLOCK(d->c.writev.q_mtx); - break; - case FILE_PWRITEV: - MUTEX_LOCK(d->c.writev.q_mtx); - driver_deq(d->c.pwritev.port, d->c.pwritev.free_size); - MUTEX_UNLOCK(d->c.writev.q_mtx); - break; - } if (desc->timer_state != timer_idle) { driver_cancel_timer(desc->port); } @@ -2078,10 +2060,9 @@ static struct t_data *async_write(file_descriptor *desc, int *errp, } #endif d->reply = reply; - d->c.writev.free_size = 0; d->c.writev.reply_size = reply_size; d->invoke = invoke_writev; - d->free = free_writev; + d->free = free_data; d->level = 1; cq_enq(desc, d); desc->write_buffered = 0; @@ -2394,7 +2375,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) desc->write_errInfo = d->errInfo; } } - free_writev(data); + free_data(data); break; case FILE_LSEEK: if (d->reply) { @@ -2524,7 +2505,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) } else { reply_Uint(desc, d->c.pwritev.n); } - free_pwritev(data); + free_data(data); break; case FILE_PREADV: if (!d->result_ok) { @@ -2559,7 +2540,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) reply_Sint64(desc, d->c.sendfile.written); desc->sendfile_state = not_sending; free_sendfile(data); - } else if (d->result_ok == 1) { // If we are using select to send the rest of the data + } else if (d->result_ok == 1) { /* If we are using select to send the rest of the data */ desc->sendfile_state = sending; desc->d = d; driver_select(desc->port, (ErlDrvEvent)(long)d->c.sendfile.out_fd, @@ -2581,7 +2562,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) } DTRACE6(efile_drv_return, sched_i1, sched_i2, sched_utag, command, result_ok, posix_errno); - if (desc->write_buffered != 0 && desc->timer_state == timer_idle) { + if (desc->write_buffered != 0 && desc->timer_state == timer_idle ) { desc->timer_state = timer_write; driver_set_timer(desc->port, desc->write_delay); } @@ -3651,7 +3632,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #ifdef USE_VM_PROBES dt_i3 = d->c.pwritev.size; #endif - d->c.pwritev.free_size = 0; if (j == 0) { /* Trivial case - nothing to write */ EF_FREE(d); @@ -3675,7 +3655,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { MUTEX_UNLOCK(desc->q_mtx); /* Execute the command */ d->invoke = invoke_pwritev; - d->free = free_pwritev; + d->free = free_data; d->level = 1; cq_enq(desc, d); } @@ -3813,7 +3793,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { res_ev->iov[0].iov_base = res_ev->binv[0]->orig_bytes; /* Fill in the number of buffers in the header */ put_int32(0, res_ev->iov[0].iov_base); - put_int32(n, res_ev->iov[0].iov_base+4); + put_int32(n, (char *)(res_ev->iov[0].iov_base) + 4); /**/ res_ev->size = res_ev->iov[0].iov_len; if (n == 0) { @@ -4114,7 +4094,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } if (hd_len != 0 || tl_len != 0 || flags != 0) { - // We do not allow header, trailers and/or flags right now + /* We do not allow header, trailers and/or flags right now */ reply_posix_error(desc, EINVAL); goto done; } diff --git a/erts/emulator/drivers/common/erl_efile.h b/erts/emulator/drivers/common/erl_efile.h index b29b4f971c..bd85e43b8c 100644 --- a/erts/emulator/drivers/common/erl_efile.h +++ b/erts/emulator/drivers/common/erl_efile.h @@ -67,7 +67,7 @@ #define FILENAMES_16BIT 1 #endif -// We use sendfilev if it exist on solaris +/* We use sendfilev if it exist on solaris */ #if !defined(HAVE_SENDFILE) && defined(HAVE_SENDFILEV) #define HAVE_SENDFILE #endif @@ -88,20 +88,6 @@ typedef struct _Efile_error { } Efile_error; /* - * This structure contains date and time. - */ - -//typedef struct _Efile_time { -// unsigned year; /* (4 digits). */ -// unsigned month; /* (1..12). */ -// unsigned day; /* (1..31). */ -// unsigned hour; /* (0..23). */ -// unsigned minute; /* (0..59). */ -// unsigned second; /* (0..59). */ -//} Efile_time; - - -/* * Describes what is returned by file:file_info/1. */ diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index fb128fff7d..2451f41a82 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -3854,8 +3854,10 @@ static void desc_close(inet_descriptor* desc) desc->forced_events = 0; desc->send_would_block = 0; #endif - // We should close the fd here, but the other driver might still - // be selecting on it. + /* + * We should close the fd here, but the other driver might still + * be selecting on it. + */ if (!desc->is_ignored) driver_select(desc->port,(ErlDrvEvent)(long)desc->event, ERL_DRV_USE, 0); diff --git a/erts/emulator/drivers/common/zlib_drv.c b/erts/emulator/drivers/common/zlib_drv.c index 60394b610b..89b7be14f2 100644 --- a/erts/emulator/drivers/common/zlib_drv.c +++ b/erts/emulator/drivers/common/zlib_drv.c @@ -119,7 +119,7 @@ static int zlib_deflate(ZLibData* d, int flush); #if defined(__WIN32__) static int i32(char* buf) #else -static inline int i32(char* buf) +static __inline__ int i32(char* buf) #endif { return (int) ( diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c index 8912d148a5..d76401a790 100644 --- a/erts/emulator/drivers/unix/ttsl_drv.c +++ b/erts/emulator/drivers/unix/ttsl_drv.c @@ -42,6 +42,9 @@ static ErlDrvData ttysl_start(ErlDrvPort, char*); #include <locale.h> #include <unistd.h> #include <termios.h> +#ifdef HAVE_WCWIDTH +#include <wchar.h> +#endif #ifdef HAVE_FCNTL_H #include <fcntl.h> #endif @@ -95,6 +98,9 @@ static int lpos; /* The current "cursor position" in the line buf */ #define CONTROL_TAG 0x10000000U /* Control character, value in first position */ #define ESCAPED_TAG 0x01000000U /* Escaped character, value in first position */ +#ifdef HAVE_WCWIDTH +#define WIDE_TAG 0x02000000U /* Wide character, value in first position */ +#endif #define TAG_MASK 0xFF000000U #define MAXSIZE (1 << 16) @@ -597,12 +603,20 @@ static int check_buf_size(byte *s, int n) } if (utf8_mode) { /* That is, terminal is UTF8 compliant */ if (ch >= 128 || isprint(ch)) { - DEBUGLOG(("Printable(UTF-8:%d):%d",(pos - opos),ch)); - size++; /* Buffer contains wide characters... */ +#ifdef HAVE_WCWIDTH + int width; +#endif + DEBUGLOG(("Printable(UTF-8:%d):%d",pos,ch)); + size++; +#ifdef HAVE_WCWIDTH + if ((width = wcwidth(ch)) > 1) { + size += width - 1; + } +#endif } else if (ch == '\t') { size += 8; } else { - DEBUGLOG(("Magic(UTF-8:%d):%d",(pos - opos),ch)); + DEBUGLOG(("Magic(UTF-8:%d):%d",pos,ch)); size += 2; } } else { @@ -823,7 +837,7 @@ static int del_chars(int n) r = llen - lpos - l; /* Characters after deleted */ /* Fix up buffer and buffer pointers. */ if (r > 0) - memcpy(lbuf + lpos, lbuf + pos, r * sizeof(Uint32)); + memmove(lbuf + lpos, lbuf + pos, r * sizeof(Uint32)); llen -= l; /* Write out characters after, blank the tail and jump back to lpos. */ write_buf(lbuf + lpos, r); @@ -842,7 +856,7 @@ static int del_chars(int n) move_cursor(lpos, lpos-l); /* Move back */ /* Fix up buffer and buffer pointers. */ if (r > 0) - memcpy(lbuf + pos, lbuf + lpos, r * sizeof(Uint32)); + memmove(lbuf + pos, lbuf + lpos, r * sizeof(Uint32)); lpos -= l; llen -= l; /* Write out characters after, blank the tail and jump back to lpos. */ @@ -868,12 +882,22 @@ static int step_over_chars(int n) end = lbuf + llen; c = lbuf + lpos; for ( ; n > 0 && c < end; --n) { +#ifdef HAVE_WCWIDTH + while (*c & WIDE_TAG) { + c++; + } +#endif c++; while (c < end && (*c & TAG_MASK) && ((*c & ~TAG_MASK) == 0)) c++; } for ( ; n < 0 && c > beg; n++) { --c; +#ifdef HAVE_WCWIDTH + while (c > beg + 1 && (c[-1] & WIDE_TAG)) { + --c; + } +#endif while (c > beg && (*c & TAG_MASK) && ((*c & ~TAG_MASK) == 0)) --c; } @@ -899,6 +923,15 @@ static int insert_buf(byte *s, int n) ++pos; } if ((utf8_mode && (ch >= 128 || isprint(ch))) || (ch <= 255 && isprint(ch))) { +#ifdef HAVE_WCWIDTH + int width; + if ((width = wcwidth(ch)) > 1) { + while (--width) { + DEBUGLOG(("insert_buf: Wide(UTF-8):%d,%d",width,ch)); + lbuf[lpos++] = (WIDE_TAG | ((Uint32) ch)); + } + } +#endif DEBUGLOG(("insert_buf: Printable(UTF-8):%d",ch)); lbuf[lpos++] = (Uint32) ch; } else if (ch >= 128) { /* not utf8 mode */ @@ -1006,6 +1039,8 @@ static int write_buf(Uint32 *s, int n) if (octbuff != octtmp) { driver_free(octbuff); } + } else if (*s & WIDE_TAG) { + --n; s++; } else { DEBUGLOG(("Very unexpected character %d",(int) *s)); ++n; diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 558651fff9..2bd5177be1 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -629,7 +629,7 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */ if (w < iov[cnt].iov_len) { /* Adjust the buffer for next write */ iov[cnt].iov_len -= w; - iov[cnt].iov_base += w; + iov[cnt].iov_base = ((char *)iov[cnt].iov_base) + w; w = 0; break; } else { diff --git a/erts/emulator/drivers/win32/ttsl_drv.c b/erts/emulator/drivers/win32/ttsl_drv.c index 1a74d21e99..8b5e3eeefd 100644 --- a/erts/emulator/drivers/win32/ttsl_drv.c +++ b/erts/emulator/drivers/win32/ttsl_drv.c @@ -414,12 +414,12 @@ static int check_buf_size(byte *s, int n) } if (utf8_mode) { /* That is, terminal is UTF8 compliant */ if (ch >= 128 || isprint(ch)) { - DEBUGLOG(("Printable(UTF-8:%d):%d",(pos - opos),ch)); + DEBUGLOG(("Printable(UTF-8:%d):%d",pos,ch)); size++; /* Buffer contains wide characters... */ } else if (ch == '\t') { size += 8; } else { - DEBUGLOG(("Magic(UTF-8:%d):%d",(pos - opos),ch)); + DEBUGLOG(("Magic(UTF-8:%d):%d",pos,ch)); size += 2; } } else { diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c index ae2c650bd2..1f76268934 100644 --- a/erts/emulator/hipe/hipe_native_bif.c +++ b/erts/emulator/hipe/hipe_native_bif.c @@ -238,7 +238,7 @@ void hipe_handle_exception(Process *c_p) if (c_p->mbuf) { erts_printf("%s line %u: p==%p, p->mbuf==%p\n", __FUNCTION__, __LINE__, c_p, c_p->mbuf); - //erts_garbage_collect(c_p, 0, NULL, 0); + /* erts_garbage_collect(c_p, 0, NULL, 0); */ } /* @@ -270,7 +270,7 @@ void hipe_handle_exception(Process *c_p) c_p->def_arg_reg[0] = exception_tag[GET_EXC_CLASS(c_p->freason)]; if (c_p->mbuf) { - //erts_printf("%s line %u: p==%p, p->mbuf==%p, p->lastbif==%p\n", __FUNCTION__, __LINE__, c_p, c_p->mbuf, c_p->hipe.lastbif); + /* erts_printf("%s line %u: p==%p, p->mbuf==%p, p->lastbif==%p\n", __FUNCTION__, __LINE__, c_p, c_p->mbuf, c_p->hipe.lastbif); */ erts_garbage_collect(c_p, 0, NULL, 0); } diff --git a/erts/emulator/hipe/hipe_x86_gc.h b/erts/emulator/hipe/hipe_x86_gc.h index ccb0d2ffb8..ac6b4f70bb 100644 --- a/erts/emulator/hipe/hipe_x86_gc.h +++ b/erts/emulator/hipe/hipe_x86_gc.h @@ -25,7 +25,7 @@ #include "hipe_x86_asm.h" /* for NR_ARG_REGS */ /* uncomment to simulate & test what the initial PowerPC port will do */ -//#define SKIP_YOUNGEST_FRAME +/* #define SKIP_YOUNGEST_FRAME */ struct nstack_walk_state { #ifdef SKIP_YOUNGEST_FRAME diff --git a/erts/emulator/hipe/hipe_x86_signal.c b/erts/emulator/hipe/hipe_x86_signal.c index 64c0e0da3e..19fc448742 100644 --- a/erts/emulator/hipe/hipe_x86_signal.c +++ b/erts/emulator/hipe/hipe_x86_signal.c @@ -183,6 +183,7 @@ static void do_init(void) #include <dlfcn.h> static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*); #define init_done() (__next_sigaction != 0) +extern int _sigaction(int, const struct sigaction*, struct sigaction*); #define __SIGACTION _sigaction static void do_init(void) { diff --git a/erts/emulator/internal_doc/dec.erl b/erts/emulator/internal_doc/dec.erl index 0315f2a52d..255018abe0 100644 --- a/erts/emulator/internal_doc/dec.erl +++ b/erts/emulator/internal_doc/dec.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -25,10 +26,10 @@ %% {RevList,Translation} %% Where 'RevList' is a reversed list of the denormalized repressentation of %% the character 'Translation'. An example would be the swedish character -%% '�', which would be represented in the file as: +%% 'ö', which would be represented in the file as: %% {[776,111],246}, as the denormalized representation of codepoint 246 %% is [111,776] (i.e an 'o' followed by the "double dot accent character 776), -%% while '�' instead is represented as {[776,97],228}, as the denormalized +%% while 'ä' instead is represented as {[776,97],228}, as the denormalized %% form would be [97,776] (same accent but an 'a' instead). %% The datafile is generated from the table on Apple's developer connection %% http://developer.apple.com/library/mac/#technotes/tn/tn1150table.html diff --git a/erts/emulator/pcre/pcre_exec.c b/erts/emulator/pcre/pcre_exec.c index 3fe13ca32e..26cb219ef1 100644 --- a/erts/emulator/pcre/pcre_exec.c +++ b/erts/emulator/pcre/pcre_exec.c @@ -36,7 +36,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- */ -//#define ERLANG_DEBUG 1 +/* #define ERLANG_DEBUG 1 */ /* This module contains erts_pcre_exec(), the externally visible function that does pattern matching using an NFA algorithm, trying to mimic Perl as closely as diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c index bd8ba82a5f..b6e2c9382b 100644 --- a/erts/emulator/sys/common/erl_mseg.c +++ b/erts/emulator/sys/common/erl_mseg.c @@ -350,7 +350,7 @@ schedule_cache_check(ErtsMsegAllctr_t *ma) { static ERTS_INLINE void * mmap_align(ErtsMsegAllctr_t *ma, void *addr, size_t length, int prot, int flags, int fd, off_t offset) { - void *p, *q; + char *p, *q; UWord d; p = mmap(addr, length, prot, flags, fd, offset); @@ -366,14 +366,14 @@ mmap_align(ErtsMsegAllctr_t *ma, void *addr, size_t length, int prot, int flags, if ((p = mmap(addr, length + MSEG_ALIGNED_SIZE, prot, flags, fd, offset)) == MAP_FAILED) return MAP_FAILED; - q = (void *)ALIGNED_CEILING(p); - d = q - p; + q = (void *)ALIGNED_CEILING((char *)p); + d = (UWord)(q - p); if (d > 0) munmap(p, d); if (MSEG_ALIGNED_SIZE - d > 0) - munmap((void *) (q + length), MSEG_ALIGNED_SIZE - d); + munmap((void *)(q + length), MSEG_ALIGNED_SIZE - d); return q; } @@ -439,7 +439,7 @@ mseg_destroy(ErtsMsegAllctr_t *ma, MemKind* mk, void *seg, Uint size) { } #if HAVE_MSEG_RECREATE -#if defined(__NetBsd__) +#if defined(__NetBSD__) #define MREMAP_FLAGS (0) #else #define MREMAP_FLAGS (MREMAP_MAYMOVE) @@ -708,7 +708,7 @@ static ERTS_INLINE void *cache_get_segment(MemKind *mk, Uint *size_p, Uint flags /* Use current cache placement for remaining segment space */ - best->seg = seg + size; + best->seg = ((char *)seg) + size; best->size = csize - size; ASSERT((size % GET_PAGE_SIZE) == 0); @@ -1028,7 +1028,7 @@ mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg, sys_memcpy(((char *) new_seg), ((char *) seg), MIN(new_size, old_size)); - mseg_dealloc(ma, atype, seg, old_size, opt); + mseg_dealloc(ma, atype, seg, old_size, flags, opt); } #endif } diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c index f2f4de869d..689be98969 100644 --- a/erts/emulator/sys/unix/sys_float.c +++ b/erts/emulator/sys/unix/sys_float.c @@ -152,7 +152,7 @@ static int mask_sse2(void) #if defined(__x86_64__) -static inline int cpu_has_sse2(void) { return 1; } +static ERTS_INLINE int cpu_has_sse2(void) { return 1; } #else /* !__x86_64__ */ @@ -179,7 +179,7 @@ static unsigned int xor_eflags(unsigned int mask) return eax; } -static __inline__ unsigned int cpuid_eax(unsigned int op) +static ERTS_INLINE unsigned int cpuid_eax(unsigned int op) { unsigned int eax, save_ebx; @@ -195,7 +195,7 @@ static __inline__ unsigned int cpuid_eax(unsigned int op) return eax; } -static __inline__ unsigned int cpuid_edx(unsigned int op) +static ERTS_INLINE unsigned int cpuid_edx(unsigned int op) { unsigned int eax, edx, save_ebx; @@ -215,7 +215,7 @@ static __inline__ unsigned int cpuid_edx(unsigned int op) * register on the Intel486 processor to generate alignment * faults. This bit cannot be set on the Intel386 processor. */ -static __inline__ int is_386(void) +static ERTS_INLINE int is_386(void) { return ((xor_eflags(1<<18) >> 18) & 1) == 0; } @@ -223,7 +223,7 @@ static __inline__ int is_386(void) /* Newer x86 processors have a CPUID instruction, as indicated by * the ID bit (#21) in EFLAGS being modifiable. */ -static __inline__ int has_CPUID(void) +static ERTS_INLINE int has_CPUID(void) { return (xor_eflags(1<<21) >> 21) & 1; } @@ -832,6 +832,8 @@ sys_chars_to_double(char* buf, double* fp) return 0; } +#ifdef USE_MATHERR + int matherr(struct exception *exc) { @@ -842,3 +844,5 @@ matherr(struct exception *exc) #endif return 1; } + +#endif diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c index fb1ffc3089..e2a777d182 100644 --- a/erts/emulator/sys/win32/sys_float.c +++ b/erts/emulator/sys/win32/sys_float.c @@ -133,6 +133,8 @@ sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t deci return s-buffer; /* i.e strlen(buffer) */ } +#ifdef USE_MATHERR + int matherr(struct _exception *exc) { @@ -141,6 +143,8 @@ matherr(struct _exception *exc) return 1; } +#endif + static void fpe_exception(int sig) { diff --git a/erts/emulator/test/code_parallel_load_SUITE.erl b/erts/emulator/test/code_parallel_load_SUITE.erl index aa9e4c96c6..d2c80c1ca0 100644 --- a/erts/emulator/test/code_parallel_load_SUITE.erl +++ b/erts/emulator/test/code_parallel_load_SUITE.erl @@ -16,7 +16,6 @@ %% %% %CopyrightEnd% %% -%% Author: Björn-Egil Dahlberg -module(code_parallel_load_SUITE). -export([ diff --git a/erts/etc/common/ct_run.c b/erts/etc/common/ct_run.c index 5e5b612a12..853785dcd1 100644 --- a/erts/etc/common/ct_run.c +++ b/erts/etc/common/ct_run.c @@ -432,18 +432,6 @@ strsave(char* string) return p; } -/* Instead of making sure basename exists, we do our own */ -static char *simple_basename(char *path) -{ - char *ptr; - for (ptr = path; *ptr != '\0'; ++ptr) { - if (*ptr == '/' || *ptr == '\\') { - path = ptr + 1; - } - } - return path; -} - static char* get_default_emulator(char* progname) { diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index 9d674a7c65..31d9b2e0ad 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -125,6 +125,7 @@ static char *pluss_val_switches[] = { "cl", "ct", "tbt", + "wct", "wt", "ws", "ss", diff --git a/erts/etc/unix/run_erl.c b/erts/etc/unix/run_erl.c index 910be3dce8..a3bcdb85d9 100644 --- a/erts/etc/unix/run_erl.c +++ b/erts/etc/unix/run_erl.c @@ -682,7 +682,7 @@ static void pass_on(pid_t childpid) } } - if (!got_some && wfd && buf[0] == '\022') { + if (!got_some && wfd && buf[0] == '\014') { char wbuf[30]; int wlen = sn_printf(wbuf,sizeof(wbuf),"[run_erl v%u-%u]\n", RUN_ERL_HI_VER, RUN_ERL_LO_VER); diff --git a/erts/etc/unix/to_erl.c b/erts/etc/unix/to_erl.c index 754b349338..094006c5fd 100644 --- a/erts/etc/unix/to_erl.c +++ b/erts/etc/unix/to_erl.c @@ -353,7 +353,7 @@ int main(int argc, char **argv) * at the start of every new to_erl-session. */ - if (write(wfd, "\022", 1) < 0) { + if (write(wfd, "\014", 1) < 0) { fprintf(stderr, "Error in writing ^R to FIFO.\n"); } diff --git a/erts/etc/win32/erlsrv/erlsrv_interactive.c b/erts/etc/win32/erlsrv/erlsrv_interactive.c index 736eabac79..3f7e20b923 100644 --- a/erts/etc/win32/erlsrv/erlsrv_interactive.c +++ b/erts/etc/win32/erlsrv/erlsrv_interactive.c @@ -525,7 +525,7 @@ int do_usage(char *arg0){ "list, give option -args as last option on command line " "with\n" "no arguments.\n\n"); - printf("Se Erlang documentation for full description.\n"); + printf("See Erlang documentation for full description.\n"); return 0; } diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex a4ddae3d5d..7903f01f76 100644 --- a/erts/preloaded/ebin/erl_prim_loader.beam +++ b/erts/preloaded/ebin/erl_prim_loader.beam diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex 684659cca1..29fb8aaebf 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam Binary files differindex 74c08fa4c9..c907ead38a 100644 --- a/erts/preloaded/ebin/erts_internal.beam +++ b/erts/preloaded/ebin/erts_internal.beam diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam Binary files differindex 143d5b18b9..c2bd80df1a 100644 --- a/erts/preloaded/ebin/init.beam +++ b/erts/preloaded/ebin/init.beam diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam Binary files differindex a6b2fdb985..226e5a4134 100644 --- a/erts/preloaded/ebin/otp_ring0.beam +++ b/erts/preloaded/ebin/otp_ring0.beam diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam Binary files differindex 9460f1da6f..67e62e53f1 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex 8c47d8b611..7b9da42e4f 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam Binary files differindex e6f3995b50..589f45e75e 100644 --- a/erts/preloaded/ebin/prim_zip.beam +++ b/erts/preloaded/ebin/prim_zip.beam diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex cdbaa43d5d..72d1090a52 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 8e4a471a82..fefe0f21e0 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -1785,7 +1785,7 @@ process_flag(_Flag, _Value) -> links | last_calls | memory | - message_que_len | + message_queue_len | messages | min_heap_size | min_bin_vheap_size | @@ -1824,7 +1824,7 @@ process_flag(_Flag, _Value) -> {links, PidsAndPorts :: [pid() | port()]} | {last_calls, false | (Calls :: [mfa()])} | {memory, Size :: non_neg_integer()} | - {message_que_len, MessageQueueLen :: non_neg_integer()} | + {message_queue_len, MessageQueueLen :: non_neg_integer()} | {messages, MessageQueue :: [term()]} | {min_heap_size, MinHeapSize :: non_neg_integer()} | {min_bin_vheap_size, MinBinVHeapSize :: non_neg_integer()} | @@ -1905,11 +1905,11 @@ setelement(_Index, _Tuple1, _Value) -> Function :: atom(), Args :: [term()], Options :: [Option], - Option :: link | monitor | {priority, Level} + Option :: link | monitor + | {priority, Level :: priority_level()} | {fullsweep_after, Number :: non_neg_integer()} | {min_heap_size, Size :: non_neg_integer()} - | {min_bin_vheap_size, VSize :: non_neg_integer()}, - Level :: low | normal | high. + | {min_bin_vheap_size, VSize :: non_neg_integer()}. spawn_opt(_Tuple) -> erlang:nif_error(undefined). @@ -2244,11 +2244,11 @@ spawn_monitor(M, F, A) -> -spec spawn_opt(Fun, Options) -> pid() | {pid(), reference()} when Fun :: function(), Options :: [Option], - Option :: link | monitor | {priority, Level} + Option :: link | monitor + | {priority, Level :: priority_level()} | {fullsweep_after, Number :: non_neg_integer()} | {min_heap_size, Size :: non_neg_integer()} - | {min_bin_vheap_size, VSize :: non_neg_integer()}, - Level :: low | normal | high. + | {min_bin_vheap_size, VSize :: non_neg_integer()}. spawn_opt(F, O) when erlang:is_function(F) -> spawn_opt(erlang, apply, [F, []], O); spawn_opt({M,F}=MF, O) when erlang:is_atom(M), erlang:is_atom(F) -> @@ -2262,11 +2262,11 @@ spawn_opt(F, O) -> Node :: node(), Fun :: function(), Options :: [Option], - Option :: link | monitor | {priority, Level} + Option :: link | monitor + | {priority, Level :: priority_level()} | {fullsweep_after, Number :: non_neg_integer()} | {min_heap_size, Size :: non_neg_integer()} - | {min_bin_vheap_size, VSize :: non_neg_integer()}, - Level :: low | normal | high. + | {min_bin_vheap_size, VSize :: non_neg_integer()}. spawn_opt(N, F, O) when N =:= erlang:node() -> spawn_opt(F, O); spawn_opt(N, F, O) when erlang:is_function(F) -> @@ -2354,11 +2354,11 @@ spawn_link(N,M,F,A) -> Function :: atom(), Args :: [term()], Options :: [Option], - Option :: link | monitor | {priority, Level} + Option :: link | monitor + | {priority, Level :: priority_level()} | {fullsweep_after, Number :: non_neg_integer()} | {min_heap_size, Size :: non_neg_integer()} - | {min_bin_vheap_size, VSize :: non_neg_integer()}, - Level :: low | normal | high. + | {min_bin_vheap_size, VSize :: non_neg_integer()}. spawn_opt(M, F, A, Opts) -> case catch erlang:spawn_opt({M,F,A,Opts}) of {'EXIT',{Reason,_}} -> @@ -2374,11 +2374,11 @@ spawn_opt(M, F, A, Opts) -> Function :: atom(), Args :: [term()], Options :: [Option], - Option :: link | monitor | {priority, Level} + Option :: link | monitor + | {priority, Level :: priority_level()} | {fullsweep_after, Number :: non_neg_integer()} | {min_heap_size, Size :: non_neg_integer()} - | {min_bin_vheap_size, VSize :: non_neg_integer()}, - Level :: low | normal | high. + | {min_bin_vheap_size, VSize :: non_neg_integer()}. spawn_opt(N, M, F, A, O) when N =:= erlang:node(), erlang:is_atom(M), erlang:is_atom(F), erlang:is_list(A), erlang:is_list(O) -> diff --git a/erts/test/nt_SUITE.erl b/erts/test/nt_SUITE.erl index f9bd15a0ce..7580a7b364 100644 --- a/erts/test/nt_SUITE.erl +++ b/erts/test/nt_SUITE.erl @@ -270,8 +270,11 @@ service_prio(Config) when is_list(Config) -> ?line {ok, OldProcs} = get_current_procs(Config), ?line start_service(Name), ?line {ok, NewProcs} = get_current_procs(Config), + timer:sleep(2000), + ?line {ok, NewProcs2} = get_current_procs(Config), ?line remove_service(Name), ?line Diff = arrived_procs(OldProcs,NewProcs), + io:format("NewProcs ~p~n after sleep~n ~p~n",[Diff, arrived_procs(OldProcs,NewProcs2)]), %% Not really correct, could fail if another heart is %% started at the same time... ?line {value, {"heart.exe",_,"high"}} = diff --git a/erts/vsn.mk b/erts/vsn.mk index 4cdc20b550..255def22ca 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -17,8 +17,8 @@ # %CopyrightEnd% # -VSN = 5.10.1 -SYSTEM_VSN = R16B +VSN = 5.10.2 +SYSTEM_VSN = R16B01 # Port number 4365 in 4.2 # Port number 4366 in 4.3 |