Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[test] Remove some unnecessary usage of TOTAL_MEMORY and INITIAL_MEMORY. NFC #21303

Merged
merged 1 commit into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 39 additions & 29 deletions test/pthread/test_pthread_sbrk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,28 @@
#define NUM_THREADS 8
#define NUM_ALLOCATIONS 10240
#if ABORTING_MALLOC
#define ALLOCATION_SIZE 1280 // Malloc aborts, so allocate a bit less of memory so all fits
// Malloc aborts, so allocate a bit less of memory so all fits
#define ALLOCATION_SIZE 1280
#else
#define ALLOCATION_SIZE 2560 // Malloc doesn't abort, allocate a bit more memory to test graceful allocation failures
// Malloc doesn't abort, allocate a bit more memory to test graceful allocation
// failures
#define ALLOCATION_SIZE 2560
#endif

#define RESULT_OK 0
#define RESULT_EXPECTED_FAILS 1
#define RESULT_BAD_FAIL 2

// Use barriers to make each thread synchronize their execution points, to maximize the possibility of seeing race conditions
// if those might occur.
// Use barriers to make each thread synchronize their execution points, to
// maximize the possibility of seeing race conditions if those might occur.
static pthread_barrier_t barrierWaitToAlloc;
static pthread_barrier_t barrierWaitToVerify;
static pthread_barrier_t barrierWaitToFree;

// Use a mutex for logging.
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

