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

[20862] Improve ThreadSettingsQoS logging #4744

Merged
merged 7 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
47 changes: 35 additions & 12 deletions src/cpp/utils/threading.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#ifndef UTILS__THREADING_HPP_
#define UTILS__THREADING_HPP_

#include <array>

#include "./thread.hpp"

namespace eprosima {
Expand All @@ -29,13 +31,30 @@ struct ThreadSettings;
/**
* @brief Give a name to the thread calling this function.
*
* @param[in] name A null-terminated string with the name to give to the calling thread.
* The implementation for certain platforms may truncate the final thread
* name if there is a limit on the length of the name of a thread.
* @param[in, out] thread_name_buffer Buffer to store the name of the thread.
* @param[in] name A null-terminated string with the name to give to the calling thread.
* The implementation for certain platforms may truncate the final thread
* name if there is a limit on the length of the name of a thread.
*/
void set_name_to_current_thread(
std::array<char, 16>& thread_name_buffer,
const char* name);

/**
* @brief Give a name to the thread calling this function.
*
* @param[in, out] thread_name_buffer Buffer to store the name of the thread.
* @param[in] fmt A null-terminated string to be used as the format argument of
* a `snprintf` like function, in order to accomodate the restrictions of
* the OS. Those restrictions may truncate the final thread name if there
* is a limit on the length of the name of a thread.
* @param[in] arg Single variadic argument passed to the formatting function.
*/
void set_name_to_current_thread(
std::array<char, 16>& thread_name_buffer,
const char* fmt,
uint32_t arg);

/**
* @brief Give a name to the thread calling this function.
*
Expand All @@ -52,25 +71,28 @@ void set_name_to_current_thread(
/**
* @brief Give a name to the thread calling this function.
*
* @param[in] fmt A null-terminated string to be used as the format argument of
* a `snprintf` like function, in order to accomodate the restrictions of
* the OS. Those restrictions may truncate the final thread name if there
* is a limit on the length of the name of a thread.
* @param[in] arg1 First variadic argument passed to the formatting function.
* @param[in] arg2 Second variadic argument passed to the formatting function.
* @param[in, out] thread_name_buffer Buffer to store the name of the thread.
* @param[in] fmt A null-terminated string to be used as the format argument of
* a `snprintf` like function, in order to accomodate the restrictions of
* the OS. Those restrictions may truncate the final thread name if there
* is a limit on the length of the name of a thread.
* @param[in] arg1 First variadic argument passed to the formatting function.
* @param[in] arg2 Second variadic argument passed to the formatting function.
*/
void set_name_to_current_thread(
std::array<char, 16>& thread_name_buffer,
const char* fmt,
uint32_t arg1,
uint32_t arg2);


/**
* @brief Apply thread settings to the thread calling this function.
*
* @param[in] thread_name Name of the thread.
* @param[in] settings Thread settings to apply.
*/
void apply_thread_settings_to_current_thread(
const char* thread_name,
const fastdds::rtps::ThreadSettings& settings);

/**
Expand All @@ -94,8 +116,9 @@ eprosima::thread create_thread(
{
return eprosima::thread(settings.stack_size, [=]()
{
apply_thread_settings_to_current_thread(settings);
set_name_to_current_thread(name, args ...);
std::array<char, 16> thread_name_buffer;
set_name_to_current_thread(thread_name_buffer, name, args ...);
apply_thread_settings_to_current_thread(thread_name_buffer.data(), settings);
func();
});
}
Expand Down
10 changes: 10 additions & 0 deletions src/cpp/utils/threading/threading_empty.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,34 @@
namespace eprosima {

void set_name_to_current_thread(
std::array<char, 16>& /* thread_name_buffer */,
MiguelCompany marked this conversation as resolved.
Show resolved Hide resolved
const char* /* name */)
{
}

void set_name_to_current_thread(
std::array<char, 16>& /* thread_name_buffer */,
const char* /* fmt */,
uint32_t /* arg */)
{
}

void set_name_to_current_thread(
const char* /* fmt */,
uint32_t /* arg */)
{
}

void set_name_to_current_thread(
MiguelCompany marked this conversation as resolved.
Show resolved Hide resolved
std::array<char, 16>& /* thread_name_buffer */,
const char* /* fmt */,
uint32_t /* arg1 */,
uint32_t /* arg2 */)
{
}

void apply_thread_settings_to_current_thread(
const char* /* thread_name */,
const fastdds::rtps::ThreadSettings& /*settings*/)
{
}
Expand Down
91 changes: 62 additions & 29 deletions src/cpp/utils/threading/threading_osx.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <array>
#include <cstdio>
#include <cstring>
#include <limits>
Expand All @@ -24,37 +25,50 @@

namespace eprosima {

template<typename... Args>
template<typename ... Args>
static void set_name_to_current_thread_impl(
const char* fmt, Args... args)
std::array<char, 16>& thread_name_buffer,
const char* fmt,
Args... args)
{
char thread_name[16]{};
snprintf(thread_name, 16, fmt, args...);
pthread_setname_np(thread_name);
snprintf(thread_name_buffer.data(), 16, fmt, args ...);
pthread_setname_np(thread_name_buffer.data());
}

