aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2010-12-22 15:14:39 +0100
committerSverker Eriksson <[email protected]>2011-02-03 17:33:44 +0100
commit0b09ffabadd38bd2d0fa9cfa735542defc380efc (patch)
treed061b64f2ca8806f961754d78b518c9735e48437
parent359517b5177756d871b91757160e6840e0fbfe4a (diff)
downloadotp-0b09ffabadd38bd2d0fa9cfa735542defc380efc.tar.gz
otp-0b09ffabadd38bd2d0fa9cfa735542defc380efc.tar.bz2
otp-0b09ffabadd38bd2d0fa9cfa735542defc380efc.zip
HALFWORD ETS 32-bit arch fixes and other cleanups
-rw-r--r--erts/emulator/beam/erl_db.c3
-rw-r--r--erts/emulator/beam/erl_db_tree.c4
-rw-r--r--erts/emulator/beam/erl_db_util.c10
-rw-r--r--erts/emulator/beam/erl_lock_check.c2
-rw-r--r--erts/emulator/beam/erl_term.h69
-rw-r--r--erts/emulator/beam/sys.h6
-rw-r--r--erts/emulator/sys/common/erl_mseg.c81
-rw-r--r--lib/stdlib/test/ets_SUITE.erl4
8 files changed, 95 insertions, 84 deletions
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index 914eedce0c..02f16899ae 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -3501,7 +3501,6 @@ static void set_heir(Process* me, DbTable* tb, Eterm heir, UWord heir_data)
/* Make a dummy 1-tuple around data to use DbTerm */
wrap_tpl = TUPLE1(tmp,heir_data);
size = size_object(wrap_tpl);
- /* SVERK: Must be low memory due to erts_send_message */
dbterm = erts_db_alloc(ERTS_ALC_T_DB_HEIR_DATA, (DbTable *)tb,
(sizeof(DbTerm) + sizeof(Eterm)*(size-1)));
dbterm->size = size;
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index d9330a3bbf..d4f02f9117 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -2753,7 +2753,7 @@ static Sint cmp_partly_bound(Eterm partly_bound_key, Eterm bound_key, Eterm* bk_
erts_fprintf(stderr," > ");
else
erts_fprintf(stderr," == ");
- erts_fprintf(stderr,"%T\n",bound_key); // SVERK: printing rterm
+ erts_fprintf(stderr,"%T\n",bound_key); // HALFWORD BUG: printing rterm
#endif
return ret;
}
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 3883ff69fa..7a6a811a60 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -1915,11 +1915,13 @@ restart:
*esp++ = hp[n];
break;
case matchPushExpr:
- ASSERT(is_tuple_rel(term,base));
#if HALFWORD_HEAP
if (base) {
- Uint sz = size_object_rel(term, base);
- Eterm* top = HAlloc(psp, sz);
+ Uint sz;
+ Eterm* top;
+ ASSERT(is_tuple_rel(term,base)); /* assume ETS */
+ sz = size_object_rel(term, base);
+ top = HAlloc(psp, sz);
*esp++ = copy_shallow_rel(tuple_val_rel(term,base), sz,
&top, &MSO(psp), base);
break;
diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c
index 0185baee6b..7cd379d2c8 100644
--- a/erts/emulator/beam/erl_lock_check.c
+++ b/erts/emulator/beam/erl_lock_check.c
@@ -155,7 +155,7 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "alcu_allocator", "index" },
{ "alcu_delayed_free", "index" },
{ "mseg", NULL },
-#ifdef HALFWORD_HEAP
+#if HALFWORD_HEAP
{ "pmmap", NULL },
#endif
#ifdef ERTS_SMP
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index 1225b6a944..161093434f 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -359,7 +359,6 @@ _ET_DECLARE_CHECKED(Eterm*,binary_val,Wterm)
#define is_fun_header(x) ((x) == HEADER_FUN)
#define make_fun(x) make_boxed((Eterm*)(x))
#define is_fun(x) (is_boxed((x)) && is_fun_header(*boxed_val((x))))
-#define is_fun_rel(x,Base) (is_boxed((x)) && is_fun_header(*boxed_val_rel((x),Base)))
#define is_not_fun(x) (!is_fun((x)))
#define _unchecked_fun_val(x) _unchecked_boxed_val((x))
_ET_DECLARE_CHECKED(Eterm*,fun_val,Wterm)
@@ -368,7 +367,6 @@ _ET_DECLARE_CHECKED(Eterm*,fun_val,Wterm)
/* export access methods */
#define make_export(x) make_boxed((x))
#define is_export(x) (is_boxed((x)) && is_export_header(*boxed_val((x))))
-#define is_export_rel(x,Base) (is_boxed((x)) && is_export_header(*boxed_val_rel((x),Base)))
#define is_not_export(x) (!is_export((x)))
#define _unchecked_export_val(x) _unchecked_boxed_val(x)
_ET_DECLARE_CHECKED(Eterm*,export_val,Wterm)
@@ -396,7 +394,6 @@ _ET_DECLARE_CHECKED(Uint,bignum_header_arity,Eterm)
#define BIG_ARITY_MAX ((1 << 19)-1)
#define make_big(x) make_boxed((x))
#define is_big(x) (is_boxed((x)) && _is_bignum_header(*boxed_val((x))))
-#define is_big_rel(x,Base) (is_boxed((x)) && _is_bignum_header(*boxed_val_rel((x),Base)))
#define is_not_big(x) (!is_big((x)))
#define _unchecked_big_val(x) _unchecked_boxed_val((x))
_ET_DECLARE_CHECKED(Eterm*,big_val,Wterm)
@@ -410,7 +407,6 @@ _ET_DECLARE_CHECKED(Eterm*,big_val,Wterm)
#endif
#define make_float(x) make_boxed((x))
#define is_float(x) (is_boxed((x)) && *boxed_val((x)) == HEADER_FLONUM)
-#define is_float_rel(x,Base) (is_boxed((x)) && *boxed_val_rel((x),Base) == HEADER_FLONUM)
#define is_not_float(x) (!is_float(x))
#define _unchecked_float_val(x) _unchecked_boxed_val((x))
_ET_DECLARE_CHECKED(Eterm*,float_val,Wterm)
@@ -451,8 +447,7 @@ typedef union float_def
*(((Uint *) (p))+1) = (f).fw[1]
#endif
-#define GET_DOUBLE(x, f) FLOAT_VAL_GET_DOUBLE(float_val(x),f)
-#define GET_DOUBLE_REL(x, f, Base) FLOAT_VAL_GET_DOUBLE(float_val_rel(x,Base),f)
+#define GET_DOUBLE(x, f) FLOAT_VAL_GET_DOUBLE(float_val(x), f)
#define DOUBLE_DATA_WORDS (sizeof(ieee754_8)/sizeof(Eterm))
#define FLOAT_SIZE_OBJECT (DOUBLE_DATA_WORDS+1)
@@ -460,7 +455,6 @@ typedef union float_def
/* tuple access methods */
#define make_tuple(x) make_boxed((x))
#define is_tuple(x) (is_boxed((x)) && is_arity_value(*boxed_val((x))))
-#define is_tuple_rel(x,Base) (is_boxed((x)) && is_arity_value(*boxed_val_rel((x),Base)))
#define is_not_tuple(x) (!is_tuple((x)))
#define is_tuple_arity(x, a) \
(is_boxed((x)) && *boxed_val((x)) == make_arityval((a)))
@@ -803,14 +797,10 @@ do { \
((RefThing*) _unchecked_internal_ref_val(x))
#define ref_thing_ptr(x) \
((RefThing*) internal_ref_val(x))
-#define ref_thing_ptr_rel(x,Base) \
- ((RefThing*) internal_ref_val_rel(x,Base))
-
#define is_internal_ref(x) \
- (_unchecked_is_boxed((x)) && is_ref_thing_header(*boxed_val((x))))
-#define is_internal_ref_rel(x,Base) \
- (_unchecked_is_boxed((x)) && is_ref_thing_header(*boxed_val_rel((x),Base)))
+ (_unchecked_is_boxed((x)) && is_ref_thing_header(*boxed_val((x))))
+
#define is_not_internal_ref(x) \
(!is_internal_ref((x)))
@@ -911,20 +901,14 @@ typedef struct external_thing_ {
#define is_external_header(x) \
(((x) & (_TAG_HEADER_MASK-_BINARY_XXX_MASK)) == _TAG_HEADER_EXTERNAL_PID)
-#define is_external(x) \
- (is_boxed((x)) && is_external_header(*boxed_val((x))))
-#define is_external_rel(x,Base) \
- (is_boxed((x)) && is_external_header(*boxed_val_rel((x),Base)))
+#define is_external(x) (is_boxed((x)) && is_external_header(*boxed_val((x))))
+
#define is_external_pid(x) \
(is_boxed((x)) && is_external_pid_header(*boxed_val((x))))
#define is_external_port(x) \
- (is_boxed((x)) && is_external_port_header(*boxed_val((x))))
-#define is_external_port_rel(x,Base) \
- (is_boxed((x)) && is_external_port_header(*boxed_val_rel((x),Base)))
-#define is_external_ref(x) \
- (_unchecked_is_boxed((x)) && is_external_ref_header(*boxed_val((x))))
-#define is_external_ref_rel(x,Base) \
- (_unchecked_is_boxed((x)) && is_external_ref_header(*boxed_val_rel((x),Base)))
+ (is_boxed((x)) && is_external_port_header(*boxed_val((x))))
+
+#define is_external_ref(x) (_unchecked_is_boxed((x)) && is_external_ref_header(*boxed_val((x))))
#define _unchecked_is_external(x) \
(_unchecked_is_boxed((x)) && is_external_header(*_unchecked_boxed_val((x))))
@@ -958,15 +942,12 @@ _ET_DECLARE_CHECKED(Uint,external_thing_data_words,ExternalThing*)
_unchecked_external_thing_data_words(_unchecked_external_thing_ptr((x)))
_ET_DECLARE_CHECKED(Uint,external_data_words,Wterm)
#define external_data_words(x) _ET_APPLY(external_data_words,(x))
-#define external_data_words_rel(x,Base) \
- external_thing_data_words(external_thing_ptr_rel((x),Base))
#define _unchecked_external_data(x) (_unchecked_external_thing_ptr((x))->data.ui)
#define _unchecked_external_node(x) (_unchecked_external_thing_ptr((x))->node)
#define external_data(x) (external_thing_ptr((x))->data.ui)
#define external_node(x) (external_thing_ptr((x))->node)
-#define external_node_rel(x,Base) (external_thing_ptr_rel((x),Base)->node)
#define _unchecked_external_pid_data_words(x) \
_unchecked_external_data_words((x))
@@ -1141,13 +1122,11 @@ extern unsigned tag_val_def(Wterm);
#if HALFWORD_HEAP
#define ptr2rel(PTR,BASE) ((Eterm*)((char*)(PTR) - (char*)(BASE)))
-#define rel2ptr(REL,BASE) ((typeof(REL)) ((UWord)(REL) + (char*)(BASE)))
#define rterm2wterm(REL,BASE) ((Wterm)(REL) + (Wterm)(BASE))
#else /* HALFWORD_HEAP */
#define ptr2rel(PTR,BASE) (PTR)
-#define rel2ptr(REL,BASE) (REL)
#define rterm2wterm(REL,BASE) (REL)
#endif /* !HALFWORD_HEAP */
@@ -1170,6 +1149,8 @@ extern unsigned tag_val_def(Wterm);
#define internal_ref_val_rel(RTERM,BASE) internal_ref_val(rterm2wterm(RTERM,BASE))
#define external_thing_ptr_rel(RTERM, BASE) external_thing_ptr(rterm2wterm(RTERM, BASE))
+#define external_data_words_rel(RTERM,BASE) external_data_words(rterm2wterm(RTERM,BASE))
+
#define external_port_node_rel(RTERM,BASE) external_port_node(rterm2wterm(RTERM,BASE))
#define external_port_data_rel(RTERM,BASE) external_port_data(rterm2wterm(RTERM,BASE))
@@ -1178,6 +1159,22 @@ extern unsigned tag_val_def(Wterm);
#define external_pid_data_rel(RTERM,BASE) external_pid_data(rterm2wterm(RTERM,BASE))
#define is_binary_rel(RTERM,BASE) is_binary(rterm2wterm(RTERM,BASE))
+#define is_float_rel(RTERM,BASE) is_float(rterm2wterm(RTERM,BASE))
+#define is_fun_rel(RTERM,BASE) is_fun(rterm2wterm(RTERM,BASE))
+#define is_big_rel(RTERM,BASE) is_big(rterm2wterm(RTERM,BASE))
+#define is_export_rel(RTERM,BASE) is_export(rterm2wterm(RTERM,BASE))
+#define is_tuple_rel(RTERM,BASE) is_tuple(rterm2wterm(RTERM,BASE))
+
+#define GET_DOUBLE_REL(RTERM, f, BASE) GET_DOUBLE(rterm2wterm(RTERM,BASE), f)
+
+#define ref_thing_ptr_rel(RTERM,BASE) ref_thing_ptr(rterm2wterm(RTERM,BASE))
+#define is_internal_ref_rel(RTERM,BASE) is_internal_ref(rterm2wterm(RTERM,BASE))
+#define is_external_rel(RTERM,BASE) is_external(rterm2wterm(RTERM,BASE))
+#define is_external_port_rel(RTERM,BASE) is_external_port(rterm2wterm(RTERM,BASE))
+#define is_external_ref_rel(RTERM,BASE) is_external_ref(rterm2wterm(RTERM,BASE))
+
+#define external_node_rel(RTERM,BASE) external_node(rterm2wterm(RTERM,BASE))
+
#if HALFWORD_HEAP
ERTS_GLB_INLINE int is_same(Eterm a, Eterm* a_base, Eterm b, Eterm* b_base);
@@ -1185,12 +1182,12 @@ ERTS_GLB_INLINE int is_same(Eterm a, Eterm* a_base, Eterm b, Eterm* b_base);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_INLINE int is_same(Eterm a, Eterm* a_base, Eterm b, Eterm* b_base)
{
- if (a_base == b_base) {
- return a == b;
- }
- /* Assume a and b are on different "heaps", ie can only be same if immed */
- ASSERT(is_immed(a) || is_immed(b) || rterm2wterm(a,a_base) != rterm2wterm(b,b_base));
- return is_immed(a) && a == b;
+ /* If bases differ, assume a and b are on different "heaps",
+ ie can only be same if immed */
+ ASSERT(a_base == b_base || is_immed(a) || is_immed(b)
+ || rterm2wterm(a,a_base) != rterm2wterm(b,b_base));
+
+ return a == b && (a_base == b_base || is_immed(a));
}
#endif
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index e36f7cf8cf..d480229999 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -225,16 +225,14 @@ int real_printf(const char *fmt, ...);
#else
#error Neither 32 nor 64 bit architecture
#endif
-#ifdef ARCH_64
-# ifdef HALFWORD_HEAP_EMULATOR
+#if defined(ARCH_64) && defined(HALFWORD_HEAP_EMULATOR)
# define HALFWORD_HEAP 1
# define HALFWORD_ASSERT 0
# define ASSERT_HALFWORD(COND) ASSERT(COND)
-# else
+#else
# define HALFWORD_HEAP 0
# define HALFWORD_ASSERT 0
# define ASSERT_HALFWORD(COND)
-# endif
#endif
#if SIZEOF_VOID_P != SIZEOF_SIZE_T
diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c
index 00da31332a..68c62ca8e1 100644
--- a/erts/emulator/sys/common/erl_mseg.c
+++ b/erts/emulator/sys/common/erl_mseg.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -362,20 +362,23 @@ mseg_create(MemKind* mk, Uint size)
}
static ERTS_INLINE void
-mseg_destroy(void *seg, Uint size)
+mseg_destroy(MemKind* mk, void *seg, Uint size)
{
#if defined(ERTS_MSEG_FAKE_SEGMENTS)
erts_sys_free(ERTS_ALC_N_INVALID, NULL, seg);
#elif HAVE_MMAP
+ int res;
-#ifdef DEBUG
- int res =
-#endif
#if HALFWORD_HEAP
- pmunmap((void *) seg, size);
-#else
- munmap((void *) seg, size);
+ if (mk == &low_mem) {
+ res = pmunmap((void *) seg, size);
+ }
+ else
#endif
+ {
+ res = munmap((void *) seg, size);
+ }
+
ASSERT(size % page_size == 0);
ASSERT(res == 0);
#else
@@ -389,7 +392,7 @@ mseg_destroy(void *seg, Uint size)
#if HAVE_MSEG_RECREATE
static ERTS_INLINE void *
-mseg_recreate(void *old_seg, Uint old_size, Uint new_size)
+mseg_recreate(MemKind* mk, void *old_seg, Uint old_size, Uint new_size)
{
void *new_seg;
@@ -400,25 +403,29 @@ mseg_recreate(void *old_seg, Uint old_size, Uint new_size)
new_seg = erts_sys_realloc(ERTS_ALC_N_INVALID, NULL, old_seg, new_size);
#elif HAVE_MREMAP
#if HALFWORD_HEAP
- new_seg = (void *) pmremap((void *) old_seg,
- (size_t) old_size,
- (size_t) new_size);
-#elif defined(__NetBSD__)
- new_seg = (void *) mremap((void *) old_seg,
- (size_t) old_size,
- NULL,
- (size_t) new_size,
- 0);
- if (new_seg == (void *) MAP_FAILED)
- new_seg = NULL;
-#else
- new_seg = (void *) mremap((void *) old_seg,
- (size_t) old_size,
- (size_t) new_size,
- MREMAP_MAYMOVE);
- if (new_seg == (void *) MAP_FAILED)
- new_seg = NULL;
+ if (mk == &low_mem) {
+ new_seg = (void *) pmremap((void *) old_seg,
+ (size_t) old_size,
+ (size_t) new_size);
+ }
+ else
#endif
+ {
+ #if defined(__NetBSD__)
+ new_seg = (void *) mremap((void *) old_seg,
+ (size_t) old_size,
+ NULL,
+ (size_t) new_size,
+ 0);
+ #else
+ new_seg = (void *) mremap((void *) old_seg,
+ (size_t) old_size,
+ (size_t) new_size,
+ MREMAP_MAYMOVE);
+ #endif
+ if (new_seg == (void *) MAP_FAILED)
+ new_seg = NULL;
+ }
#else
#error "Missing mseg_recreate() implementation"
#endif
@@ -538,7 +545,7 @@ adjust_cache_size(MemKind* mk, int force_check_limits)
}
if (erts_mtrace_enabled)
erts_mtrace_crr_free(SEGTYPE, SEGTYPE, cd->seg);
- mseg_destroy(cd->seg, cd->size);
+ mseg_destroy(mk, cd->seg, cd->size);
unlink_cd(mk,cd);
free_cd(mk,cd);
}
@@ -593,7 +600,14 @@ mseg_clear_cache(MemKind* mk)
static ERTS_INLINE MemKind* type2mk(ErtsAlcType_t atype)
{
#if HALFWORD_HEAP
- return (atype == ERTS_ALC_A_ETS) ? &hi_mem : &low_mem;
+ switch (atype) {
+ case ERTS_ALC_A_ETS:
+ //case ERTS_ALC_A_BINARY:
+ //case ERTS_ALC_A_FIXED_SIZE:
+ return &hi_mem;
+ default:
+ return &low_mem;
+ }
#else
return &the_mem;
#endif
@@ -726,7 +740,7 @@ mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size,
if (!opt->cache || max_cache_size == 0) {
if (erts_mtrace_enabled)
erts_mtrace_crr_free(atype, SEGTYPE, seg);
- mseg_destroy(seg, size);
+ mseg_destroy(mk, seg, size);
}
else {
int check_limits = 0;
@@ -744,7 +758,7 @@ mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size,
}
if (erts_mtrace_enabled)
erts_mtrace_crr_free(SEGTYPE, SEGTYPE, cd->seg);
- mseg_destroy(cd->seg, cd->size);
+ mseg_destroy(mk, cd->seg, cd->size);
unlink_cd(mk,cd);
free_cd(mk,cd);
}
@@ -841,7 +855,7 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
SEGTYPE,
seg,
new_size);
- mseg_destroy(((char *) seg) + new_size, shrink_sz);
+ mseg_destroy(mk, ((char *) seg) + new_size, shrink_sz);
}
#elif HAVE_MSEG_RECREATE
@@ -875,7 +889,7 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
#if !CAN_PARTLY_DESTROY
do_recreate:
#endif
- new_seg = mseg_recreate((void *) seg, old_size, new_size);
+ new_seg = mseg_recreate(mk, (void *) seg, old_size, new_size);
if (erts_mtrace_enabled)
erts_mtrace_crr_realloc(new_seg, atype, SEGTYPE, seg, new_size);
if (!new_seg)
@@ -1828,6 +1842,7 @@ static int pmunmap(void *p, size_t size)
FreeBlock *last;
FreeBlock *nb = (FreeBlock *) p;
+ ASSERT(((unsigned long)p & CHECK_POINTER_MASK)==0);
if (real_size > pagsz) {
if (do_unmap(((char *) p) + pagsz,real_size - pagsz)) {
return 1;
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index a2c19fa10f..691b1189be 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -4056,7 +4056,7 @@ do_lookup_element(Tab, N, M) ->
end.
-heavy_concurrent(_Config) ->
+heavy_concurrent(Config) when is_list(Config) ->
repeat_for_opts(do_heavy_concurrent).
do_heavy_concurrent(Opts) ->