static void *thread_start(void *arg)
{
static void *thread_start(void *arg) {
#if DEBUG
pthread_mutex_lock( &mutex );
printf("thread started, will try %d allocations of size %d\n", NUM_ALLOCATIONS, ALLOCATION_SIZE);
Expand All @@ -48,47 +50,57 @@ static void *thread_start(void *arg)
int some_allocations_failed = 0;
size_t allocated = 0;

pthread_barrier_wait(&barrierWaitToAlloc); // Halt until all threads reach here, then proceed synchronously.
for(int i = 0; i < NUM_ALLOCATIONS; ++i)
{
// Halt until all threads reach here, then proceed synchronously.
pthread_barrier_wait(&barrierWaitToAlloc);
for (int i = 0; i < NUM_ALLOCATIONS; ++i) {
allocated_buffers[i] = (uint8_t*)malloc(ALLOCATION_SIZE);
if (allocated_buffers[i]) {
memset(allocated_buffers[i], id, ALLOCATION_SIZE);
allocated += ALLOCATION_SIZE;
} else
} else {
some_allocations_failed = 1;
}
}
#if DEBUG
pthread_mutex_lock( &mutex );
printf("total allocations: %u (%d of size %d tried), some failed? %d\n", allocated, NUM_ALLOCATIONS, ALLOCATION_SIZE, some_allocations_failed);
pthread_mutex_unlock( &mutex );
#endif
pthread_barrier_wait(&barrierWaitToVerify); // Halt until all threads reach here, then proceed synchronously.
// Halt until all threads reach here, then proceed synchronously.
pthread_barrier_wait(&barrierWaitToVerify);
int reported_once = 0;
for(int i = 0; i < NUM_ALLOCATIONS; ++i)
{
for (int i = 0; i < NUM_ALLOCATIONS; ++i) {
if (!allocated_buffers[i]) continue;
for(int j = 0; j < ALLOCATION_SIZE; ++j)
if (allocated_buffers[i][j] != id)
{
++return_code; // Failed! (but run to completion so that the barriers will all properly proceed without hanging)
for (int j = 0; j < ALLOCATION_SIZE; ++j)
if (allocated_buffers[i][j] != id) {
// Failed! (but run to completion so that the barriers will all properly
// proceed without hanging)
++return_code;
if (!reported_once) {
emscripten_errf("Memory corrupted! mem[i]: %d != %ld, i: %d, j: %d", allocated_buffers[i][j], id, i, j);
reported_once = 1; // Avoid print flood that makes debugging hard.
// Avoid print flood that makes debugging hard.
reported_once = 1;
}
}
}

pthread_barrier_wait(&barrierWaitToFree); // Halt until all threads reach here, then proceed synchronously.
for(int i = 0; i < NUM_ALLOCATIONS; ++i)
for (int i = 0; i < NUM_ALLOCATIONS; ++i) {
free(allocated_buffers[i]);
}

#if ABORTING_MALLOC
if (some_allocations_failed)
return_code = RESULT_BAD_FAIL; // We expect allocations not to fail (if they did, shouldn't reach here, but we should have aborted)
if (some_allocations_failed) {
// We expect allocations not to fail (if they did, shouldn't reach here, but
// we should have aborted)
return_code = RESULT_BAD_FAIL;
}
#else
if (some_allocations_failed)
return_code = RESULT_EXPECTED_FAILS; // We expect to be allocating so much memory that some of the allocations fail.
if (some_allocations_failed) {
// We expect to be allocating so much memory that some of the allocations
// fail.
return_code = RESULT_EXPECTED_FAILS;
}
// Otherwise, the fails might happen in another thread, that's cool.
#endif
#if DEBUG
Expand All @@ -99,8 +111,7 @@ static void *thread_start(void *arg)
pthread_exit((void*)return_code);
}

int main()
{
int main() {
printf("starting test, aborting? %d\n", ABORTING_MALLOC);

int ret = pthread_barrier_init(&barrierWaitToAlloc, NULL, NUM_THREADS);
Expand All @@ -110,9 +121,8 @@ int main()
ret = pthread_barrier_init(&barrierWaitToFree, NULL, NUM_THREADS);
assert(ret == 0);

pthread_t thr[8/*NUM_THREADS*/];
for(intptr_t i = 0; i < NUM_THREADS; ++i)
{
pthread_t thr[NUM_THREADS];
for (intptr_t i = 0; i < NUM_THREADS; ++i) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, NUM_ALLOCATIONS*80);
Expand All @@ -122,7 +132,7 @@ int main()

int seen_expected_fails = 0;

for(int i = 0; i < NUM_THREADS; ++i) {
for (int i = 0; i < NUM_THREADS; ++i) {
int res = 0;
ret = pthread_join(thr[i], (void**)&res);
assert(ret == 0);
Expand Down
8 changes: 4 additions & 4 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3880,17 +3880,17 @@ def prep_no_SAB(self):
@requires_threads
def test_pthread_c11_threads(self):
self.btest_exit('pthread/test_pthread_c11_threads.c',
args=['-gsource-map', '-std=gnu11', '-pthread', '-sPROXY_TO_PTHREAD', '-sTOTAL_MEMORY=64mb'])
args=['-gsource-map', '-std=gnu11', '-pthread', '-sPROXY_TO_PTHREAD'])

@requires_threads
def test_pthread_pool_size_strict(self):
# Check that it doesn't fail with sufficient number of threads in the pool.
self.btest_exit('pthread/test_pthread_c11_threads.c',
args=['-g2', '-std=gnu11', '-pthread', '-sPTHREAD_POOL_SIZE=4', '-sPTHREAD_POOL_SIZE_STRICT=2', '-sTOTAL_MEMORY=64mb'])
args=['-g2', '-std=gnu11', '-pthread', '-sPTHREAD_POOL_SIZE=4', '-sPTHREAD_POOL_SIZE_STRICT=2'])
# Check that it fails instead of deadlocking on insufficient number of threads in the pool.
self.btest('pthread/test_pthread_c11_threads.c',
expected='abort:Assertion failed: thrd_create(&t4, thread_main, NULL) == thrd_success',
args=['-g2', '-std=gnu11', '-pthread', '-sPTHREAD_POOL_SIZE=3', '-sPTHREAD_POOL_SIZE_STRICT=2', '-sTOTAL_MEMORY=64mb'])
args=['-g2', '-std=gnu11', '-pthread', '-sPTHREAD_POOL_SIZE=3', '-sPTHREAD_POOL_SIZE_STRICT=2'])

@requires_threads
def test_pthread_in_pthread_pool_size_strict(self):
Expand All @@ -3911,7 +3911,7 @@ def test_pthread_atomics(self, args):
# Test 64-bit atomics.
@requires_threads
def test_pthread_64bit_atomics(self):
self.btest_exit('pthread/test_pthread_64bit_atomics.c', args=['-sINITIAL_MEMORY=64MB', '-O3', '-pthread', '-sPTHREAD_POOL_SIZE=8'])
self.btest_exit('pthread/test_pthread_64bit_atomics.c', args=['-O3', '-pthread', '-sPTHREAD_POOL_SIZE=8'])

# Test 64-bit C++11 atomics.
@parameterized({
Expand Down
Loading