void set_name_to_current_thread(
std::array<char, 16>& thread_name_buffer,
const char* name)
{
set_name_to_current_thread_impl("%s", name);
set_name_to_current_thread_impl(thread_name_buffer, "%s", name);
}

void set_name_to_current_thread(
std::array<char, 16>& thread_name_buffer,
const char* fmt,
uint32_t arg)
{
set_name_to_current_thread_impl(thread_name_buffer, fmt, arg);
}

void set_name_to_current_thread(
const char* fmt,
uint32_t arg)
{
set_name_to_current_thread_impl(fmt, arg);
std::array<char, 16> thread_name_buffer;
set_name_to_current_thread(thread_name_buffer, fmt, arg);
}

MiguelCompany marked this conversation as resolved.
Show resolved Hide resolved
void set_name_to_current_thread(
std::array<char, 16>& thread_name_buffer,
const char* fmt,
uint32_t arg1,
uint32_t arg2)
{
set_name_to_current_thread_impl(fmt, arg1, arg2);
set_name_to_current_thread_impl(thread_name_buffer, fmt, arg1, arg2);
}

static void configure_current_thread_scheduler(
const char* thread_name,
int sched_class,
int sched_priority)
{
Expand All @@ -64,67 +78,86 @@ static void configure_current_thread_scheduler(
int current_class;
int result = 0;
bool change_priority = (std::numeric_limits<int32_t>::min() != sched_priority);

// Get current scheduling parameters
memset(&current_param, 0, sizeof(current_param));
pthread_getschedparam(self_tid, &current_class, &current_param);

memset(&param, 0, sizeof(param));
param.sched_priority = 0;
sched_class = (sched_class == -1) ? current_class : sched_class;

//
// Set Scheduler Class and Priority
// Set Scheduler Class and Priority
//
if(sched_class == SCHED_OTHER)
{

if (sched_class == SCHED_OTHER)
{

//
// Sched OTHER has a nice value, that we pull from the priority parameter.
// - Requires priorty value to be zero (0).
//
//
result = pthread_setschedparam(self_tid, sched_class, &param);
if(0 == result && change_priority)
if (0 == result && change_priority)
{
uint64_t tid;
pthread_threadid_np(NULL, &tid);
result = setpriority(PRIO_PROCESS, tid, sched_priority);
}
if (0 != result)
{
EPROSIMA_LOG_ERROR(SYSTEM, "Problem to set priority of thread with id [" << tid << "," << thread_name << "] to value " << sched_priority << ". Error '" << strerror(
result) << "'");
}
}
else if (0 != result)
{
EPROSIMA_LOG_ERROR(SYSTEM, "Problem to set scheduler of thread with id [" << self_tid << "," << thread_name << "] to value " << sched_class << ". Error '" << strerror(
result) << "'");
}
}
else if((sched_class == SCHED_FIFO) ||
else if ((sched_class == SCHED_FIFO) ||
(sched_class == SCHED_RR))
{
//
// RT Policies use a different priority numberspace.
//

param.sched_priority = change_priority ? sched_priority : current_param.sched_priority;
result = pthread_setschedparam(self_tid, sched_class, &param);
}

if (0 != result)
{
EPROSIMA_LOG_ERROR(SYSTEM, "Error '" << strerror(result) << "' configuring scheduler for thread " << self_tid);
if (0 != result)
{
EPROSIMA_LOG_ERROR(SYSTEM, "Problem to set scheduler of thread with id [" << self_tid << "," << thread_name << "] to value " << sched_class << " with priority " << param.sched_priority << ". Error '" << strerror(
result) << "'");
}
}
}

static void configure_current_thread_affinity(
const char* thread_name,
uint64_t affinity)
{
if (affinity <= static_cast<uint64_t>(std::numeric_limits<integer_t>::max()))
{
int result = 0;
thread_affinity_policy_data_t policy = { static_cast<integer_t>(affinity) };
pthread_t self_tid = pthread_self();
thread_policy_set(pthread_mach_thread_np(self_tid), THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 1);
result =
thread_policy_set(pthread_mach_thread_np(self_tid), THREAD_AFFINITY_POLICY, (thread_policy_t)&policy,
1);
if (0 != result)
{
EPROSIMA_LOG_ERROR(SYSTEM, "Problem to set affinity of thread with id [" << self_tid << "," << thread_name << "] to value " << affinity << ". Error '" << strerror(
result) << "'");
}
}
}

void apply_thread_settings_to_current_thread(
const char* thread_name,
const fastdds::rtps::ThreadSettings& settings)
{
configure_current_thread_scheduler(settings.scheduling_policy, settings.priority);
configure_current_thread_affinity(settings.affinity);
configure_current_thread_scheduler(thread_name, settings.scheduling_policy, settings.priority);
configure_current_thread_affinity(thread_name, settings.affinity);
}

} // namespace eprosima
Loading
Loading