blob: 3d61cb4d1687626562e2b92c8d57fa5b99c9a122 [file] [log] [blame]
# -*- python -*-
# Copyright (c) 2012 The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
Import('env')
egyptian_cotton_nexe = env.ComponentProgram('egyptian_cotton',
'egyptian_cotton.c',
EXTRA_LIBS=['${PTHREAD_LIBS}',
'${NONIRT_LIBS}'])
platform_limits_known = False
# this test accepts the number of threads to attempt to create as an
# argument. NACL_THREAD_MAX is 8192 for x86-32 and x86-64, and 4096
# for the Arm. See the header files
# src/trusted/service_runtime/arch/{x86,arm}/sel_ldr_{x86,arm}.h for
# the current values (and update this comment to reflect reality!).
# On the x86_32, the actual number of threads possible is slightly
# fewer than 8192, since the service runtime's trusted internal
# threads use the same resource pool. In practice, 8189 works as of
# this writing (2010-03-10), but applications should not rely on this
# going forward, and we only test for 8180 below. Furthermore, there
# may be other limitations, e.g, for x86_32, OSX may limit us to far
# fewer than 8192 (got to 2558 in one test run, when egyptian_cotton
# was compiled as a standalone non-NaCl program.)
#
# The following runs the test with different numbers of threads to be
# spawned depending on the architecture. For the Arm, it is 4095
# threads. Note that the main thread also counts as one more thread.
#
# BUG(bsy): With the Arm architecture under qemu, spawning more than 3
# threads under will cause qemu to deadlock on exit, even though the
# test passes, so this is marked as a hardware-only test. If we were
# to compile this using the trusted toolchain and run the resultant
# Arm binary under qemu, qemu will segfault at 375 threads. It is
# unclear as of this writing (2010-03-11) whether this is a qemu bug
# or a limitation/bug of the codesourcery pthread library.
large_stack_args = ['-s', '0x400000', '-n', '4095', '-f' ]
#
# WARNING: Magic numbers ahead!
#
# The high_thread_count_args is used to stress test the thread library and
# the service runtime by having the test binary (egyptian_cotton.nexe)
# allocate a large number of concurrent threads. This is done to ensure
# that there are no sudden decrease in the number of threads that can be
# created. While limits imposed by our threading design -- 8192 for
# x86-32, and essentially unlimited for x86-64 and arm (though there's a
# statically sized table involved, so we chose to limit to 8192 as well) --
# are of our design and thus easy to determine, the underlying host
# operating system also imposes limits on the number of real underlying
# host OS threads that can be created. Thus, the magic numbers below are
# *empirically* determined. This is somewhat unfortunate, since it'd be
# nice to have a better understanding of the source of these limits, and
# it'd be especially nice if, for example, they could be lifted by some
# simple configuration parameter (that do not require administrative
# rights). Nonetheless, we use the empirically determined values to detect
# changes that might further reduce the thread limit in practice. The
# limits were obtained by simply running egyptian_cotton.nexe manually and
# seeing where it fails, and subtracting a few, so that minor,
# inconsequential and negligible changes to the runtime libraries etc won't
# require updating this test.
#
if env.Bit('build_arm'):
# so far, only linux.
# The arm-hw-bot was actually clocked at successfully doing 8191,
# though it gets pretty resource-starved near the top and might
# crash if anything else is being done on the bot, and takes a
# really long time. Limit to 7000 since that's more than 4096
# but not enough to take too long.
high_thread_count_nthreads = 7000
platform_limits_known = True
elif env.Bit('build_mips32'):
# Based on MIPS Malta 74Kc board.
high_thread_count_nthreads = 3500
platform_limits_known = True
elif env.Bit('build_x86'):
trusted_env = env.get('TRUSTED_ENV')
if trusted_env:
platform_limits_known = True
if trusted_env.Bit('linux'):
high_thread_count_nthreads = 8180
elif trusted_env.Bit('mac'):
# A value of 2558 worked on OS X 10.5 (Leopard).
# This had to be reduced to 2556 to pass on OS X 10.6 (Snow Leopard).
# It then had to be reduced to 2044 to pass on OS X 10.7 (Lion).
high_thread_count_nthreads = 2044
if trusted_env.Bit('asan') and trusted_env.Bit('build_x86_32'):
# Under ASan less address space is available. On MacOS 10.6 on
# x86-32 under ASan, ~1100 threads fit (there is some
# non-determinism in the upper bound, perhaps due to ASLR).
high_thread_count_nthreads = 1100
elif trusted_env.Bit('windows'):
if trusted_env.Bit('build_x86_32'):
high_thread_count_nthreads = 700
else:
high_thread_count_nthreads = 900
else:
raise Exception('Unknown host OS: threading limit unknown')
else:
raise Exception('Unknown target architecture -- '
'architecture/host OS thread limits are unknown')
if not platform_limits_known:
Return()
# Valgrind's internal configuration variable VG_N_THREAD defaults to
# 500 (valgrind version 3.8.1), which would be insufficient to keep
# track of the high thread count used in the egyptian cotton test.
# Since this test is primarily for catching regressions where we
# reduce the maximum number of threads available to the NaCl module,
# reducing it for the valgrind tests is reasonable -- the tests aren't
# trying to expose thread race conditions or memory leaks.
# VG_N_SEGMENTS can also cause trouble, due to thread stack
# allocation.
if env.IsRunningUnderValgrind():
high_thread_count_nthreads = min(high_thread_count_nthreads, 400)
high_thread_count_args = ['-n', str(high_thread_count_nthreads)]
if env.Bit('nacl_glibc'):
high_thread_count_args.append('-m')
elif env.Bit('tests_use_irt'):
# With the IRT, there is less address space available for thread stacks.
high_thread_count_args += ['-s', str(0x2000)]
tests = [ ('egyptian_cotton_test', high_thread_count_args),
('thread_stack_alloc_test', large_stack_args) ]
# This test does not make much sense on Valgrind, and is too slow.
if env.IsRunningUnderValgrind():
tests = [t for t in tests if t[0] != 'thread_stack_alloc_test']
def ThreadTestNode(name, args):
return env.CommandSelLdrTestNacl(name + '.out',
egyptian_cotton_nexe,
size='large',
args=args)
nodes = [ ThreadTestNode(name, args) for name, args in tests ]
for p, n in zip(tests, nodes):
env.AddNodeToTestSuite(n, ['medium_tests', 'sel_ldr_tests'], 'run_' + p[0])