aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test/alloc_SUITE_data
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2014-12-08 15:38:04 +0100
committerSverker Eriksson <[email protected]>2015-11-10 16:40:24 +0100
commit38ddf72b48377bd6b2fb8c4b6981360ae7d44d79 (patch)
treeccf98c7822d0fc0dc56edcb882706166b5357fb8 /erts/emulator/test/alloc_SUITE_data
parentb72ad981e96fcc14c245ef2bd10c5c98c6a239f6 (diff)
downloadotp-38ddf72b48377bd6b2fb8c4b6981360ae7d44d79.tar.gz
otp-38ddf72b48377bd6b2fb8c4b6981360ae7d44d79.tar.bz2
otp-38ddf72b48377bd6b2fb8c4b6981360ae7d44d79.zip
erts: Add alloc_SUITE:migration
Diffstat (limited to 'erts/emulator/test/alloc_SUITE_data')
-rw-r--r--erts/emulator/test/alloc_SUITE_data/Makefile.src3
-rw-r--r--erts/emulator/test/alloc_SUITE_data/allocator_test.h2
-rw-r--r--erts/emulator/test/alloc_SUITE_data/migration.c229
-rw-r--r--erts/emulator/test/alloc_SUITE_data/testcase_driver.c14
-rw-r--r--erts/emulator/test/alloc_SUITE_data/testcase_driver.h1
5 files changed, 248 insertions, 1 deletions
diff --git a/erts/emulator/test/alloc_SUITE_data/Makefile.src b/erts/emulator/test/alloc_SUITE_data/Makefile.src
index a441fe946b..e31de54e1b 100644
--- a/erts/emulator/test/alloc_SUITE_data/Makefile.src
+++ b/erts/emulator/test/alloc_SUITE_data/Makefile.src
@@ -25,7 +25,8 @@ TEST_DRVS = basic@dll@ \
bucket_mask@dll@ \
rbtree@dll@ \
mseg_clear_cache@dll@ \
- cpool@dll@
+ cpool@dll@ \
+ migration@dll@
CC = @CC@
LD = @LD@
diff --git a/erts/emulator/test/alloc_SUITE_data/allocator_test.h b/erts/emulator/test/alloc_SUITE_data/allocator_test.h
index a7f12c6ca8..bfd0bb3094 100644
--- a/erts/emulator/test/alloc_SUITE_data/allocator_test.h
+++ b/erts/emulator/test/alloc_SUITE_data/allocator_test.h
@@ -85,6 +85,7 @@ typedef void* erts_cond;
#define CPOOL_DELETE(A,B) ((Carrier_t *) ALC_TEST2(0x022, (A), (B)))
#define CPOOL_IS_EMPTY(A) ((int) ALC_TEST1(0x023, (A)))
#define CPOOL_IS_IN_POOL(A,B) ((int) ALC_TEST2(0x024, (A), (B)))
+#define UMEM2BLK_TEST(P) ((Block_t*) ALC_TEST1(0x025, (P)))
/* From erl_goodfit_alloc.c */
#define BKT_IX(A, S) ((Ulong) ALC_TEST2(0x100, (A), (S)))
@@ -144,5 +145,6 @@ typedef void* erts_cond;
#define IS_SMP_ENABLED ((int) ALC_TEST0(0xf13))
#define ALLOC_TEST(S) ((void*) ALC_TEST1(0xf14, (S)))
#define FREE_TEST(P) ((void) ALC_TEST1(0xf15, (P)))
+#define SET_TEST_MBC_USER_HEADER(SZ,CMBC,DMBC) ((int)ALC_TEST3(0xf16, (SZ), (CMBC), (DMBC)))
#endif
diff --git a/erts/emulator/test/alloc_SUITE_data/migration.c b/erts/emulator/test/alloc_SUITE_data/migration.c
new file mode 100644
index 0000000000..dd58a0d3dd
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/migration.c
@@ -0,0 +1,229 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2014. 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%
+ */
+
+/*
+ * Test the carrier migration logic
+ */
+
+#ifndef __WIN32__
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include "testcase_driver.h"
+#include "allocator_test.h"
+
+#define FATAL_ASSERT(A) \
+ ((void) ((A) \
+ ? 1 \
+ : (fatal_assert_failed(#A, \
+ (char *) __FILE__, \
+ __LINE__), \
+ 0)))
+
+static void
+fatal_assert_failed(char* expr, char* file, int line)
+{
+ fflush(stdout);
+ fprintf(stderr, "%s:%d: Assertion failed: %s\n",
+ file, line, expr);
+ fflush(stderr);
+ abort();
+}
+
+
+char *
+testcase_name(void)
+{
+ return "migration";
+}
+
+void
+testcase_cleanup(TestCaseState_t *tcs)
+{
+}
+
+#define MAX_BLOCK_PER_THR 100
+#define MAX_ROUNDS 10
+
+typedef struct MyBlock_ {
+ struct MyBlock_* next;
+ struct MyBlock_** prevp;
+} MyBlock;
+
+typedef struct {
+ MyBlock* blockv[MAX_BLOCK_PER_THR];
+ enum { GROWING, SHRINKING, CLEANUP, DONE } phase;
+ int ix;
+ int round;
+} MigrationState;
+
+typedef struct {
+ ErlDrvMutex* mtx;
+ int nblocks;
+ MyBlock* first;
+} MyCrrInfo;
+
+
+static int crr_info_offset = -1;
+static void (*orig_create_mbc_fn)(Allctr_t *allctr, Carrier_t *carrier);
+static void (*orig_destroying_mbc_fn)(Allctr_t *allctr, Carrier_t *carrier);
+
+static void my_creating_mbc(Allctr_t *allctr, Carrier_t *carrier)
+{
+ MyCrrInfo* mci = (MyCrrInfo*) ((char*)carrier + crr_info_offset);
+ if (orig_create_mbc_fn)
+ orig_create_mbc_fn(allctr, carrier);
+
+ mci->mtx = erl_drv_mutex_create("alloc_SUITE.migration");
+ mci->nblocks = 0;
+ mci->first = NULL;
+}
+
+static void my_destroying_mbc(Allctr_t *allctr, Carrier_t *carrier)
+{
+ MyCrrInfo* mci = (MyCrrInfo*) ((char*)carrier + crr_info_offset);
+
+ FATAL_ASSERT(mci->nblocks == 0);
+ FATAL_ASSERT(mci->first == NULL);
+ erl_drv_mutex_destroy(mci->mtx);
+
+ if (orig_destroying_mbc_fn)
+ orig_destroying_mbc_fn(allctr, carrier);
+}
+
+
+static void setup(TestCaseState_t* tcs)
+{
+ void* creating_mbc_arg = (void*)my_creating_mbc;
+ void* destroying_mbc_arg = (void*)my_destroying_mbc;
+ crr_info_offset = SET_TEST_MBC_USER_HEADER(sizeof(MyCrrInfo),
+ &creating_mbc_arg,
+ &destroying_mbc_arg);
+ ASSERT(tcs, crr_info_offset >= 0);
+ orig_create_mbc_fn = creating_mbc_arg;
+ orig_destroying_mbc_fn = destroying_mbc_arg;
+}
+
+static void add_block(MyBlock* p)
+{
+ MyCrrInfo* mci = (MyCrrInfo*)((char*)BLK_TO_MBC(UMEM2BLK_TEST(p)) + crr_info_offset);
+
+ erl_drv_mutex_lock(mci->mtx);
+ mci->nblocks++;
+ p->next = mci->first;
+ p->prevp = &mci->first;
+ mci->first = p;
+ if (p->next)
+ p->next->prevp = &p->next;
+ erl_drv_mutex_unlock(mci->mtx);
+}
+
+static void remove_block(MyBlock* p)
+{
+ MyCrrInfo* mci = (MyCrrInfo*)((char*)BLK_TO_MBC(UMEM2BLK_TEST(p)) + crr_info_offset);
+
+ erl_drv_mutex_lock(mci->mtx);
+ mci->nblocks--;
+ if (p->next)
+ p->next->prevp = p->prevp;
+ *p->prevp = p->next;
+ erl_drv_mutex_unlock(mci->mtx);
+}
+
+void
+testcase_run(TestCaseState_t *tcs)
+{
+ MigrationState* state = (MigrationState*) tcs->extra;
+
+ if (tcs->command_len == 4
+ && memcmp(tcs->command, "init", tcs->command_len) == 0) {
+ setup(tcs);
+ return;
+ }
+
+ if (!tcs->extra) {
+ if (!IS_SMP_ENABLED)
+ testcase_skipped(tcs, "No SMP support");
+
+ tcs->extra = driver_alloc(sizeof(MigrationState));
+ state = (MigrationState*) tcs->extra;
+ memset(state->blockv, 0, sizeof(state->blockv));
+ state->phase = GROWING;
+ state->ix = 0;
+ state->round = 0;
+ }
+
+ switch (state->phase) {
+ case GROWING: {
+ MyBlock* p;
+ FATAL_ASSERT(!state->blockv[state->ix]);
+ p = ALLOC_TEST((1 << 18) / 5);
+ FATAL_ASSERT(p);
+ add_block(p);
+ state->blockv[state->ix] = p;
+ do {
+ if (++state->ix >= MAX_BLOCK_PER_THR) {
+ state->phase = SHRINKING;
+ state->ix = 0;
+ break;
+ }
+ } while (state->blockv[state->ix] != NULL);
+ break;
+ }
+ case SHRINKING:
+ FATAL_ASSERT(state->blockv[state->ix]);
+ remove_block(state->blockv[state->ix]);
+ FREE_TEST(state->blockv[state->ix]);
+ state->blockv[state->ix] = NULL;
+
+ state->ix += 1 + ((state->ix % 3) == 0);
+ if (state->ix >= MAX_BLOCK_PER_THR) {
+ if (++state->round >= MAX_ROUNDS) {
+ state->phase = CLEANUP;
+ } else {
+ state->phase = GROWING;
+ }
+ state->ix = 0;
+ }
+ break;
+
+ case CLEANUP:
+ if (state->blockv[state->ix]) {
+ remove_block(state->blockv[state->ix]);
+ FREE_TEST(state->blockv[state->ix]);
+ }
+ if (++state->ix >= MAX_BLOCK_PER_THR)
+ state->phase = DONE;
+ break;
+
+ default:
+ FATAL_ASSERT(!"Invalid phase");
+ }
+
+ if (state->phase == DONE) {
+ driver_free(tcs->extra);
+ tcs->extra = NULL;
+ }
+ else
+ testcase_continue(tcs);
+}
diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
index bc674c56b7..d04eb1bcb0 100644
--- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
+++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
@@ -39,6 +39,7 @@
#define TESTCASE_FAILED 0
#define TESTCASE_SKIPPED 1
#define TESTCASE_SUCCEEDED 2
+#define TESTCASE_CONTINUE 3
typedef struct {
TestCaseState_t visible;
@@ -129,6 +130,12 @@ testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
}
switch (itcs->result) {
+ case TESTCASE_CONTINUE:
+ msg[0] = ERL_DRV_ATOM;
+ msg[1] = driver_mk_atom("continue");
+ erl_drv_output_term(itcs->port_id, msg, 2);
+ return;
+
case TESTCASE_SUCCEEDED:
result_atom = driver_mk_atom("succeeded");
break;
@@ -239,6 +246,13 @@ void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...)
longjmp(itcs->done_jmp_buf, 1);
}
+void testcase_continue(TestCaseState_t *tcs)
+{
+ InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
+ itcs->result = TESTCASE_CONTINUE;
+ longjmp(itcs->done_jmp_buf, 1);
+}
+
void testcase_failed(TestCaseState_t *tcs, char *frmt, ...)
{
InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.h b/erts/emulator/test/alloc_SUITE_data/testcase_driver.h
index 5d17eaec64..5d439735b7 100644
--- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.h
+++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.h
@@ -37,6 +37,7 @@ typedef struct {
void testcase_printf(TestCaseState_t *tcs, char *frmt, ...);
void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...);
void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...);
+void testcase_continue(TestCaseState_t *tcs);
void testcase_failed(TestCaseState_t *tcs, char *frmt, ...);
int testcase_assertion_failed(TestCaseState_t *tcs, char *file, int line,
char *assertion);