Merge "fix confusion between "input" and "output""
diff --git a/aos/build/aos.gyp b/aos/build/aos.gyp
index 96cfc1b..1187d05 100644
--- a/aos/build/aos.gyp
+++ b/aos/build/aos.gyp
@@ -21,6 +21,9 @@
'sources': [
'<(AOS)/linux_code/logging/linux_interface.cc',
],
+ 'dependencies': [
+ '<(AOS)/linux_code/linux_code.gyp:complex_thread_local',
+ ],
}],
],
'dependencies': [
diff --git a/aos/build/aos.gypi b/aos/build/aos.gypi
index c390052..5a9119d 100644
--- a/aos/build/aos.gypi
+++ b/aos/build/aos.gypi
@@ -28,6 +28,12 @@
['CXX', '<!(readlink -f <(AOS)/build/crio_cxx)'],
],
}
+ ], ['PLATFORM=="linux-arm-gcc_frc"', {
+ 'make_global_settings': [
+ ['CC', '<(ccache)<!(which arm-frc-linux-gnueabi-gcc-4.9)'],
+ ['CXX', '<(ccache)<!(which arm-frc-linux-gnueabi-g++-4.9)'],
+ ],
+ },
], ['PLATFORM=="linux-arm-gcc"', {
'make_global_settings': [
['CC', '<(ccache)<!(which arm-linux-gnueabihf-gcc-4.7)'],
@@ -105,7 +111,7 @@
],
},
},
- ], ['SANITIZER_FPIE!=""', {
+ ], ['EXTERNALS_EXTRA=="-fPIE"', {
'target_defaults': {
'cflags': [
'-fPIE',
@@ -137,7 +143,6 @@
'__STDC_FORMAT_MACROS',
'__STDC_CONSTANT_MACROS',
'__STDC_LIMIT_MACROS',
- '_FORTIFY_SOURCE=2',
],
'ldflags': [
'-pipe',
@@ -193,6 +198,7 @@
}, { # 'DEBUG=="no"'
'defines': [
'AOS_DEBUG=0',
+ '_FORTIFY_SOURCE=2',
],
'cflags': [
'-O3',
@@ -209,12 +215,6 @@
'-fno-strict-aliasing',
],
}],
- ['ARCHITECTURE=="arm"', {
- 'cflags': [
- '-mcpu=cortex-a8',
- '-mfpu=neon',
- ],
- }],
['ARCHITECTURE=="amd64"', {
'cflags': [
'-fstack-protector-all',
@@ -234,6 +234,28 @@
],
}
],
+ ['ARCHITECTURE=="arm" and FULL_COMPILER!="gcc_frc"', {
+ 'cflags': [
+ '-mcpu=cortex-a8',
+ '-mfpu=neon',
+ ],
+ 'ldflags': [
+ '-mcpu=cortex-a8',
+ '-mfpu=neon',
+ ],
+ }],
+ ['ARCHITECTURE=="arm" and FULL_COMPILER=="gcc_frc"', {
+ 'cflags': [
+ '-mcpu=cortex-a9',
+ '-mfpu=neon',
+ '-mfloat-abi=softfp',
+ ],
+ 'ldflags': [
+ '-mcpu=cortex-a9',
+ '-mfpu=neon',
+ '-mfloat-abi=softfp',
+ ],
+ }],
['PLATFORM=="crio"', {
'target_conditions': [
['_type=="shared_library"', {
diff --git a/aos/build/aos_all.gyp b/aos/build/aos_all.gyp
index 2f6be93..1caac63 100644
--- a/aos/build/aos_all.gyp
+++ b/aos/build/aos_all.gyp
@@ -1,6 +1,5 @@
# This file has the executables etc that AOS builds.
# User .gyp files for the prime should depend on :Prime.
-# User .gyp files for the crio should depend on :Crio.
{
'targets': [
{
@@ -10,6 +9,7 @@
'no_rsync': 1,
},
'dependencies': [
+ 'Common',
'<(AOS)/linux_code/linux_code.gyp:core',
'<(AOS)/linux_code/logging/logging.gyp:binary_log_writer',
'<(AOS)/linux_code/logging/logging.gyp:log_streamer',
@@ -18,27 +18,7 @@
'<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:ipc_stress_test',
'<(AOS)/linux_code/starter/starter.gyp:starter_exe',
'<(AOS)/linux_code/starter/starter.gyp:netconsole',
- '<(AOS)/common/common.gyp:queue_test',
- '<(AOS)/common/common.gyp:die_test',
- '<(AOS)/common/common.gyp:queue_types_test',
- '<(AOS)/common/util/util.gyp:string_to_num_test',
- '<(AOS)/common/util/util.gyp:trapezoid_profile_test',
- '<(AOS)/common/util/util.gyp:wrapping_counter_test',
- '<(AOS)/common/libc/libc.gyp:dirname_test',
- '<(AOS)/common/libc/libc.gyp:aos_strerror_test',
- '<(AOS)/common/libc/libc.gyp:aos_strsignal_test',
- '<(AOS)/common/util/util.gyp:run_command_test',
- '<(DEPTH)/bbb_cape/src/bbb/bbb.gyp:cows_test',
- '<(DEPTH)/bbb_cape/src/bbb/bbb.gyp:packet_finder_test',
'<(AOS)/linux_code/linux_code.gyp:complex_thread_local_test',
- 'Common',
- ],
- },
- {
- 'target_name': 'Crio',
- 'type': 'none',
- 'dependencies': [
- 'Common',
],
},
{
@@ -55,6 +35,15 @@
'<(AOS)/common/common.gyp:once_test',
'<(AOS)/common/logging/logging.gyp:logging_impl_test',
'<(AOS)/common/util/util.gyp:options_test',
+ '<(AOS)/common/common.gyp:queue_test',
+ '<(AOS)/common/common.gyp:die_test',
+ '<(AOS)/common/common.gyp:queue_types_test',
+ '<(AOS)/common/util/util.gyp:trapezoid_profile_test',
+ '<(AOS)/common/util/util.gyp:wrapping_counter_test',
+ '<(AOS)/common/libc/libc.gyp:dirname_test',
+ '<(AOS)/common/libc/libc.gyp:aos_strerror_test',
+ '<(AOS)/common/libc/libc.gyp:aos_strsignal_test',
+ '<(AOS)/common/util/util.gyp:run_command_test',
],
},
],
diff --git a/aos/build/build.py b/aos/build/build.py
index f0300f9..faa6fe1 100755
--- a/aos/build/build.py
+++ b/aos/build/build.py
@@ -553,7 +553,7 @@
return r
ARCHITECTURES = ('arm', 'amd64')
- COMPILERS = ('clang', 'gcc', 'gcc_4.8')
+ COMPILERS = ('clang', 'gcc', 'gcc_4.8', 'gcc_frc')
SANITIZERS = ('address', 'undefined', 'integer', 'memory', 'thread', 'none')
SANITIZER_TEST_WARNINGS = {
'memory': (True,
@@ -570,7 +570,8 @@
for architecture in PrimeProcessor.ARCHITECTURES:
for compiler in PrimeProcessor.COMPILERS:
for debug in [True, False]:
- if architecture == 'arm' and compiler == 'gcc_4.8':
+ if ((architecture == 'arm' and compiler == 'gcc_4.8') or
+ (architecture == 'amd64' and compiler == 'gcc_frc')):
# We don't have a compiler to use here.
continue
platforms.append(
@@ -611,13 +612,21 @@
def download_externals(self, platforms):
to_download = set()
for architecture in PrimeProcessor.ARCHITECTURES:
+ pie_sanitizers = set()
for sanitizer in PrimeProcessor.PIE_SANITIZERS:
- if platforms & self.select_platforms(architecture=architecture,
- sanitizer=sanitizer):
- to_download.add(architecture + '-fPIE')
- if platforms & self.select_platforms(architecture=architecture,
- sanitizer='none'):
- to_download.add(architecture)
+ pie_sanitizers.update(self.select_platforms(architecture=architecture,
+ sanitizer=sanitizer))
+ if platforms & pie_sanitizers:
+ to_download.add(architecture + '-fPIE')
+
+ frc_platforms = self.select_platforms(architecture=architecture,
+ compiler='gcc_frc')
+ if platforms & frc_platforms:
+ to_download.add(architecture + '_frc')
+
+ if platforms & (self.platforms() - pie_sanitizers - frc_platforms):
+ to_download.add(architecture)
+
for download_target in to_download:
call_download_externals(download_target)
@@ -695,6 +704,9 @@
if platform.compiler() == 'gcc' and platform.architecture() == 'amd64':
packages.add('gcc-4.7')
packages.add('g++-4.7')
+ elif platform.compiler() == 'gcc_frc':
+ packages.add('gcc-4.9-arm-frc-linux-gnueabi')
+ packages.add('g++-4.9-arm-frc-linux-gnueabi')
self.do_check_installed(tuple(packages))
@@ -955,9 +967,9 @@
'-DFULL_COMPILER=%s' % platform.compiler(),
'-DDEBUG=%s' % ('yes' if platform.debug() else 'no'),
'-DSANITIZER=%s' % platform.sanitizer(),
- '-DSANITIZER_FPIE=%s' %
+ '-DEXTERNALS_EXTRA=%s' %
('-fPIE' if platform.sanitizer() in PrimeProcessor.PIE_SANITIZERS
- else '')) +
+ else ('_frc' if platform.compiler() == 'gcc_frc' else ''))) +
processor.extra_gyp_flags() + (args.main_gyp,),
stdin=subprocess.PIPE)
gyp.communicate(("""
diff --git a/aos/build/download_externals.sh b/aos/build/download_externals.sh
index 106e2db..ecd1b01 100755
--- a/aos/build/download_externals.sh
+++ b/aos/build/download_externals.sh
@@ -10,6 +10,11 @@
# the value from CONFIGURE_FLAGS has to get overriden in some places.
ALL_LDFLAGS=""
+# Flags that should get passed to all configure scripts.
+# Some of them need to set LDFLAGS separately to work around stupid configure
+# scripts, so we can't just set that here.
+CONFIGURE_FLAGS=""
+
if [ "$1" == "arm" ]; then
COMPILED=${EXTERNALS}/../compiled-arm
@@ -20,11 +25,19 @@
export CFLAGS="-mcpu=cortex-a8 -mfpu=neon"
export CXXFLAGS="-mcpu=cortex-a8 -mfpu=neon"
export OBJDUMP=${CROSS_COMPILE}objdump
- # Flags that should get passed to all configure scripts.
- # Some of them need to set LDFLAGS separately to work around stupid configure
- # scripts, so we can't just set that here.
CONFIGURE_FLAGS="--host=arm-linux-gnueabihf CC=${CC} CXX=${CXX} CFLAGS=\"${CFLAGS}\" CXXFLAGS=\"${CXXFLAGS}\" OBJDUMP=${OBJDUMP}"
IS_CRIO=0
+elif [ "$1" == "arm_frc" ]; then
+ COMPILED=${EXTERNALS}/../compiled-arm_frc
+
+ CROSS_COMPILE=arm-frc-linux-gnueabi-
+
+ export CC=${CROSS_COMPILE}gcc-4.9
+ export CXX=${CROSS_COMPILE}g++-4.9
+ export CFLAGS="-mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp"
+ export CXXFLAGS="-mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp"
+ export OBJDUMP=${CROSS_COMPILE}objdump
+ CONFIGURE_FLAGS="--host=arm-frc-linux-gnueabi CC=${CC} CXX=${CXX} CFLAGS=\"${CFLAGS}\" CXXFLAGS=\"${CXXFLAGS}\" OBJDUMP=${OBJDUMP}"
elif [ "$1" == "amd64" ]; then
COMPILED=${EXTERNALS}/../compiled-amd64
IS_CRIO=0
diff --git a/aos/build/externals.gyp b/aos/build/externals.gyp
index 44ca1d7..a097fd7 100644
--- a/aos/build/externals.gyp
+++ b/aos/build/externals.gyp
@@ -4,8 +4,8 @@
'variables': {
'externals': '<(AOS)/../output/downloaded',
'externals_abs': '<!(readlink -f ../../output/downloaded)',
- 'compiled': '<(externals)/../compiled-<(ARCHITECTURE)<(SANITIZER_FPIE)',
- 'compiled_abs': '<(externals_abs)/../compiled-<(ARCHITECTURE)<(SANITIZER_FPIE)',
+ 'compiled': '<(externals)/../compiled-<(ARCHITECTURE)<(EXTERNALS_EXTRA)',
+ 'compiled_abs': '<(externals_abs)/../compiled-<(ARCHITECTURE)<(EXTERNALS_EXTRA)',
# These versions have to be kept in sync with the ones in download_externals.sh.
'eigen_version': '3.2.1',
diff --git a/aos/common/common.gyp b/aos/common/common.gyp
index e098c0f..fb410b7 100644
--- a/aos/common/common.gyp
+++ b/aos/common/common.gyp
@@ -305,6 +305,7 @@
'queue_testutils',
'<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:core_lib',
'die',
+ '<(AOS)/common/util/util.gyp:thread',
],
},
{
diff --git a/aos/common/condition.h b/aos/common/condition.h
index c913b47..ef51b89 100644
--- a/aos/common/condition.h
+++ b/aos/common/condition.h
@@ -54,7 +54,8 @@
// and will be locked when this method returns.
// NOTE: The relocking of the mutex is not performed atomically with waking
// up.
- void Wait();
+ // Returns false.
+ bool Wait();
// Signals at most 1 other process currently Wait()ing on this condition
// variable. Calling this does not require the mutex associated with this
diff --git a/aos/common/condition_test.cc b/aos/common/condition_test.cc
index 6914a8b..7b9145d 100644
--- a/aos/common/condition_test.cc
+++ b/aos/common/condition_test.cc
@@ -4,6 +4,8 @@
#include <sys/types.h>
#include <sys/wait.h>
+#include <atomic>
+
#include "gtest/gtest.h"
#include "aos/common/time.h"
@@ -14,6 +16,7 @@
#include "aos/common/logging/logging.h"
#include "aos/common/macros.h"
#include "aos/common/die.h"
+#include "aos/common/util/thread.h"
using ::aos::time::Time;
using ::aos::common::testing::GlobalCoreInstance;
@@ -21,7 +24,57 @@
namespace aos {
namespace testing {
-class ConditionTest : public ::testing::Test {
+class ConditionTestCommon : public ::testing::Test {
+ public:
+ ConditionTestCommon() {}
+
+ void Settle() {
+ time::SleepFor(::Time::InSeconds(0.008));
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ConditionTestCommon);
+};
+
+// Some simple tests that don't rely on a GlobalCoreInstance to help with
+// debugging problems that cause tests using that to just completely lock up.
+class SimpleConditionTest : public ConditionTestCommon {
+ public:
+ SimpleConditionTest() : condition_(&mutex_) {}
+
+ Mutex mutex_;
+ Condition condition_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SimpleConditionTest);
+};
+
+// Makes sure that nothing crashes or anything with a basic Wait() and then
+// Signal().
+// This test is written to hopefully fail instead of deadlocking on failure, but
+// it's tricky because there's no way to kill the child in the middle.
+TEST_F(SimpleConditionTest, Basic) {
+ ::std::atomic_bool child_finished(false);
+ Condition child_ready(&mutex_);
+ ASSERT_FALSE(mutex_.Lock());
+ util::FunctionThread child([this, &child_finished, &child_ready](
+ util::FunctionThread *) {
+ ASSERT_FALSE(mutex_.Lock());
+ child_ready.Broadcast();
+ ASSERT_FALSE(condition_.Wait());
+ child_finished.store(true);
+ mutex_.Unlock();
+ });
+ child.Start();
+ ASSERT_FALSE(child_ready.Wait());
+ EXPECT_FALSE(child_finished.load());
+ condition_.Signal();
+ mutex_.Unlock();
+ child.Join();
+ EXPECT_TRUE(child_finished.load());
+}
+
+class ConditionTest : public ConditionTestCommon {
public:
struct Shared {
Shared() : condition(&mutex) {}
@@ -40,10 +93,6 @@
Shared *const shared_;
- void Settle() {
- time::SleepFor(::Time::InSeconds(0.008));
- }
-
protected:
void SetUp() override {
SetDieTestMode(true);
diff --git a/aos/common/mutex.h b/aos/common/mutex.h
index ff953e4..251eb3c 100644
--- a/aos/common/mutex.h
+++ b/aos/common/mutex.h
@@ -28,7 +28,8 @@
~Mutex();
#endif
// Locks the mutex. If it fails, it calls LOG(FATAL).
- void Lock();
+ // Returns false.
+ bool Lock();
// Unlocks the mutex. Fails like Lock.
// Multiple unlocking is undefined.
void Unlock();
diff --git a/aos/linux_code/ipc_lib/condition.cc b/aos/linux_code/ipc_lib/condition.cc
index 0ba4145..ed488c5 100644
--- a/aos/linux_code/ipc_lib/condition.cc
+++ b/aos/linux_code/ipc_lib/condition.cc
@@ -11,8 +11,9 @@
Condition::Condition(Mutex *m) : impl_(), m_(m) {}
-void Condition::Wait() {
+bool Condition::Wait() {
condition_wait(&impl_, &m_->impl_);
+ return false;
}
void Condition::Signal() {
diff --git a/aos/linux_code/ipc_lib/mutex.cpp b/aos/linux_code/ipc_lib/mutex.cpp
index 8c98204..4bd0759 100644
--- a/aos/linux_code/ipc_lib/mutex.cpp
+++ b/aos/linux_code/ipc_lib/mutex.cpp
@@ -17,9 +17,11 @@
// Lock and Unlock use the return values of mutex_lock/mutex_unlock
// to determine whether the lock/unlock succeeded.
-void Mutex::Lock() {
+bool Mutex::Lock() {
if (mutex_grab(&impl_) != 0) {
PLOG(FATAL, "mutex_grab(%p(=%" PRIu32 ")) failed", &impl_, impl_);
+ } else {
+ return false;
}
}
diff --git a/aos/linux_code/logging/linux_interface.cc b/aos/linux_code/logging/linux_interface.cc
index 0945ddd..0040e94 100644
--- a/aos/linux_code/logging/linux_interface.cc
+++ b/aos/linux_code/logging/linux_interface.cc
@@ -2,6 +2,7 @@
#include <sys/prctl.h>
+#include "aos/linux_code/complex_thread_local.h"
#include "aos/linux_code/thread_local.h"
#include "aos/common/die.h"
@@ -39,23 +40,23 @@
return process_name + '.' + thread_name;
}
-AOS_THREAD_LOCAL Context *my_context(nullptr);
+::aos::ComplexThreadLocal<Context> my_context;
-// A temporary stash for Context objects that we're going to delete ASAP. The
+// True if we're going to delete the current Context object ASAP. The
// reason for doing this instead of just deleting them is that tsan (at least)
// doesn't like it when pthread_atfork handlers do complicated stuff and it's
// not a great idea anyways.
-AOS_THREAD_LOCAL Context *old_context(nullptr);
+AOS_THREAD_LOCAL bool delete_current_context(false);
} // namespace
Context *Context::Get() {
- if (__builtin_expect(my_context == nullptr, 0)) {
- if (old_context != nullptr) {
- delete old_context;
- old_context = nullptr;
- }
- my_context = new Context();
+ if (__builtin_expect(delete_current_context, false)) {
+ my_context.Clear();
+ delete_current_context = false;
+ }
+ if (__builtin_expect(!my_context.created(), false)) {
+ my_context.Create();
my_context->name = GetMyName();
if (my_context->name.size() + 1 > sizeof(LogMessage::name)) {
Die("logging: process/thread name '%s' is too long\n",
@@ -63,17 +64,11 @@
}
my_context->source = getpid();
}
- return my_context;
+ return my_context.get();
}
void Context::Delete() {
- if (my_context != nullptr) {
- if (old_context != nullptr) {
- delete old_context;
- }
- old_context = my_context;
- my_context = nullptr;
- }
+ delete_current_context = true;
}
} // namespace internal