summaryrefslogtreecommitdiff
path: root/src/components/utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/utils/src')
-rw-r--r--src/components/utils/src/appenders_loader.cc2
-rw-r--r--src/components/utils/src/back_trace.cc4
-rw-r--r--src/components/utils/src/bitstream.cc2
-rw-r--r--src/components/utils/src/conditional_variable_posix.cc23
-rw-r--r--src/components/utils/src/date_time.cc81
-rw-r--r--src/components/utils/src/file_system.cc17
-rw-r--r--src/components/utils/src/gen_hash.cc53
-rw-r--r--src/components/utils/src/lock_posix.cc57
-rw-r--r--src/components/utils/src/logger_status.cc2
-rw-r--r--src/components/utils/src/resource_usage.cc6
-rw-r--r--src/components/utils/src/rwlock_posix.cc30
-rw-r--r--src/components/utils/src/signals_linux.cc83
-rw-r--r--src/components/utils/src/system.cc21
-rw-r--r--src/components/utils/src/threads/posix_thread.cc299
-rw-r--r--src/components/utils/src/threads/pulse_thread_delegate.cc4
-rw-r--r--src/components/utils/src/threads/thread_delegate.cc6
-rw-r--r--src/components/utils/src/threads/thread_validator.cc15
17 files changed, 446 insertions, 259 deletions
diff --git a/src/components/utils/src/appenders_loader.cc b/src/components/utils/src/appenders_loader.cc
index cbbd039060..9741bd1b8d 100644
--- a/src/components/utils/src/appenders_loader.cc
+++ b/src/components/utils/src/appenders_loader.cc
@@ -39,7 +39,7 @@ namespace utils {
AppendersLoader appenders_loader;
AppendersLoader::AppendersLoader() {
- handle_ = dlopen("libappenders.so", RTLD_LAZY | RTLD_NODELETE);
+ handle_ = dlopen("libappenders.so", RTLD_LAZY);
}
AppendersLoader::~AppendersLoader() {
diff --git a/src/components/utils/src/back_trace.cc b/src/components/utils/src/back_trace.cc
index 23b1b4d1e9..f49c60b467 100644
--- a/src/components/utils/src/back_trace.cc
+++ b/src/components/utils/src/back_trace.cc
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
@@ -89,7 +89,7 @@ vector<string> Backtrace::CallStack() const {
return callstack;
}
-Thread::Id Backtrace::ThreadId() const {
+threads::PlatformThreadHandle Backtrace::ThreadId() const {
return thread_id_;
}
diff --git a/src/components/utils/src/bitstream.cc b/src/components/utils/src/bitstream.cc
index c616b1ae4a..ae353b44c6 100644
--- a/src/components/utils/src/bitstream.cc
+++ b/src/components/utils/src/bitstream.cc
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
diff --git a/src/components/utils/src/conditional_variable_posix.cc b/src/components/utils/src/conditional_variable_posix.cc
index a89f8cab65..2928cac9db 100644
--- a/src/components/utils/src/conditional_variable_posix.cc
+++ b/src/components/utils/src/conditional_variable_posix.cc
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
@@ -83,14 +83,29 @@ void ConditionalVariable::Broadcast() {
}
-void ConditionalVariable::Wait(AutoLock& auto_lock) {
+bool ConditionalVariable::Wait(Lock& lock) {
+ lock.AssertTakenAndMarkFree();
+ int32_t wait_status = pthread_cond_wait(&cond_var_,
+ &lock.mutex_);
+ lock.AssertFreeAndMarkTaken();
+ if (wait_status != 0) {
+ LOG4CXX_ERROR(logger_, "Failed to wait for conditional variable");
+ return false;
+ }
+ return true;
+}
+
+bool ConditionalVariable::Wait(AutoLock& auto_lock) {
Lock& lock = auto_lock.GetLock();
lock.AssertTakenAndMarkFree();
int32_t wait_status = pthread_cond_wait(&cond_var_,
&lock.mutex_);
lock.AssertFreeAndMarkTaken();
- if (wait_status != 0)
+ if (wait_status != 0) {
LOG4CXX_ERROR(logger_, "Failed to wait for conditional variable");
+ return false;
+ }
+ return true;
}
ConditionalVariable::WaitStatus ConditionalVariable::WaitFor(
@@ -104,7 +119,6 @@ ConditionalVariable::WaitStatus ConditionalVariable::WaitFor(
(milliseconds % kMillisecondsPerSecond) * kNanosecondsPerMillisecond;
wait_interval.tv_sec += wait_interval.tv_nsec / kNanosecondsPerSecond;
wait_interval.tv_nsec %= kNanosecondsPerSecond;
-
Lock& lock = auto_lock.GetLock();
lock.AssertTakenAndMarkFree();
int32_t timedwait_status = pthread_cond_timedwait(&cond_var_,
@@ -129,7 +143,6 @@ ConditionalVariable::WaitStatus ConditionalVariable::WaitFor(
LOG4CXX_ERROR(logger_, "Failed to timewait for conditional variable timedwait_status: " << timedwait_status);
}
}
-
return wait_status;
}
diff --git a/src/components/utils/src/date_time.cc b/src/components/utils/src/date_time.cc
index f190951647..42a199e0fb 100644
--- a/src/components/utils/src/date_time.cc
+++ b/src/components/utils/src/date_time.cc
@@ -1,49 +1,50 @@
/*
-* Copyright (c) 2014, Ford Motor Company
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-*
-* Redistributions of source code must retain the above copyright notice, this
-* list of conditions and the following disclaimer.
-*
-* Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided with the
-* distribution.
-*
-* Neither the name of the Ford Motor Company nor the names of its contributors
-* may be used to endorse or promote products derived from this software
-* without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*/
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
#include <sys/time.h>
#include <stdint.h>
#include "utils/date_time.h"
+
namespace date_time {
-TimevalStruct DateTime::getCurrentTime() {
- TimevalStruct currentTime;
- timezone timeZone;
+ TimevalStruct DateTime::getCurrentTime() {
+ TimevalStruct currentTime;
+ timezone timeZone;
- gettimeofday(&currentTime, &timeZone);
+ gettimeofday(&currentTime, &timeZone);
- return currentTime;
-}
+ return currentTime;
+ }
int64_t date_time::DateTime::getSecs(const TimevalStruct &time) {
return static_cast<int64_t>(time.tv_sec);
@@ -100,3 +101,11 @@ TimeCompare date_time::DateTime::compareTime(const TimevalStruct &time1, const T
}
} // namespace date_time
+
+bool operator<(const TimevalStruct& time1, const TimevalStruct& time2) {
+ return date_time::DateTime::Less(time1, time2);
+}
+
+bool operator==(const TimevalStruct& time1, const TimevalStruct& time2) {
+ return date_time::DateTime::Equal(time1, time2);
+}
diff --git a/src/components/utils/src/file_system.cc b/src/components/utils/src/file_system.cc
index 64e021a6f1..69efcad863 100644
--- a/src/components/utils/src/file_system.cc
+++ b/src/components/utils/src/file_system.cc
@@ -325,10 +325,12 @@ std::vector<std::string> file_system::ListFiles(
}
closedir(directory);
+
+ }
+
#ifdef __QNXNTO__
- delete[] direntbuffer;
+ delete[] direntbuffer;
#endif
- }
return listFiles;
}
@@ -410,3 +412,14 @@ bool file_system::CreateFile(const std::string& path) {
return true;
}
}
+
+
+uint64_t file_system::GetFileModificationTime(const std::string& path) {
+ struct stat info;
+ stat(path.c_str(), &info);
+#ifndef __QNXNTO__
+ return static_cast<uint64_t>(info.st_mtim.tv_nsec);
+#else
+ return static_cast<uint64_t>(info.st_mtime);
+#endif
+}
diff --git a/src/components/utils/src/gen_hash.cc b/src/components/utils/src/gen_hash.cc
new file mode 100644
index 0000000000..6ac5c217c3
--- /dev/null
+++ b/src/components/utils/src/gen_hash.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "utils/gen_hash.h"
+
+#include <cstdlib>
+
+namespace utils {
+
+const std::string gen_hash(size_t size) {
+ static const char symbols[] = "0123456789"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ static const size_t capacity = sizeof(symbols) - 1;
+
+ std::string hash(size, '\0');
+ for (std::string::iterator i = hash.begin(); i != hash.end(); ++i) {
+ int index = std::rand() % capacity;
+ *i = symbols[index];
+ }
+ return hash;
+}
+
+} // namespace utils
diff --git a/src/components/utils/src/lock_posix.cc b/src/components/utils/src/lock_posix.cc
index f75b7ee9ea..d2837708fa 100644
--- a/src/components/utils/src/lock_posix.cc
+++ b/src/components/utils/src/lock_posix.cc
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
@@ -34,6 +34,8 @@
#include <errno.h>
#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
#include "utils/logger.h"
@@ -43,11 +45,11 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "Utils")
Lock::Lock()
#ifndef NDEBUG
- : lock_taken_(0),
- is_mutex_recursive_(false)
+ : lock_taken_(0),
+ is_mutex_recursive_(false)
#endif // NDEBUG
{
- int32_t status = pthread_mutex_init(&mutex_, NULL);
+ const int32_t status = pthread_mutex_init(&mutex_, NULL);
if (status != 0) {
LOG4CXX_ERROR(logger_, "Failed to initialize mutex");
}
@@ -55,8 +57,8 @@ Lock::Lock()
Lock::Lock(bool is_mutex_recursive)
#ifndef NDEBUG
- : lock_taken_(0),
- is_mutex_recursive_(is_mutex_recursive)
+ : lock_taken_(0),
+ is_mutex_recursive_(is_mutex_recursive)
#endif // NDEBUG
{
int32_t status;
@@ -67,6 +69,7 @@ Lock::Lock(bool is_mutex_recursive)
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
status = pthread_mutex_init(&mutex_, &attr);
+ pthread_mutexattr_destroy(&attr);
} else {
status = pthread_mutex_init(&mutex_, NULL);
}
@@ -79,54 +82,41 @@ Lock::Lock(bool is_mutex_recursive)
Lock::~Lock() {
#ifndef NDEBUG
if (lock_taken_ > 0) {
- LOG4CXX_ERROR(logger_, "Destroying non-released mutex");
+ LOG4CXX_ERROR(logger_, "Destroying non-released mutex " << &mutex_);
}
#endif
int32_t status = pthread_mutex_destroy(&mutex_);
if (status != 0) {
- LOG4CXX_ERROR(logger_, "Failed to destroy mutex");
+ LOG4CXX_ERROR(logger_, "Failed to destroy mutex " << &mutex_ << ": " << strerror(status));
}
}
void Lock::Acquire() {
- int32_t status = pthread_mutex_lock(&mutex_);
+ const int32_t status = pthread_mutex_lock(&mutex_);
if (status != 0) {
- LOG4CXX_ERROR(logger_, "Failed to acquire mutex");
+ LOG4CXX_ERROR(logger_, "Failed to acquire mutex " << &mutex_ << ": " << strerror(status));
+ } else {
+ AssertFreeAndMarkTaken();
}
- AssertFreeAndMarkTaken();
}
void Lock::Release() {
AssertTakenAndMarkFree();
- int32_t status = pthread_mutex_unlock(&mutex_);
+ const int32_t status = pthread_mutex_unlock(&mutex_);
if (status != 0) {
- LOG4CXX_ERROR(logger_, "Failed to unlock mutex");
+ LOG4CXX_ERROR(logger_, "Failed to unlock mutex" << &mutex_ << ": " << strerror(status));
}
}
bool Lock::Try() {
- bool ackquired = false;
-#ifndef NDEBUG
- if ((lock_taken_ > 0) && !is_mutex_recursive_) {
- LOG4CXX_ERROR(logger_, "Trying to lock already taken not recurcive mutex");
- }
-#endif
- switch(pthread_mutex_trylock(&mutex_)) {
- case 0: {
- ackquired = true;
+ const int32_t status = pthread_mutex_trylock(&mutex_);
+ if (status == 0) {
#ifndef NDEBUG
- lock_taken_++;
+ lock_taken_++;
#endif
- } break;
- case EBUSY: {
- ackquired = false;
- } break;
- default: {
- ackquired = false;
- LOG4CXX_ERROR(logger_, "Failed to try lock the mutex");
- }
+ return true;
}
- return ackquired;
+ return false;
}
#ifndef NDEBUG
@@ -146,5 +136,4 @@ void Lock::AssertTakenAndMarkFree() {
}
#endif
-
-} // namespace sync_primitives
+} // namespace sync_primitives
diff --git a/src/components/utils/src/logger_status.cc b/src/components/utils/src/logger_status.cc
index be341b9add..ea9dfa3f22 100644
--- a/src/components/utils/src/logger_status.cc
+++ b/src/components/utils/src/logger_status.cc
@@ -34,6 +34,6 @@
namespace logger {
-LoggerStatus logger_status = LoggerThreadNotCreated;
+volatile LoggerStatus logger_status = LoggerThreadNotCreated;
} // namespace logger
diff --git a/src/components/utils/src/resource_usage.cc b/src/components/utils/src/resource_usage.cc
index aaa9c1b4a7..62c8d25b82 100644
--- a/src/components/utils/src/resource_usage.cc
+++ b/src/components/utils/src/resource_usage.cc
@@ -124,6 +124,8 @@ bool Resources::GetProcInfo(Resources::PidStats& output) {
if (0 >= fd) {
LOG4CXX_ERROR(logger_, "Failed open process proc file : " << GetProcPath() <<
"; error no : " << strerror( errno ) );
+
+ close(fd);
return false;
}
devctl(fd, DCMD_PROC_INFO, &output, sizeof(output), 0);
@@ -148,14 +150,14 @@ bool Resources::GetMemInfo(Resources::MemInfo &output) {
std::string as_path = GetStatPath();
struct stat st;
struct _dir* proc_dir = 0;
- struct dirent* proc_entry = 0;
if (0 == (proc_dir = opendir(proc))) {
LOG4CXX_ERROR(logger_, "Unable to access to " << proc);
result = false;
return result;
}
- if (0 == (proc_entry = readdir(proc_dir))) {
+ if (0 == readdir(proc_dir)) {
LOG4CXX_ERROR(logger_, "Unable to read : " << proc_dir);
+ closedir(proc_dir);
result = false;
return result;
}
diff --git a/src/components/utils/src/rwlock_posix.cc b/src/components/utils/src/rwlock_posix.cc
index 7cc850b25b..08edb8cb0c 100644
--- a/src/components/utils/src/rwlock_posix.cc
+++ b/src/components/utils/src/rwlock_posix.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Ford Motor Company
+ * Copyright (c) 2015, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,22 +49,44 @@ RWLock::~RWLock() {
}
}
-void RWLock::AcquireForReading() {
+bool RWLock::AcquireForReading() {
if (pthread_rwlock_rdlock(&rwlock_) != 0) {
LOG4CXX_ERROR(logger_, "Failed to acquire rwlock for reading");
+ return false;
}
+ return true;
}
-void RWLock::AcquireForWriting() {
+bool RWLock::TryAcquireForReading() {
+ if (pthread_rwlock_tryrdlock(&rwlock_) != 0) {
+ LOG4CXX_ERROR(logger_, "Failed to acquire rwlock for reading");
+ return false;
+ }
+ return true;
+}
+
+bool RWLock::AcquireForWriting() {
if (pthread_rwlock_wrlock(&rwlock_) != 0) {
LOG4CXX_ERROR(logger_, "Failed to acquire rwlock for writing");
+ return false;
+ }
+ return true;
+}
+
+bool RWLock::TryAcquireForWriting() {
+ if (pthread_rwlock_trywrlock(&rwlock_) != 0) {
+ LOG4CXX_ERROR(logger_, "Failed to acquire rwlock for writing");
+ return false;
}
+ return true;
}
-void RWLock::Release() {
+bool RWLock::Release() {
if (pthread_rwlock_unlock(&rwlock_) != 0) {
LOG4CXX_ERROR(logger_, "Failed to release rwlock");
+ return false;
}
+ return true;
}
} // namespace sync_primitives
diff --git a/src/components/utils/src/signals_linux.cc b/src/components/utils/src/signals_linux.cc
index 3ded6a5877..2e598d1b0f 100644
--- a/src/components/utils/src/signals_linux.cc
+++ b/src/components/utils/src/signals_linux.cc
@@ -1,54 +1,63 @@
/*
-* Copyright (c) 2014, Ford Motor Company
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-*
-* Redistributions of source code must retain the above copyright notice, this
-* list of conditions and the following disclaimer.
-*
-* Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided with the
-* distribution.
-*
-* Neither the name of the Ford Motor Company nor the names of its contributors
-* may be used to endorse or promote products derived from this software
-* without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*/
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
#include <csignal>
#include <cstdlib>
#include <stdint.h>
+#include "utils/signals.h"
+
namespace utils {
-bool SubscribeToTerminateSignal(void (*func)(int32_t p)) {
+bool SubscribeToTerminateSignal(sighandler_t func) {
struct sigaction act;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
- return (sigaction(SIGINT, &act, NULL) == 0)
- && (sigaction(SIGTERM, &act, NULL) == 0);
+ bool sigint_subscribed = (sigaction(SIGINT, &act, NULL) == 0);
+ bool sigterm_subscribed = (sigaction(SIGTERM, &act, NULL) == 0);
+
+ return sigint_subscribed && sigterm_subscribed;
}
-bool ResetSubscribeToTerminateSignal() {
- void (*prev_func)(int32_t p);
- prev_func = signal(SIGINT, SIG_DFL);
- return (SIG_ERR != prev_func);
+bool SubscribeToFaultSignal(sighandler_t func) {
+ struct sigaction act;
+ act.sa_handler = func;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESETHAND; // we only want to catch SIGSEGV once to flush logger queue
+
+ bool sigsegv_subscribed = (sigaction(SIGSEGV, &act, NULL) == 0);
+
+ return sigsegv_subscribed;
}
} // namespace utils
diff --git a/src/components/utils/src/system.cc b/src/components/utils/src/system.cc
index ee90315db0..70659419a7 100644
--- a/src/components/utils/src/system.cc
+++ b/src/components/utils/src/system.cc
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2014, Ford Motor Company
* All rights reserved.
*
@@ -42,6 +42,7 @@
#include <algorithm>
#include <functional>
#include <cstring>
+#include <iostream>
#include "utils/logger.h"
#include "utils/system.h"
@@ -66,15 +67,23 @@ System::System(const std::string& file, const std::string& command)
argv_.push_back(command);
}
-bool System::Execute() {
- return Execute(false);
-}
-
System& System::Add(const std::string& arg) {
argv_.push_back(arg);
return *this;
}
+std::string System::command() const {
+ return command_;
+}
+
+std::vector<std::string> System::argv() const {
+ return argv_;
+}
+
+bool System::Execute() {
+ return Execute(false);
+}
+
#ifdef __QNX__
bool System::Execute(bool wait) {
@@ -89,7 +98,7 @@ bool System::Execute(bool wait) {
if (ret == -1) {
LOG4CXX_ERROR(logger_, "Can't execute command: " << command_
- << " Errno is: " << std::strerror(errno));
+ << " Errno is: " << std::strerror(errno));
return false;
}
diff --git a/src/components/utils/src/threads/posix_thread.cc b/src/components/utils/src/threads/posix_thread.cc
index 3f7e006eca..82dd8c59b3 100644
--- a/src/components/utils/src/threads/posix_thread.cc
+++ b/src/components/utils/src/threads/posix_thread.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Ford Motor Company
+ * Copyright (c) 2015, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,125 +31,168 @@
*/
#include <errno.h>
-
#include <limits.h>
#include <stddef.h>
#include <signal.h>
-#include "utils/atomic.h"
+#ifdef BUILD_TESTS
+// Temporary fix for UnitTest until APPLINK-9987 is resolved
+#include <unistd.h>
+#endif
+
#include "utils/threads/thread.h"
-#include "utils/threads/thread_manager.h"
-#include "utils/logger.h"
#include "pthread.h"
-
+#include "utils/atomic.h"
+#include "utils/threads/thread_delegate.h"
+#include "utils/logger.h"
#ifndef __QNXNTO__
- const int EOK = 0;
+const int EOK = 0;
#endif
#if defined(OS_POSIX)
- const size_t THREAD_NAME_SIZE = 15;
+const size_t THREAD_NAME_SIZE = 15;
#endif
namespace threads {
CREATE_LOGGERPTR_GLOBAL(logger_, "Utils")
-namespace {
-
-static void* threadFunc(void* arg) {
- LOG4CXX_INFO(logger_, "Thread #" << pthread_self() << " started successfully");
- threads::Thread* thread = static_cast<threads::Thread*>(arg);
- threads::ThreadDelegate* delegate = thread->delegate();
- delegate->threadMain();
- thread->set_running(false);
- MessageQueue<ThreadManager::ThreadDesc>& threads = ::threads::ThreadManager::instance()->threads_to_terminate;
- if (!threads.IsShuttingDown()) {
- LOG4CXX_INFO(logger_, "Pushing thread #" << pthread_self() << " to join queue");
- ThreadManager::ThreadDesc desc = { pthread_self(), delegate };
- threads.push(desc);
- }
- LOG4CXX_INFO(logger_, "Thread #" << pthread_self() << " exited successfully");
- return NULL;
-}
+size_t Thread::kMinStackSize = PTHREAD_STACK_MIN; /* Ubuntu : 16384 ; QNX : 256; */
+void Thread::cleanup(void* arg) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ Thread* thread = reinterpret_cast<Thread*>(arg);
+ sync_primitives::AutoLock auto_lock(thread->state_lock_);
+ thread->isThreadRunning_ = false;
+ thread->state_cond_.Broadcast();
}
-size_t Thread::kMinStackSize = PTHREAD_STACK_MIN; /* Ubuntu : 16384 ; QNX : 256; */
+void* Thread::threadFunc(void* arg) {
+ // 0 - state_lock unlocked
+ // stopped = 0
+ // running = 0
+ // finalized = 0
+ // 4 - state_lock unlocked
+ // stopped = 1
+ // running = 1
+ // finalized = 0
+ // 5 - state_lock unlocked
+ // stopped = 1
+ // running = 1
+ // finalized = 1
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ LOG4CXX_DEBUG(logger_,
+ "Thread #" << pthread_self() << " started successfully");
+
+ threads::Thread* thread = reinterpret_cast<Thread*>(arg);
+ DCHECK(thread);
+
+ pthread_cleanup_push(&cleanup, thread);
+
+ thread->state_lock_.Acquire();
+ thread->state_cond_.Broadcast();
+
+ while (!thread->finalized_) {
+ LOG4CXX_DEBUG(logger_, "Thread #" << pthread_self() << " iteration");
+ thread->run_cond_.Wait(thread->state_lock_);
+ LOG4CXX_DEBUG(
+ logger_,
+ "Thread #" << pthread_self() << " execute. " << "stopped_ = " << thread->stopped_ << "; finalized_ = " << thread->finalized_);
+ if (!thread->stopped_ && !thread->finalized_) {
+ thread->isThreadRunning_ = true;
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_testcancel();
+
+ thread->state_lock_.Release();
+ thread->delegate_->threadMain();
+ thread->state_lock_.Acquire();
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ thread->isThreadRunning_ = false;
+ }
+ thread->state_cond_.Broadcast();
+ LOG4CXX_DEBUG(logger_,
+ "Thread #" << pthread_self() << " finished iteration");
+ }
-/*
-void ThreadBase::set_name(const std::string name) {
- std::string trimname = name.erase(15);
- if(pthread_setname_np(thread_handle_, trimname.c_str()) != EOK) {
- LOG4CXX_WARN(logger_, "Couldn't set pthread name \""
- << trimname
- << "\", error code "
- << pthread_result
- << " ("
- << strerror(pthread_result)
- << ")");
- }
+ thread->state_lock_.Release();
+ pthread_cleanup_pop(1);
+
+ LOG4CXX_DEBUG(logger_,
+ "Thread #" << pthread_self() << " exited successfully");
+ return NULL;
}
-*/
-
-void Thread::SetNameForId(const Id& thread_id, const std::string& name) {
- std::string nm = name;
- std::string& trimname = nm.size() > 15 ? nm.erase(15) : nm;
- const int rc = pthread_setname_np(thread_id.id_, trimname.c_str());
- if(rc == EOK) {
- LOG4CXX_WARN(logger_, "Couldn't set pthread name \""
- << trimname
- << "\", error code "
- << rc
- << " ("
- << strerror(rc)
- << ")");
+
+void Thread::SetNameForId(const PlatformThreadHandle& thread_id,
+ std::string name) {
+ if (name.size() > THREAD_NAME_SIZE)
+ name.erase(THREAD_NAME_SIZE);
+ const int rc = pthread_setname_np(thread_id, name.c_str());
+ if (rc != EOK) {
+ LOG4CXX_WARN(
+ logger_,
+ "Couldn't set pthread name \"" << name << "\", error code " << rc << " (" << strerror(rc) << ")");
}
}
Thread::Thread(const char* name, ThreadDelegate* delegate)
- : name_(name ? name : "undefined"),
- delegate_(delegate),
- thread_handle_(0),
- thread_options_(),
- isThreadRunning_(0) {
-}
-
-ThreadDelegate* Thread::delegate() const {
- return delegate_;
+ : name_(name ? name : "undefined"),
+ delegate_(delegate),
+ handle_(0),
+ thread_options_(),
+ isThreadRunning_(0),
+ stopped_(false),
+ finalized_(false),
+ thread_created_(false) {
}
bool Thread::start() {
- return startWithOptions(thread_options_);
+ return start(thread_options_);
}
-Thread::Id Thread::CurrentId() {
- return Id(pthread_self());
+PlatformThreadHandle Thread::CurrentId() {
+ return pthread_self();
}
-bool Thread::startWithOptions(const ThreadOptions& options) {
- LOG4CXX_TRACE_ENTER(logger_);
+bool Thread::start(const ThreadOptions& options) {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ sync_primitives::AutoLock auto_lock(state_lock_);
+ // 1 - state_lock locked
+ // stopped = 0
+ // running = 0
+
if (!delegate_) {
- NOTREACHED();
- LOG4CXX_ERROR(logger_, "NULL delegate");
- LOG4CXX_TRACE_EXIT(logger_);
+ LOG4CXX_ERROR(logger_,
+ "Cannot start thread " << name_ << ": delegate is NULL");
+ // 0 - state_lock unlocked
return false;
}
+ if (isThreadRunning_) {
+ LOG4CXX_TRACE(
+ logger_,
+ "EXIT thread "<< name_ << " #" << handle_ << " is already running");
+ return true;
+ }
+
thread_options_ = options;
pthread_attr_t attributes;
int pthread_result = pthread_attr_init(&attributes);
if (pthread_result != EOK) {
- LOG4CXX_WARN(logger_,"Couldn't init pthread attributes. Error code = "
- << pthread_result << "(\"" << strerror(pthread_result) << "\")");
+ LOG4CXX_WARN(
+ logger_,
+ "Couldn't init pthread attributes. Error code = " << pthread_result << " (\"" << strerror(pthread_result) << "\")");
}
if (!thread_options_.is_joinable()) {
pthread_result = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
if (pthread_result != EOK) {
- LOG4CXX_WARN(logger_,"Couldn't set detach state attribute.. Error code = "
- << pthread_result << "(\"" << strerror(pthread_result) << "\")");
+ LOG4CXX_WARN(
+ logger_,
+ "Couldn't set detach state attribute. Error code = " << pthread_result << " (\"" << strerror(pthread_result) << "\")");
thread_options_.is_joinable(false);
}
}
@@ -158,72 +201,94 @@ bool Thread::startWithOptions(const ThreadOptions& options) {
if (stack_size >= Thread::kMinStackSize) {
pthread_result = pthread_attr_setstacksize(&attributes, stack_size);
if (pthread_result != EOK) {
- LOG4CXX_WARN(logger_,"Couldn't set stacksize = " << stack_size <<
- ". Error code = " << pthread_result << "(\""
- << strerror(pthread_result) << "\")");
+ LOG4CXX_WARN(
+ logger_,
+ "Couldn't set stacksize = " << stack_size << ". Error code = " << pthread_result << " (\"" << strerror(pthread_result) << "\")");
}
}
+ else {
+ ThreadOptions thread_options_temp(Thread::kMinStackSize, thread_options_.is_joinable());
+ thread_options_ = thread_options_temp;
+ }
- pthread_result = pthread_create(&thread_handle_, &attributes, threadFunc, this);
- isThreadRunning_ = (pthread_result == EOK);
- if (!isThreadRunning_) {
- LOG4CXX_WARN(logger_, "Couldn't create thread. Error code = "
- << pthread_result << "(\"" << strerror(pthread_result) << "\")");
- } else {
- LOG4CXX_INFO(logger_,"Created thread: " << name_);
- SetNameForId(Id(thread_handle_), name_);
+ if (!thread_created_) {
+ // state_lock 1
+ pthread_result = pthread_create(&handle_, &attributes, threadFunc, this);
+ if (pthread_result == EOK) {
+ LOG4CXX_DEBUG(logger_, "Created thread: " << name_);
+ SetNameForId(handle_, name_);
+ // state_lock 0
+ // possible concurrencies: stop and threadFunc
+ state_cond_.Wait(auto_lock);
+ thread_created_ = true;
+ } else {
+ LOG4CXX_ERROR(
+ logger_,
+ "Couldn't create thread " << name_ << ". Error code = " << pthread_result << " (\"" << strerror(pthread_result) << "\")");
+ }
}
- LOG4CXX_TRACE_EXIT(logger_);
- return isThreadRunning_;
+ stopped_ = false;
+ run_cond_.NotifyOne();
+ LOG4CXX_DEBUG(
+ logger_,
+ "Thread " << name_ << " #" << handle_ << " started. pthread_result = " << pthread_result);
+ pthread_attr_destroy(&attributes);
+ return pthread_result == EOK;
}
void Thread::stop() {
- LOG4CXX_TRACE_ENTER(logger_);
+ LOG4CXX_AUTO_TRACE(logger_);
+ sync_primitives::AutoLock auto_lock(state_lock_);
- if (!atomic_post_clr(&isThreadRunning_))
- {
- return;
- }
+#ifdef BUILD_TESTS
+ // Temporary fix for UnitTest until APPLINK-9987 is resolved
+ usleep(100000);
+#endif
- if (delegate_ && !delegate_->exitThreadMain()) {
- if (thread_handle_ != pthread_self()) {
- LOG4CXX_WARN(logger_, "Cancelling thread #" << thread_handle_);
- const int pthread_result = pthread_cancel(thread_handle_);
- if (pthread_result != EOK) {
- LOG4CXX_WARN(logger_,
- "Couldn't cancel thread (#" << thread_handle_ << " \"" << name_ <<
- "\") from thread #" << pthread_self() << ". Error code = "
- << pthread_result << " (\"" << strerror(pthread_result) << "\")");
- }
- } else {
- LOG4CXX_ERROR(logger_,
- "Couldn't cancel the same thread (#" << thread_handle_
- << "\"" << name_ << "\")");
- }
+ stopped_ = true;
+
+ LOG4CXX_DEBUG(logger_, "Stopping thread #" << handle_
+
+ << " \"" << name_ << " \"");
+
+ if (delegate_ && isThreadRunning_) {
+ delegate_->exitThreadMain();
}
- LOG4CXX_TRACE_EXIT(logger_);
+ LOG4CXX_DEBUG(logger_,
+ "Stopped thread #" << handle_ << " \"" << name_ << " \"");
}
-bool Thread::Id::operator==(const Thread::Id& other) const {
- return pthread_equal(id_, other.id_) != 0;
-}
+void Thread::join() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ DCHECK(!pthread_equal(pthread_self(), handle_));
-std::ostream& operator<<(std::ostream& os, const Thread::Id& thread_id) {
- char name[32];
- if(pthread_getname_np(thread_id.Handle(), name, 32) == 0) {
- os << name;
+ stop();
+
+ sync_primitives::AutoLock auto_lock(state_lock_);
+ run_cond_.NotifyOne();
+ if (isThreadRunning_) {
+ if (!pthread_equal(pthread_self(), handle_)) {
+ state_cond_.Wait(auto_lock);
+ }
}
- return os;
+}
+
+Thread::~Thread() {
+ finalized_ = true;
+ stopped_ = true;
+ join();
+ pthread_join(handle_, NULL);
}
Thread* CreateThread(const char* name, ThreadDelegate* delegate) {
- return new Thread(name, delegate);
+ Thread* thread = new Thread(name, delegate);
+ delegate->set_thread(thread);
+ return thread;
}
void DeleteThread(Thread* thread) {
delete thread;
}
-
} // namespace threads
diff --git a/src/components/utils/src/threads/pulse_thread_delegate.cc b/src/components/utils/src/threads/pulse_thread_delegate.cc
index 8c580bea83..68db5dcbea 100644
--- a/src/components/utils/src/threads/pulse_thread_delegate.cc
+++ b/src/components/utils/src/threads/pulse_thread_delegate.cc
@@ -91,7 +91,7 @@ void PulseThreadDelegate::threadMain() {
Finalize();
}
-bool PulseThreadDelegate::exitThreadMain() {
+void PulseThreadDelegate::exitThreadMain() {
run_ = false;
LOG4CXX_TRACE(logger_, "Disconnecting from QNX channel " << chid_);
@@ -109,8 +109,6 @@ bool PulseThreadDelegate::exitThreadMain() {
else {
LOG4CXX_WARN(logger_, "Failed to destroy QNX channel " << chid_);
}
-
- return true;
}
} // namespace threads
diff --git a/src/components/utils/src/threads/thread_delegate.cc b/src/components/utils/src/threads/thread_delegate.cc
index 13271166ff..1436ea3377 100644
--- a/src/components/utils/src/threads/thread_delegate.cc
+++ b/src/components/utils/src/threads/thread_delegate.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Ford Motor Company
+ * Copyright (c) 2015, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,7 @@
namespace threads {
ThreadDelegate::~ThreadDelegate() {
- if(thread_) {
+ if (thread_) {
thread_->set_delegate(NULL);
}
}
@@ -60,4 +60,4 @@ void ThreadDelegate::set_thread(Thread *thread) {
thread_ = thread;
}
-}
+} // namespace threads
diff --git a/src/components/utils/src/threads/thread_validator.cc b/src/components/utils/src/threads/thread_validator.cc
index 5e9c88a7c9..99b812c456 100644
--- a/src/components/utils/src/threads/thread_validator.cc
+++ b/src/components/utils/src/threads/thread_validator.cc
@@ -1,5 +1,5 @@
-/**
- * Copyright (c) 2013, Ford Motor Company
+/*
+ * Copyright (c) 2014, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,7 @@ SingleThreadSimpleValidator::~SingleThreadSimpleValidator() {
}
void SingleThreadSimpleValidator::AssertRunningOnCreationThread() const {
- Thread::Id current_id = Thread::CurrentId();
+ PlatformThreadHandle current_id = Thread::CurrentId();
if (creation_thread_id_ != current_id) {
LOG4CXX_ERROR(logger_, "Single-threaded object created at thread "
<< creation_thread_id_
@@ -60,6 +60,11 @@ void SingleThreadSimpleValidator::AssertRunningOnCreationThread() const {
}
}
+PlatformThreadHandle SingleThreadSimpleValidator::creation_thread_id() const
+{
+ return creation_thread_id_;
+}
+
SingleThreadValidator::SingleThreadValidator()
: owning_thread_id_(Thread::CurrentId()){
@@ -68,12 +73,12 @@ SingleThreadValidator::SingleThreadValidator()
SingleThreadValidator::~SingleThreadValidator() {
}
-void SingleThreadValidator::PassToThread(Thread::Id thread_id) const {
+void SingleThreadValidator::PassToThread(PlatformThreadHandle thread_id) const {
owning_thread_id_ = thread_id;
}
void SingleThreadValidator::AssertRunningOnValidThread() const {
- Thread::Id current_id = Thread::CurrentId();
+ PlatformThreadHandle current_id = Thread::CurrentId();
if (owning_thread_id_ != current_id) {
LOG4CXX_ERROR(logger_, "Single-threaded object owned by thread "
<< owning_thread_id_