diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/.gitignore | 1 | ||||
-rw-r--r-- | erts/configure.in | 5 | ||||
-rw-r--r-- | erts/doc/src/erl_driver.xml | 37 | ||||
-rw-r--r-- | erts/emulator/beam/erl_ptab.c | 139 | ||||
-rw-r--r-- | erts/emulator/beam/erl_ptab.h | 2 | ||||
-rw-r--r-- | erts/emulator/test/Makefile | 3 | ||||
-rw-r--r-- | erts/emulator/test/emulator_smoke.spec | 3 | ||||
-rw-r--r-- | erts/etc/Makefile | 3 | ||||
-rw-r--r-- | erts/etc/unix/Makefile | 46 | ||||
-rw-r--r-- | erts/etc/unix/etp-commands.in (renamed from erts/etc/unix/etp-commands) | 4 | ||||
-rw-r--r-- | erts/etc/unix/etp-thr.py | 55 | ||||
-rw-r--r-- | erts/include/internal/ethread.h | 4 | ||||
-rw-r--r-- | erts/include/internal/gcc/ethread.h | 5 | ||||
-rw-r--r-- | erts/test/Makefile | 2 | ||||
-rw-r--r-- | erts/test/system_smoke.spec | 3 |
15 files changed, 237 insertions, 75 deletions
diff --git a/erts/.gitignore b/erts/.gitignore index 526d5da0b9..e515dc8811 100644 --- a/erts/.gitignore +++ b/erts/.gitignore @@ -11,6 +11,7 @@ /etc/common/Install /etc/common/erl.src +/etc/unix/etp-commands /test/Emakefile /test/*.beam diff --git a/erts/configure.in b/erts/configure.in index 2f624e5853..64436e933c 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -1051,12 +1051,15 @@ if test $ERTS_BUILD_SMP_EMU = yes; then AC_DEFINE(ERTS_HAVE_SMP_EMU, 1, [Define if the smp emulator is built]) + test "X$smp_require_native_atomics" = "Xyes" && + AC_DEFINE(ETHR_SMP_REQUIRE_NATIVE_IMPLS, 1, [Define if you want to enable check for native ethread implementations]) + case "$ethr_have_native_atomics-$smp_require_native_atomics-$ethr_have_native_spinlock" in yes-*) ;; no-yes-*) - AC_MSG_ERROR([No native atomic implementation found. See INSTALL.md for more information.]) + AC_MSG_ERROR([No native atomic implementation found. See Configuring section in INSTALL.md for more information.]) ;; no-no-yes) diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml index efe0483b31..f52d973709 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -666,7 +666,7 @@ typedef struct ErlDrvBinary { <item> <p>The <c>ErlDrvData</c> is a handle to driver-specific data, passed to the driver call-backs. It is a pointer, and is - most often type casted to a specific pointer in the driver.</p> + most often type cast to a specific pointer in the driver.</p> </item> <tag>SysIOVec</tag> <item> @@ -1014,7 +1014,7 @@ typedef struct ErlIOVec { <fsummary>Read a system timestamp</fsummary> <desc> <marker id="driver_get_now"></marker> - <p>This function reads a timestamp into the memory pointed to by + <p>This function reads a timestamp into the memory pointed to by the parameter <c>now</c>. See the description of <seealso marker="#ErlDrvNowData">ErlDrvNowData</seealso> for specification of its fields. </p> <p>The return value is 0 unless the <c>now</c> pointer is not @@ -1056,7 +1056,7 @@ typedef struct ErlIOVec { returned. Another thread may still be using the event object internally. To safely close an event object call <c>driver_select</c> with <c>ERL_DRV_USE</c> and <c>on==0</c>. That - will clear all events and then call + will clear all events and then call <seealso marker="driver_entry#stop_select">stop_select</seealso> when it is safe to close the event object. <c>ERL_DRV_USE</c> should be set together with the first event @@ -1068,7 +1068,7 @@ typedef struct ErlIOVec { <p>ERL_DRV_USE was added in OTP release R13. Old drivers will still work as before. But it is recommended to update them to use <c>ERL_DRV_USE</c> and <c>stop_select</c> to make sure that event objects are closed in a safe way.</p> - </note> + </note> <p>The return value is 0 (failure, -1, only if the <c>ready_input</c>/<c>ready_output</c> is <c>NULL</c>).</p> @@ -1524,7 +1524,7 @@ typedef struct ErlIOVec { <marker id="remove_driver_entry"></marker> <p>This function removes a driver entry <c>de</c> previously added with <c>add_driver_entry</c>.</p> - <p>Driver entries added by the <c>erl_ddll</c> erlang interface can + <p>Driver entries added by the <c>erl_ddll</c> erlang interface can not be removed by using this interface.</p> </desc> </func> @@ -1758,7 +1758,7 @@ typedef struct ErlIOVec { <pre> Term type Argument(s) =========================================== -ERL_DRV_NIL +ERL_DRV_NIL ERL_DRV_ATOM ErlDrvTermData atom (from driver_mk_atom(char *string)) ERL_DRV_INT ErlDrvSInt integer ERL_DRV_UINT ErlDrvUInt integer @@ -1779,11 +1779,11 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len signed integer data type <c>ErlDrvSInt</c> are 64 bits wide on a 64 bit runtime system and 32 bits wide on a 32 bit runtime system. They were introduced in erts version 5.6, - and replaced some of the <c>int</c> arguments in the list above. + and replaced some of the <c>int</c> arguments in the list above. </p> <p>The unsigned integer data type <c>ErlDrvUInt64</c> and the signed integer data type <c>ErlDrvSInt64</c> are always 64 bits - wide. They were introduced in erts version 5.7.4. + wide. They were introduced in erts version 5.7.4. </p> <p>To build the tuple <c>{tcp, Port, [100 | Binary]}</c>, the @@ -1879,7 +1879,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len <fsummary>Send term data from driver to port owner</fsummary> <desc> <marker id="driver_output_term"></marker> - <warning><p><c>driver_output_term()</c> is deferred and will + <warning><p><c>driver_output_term()</c> is deprecated and will be removed in the OTP-R17 release. Use <seealso marker="#erl_drv_send_term">erl_drv_output_term()</seealso> instead.</p> @@ -1937,7 +1937,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len <fsummary>Send term data to other process than port owner process</fsummary> <desc> <marker id="driver_send_term"></marker> - <warning><p><c>driver_send_term()</c> is deferred and will + <warning><p><c>driver_send_term()</c> is deprecated and will be removed in the OTP-R17 release. Use <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso> instead.</p> @@ -1998,7 +1998,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len The data should be freed in <c>async_free</c>, because it's called if <c>driver_async_cancel</c> is called.</p> <p>When the async operation is done, <seealso marker="driver_entry#ready_async">ready_async</seealso> driver - entry function is called. If <c>async_ready</c> is null in + entry function is called. If <c>ready_async</c> is null in the driver entry, the <c>async_free</c> function is called instead.</p> <p>The return value is a handle to the asynchronous task, which @@ -2035,7 +2035,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len as of OTP-R15B <c>driver_async_cancel()</c> is deprecated, and scheduled for removal in OTP-R16. It will currently always fail, and return 0.</p> - <warning><p><c>driver_async_cancel()</c> is deferred and will + <warning><p><c>driver_async_cancel()</c> is deprecated and will be removed in the OTP-R16 release.</p> </warning> @@ -2048,7 +2048,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len <marker id="driver_lock_driver"></marker> <p>This function locks the driver used by the port <c>port</c> in memory for the rest of the emulator process' - lifetime. After this call, the driver behaves as one of Erlang's + lifetime. After this call, the driver behaves as one of Erlang's statically linked in drivers.</p> </desc> </func> @@ -2076,7 +2076,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len <seealso marker="driver_entry">driver_entry</seealso>).</item> <tag><c>drv_data</c></tag> <item>The driver defined handle that will be passed in subsequent - calls to driver call-backs. Note, that the + calls to driver call-backs. Note, that the <seealso marker="driver_entry#start">driver start call-back</seealso> will not be called for this new driver instance. The driver defined handle is normally created in the @@ -2284,7 +2284,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len <item>A thread identifier.</item> </taglist> <p>This function compares two thread identifiers for equality, - and returns <c>0</c> it they aren't equal, and + and returns <c>0</c> it they aren't equal, and a value not equal to <c>0</c> if they are equal.</p> <note><p>A Thread identifier may be reused very quickly after a thread has terminated. Therefore, if a thread @@ -2469,7 +2469,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len </taglist> <p>This function broadcasts on a condition variable. That is, if other threads are waiting on the condition variable being - broadcasted on, <em>all</em> of them will be woken. + broadcast on, <em>all</em> of them will be woken. </p> <p>This function is thread-safe.</p> </desc> @@ -2498,7 +2498,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len the calling thread when calling this function. </p> <note><p><c>erl_drv_cond_wait()</c> might return even though - no-one has signaled or broadcasted on the condition + no-one has signaled or broadcast on the condition variable. Code calling <c>erl_drv_cond_wait()</c> should always be prepared for <c>erl_drv_cond_wait()</c> returning even though the condition that the thread was @@ -2822,7 +2822,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len <item>A pointer to an output buffer.</item> <tag><c>value_size</c></tag> <item>A pointer to an integer. The integer is both used for - passing input and output sizes (see below). + passing input and output sizes (see below). </item> </taglist> <p>This function retrieves the value of an environment variable. @@ -2900,4 +2900,3 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len Guide Ch. 3)</p> </section> </cref> - diff --git a/erts/emulator/beam/erl_ptab.c b/erts/emulator/beam/erl_ptab.c index d69619dd44..fa5482b841 100644 --- a/erts/emulator/beam/erl_ptab.c +++ b/erts/emulator/beam/erl_ptab.c @@ -433,7 +433,7 @@ erts_ptab_mem_size(ErtsPTab *ptab) { UWord size = ptab->r.o.max*sizeof(erts_smp_atomic_t); if (ptab->r.o.free_id_data) - size += ptab->r.o.max*sizeof(Uint32); + size += ptab->r.o.max*sizeof(erts_smp_atomic32_t); return size; } @@ -474,7 +474,7 @@ erts_ptab_init_table(ErtsPTab *ptab, tab_sz = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(size*sizeof(erts_smp_atomic_t)); alloc_sz = tab_sz; if (!legacy) - alloc_sz += ERTS_ALC_CACHE_LINE_ALIGN_SIZE(size*sizeof(Uint32)); + alloc_sz += ERTS_ALC_CACHE_LINE_ALIGN_SIZE(size*sizeof(erts_smp_atomic32_t)); ptab->r.o.tab = erts_alloc_permanent_cache_aligned(atype, alloc_sz); tab_end = ((char *) ptab->r.o.tab) + tab_sz; tab_entry = ptab->r.o.tab; @@ -497,6 +497,10 @@ erts_ptab_init_table(ErtsPTab *ptab, ASSERT(ptab->r.o.pix_cl_shift + ptab->r.o.pix_cli_shift == bits); + ptab->r.o.invalid_element = invalid_element; + ptab->r.o.invalid_data = erts_ptab_id2data(ptab, invalid_element->id); + ptab->r.o.release_element = release_element; + if (legacy) { ptab->r.o.free_id_data = NULL; ptab->r.o.dix_cl_mask = 0; @@ -506,11 +510,11 @@ erts_ptab_init_table(ErtsPTab *ptab, } else { - tab_sz = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(size*sizeof(Uint32)); - ptab->r.o.free_id_data = (Uint32 *) tab_end; + tab_sz = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(size*sizeof(erts_smp_atomic32_t)); + ptab->r.o.free_id_data = (erts_smp_atomic32_t *) tab_end; tab_cache_lines = tab_sz/ERTS_CACHE_LINE_SIZE; - ix_per_cache_line = (ERTS_CACHE_LINE_SIZE/sizeof(Uint32)); + ix_per_cache_line = (ERTS_CACHE_LINE_SIZE/sizeof(erts_smp_atomic32_t)); ptab->r.o.dix_cl_mask = tab_cache_lines-1; ptab->r.o.dix_cl_shift = erts_fit_in_bits_int32(ix_per_cache_line-1); @@ -525,7 +529,9 @@ erts_ptab_init_table(ErtsPTab *ptab, ix = 0; for (cl = 0; cl < tab_cache_lines; cl++) { for (cli = 0; cli < ix_per_cache_line; cli++) { - ptab->r.o.free_id_data[ix] = cli*tab_cache_lines+cl; + erts_smp_atomic32_init_nob(&ptab->r.o.free_id_data[ix], + cli*tab_cache_lines+cl); + ASSERT(erts_smp_atomic32_read_nob(&ptab->r.o.free_id_data[ix]) != ptab->r.o.invalid_data); ix++; } } @@ -534,9 +540,6 @@ erts_ptab_init_table(ErtsPTab *ptab, erts_smp_atomic32_init_nob(&ptab->vola.tile.fid_ix, -1); } - ptab->r.o.invalid_element = invalid_element; - ptab->r.o.invalid_data = erts_ptab_id2data(ptab, invalid_element->id); - ptab->r.o.release_element = release_element; erts_smp_interval_init(&ptab->list.data.interval); ptab->list.data.deleted.start = NULL; @@ -606,11 +609,13 @@ erts_ptab_new_element(ErtsPTab *ptab, = erts_smp_current_interval_nob(erts_ptab_interval(ptab)); if (ptab->r.o.free_id_data) { + do { + ix = (Uint32) erts_smp_atomic32_inc_read_acqb(&ptab->vola.tile.aid_ix); + ix = ix_to_free_id_data_ix(ptab, ix); - ix = (Uint32) erts_smp_atomic32_inc_read_acqb(&ptab->vola.tile.aid_ix); - ix = ix_to_free_id_data_ix(ptab, ix); - - data = ptab->r.o.free_id_data[ix]; + data = erts_smp_atomic32_xchg_nob(&ptab->r.o.free_id_data[ix], + (erts_aint32_t)ptab->r.o.invalid_data); + }while ((Eterm)data == ptab->r.o.invalid_data); init_ptab_el(init_arg, (Eterm) data); @@ -763,7 +768,7 @@ erts_ptab_delete_element(ErtsPTab *ptab, erts_smp_atomic_set_relb(&ptab->r.o.tab[pix], ERTS_AINT_NULL); if (ptab->r.o.free_id_data) { - + Uint32 prev_data; /* Next data for this slot... */ data = (Uint32) erts_ptab_id2data(ptab, ptab_el->id); data += ptab->r.o.max; @@ -772,14 +777,17 @@ erts_ptab_delete_element(ErtsPTab *ptab, data += ptab->r.o.max; data &= ~(~((Uint32) 0) << ERTS_PTAB_ID_DATA_SIZE); } - ASSERT(data != ptab->r.o.invalid_data); ASSERT(pix == erts_ptab_data2pix(ptab, data)); - ix = (Uint32) erts_smp_atomic32_inc_read_relb(&ptab->vola.tile.fid_ix); - ix = ix_to_free_id_data_ix(ptab, ix); - - ptab->r.o.free_id_data[ix] = data; + do { + ix = (Uint32) erts_smp_atomic32_inc_read_relb(&ptab->vola.tile.fid_ix); + ix = ix_to_free_id_data_ix(ptab, ix); + + prev_data = erts_smp_atomic32_cmpxchg_nob(&ptab->r.o.free_id_data[ix], + data, + ptab->r.o.invalid_data); + }while ((Eterm)prev_data != ptab->r.o.invalid_data); } ASSERT(erts_smp_atomic32_read_nob(&ptab->vola.tile.count) > 0); @@ -1392,6 +1400,31 @@ erts_ptab_init(void) * Debug stuff */ +static void assert_ptab_consistency(ErtsPTab *ptab) +{ +#ifdef DEBUG + if (ptab->r.o.free_id_data) { + Uint32 ix, pix, data; + int free_pids = 0; + int null_slots = 0; + + for (ix=0; ix < ptab->r.o.max; ix++) { + if (erts_smp_atomic32_read_nob(&ptab->r.o.free_id_data[ix]) != ptab->r.o.invalid_data) { + ++free_pids; + data = erts_smp_atomic32_read_nob(&ptab->r.o.free_id_data[ix]); + pix = erts_ptab_data2pix(ptab, (Eterm) data); + ASSERT(erts_ptab_pix2intptr_nob(ptab, pix) == ERTS_AINT_NULL); + } + if (erts_smp_atomic_read_nob(&ptab->r.o.tab[ix]) == ERTS_AINT_NULL) { + ++null_slots; + } + } + ASSERT(free_pids == null_slots); + ASSERT(free_pids == ptab->r.o.max - erts_smp_atomic32_read_nob(&ptab->vola.tile.count)); + } +#endif +} + Sint erts_ptab_test_next_id(ErtsPTab *ptab, int set, Uint next) { @@ -1402,46 +1435,49 @@ erts_ptab_test_next_id(ErtsPTab *ptab, int set, Uint next) erts_ptab_rwlock(ptab); + assert_ptab_consistency(ptab); + if (ptab->r.o.free_id_data) { - Uint32 aid_ix, dix; + Uint32 id_ix, dix; if (set) { - Uint32 max_ix, ser, num, start; + Uint32 i, max_ix, num, stop_id_ix; max_ix = ptab->r.o.max - 1; - ser = next & ~max_ix; - start = num = next & max_ix; - - aid_ix = (Uint32) erts_smp_atomic32_read_nob(&ptab->vola.tile.aid_ix) + 1; - - do { - Uint32 pix = erts_ptab_data2pix(ptab, num); + num = next; + id_ix = (Uint32) erts_smp_atomic32_read_nob(&ptab->vola.tile.aid_ix); + + for (i=0; i <= max_ix; ++i) { + Uint32 pix; + ++num; + num &= ~(~((Uint32) 0) << ERTS_PTAB_ID_DATA_SIZE); + if (num == ptab->r.o.invalid_data) { + num += ptab->r.o.max; + num &= ~(~((Uint32) 0) << ERTS_PTAB_ID_DATA_SIZE); + } + pix = erts_ptab_data2pix(ptab, num); if (ERTS_AINT_NULL == erts_ptab_pix2intptr_nob(ptab, pix)) { - dix = ix_to_free_id_data_ix(ptab, aid_ix); - ptab->r.o.free_id_data[dix] = ser + num; - ASSERT(pix == erts_ptab_data2pix(ptab, ser+num)); - if (aid_ix == max_ix) - aid_ix = 0; - else - aid_ix++; + ++id_ix; + dix = ix_to_free_id_data_ix(ptab, id_ix); + erts_smp_atomic32_set_nob(&ptab->r.o.free_id_data[dix], num); + ASSERT(pix == erts_ptab_data2pix(ptab, num)); } - if (num == max_ix) - num = 0; - else - num++; - } while (num != start); + } + erts_smp_atomic32_set_nob(&ptab->vola.tile.fid_ix, id_ix); -#ifdef DEBUG - if (aid_ix == 0) - aid_ix = max_ix; - else - aid_ix--; - ASSERT((aid_ix & max_ix) == (((Uint32) erts_smp_atomic32_read_nob(&ptab->vola.tile.fid_ix)) & max_ix)); -#endif + /* Write invalid_data in rest of free_id_data[]: */ + stop_id_ix = (1 + erts_smp_atomic32_read_nob(&ptab->vola.tile.aid_ix)) & max_ix; + while (1) { + id_ix = (id_ix+1) & max_ix; + if (id_ix == stop_id_ix) + break; + dix = ix_to_free_id_data_ix(ptab, id_ix); + erts_smp_atomic32_set_nob(&ptab->r.o.free_id_data[dix], + ptab->r.o.invalid_data); + } } - - aid_ix = (Uint32) erts_smp_atomic32_read_nob(&ptab->vola.tile.aid_ix) + 1; - dix = ix_to_free_id_data_ix(ptab, aid_ix); - res = (Sint) ptab->r.o.free_id_data[dix]; + id_ix = (Uint32) erts_smp_atomic32_read_nob(&ptab->vola.tile.aid_ix) + 1; + dix = ix_to_free_id_data_ix(ptab, id_ix); + res = (Sint) erts_smp_atomic32_read_nob(&ptab->r.o.free_id_data[dix]); } else { /* Deprecated legacy algorithm... */ @@ -1485,6 +1521,7 @@ erts_ptab_test_next_id(ErtsPTab *ptab, int set, Uint next) } } + assert_ptab_consistency(ptab); erts_ptab_rwunlock(ptab); return res; diff --git a/erts/emulator/beam/erl_ptab.h b/erts/emulator/beam/erl_ptab.h index c2d8bd9cad..e3e05f14af 100644 --- a/erts/emulator/beam/erl_ptab.h +++ b/erts/emulator/beam/erl_ptab.h @@ -100,7 +100,7 @@ typedef struct { typedef struct { erts_smp_atomic_t *tab; - Uint32 *free_id_data; + erts_smp_atomic32_t *free_id_data; Uint32 max; Uint32 pix_mask; Uint32 pix_cl_mask; diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 9594ab48b1..f02ca3cb98 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -140,7 +140,8 @@ EMAKEFILE=Emakefile TEST_SPEC_FILES= emulator.spec \ emulator.spec.win \ - emulator_bench.spec + emulator_bench.spec \ + emulator_smoke.spec # ---------------------------------------------------- # Release directory specification diff --git a/erts/emulator/test/emulator_smoke.spec b/erts/emulator/test/emulator_smoke.spec new file mode 100644 index 0000000000..3219aeb823 --- /dev/null +++ b/erts/emulator/test/emulator_smoke.spec @@ -0,0 +1,3 @@ +{suites,"../emulator_test",[smoke_test_SUITE,time_SUITE]}. +{cases,"../emulator_test",crypto_SUITE,[t_md5]}. +{cases,"../emulator_test",float_SUITE,[fpe,cmp_integer]}.
\ No newline at end of file diff --git a/erts/etc/Makefile b/erts/etc/Makefile index 2b32b8ae50..5b54ef9c3e 100644 --- a/erts/etc/Makefile +++ b/erts/etc/Makefile @@ -18,10 +18,11 @@ # include $(ERL_TOP)/make/target.mk - SUB_DIRECTORIES = common ifeq ($(TARGET),win32) SUB_DIRECTORIES += win32 +else +SUB_DIRECTORIES += unix endif include $(ERL_TOP)/make/otp_subdir.mk diff --git a/erts/etc/unix/Makefile b/erts/etc/unix/Makefile new file mode 100644 index 0000000000..e85d2fab0c --- /dev/null +++ b/erts/etc/unix/Makefile @@ -0,0 +1,46 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2013. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include $(ERL_TOP)/make/output.mk +include $(ERL_TOP)/make/target.mk + +include $(ERL_TOP)/make/$(TARGET)/otp.mk +include ../../vsn.mk + +opt debug: etc + +.PHONY: etc +etc: etp-commands + +etp-commands: etp-commands.in + sed 's:@ERL_TOP@:${ERL_TOP}:g' etp-commands.in > etp-commands + +.PHONY: docs +docs: + +.PHONY: clean +clean: + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +.PHONY: release_spec +release_spec: etc
\ No newline at end of file diff --git a/erts/etc/unix/etp-commands b/erts/etc/unix/etp-commands.in index 35f75df5c1..54ff7b3e3a 100644 --- a/erts/etc/unix/etp-commands +++ b/erts/etc/unix/etp-commands.in @@ -2757,6 +2757,10 @@ document etp-run %--------------------------------------------------------------------------- end +define etp-thr + source @ERL_TOP@/erts/etc/unix/etp-thr.py +end + ############################################################################ # Toolbox parameter handling # diff --git a/erts/etc/unix/etp-thr.py b/erts/etc/unix/etp-thr.py new file mode 100644 index 0000000000..64fb858d20 --- /dev/null +++ b/erts/etc/unix/etp-thr.py @@ -0,0 +1,55 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2013. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +def get_thread_name(t): + f = gdb.newest_frame(); + while f: + if f.name() == "async_main": + return "async"; + elif f.name() == "erts_sys_main_thread": + return "main"; + elif f.name() == "signal_dispatcher_thread_func": + return "signal_dispatcher"; + elif f.name() == "sys_msg_dispatcher_func": + return "sys_msg_dispatcher"; + elif f.name() == "child_waiter": + return "child_waiter"; + elif f.name() == "sched_thread_func": + return "scheduler"; + elif f.name() == "aux_thread": + return "aux"; + f = f.older(); + return "unknown"; + + +curr_thread = gdb.selected_thread(); + +for i in gdb.inferiors(): + gdb.write(" Id Thread Name Frame\n"); + for t in i.threads(): + t.switch(); + if curr_thread == t: + gdb.write("*"); + else: + gdb.write(" "); + gdb.write("{0:<3} {1:20} {2}\n".format( + t.num,get_thread_name(t), + gdb.newest_frame().name())); + +curr_thread.switch(); diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h index 407097d4b1..38b8e9e9b6 100644 --- a/erts/include/internal/ethread.h +++ b/erts/include/internal/ethread.h @@ -361,6 +361,10 @@ extern ethr_runtime_t ethr_runtime__; # endif #endif /* !ETHR_DISABLE_NATIVE_IMPLS */ +#if !defined(ETHR_HAVE_NATIVE_ATOMIC32) && !defined(ETHR_HAVE_NATIVE_ATOMIC64) && !defined(ETHR_DISABLE_NATIVE_IMPLS) && defined(ETHR_SMP_REQUIRE_NATIVE_IMPLS) +#error "No native ethread implementation found. If you want to use fallbacks you have to disable native ethread support with configure." +#endif + #include "ethr_atomics.h" /* The atomics API */ #if defined(__GNUC__) diff --git a/erts/include/internal/gcc/ethread.h b/erts/include/internal/gcc/ethread.h index fcfdc39441..365a3535cf 100644 --- a/erts/include/internal/gcc/ethread.h +++ b/erts/include/internal/gcc/ethread.h @@ -25,6 +25,9 @@ #ifndef ETHREAD_GCC_H__ #define ETHREAD_GCC_H__ +#if defined(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32) \ + || defined(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64) + #ifndef ETHR_MEMBAR # include "ethr_membar.h" #endif @@ -46,3 +49,5 @@ #endif #endif + +#endif diff --git a/erts/test/Makefile b/erts/test/Makefile index 6b409e2f1b..74a5bb1ccc 100644 --- a/erts/test/Makefile +++ b/erts/test/Makefile @@ -79,7 +79,7 @@ release_spec: release_tests_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)" - $(INSTALL_DATA) system.spec system.dynspec \ + $(INSTALL_DATA) system.spec system.dynspec system_smoke.spec \ $(ERL_FILES) $(TARGET_FILES) "$(RELSYSDIR)" chmod -R u+w "$(RELSYSDIR)" tar cf - *_SUITE_data utils | (cd "$(RELSYSDIR)"; tar xf -) diff --git a/erts/test/system_smoke.spec b/erts/test/system_smoke.spec new file mode 100644 index 0000000000..933d1ba22d --- /dev/null +++ b/erts/test/system_smoke.spec @@ -0,0 +1,3 @@ +{suites,"../system_test",[ethread_SUITE]}. +{cases,"../system_test",otp_SUITE,[undefined_functions]}. +{skip_cases,"../system_test",ethread_SUITE,[max_threads],"Skip"}. |