diff options
Diffstat (limited to 'erts')
23 files changed, 309 insertions, 105 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index e197791ca9..59ac3dc66c 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -80,7 +80,7 @@ iolist() = [char() | binary() | iolist()] </desc> </func> <func> - <name>adler32(Data) -> int()</name> + <name>erlang:adler32(Data) -> int()</name> <fsummary>Compute adler32 checksum</fsummary> <type> <v>Data = iodata()</v> @@ -90,7 +90,7 @@ iolist() = [char() | binary() | iolist()] </desc> </func> <func> - <name>adler32(OldAdler, Data) -> int()</name> + <name>erlang:adler32(OldAdler, Data) -> int()</name> <fsummary>Compute adler32 checksum</fsummary> <type> <v>OldAdler = int()</v> @@ -102,17 +102,17 @@ iolist() = [char() | binary() | iolist()] <c>Data</c>.</p> <p>The following code:</p> <code> - X = adler32(Data1), - Y = adler32(X,Data2). + X = erlang:adler32(Data1), + Y = erlang:adler32(X,Data2). </code> <p>- would assign the same value to <c>Y</c> as this would:</p> <code> - Y = adler32([Data1,Data2]). + Y = erlang:adler32([Data1,Data2]). </code> </desc> </func> <func> - <name>adler32_combine(FirstAdler, SecondAdler, SecondSize) -> int()</name> + <name>erlang:adler32_combine(FirstAdler, SecondAdler, SecondSize) -> int()</name> <fsummary>Combine two adler32 checksums</fsummary> <type> <v>FirstAdler = SecondAdler = int()</v> @@ -124,14 +124,14 @@ iolist() = [char() | binary() | iolist()] the second checksum to be known.</p> <p>The following code:</p> <code> - Y = adler32(Data1), - Z = adler32(Y,Data2). + Y = erlang:adler32(Data1), + Z = erlang:adler32(Y,Data2). </code> <p>- would assign the same value to <c>Z</c> as this would:</p> <code> - X = adler32(Data1), - Y = adler32(Data2), - Z = adler32_combine(X,Y,iolist_size(Data2)). + X = erlang:adler32(Data1), + Y = erlang:adler32(Data2), + Z = erlang:adler32_combine(X,Y,iolist_size(Data2)). </code> </desc> </func> @@ -147,7 +147,7 @@ iolist() = [char() | binary() | iolist()] <c>Tuple1</c>, and contains the elements in <c>Tuple1</c> followed by <c>Term</c> as the last element. Semantically equivalent to - <c>list_to_tuple(tuple_to_list(Tuple ++ [Term])</c>, but much + <c>list_to_tuple(tuple_to_list(Tuple) ++ [Term])</c>, but much faster.</p> <pre> > <input>erlang:append_element({one, two}, three).</input> @@ -553,7 +553,7 @@ false</pre> </desc> </func> <func> - <name>crc32(Data) -> int()</name> + <name>erlang:crc32(Data) -> int()</name> <fsummary>Compute crc32 (IEEE 802.3) checksum</fsummary> <type> <v>Data = iodata()</v> @@ -563,7 +563,7 @@ false</pre> </desc> </func> <func> - <name>crc32(OldCrc, Data) -> int()</name> + <name>erlang:crc32(OldCrc, Data) -> int()</name> <fsummary>Compute crc32 (IEEE 802.3) checksum</fsummary> <type> <v>OldCrc = int()</v> @@ -575,17 +575,17 @@ false</pre> <c>Data</c>.</p> <p>The following code:</p> <code> - X = crc32(Data1), - Y = crc32(X,Data2). + X = erlang:crc32(Data1), + Y = erlang:crc32(X,Data2). </code> <p>- would assign the same value to <c>Y</c> as this would:</p> <code> - Y = crc32([Data1,Data2]). + Y = erlang:crc32([Data1,Data2]). </code> </desc> </func> <func> - <name>crc32_combine(FirstCrc, SecondCrc, SecondSize) -> int()</name> + <name>erlang:crc32_combine(FirstCrc, SecondCrc, SecondSize) -> int()</name> <fsummary>Combine two crc32 (IEEE 802.3) checksums</fsummary> <type> <v>FirstCrc = SecondCrc = int()</v> @@ -597,14 +597,14 @@ false</pre> the second checksum to be known.</p> <p>The following code:</p> <code> - Y = crc32(Data1), - Z = crc32(Y,Data2). + Y = erlang:crc32(Data1), + Z = erlang:crc32(Y,Data2). </code> <p>- would assign the same value to <c>Z</c> as this would:</p> <code> - X = crc32(Data1), - Y = crc32(Data2), - Z = crc32_combine(X,Y,iolist_size(Data2)). + X = erlang:crc32(Data1), + Y = erlang:crc32(Data2), + Z = erlang:crc32_combine(X,Y,iolist_size(Data2)). </code> </desc> </func> @@ -624,7 +624,7 @@ false</pre> </desc> </func> <func> - <name>decode_packet(Type,Bin,Options) -> {ok,Packet,Rest} | {more,Length} | {error,Reason}</name> + <name>erlang:decode_packet(Type,Bin,Options) -> {ok,Packet,Rest} | {more,Length} | {error,Reason}</name> <fsummary>Extracts a protocol packet from a binary</fsummary> <type> <v>Bin = binary()</v> @@ -760,7 +760,7 @@ false</pre> </desc> </func> <func> - <name>erlang:demonitor(MonitorRef) -> true</name> + <name>demonitor(MonitorRef) -> true</name> <fsummary>Stop monitoring</fsummary> <type> <v>MonitorRef = reference()</v> @@ -768,10 +768,10 @@ false</pre> <desc> <p>If <c>MonitorRef</c> is a reference which the calling process obtained by calling - <seealso marker="#monitor/2">erlang:monitor/2</seealso>, + <seealso marker="#monitor/2">monitor/2</seealso>, this monitoring is turned off. If the monitoring is already turned off, nothing happens.</p> - <p>Once <c>erlang:demonitor(MonitorRef)</c> has returned it is + <p>Once <c>demonitor(MonitorRef)</c> has returned it is guaranteed that no <c>{'DOWN', MonitorRef, _, _, _}</c> message due to the monitor will be placed in the callers message queue in the future. A <c>{'DOWN', MonitorRef, _, _, _}</c> message @@ -779,10 +779,10 @@ false</pre> the call, though. Therefore, in most cases, it is advisable to remove such a <c>'DOWN'</c> message from the message queue after monitoring has been stopped. - <seealso marker="#demonitor/2">erlang:demonitor(MonitorRef, [flush])</seealso> can be used instead of - <c>erlang:demonitor(MonitorRef)</c> if this cleanup is wanted.</p> + <seealso marker="#demonitor/2">demonitor(MonitorRef, [flush])</seealso> can be used instead of + <c>demonitor(MonitorRef)</c> if this cleanup is wanted.</p> <note> - <p>Prior to OTP release R11B (erts version 5.5) <c>erlang:demonitor/1</c> + <p>Prior to OTP release R11B (erts version 5.5) <c>demonitor/1</c> behaved completely asynchronous, i.e., the monitor was active until the "demonitor signal" reached the monitored entity. This had one undesirable effect, though. You could never know when @@ -800,7 +800,7 @@ false</pre> </desc> </func> <func> - <name>erlang:demonitor(MonitorRef, OptionList) -> true|false</name> + <name>demonitor(MonitorRef, OptionList) -> true|false</name> <fsummary>Stop monitoring</fsummary> <type> <v>MonitorRef = reference()</v> @@ -812,8 +812,8 @@ false</pre> <p>The returned value is <c>true</c> unless <c>info</c> is part of <c>OptionList</c>. </p> - <p><c>erlang:demonitor(MonitorRef, [])</c> is equivalent to - <seealso marker="#demonitor/1">erlang:demonitor(MonitorRef)</seealso>.</p> + <p><c>demonitor(MonitorRef, [])</c> is equivalent to + <seealso marker="#demonitor/1">demonitor(MonitorRef)</seealso>.</p> <p>Currently the following <c>Option</c>s are valid:</p> <taglist> <tag><c>flush</c></tag> @@ -821,11 +821,11 @@ false</pre> <p>Remove (one) <c>{_, MonitorRef, _, _, _}</c> message, if there is one, from the callers message queue after monitoring has been stopped.</p> - <p>Calling <c>erlang:demonitor(MonitorRef, [flush])</c> + <p>Calling <c>demonitor(MonitorRef, [flush])</c> is equivalent to the following, but more efficient:</p> <code type="none"> - erlang:demonitor(MonitorRef), + demonitor(MonitorRef), receive {_, MonitorRef, _, _, _} -> true @@ -863,7 +863,7 @@ false</pre> </note> <p>Failure: <c>badarg</c> if <c>OptionList</c> is not a list, or if <c>Option</c> is not a valid option, or the same failure as for - <seealso marker="#demonitor/1">erlang:demonitor/1</seealso></p> + <seealso marker="#demonitor/1">demonitor/1</seealso></p> </desc> </func> <func> @@ -944,7 +944,7 @@ b</pre> </desc> </func> <func> - <name>erlang:error(Reason)</name> + <name>error(Reason)</name> <fsummary>Stop execution with a given reason</fsummary> <type> <v>Reason = term()</v> @@ -957,7 +957,7 @@ b</pre> function first). Since evaluating this function causes the process to terminate, it has no return value.</p> <pre> -> <input>catch erlang:error(foobar).</input> +> <input>catch error(foobar).</input> {'EXIT',{foobar,[{erl_eval,do_apply,5}, {erl_eval,expr,5}, {shell,exprs,6}, @@ -966,7 +966,7 @@ b</pre> </desc> </func> <func> - <name>erlang:error(Reason, Args)</name> + <name>error(Reason, Args)</name> <fsummary>Stop execution with a given reason</fsummary> <type> <v>Reason = term()</v> @@ -1483,7 +1483,7 @@ os_prompt%</pre> </desc> </func> <func> - <name>erlang:integer_to_list(Integer, Base) -> string()</name> + <name>integer_to_list(Integer, Base) -> string()</name> <fsummary>Text representation of an integer</fsummary> <type> <v>Integer = int()</v> @@ -1493,7 +1493,7 @@ os_prompt%</pre> <p>Returns a string which corresponds to the text representation of <c>Integer</c> in base <c>Base</c>.</p> <pre> -> <input>erlang:integer_to_list(1023, 16).</input> +> <input>integer_to_list(1023, 16).</input> "3FF"</pre> </desc> </func> @@ -1932,7 +1932,7 @@ os_prompt%</pre> </desc> </func> <func> - <name>erlang:list_to_integer(String, Base) -> int()</name> + <name>list_to_integer(String, Base) -> int()</name> <fsummary>Convert from text representation to an integer</fsummary> <type> <v>String = string()</v> @@ -1942,7 +1942,7 @@ os_prompt%</pre> <p>Returns an integer whose text representation in base <c>Base</c> is <c>String</c>.</p> <pre> -> <input>erlang:list_to_integer("3FF", 16).</input> +> <input>list_to_integer("3FF", 16).</input> 1023</pre> <p>Failure: <c>badarg</c> if <c>String</c> contains a bad representation of an integer.</p> @@ -2488,7 +2488,7 @@ os_prompt%</pre> </desc> </func> <func> - <name>erlang:monitor(Type, Item) -> MonitorRef</name> + <name>monitor(Type, Item) -> MonitorRef</name> <fsummary>Start monitoring</fsummary> <type> <v>Type = process</v> @@ -2524,7 +2524,7 @@ os_prompt%</pre> <note> <p>When a process is monitored by registered name, the process that has the registered name at the time when - <c>erlang:monitor/2</c> is called will be monitored. + <c>monitor/2</c> is called will be monitored. The monitor will not be effected, if the registered name is unregistered.</p> </note> @@ -2558,20 +2558,20 @@ os_prompt%</pre> </item> </taglist> <note> - <p>If/when <c>erlang:monitor/2</c> is extended (e.g. to + <p>If/when <c>monitor/2</c> is extended (e.g. to handle other item types than <c>process</c>), other possible values for <c>Object</c>, and <c>Info</c> in the <c>'DOWN'</c> message will be introduced.</p> </note> <p>The monitoring is turned off either when the <c>'DOWN'</c> message is sent, or when - <seealso marker="#demonitor/1">erlang:demonitor/1</seealso> + <seealso marker="#demonitor/1">demonitor/1</seealso> is called.</p> <p>If an attempt is made to monitor a process on an older node (where remote process monitoring is not implemented or one where remote process monitoring by registered name is not implemented), the call fails with <c>badarg</c>.</p> - <p>Making several calls to <c>erlang:monitor/2</c> for the same + <p>Making several calls to <c>monitor/2</c> for the same <c>Item</c> is not an error; it results in as many, completely independent, monitorings.</p> <note> @@ -3899,11 +3899,11 @@ os_prompt%</pre> <tag><c>{monitored_by, Pids}</c></tag> <item> <p>A list of pids that are monitoring the process (with - <c>erlang:monitor/2</c>).</p> + <c>monitor/2</c>).</p> </item> <tag><c>{monitors, Monitors}</c></tag> <item> - <p>A list of monitors (started by <c>erlang:monitor/2</c>) + <p>A list of monitors (started by <c>monitor/2</c>) that are active for the process. For a local process monitor or a remote process monitor by pid, the list item is <c>{process, Pid}</c>, and for a remote process @@ -4092,7 +4092,7 @@ os_prompt%</pre> terminate, it has no return value - unless the arguments are invalid, in which case the function <em>returns the error reason</em>, that is <c>badarg</c>. If you want to be really sure not to return you can call - <c>erlang:error(erlang:raise(Class, Reason, Stacktrace))</c> + <c>error(erlang:raise(Class, Reason, Stacktrace))</c> and hope to distinguish exceptions later.</p> </desc> </func> @@ -4693,7 +4693,7 @@ true</pre> <tag><c>monitor</c></tag> <item> <p>Monitor the new process (just like - <seealso marker="#monitor/2">erlang:monitor/2</seealso> does).</p> + <seealso marker="#monitor/2">monitor/2</seealso> does).</p> </item> <tag><c>{priority, Level}</c></tag> <item> diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c index 6b3c106a97..b97705ed96 100644 --- a/erts/emulator/beam/atom.c +++ b/erts/emulator/beam/atom.c @@ -303,7 +303,7 @@ init_atom_table(void) HashFunctions f; int i; Atom a; - erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER; + erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER; rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ; rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED; diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index b0369a402b..52d5f86ee0 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -265,7 +265,7 @@ static ERTS_INLINE void db_init_lock(DbTable* tb, int use_frequent_read_lock, char *rwname, char* fixname) { #ifdef ERTS_SMP - erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER; + erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER; if (use_frequent_read_lock) rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ; #endif @@ -2746,7 +2746,7 @@ void init_db(void) size_t size; #ifdef ERTS_SMP - erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER; + erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER; rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ; rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED; diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c index 5abd2e50fa..fa707f4eed 100644 --- a/erts/emulator/beam/erl_db_hash.c +++ b/erts/emulator/beam/erl_db_hash.c @@ -623,7 +623,7 @@ int db_create_hash(Process *p, DbTable *tbl) erts_smp_atomic_init(&tb->is_resizing, 0); #ifdef ERTS_SMP if (tb->common.type & DB_FINE_LOCKED) { - erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER; + erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER; int i; if (tb->common.type & DB_FREQ_READ) rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ; diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c index 5dce5ad262..84869f12d6 100644 --- a/erts/emulator/beam/erl_fun.c +++ b/erts/emulator/beam/erl_fun.c @@ -55,7 +55,7 @@ void erts_init_fun_table(void) { HashFunctions f; - erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER; + erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER; rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ; rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED; diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c index e430b4ad77..d0b08bf72e 100644 --- a/erts/emulator/beam/erl_node_tables.c +++ b/erts/emulator/beam/erl_node_tables.c @@ -80,7 +80,7 @@ dist_table_alloc(void *dep_tmpl) Eterm chnl_nr; Eterm sysname; DistEntry *dep; - erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER; + erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER; rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ; if(((DistEntry *) dep_tmpl) == erts_this_dist_entry) @@ -710,7 +710,7 @@ erts_set_this_node(Eterm sysname, Uint creation) void erts_init_node_tables(void) { - erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER; + erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER; HashFunctions f; rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ; diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c index 5e81a2d624..5bc402fe22 100644 --- a/erts/emulator/beam/export.c +++ b/erts/emulator/beam/export.c @@ -109,7 +109,7 @@ void init_export_table(void) { HashFunctions f; - erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER; + erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER; rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ; rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED; diff --git a/erts/emulator/beam/register.c b/erts/emulator/beam/register.c index c9bb7bbe91..26d64887d0 100644 --- a/erts/emulator/beam/register.c +++ b/erts/emulator/beam/register.c @@ -145,7 +145,7 @@ static void reg_free(RegProc *obj) void init_register_table(void) { HashFunctions f; - erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_THR_OPTS_DEFAULT_INITER; + erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER; rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ; rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED; diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 3f761eeb19..3de48194fb 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -2174,7 +2174,7 @@ static int http_error_inetdrv(void* arg, const char* buf, int len) ErlDrvTermData spec[19]; if (desc->inet.active == INET_PASSIVE) { - /* {inet_async,S,Ref,{error,{http_error,Line}}} */ + /* {inet_async,S,Ref,{ok,{http_error,Line}}} */ int req; int aid; ErlDrvTermData caller; @@ -2184,7 +2184,7 @@ static int http_error_inetdrv(void* arg, const char* buf, int len) i = LOAD_ATOM(spec, i, am_inet_async); i = LOAD_PORT(spec, i, desc->inet.dport); i = LOAD_INT(spec, i, aid); - i = LOAD_ATOM(spec, i, am_error); + i = LOAD_ATOM(spec, i, am_ok); i = LOAD_ATOM(spec, i, am_http_error); i = http_load_string(desc, spec, i, buf, len); i = LOAD_TUPLE(spec, i, 2); diff --git a/erts/include/internal/ethr_mutex.h b/erts/include/internal/ethr_mutex.h index 4ce3e75c78..8d9d5e3d08 100644 --- a/erts/include/internal/ethr_mutex.h +++ b/erts/include/internal/ethr_mutex.h @@ -346,7 +346,9 @@ do { \ #ifdef ETHR_USE_OWN_MTX_IMPL__ -#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT 1000 +#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX 2000 +#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_BASE 800 +#define ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_INC 50 #define ETHR_MTX_DEFAULT_AUX_SPINCOUNT 50 #define ETHR_CND_DEFAULT_MAIN_SPINCOUNT 0 @@ -443,7 +445,9 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx) #ifdef ETHR_USE_OWN_RWMTX_IMPL__ -#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT 1000 +#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX 2000 +#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_BASE 800 +#define ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_INC 50 #define ETHR_RWMTX_DEFAULT_AUX_SPINCOUNT 50 #else /* pthread_rwlock */ diff --git a/erts/include/internal/gcc/ethr_atomic.h b/erts/include/internal/gcc/ethr_atomic.h index 5fe6e23477..e8e529dd48 100644 --- a/erts/include/internal/gcc/ethr_atomic.h +++ b/erts/include/internal/gcc/ethr_atomic.h @@ -31,7 +31,7 @@ #define ETHR_IMMED_ATOMIC_SET_GET_SAFE__ 0 /* Enable immediate read/write on platforms where we know it is safe */ #if defined(__i386__) || defined(__x86_64__) || defined(__sparc__) \ - || defined(__powerpc__) || defined(__ppc__) + || defined(__powerpc__) || defined(__ppc__) || defined(__mips__) # undef ETHR_IMMED_ATOMIC_SET_GET_SAFE__ # define ETHR_IMMED_ATOMIC_SET_GET_SAFE__ 1 #endif @@ -48,13 +48,18 @@ typedef struct { * a noop on at least some platforms with some gcc versions. * This has suposedly been fixed in some gcc version, but we * don't know from which version. Therefore, we use the - * workaround implemented below on all gcc versions. + * workaround implemented below on all gcc versions except + * for gcc 4.2 or above for MIPS, where it's been verified. */ +#if defined(__mips__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) +#define ETHR_MEMORY_BARRIER __sync_synchronize() +#else #define ETHR_MEMORY_BARRIER \ do { \ volatile long x___ = 0; \ (void) __sync_val_compare_and_swap(&x___, (long) 0, (long) 1); \ } while (0) +#endif #define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_MEMORY_BARRIER #if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__) diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c index aac0d44a32..78323b62a3 100644 --- a/erts/lib_src/common/ethr_mutex.c +++ b/erts/lib_src/common/ethr_mutex.c @@ -35,7 +35,7 @@ #define ETHR_SPIN_WITH_WAITERS 1 -#define ETHR_MTX_MAX_FLGS_SPIN 1000 +#define ETHR_MTX_MAX_FLGS_SPIN 10 #ifdef ETHR_USE_OWN_RWMTX_IMPL__ static int default_rwmtx_main_spincount; @@ -90,7 +90,7 @@ ethr_mutex_lib_init(int cpu_conf) no_spin = cpu_conf == 1; #ifdef ETHR_USE_OWN_MTX_IMPL__ - default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT; + default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_BASE; default_mtx_aux_spincount = ETHR_MTX_DEFAULT_AUX_SPINCOUNT; default_cnd_main_spincount = ETHR_CND_DEFAULT_MAIN_SPINCOUNT; default_cnd_aux_spincount = ETHR_CND_DEFAULT_AUX_SPINCOUNT; @@ -98,7 +98,7 @@ ethr_mutex_lib_init(int cpu_conf) #ifdef ETHR_USE_OWN_RWMTX_IMPL__ - default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT; + default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_BASE; default_rwmtx_aux_spincount = ETHR_RWMTX_DEFAULT_AUX_SPINCOUNT; #else @@ -146,7 +146,21 @@ static int main_threads_array_size = 0; int ethr_mutex_lib_late_init(int no_reader_groups, int no_main_threads) { + +#ifdef ETHR_USE_OWN_MTX_IMPL__ + default_mtx_main_spincount += (no_main_threads + * ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_INC); + if (default_mtx_main_spincount > ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX) + default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX; +#endif + #ifdef ETHR_USE_OWN_RWMTX_IMPL__ + + default_rwmtx_main_spincount += (no_main_threads + * ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_INC); + if (default_rwmtx_main_spincount > ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX) + default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX; + reader_groups_array_size = (no_reader_groups <= 1 ? 1 : no_reader_groups + 1); @@ -593,24 +607,31 @@ initial_spincount(struct ethr_mutex_base_ *mtxb) static ETHR_INLINE int update_spincount(struct ethr_mutex_base_ *mtxb, ethr_ts_event *tse, - int *start_scnt, + int *scnt_state, int *scnt) { - int sscnt = *start_scnt; - if (sscnt < 0) { - *scnt = ((tse->iflgs & ETHR_TS_EV_MAIN_THR) - ? mtxb->main_scnt - : mtxb->aux_scnt); - *scnt -= ETHR_MTX_MAX_FLGS_SPIN; + int state = *scnt_state; + if (state <= 0) { + /* Here state is max spincount to do on event negated */ + *scnt = -state; } else { + /* Here state is initial spincount made on flags */ *scnt = ((tse->iflgs & ETHR_TS_EV_MAIN_THR) ? mtxb->main_scnt : mtxb->aux_scnt); - *scnt -= sscnt; - if (*scnt > 0 && sscnt < ETHR_MTX_MAX_FLGS_SPIN) { - *scnt = ETHR_MTX_MAX_FLGS_SPIN - sscnt; - *start_scnt = -1; + if (*scnt <= state) + *scnt = 0; + else { + if (*scnt <= ETHR_MTX_MAX_FLGS_SPIN) + *scnt_state = 0; /* No spin on event */ + else { + /* Spin on event after... */ + *scnt_state = -1*(*scnt - ETHR_MTX_MAX_FLGS_SPIN); + /* ... we have spun on flags */ + *scnt = ETHR_MTX_MAX_FLGS_SPIN; + } + *scnt -= state; return 0; } } @@ -619,8 +640,7 @@ update_spincount(struct ethr_mutex_base_ *mtxb, int check_readers_array(ethr_rwmutex *rwmtx, int start_rix, - int length, - int pre_check); + int length); static ETHR_INLINE void write_lock_wait(struct ethr_mutex_base_ *mtxb, @@ -666,8 +686,7 @@ write_lock_wait(struct ethr_mutex_base_ *mtxb, } res = check_readers_array(rwmtx, freq_read_start_ix, - freq_read_size, - 1); + freq_read_size); scnt--; if (res == 0) { act = ethr_atomic_read(&mtxb->flgs); @@ -708,7 +727,6 @@ write_lock_wait(struct ethr_mutex_base_ *mtxb, act = ethr_atomic_read(&mtxb->flgs); scnt--; } - ETHR_ASSERT(scnt >= 0); exp = act; @@ -985,7 +1003,6 @@ enqueue_mtx(ethr_mutex *mtx, ethr_ts_event *tse_start, ethr_ts_event *tse_end) int ethr_cond_init_opt(ethr_cond *cnd, ethr_cond_opt *opt) { - int res; #if ETHR_XCHK if (!cnd) { ETHR_ASSERT(0); @@ -1085,7 +1102,6 @@ ethr_cond_signal(ethr_cond *cnd) void ethr_cond_broadcast(ethr_cond *cnd) { - int res; int got_all; ethr_ts_event *tse; ETHR_ASSERT(!ethr_not_inited__); @@ -1153,7 +1169,6 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx) { int woken; int scnt; - int res; void *udata = NULL; ethr_ts_event *tse; @@ -1466,17 +1481,11 @@ multiple_w_waiters(ethr_rwmutex *rwmtx) int check_readers_array(ethr_rwmutex *rwmtx, int start_rix, - int length, - int pre_check) + int length) { int ix = start_rix; -#ifndef ETHR_READ_MEMORY_BARRIER_IS_FULL - if (pre_check) - ETHR_READ_MEMORY_BARRIER; - else -#endif - ETHR_MEMORY_BARRIER; + ETHR_MEMORY_BARRIER; do { long act = rwmutex_freqread_rdrs_read(rwmtx, ix); @@ -1559,7 +1568,7 @@ rwmutex_try_complete_runlock(ethr_rwmutex *rwmtx, ethr_leave_ts_event(tse_tmp); if (check_before_try) { - res = check_readers_array(rwmtx, six, length, 1); + res = check_readers_array(rwmtx, six, length); if (res == EBUSY) return try_write_lock ? EBUSY : 0; } @@ -1597,7 +1606,7 @@ rwmutex_try_complete_runlock(ethr_rwmutex *rwmtx, } } - res = check_readers_array(rwmtx, six, length, 0); + res = check_readers_array(rwmtx, six, length); if (res == EBUSY) { act = ethr_atomic_dec_read(&rwmtx->mtxb.flgs); if (act & ETHR_RWMTX_R_MASK__) @@ -1691,7 +1700,7 @@ rwmutex_normal_rlock_wait(ethr_rwmutex *rwmtx, #endif while (act & (ETHR_RWMTX_W_FLG__|ETHR_RWMTX_W_WAIT_FLG__)) { - if (scnt == 0) { + if (scnt >= 0) { tse = ethr_get_ts_event(); if (update_spincount(&rwmtx->mtxb, tse, &start_scnt, &scnt)) { event_wait(&rwmtx->mtxb, tse, scnt, @@ -1708,7 +1717,6 @@ rwmutex_normal_rlock_wait(ethr_rwmutex *rwmtx, scnt--; } exp = act; - ETHR_ASSERT(scnt >= 0); #ifdef ETHR_RLOCK_WITH_INC_DEC act = ethr_atomic_inc_read(&rwmtx->mtxb.flgs); @@ -1749,7 +1757,7 @@ rwmutex_freqread_rlock_wait(ethr_rwmutex *rwmtx, act = ethr_atomic_read(&rwmtx->mtxb.flgs); while (act & ~(ETHR_RWMTX_R_FLG__|ETHR_RWMTX_R_WAIT_FLG__)) { - if (scnt == 0) { + if (scnt >= 0) { if (update_spincount(&rwmtx->mtxb, tse, &start_scnt, &scnt)) { event_wait(&rwmtx->mtxb, tse, scnt, ETHR_RWMTX_R_WAIT_FLG__, 1, 1); @@ -1765,8 +1773,6 @@ rwmutex_freqread_rlock_wait(ethr_rwmutex *rwmtx, scnt--; } - ETHR_ASSERT(scnt >= 0); - rwmutex_freqread_rdrs_inc(rwmtx, tse); ETHR_MEMORY_BARRIER; diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex 7b824f1ab4..222809e662 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 3cab91b722..65c7369b76 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam Binary files differindex 9f88ddd51e..f1b54b7fcb 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 4c9cc9675b..abf17bcb0e 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 9a4904b6a1..a3f300268f 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 71f6643368..a777971b32 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 c57d37725e..0fe38a1fb2 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 6b14d3fd66..7108bf44d0 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/test/Makefile b/erts/test/Makefile index 796403e182..94458da019 100644 --- a/erts/test/Makefile +++ b/erts/test/Makefile @@ -28,6 +28,7 @@ EBIN = . # ---------------------------------------------------- MODULES= \ + autoimport_SUITE \ erlc_SUITE \ install_SUITE \ nt_SUITE \ @@ -38,12 +39,14 @@ MODULES= \ erlexec_SUITE \ z_SUITE +ERL_XML = $(ERL_TOP)/erts/doc/src/erlang.xml +ERL_XML_TARGET = autoimport_SUITE_data/erlang.xml ERL_FILES= $(MODULES:%=%.erl) TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) -EXTRA_FILES = install_SUITE_data/install_bin +EXTRA_FILES = install_SUITE_data/install_bin $(ERL_XML_TARGET) # ---------------------------------------------------- # Release directory specification @@ -65,6 +68,10 @@ install_SUITE_data/install_bin: ../../make/install_bin rm -f $@ cp -p $< $@ +$(ERL_XML_TARGET): $(ERL_XML) + rm -f $@ + cp -p $< $@ + clean: rm -f $(TARGET_FILES) $(EXTRA_FILES) rm -f core *~ diff --git a/erts/test/autoimport_SUITE.erl b/erts/test/autoimport_SUITE.erl new file mode 100644 index 0000000000..2430dac78d --- /dev/null +++ b/erts/test/autoimport_SUITE.erl @@ -0,0 +1,163 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%% Purpose: Test erlang.xml re autoimports +-module(autoimport_SUITE). + +-include_lib("test_server/include/test_server.hrl"). +-export([all/1,init_per_testcase/2,fin_per_testcase/2,autoimports/1]). +-define(TEST_TIMEOUT, ?t:seconds(180)). + +all(suite) -> [autoimports]. + +init_per_testcase(_Func, Config) -> + Dog = test_server:timetrap(?TEST_TIMEOUT), + [{watchdog, Dog} | Config]. + +fin_per_testcase(_Func, Config) -> + Dog = ?config(watchdog, Config), + catch test_server:timetrap_cancel(Dog), + ok. + + +autoimports(suite) -> + []; +autoimports(doc) -> + ["Check that erlang.xml documents autoimports correctly"]; +autoimports(Config) when is_list(Config) -> + ?line XML = filename:join([?config(data_dir,Config),"erlang.xml"]), + ?line case xml(XML) of + [] -> + ok; + List -> + lists:foreach(fun({[],F,A}) -> + io:format("erlang:~s/~p is wrongly " + "documented as ~s/~p~n", + [F,A,F,A]); + ({"erlang",F,A}) -> + io:format("~s/~p is wrongly " + "documented as " + "erlang:~s/~p~n", + [F,A,F,A]) + end,List), + ?t:fail({wrong_autoimports,List}) + end. + +%% +%% Ugly chunk of code to heuristically analyze the erlang.xml +%% documentation file. Don't view this as an example... +%% + +xml(XMLFile) -> + {ok,File} = file:open(XMLFile,[read]), + DocData = xloop(file:read_line(File),File), + file:close(File), + analyze(DocData). + +xloop({ok,Line},File) -> + case re:run(Line,"\\<name\\>",[{capture,none}]) of + nomatch -> + xloop(file:read_line(File),File); + match -> + X = re:replace(Line,"\\).*",")",[{return,list}]), + Y = re:replace(X,".*\\>","",[{return,list}]), + Mod = get_module(Y), + Rest1 = fstrip(Mod++":",Y), + Func = get_function(Rest1), + Rest2 = fstrip(Func++"(", Rest1), + Argc = count_args(Rest2,1,0,false), + [{Mod,Func,Argc} | + xloop(file:read_line(File),File)] + end; +xloop(_,_) -> + []. + +analyze([{[],Func,Arity}|T]) -> + case erl_internal:bif(list_to_atom(Func),Arity) of + true -> + analyze(T); + false -> + [{[],Func,Arity} | + analyze(T)] + end; +analyze([{"erlang",Func,Arity}|T]) -> + case erl_internal:bif(list_to_atom(Func),Arity) of + true -> + [{"erlang",Func,Arity}|analyze(T)]; + false -> + analyze(T) + end; +analyze([_|T]) -> + analyze(T); +analyze([]) -> + []. + + +count_args([],_,N,false) -> + N; +count_args([],_,N,true) -> + N+1; +count_args(_,0,N,true) -> + N+1; +count_args(_,0,N,false) -> + N; +count_args([Par|T],Level,N,Got) when (Par =:= 40) or + (Par =:= 123) or (Par =:= 91) -> + count_args(T,Level+1,N,(Level =:= 1) or Got); +count_args([41|T],1,N,true) -> + count_args(T,0,N+1,false); +count_args([Par|T],Level,N, Got) when (Par =:= 41) or + (Par =:= 125) or (Par =:= 93) -> + count_args(T,Level-1,N,Got); +count_args([$,|T],1,N,true) -> + count_args(T,1,N+1,false); +count_args([$ |T],A,B,C) -> + count_args(T,A,B,C); +count_args([_|T],1,N,_) -> + count_args(T,1,N,true); +count_args([_|T],A,B,C) -> + count_args(T,A,B,C). + +fstrip([],X) -> + X; +fstrip(_,[]) -> + []; +fstrip([H|T1],[H|T2]) -> + fstrip(T1,T2); +fstrip(_,L) -> + L. + +get_module(X) -> + get_module(X,[]). +get_module([],_) -> + []; +get_module([$:|_],Acc) -> + lists:reverse(Acc); +get_module([40|_],_) -> %( + []; +get_module([H|T],Acc) -> + get_module(T,[H|Acc]). + +get_function(X) -> + get_function(X,[]). +get_function([],_) -> + []; +get_function([40|_],Acc) -> %( + lists:reverse(Acc); +get_function([H|T],Acc) -> + get_function(T,[H|Acc]). diff --git a/erts/test/autoimport_SUITE_data/dummy.txt b/erts/test/autoimport_SUITE_data/dummy.txt new file mode 100644 index 0000000000..972643e527 --- /dev/null +++ b/erts/test/autoimport_SUITE_data/dummy.txt @@ -0,0 +1,19 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% Purpouse: Dummy |