blob: e7dbc9a94d0f6ad85b12927d5e7fa2bb933f12ce [file] [log] [blame]
Brian Silvermanf7f267a2017-02-04 16:16:08 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008-2017. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "Task.h"
9
10#include <signal.h>
11
12#include <cerrno>
13
14#include "WPIErrors.h"
15
16namespace frc {
17
18const int Task::kDefaultPriority;
19
20Task& Task::operator=(Task&& task) {
21 m_thread.swap(task.m_thread);
22 m_taskName = std::move(task.m_taskName);
23
24 return *this;
25}
26
27Task::~Task() {
28 if (m_thread.joinable()) {
29 std::cout << "[HAL] Exited task " << m_taskName << std::endl;
30 }
31}
32
33bool Task::joinable() const noexcept { return m_thread.joinable(); }
34
35void Task::join() { m_thread.join(); }
36
37void Task::detach() { m_thread.detach(); }
38
39std::thread::id Task::get_id() const noexcept { return m_thread.get_id(); }
40
41std::thread::native_handle_type Task::native_handle() {
42 return m_thread.native_handle();
43}
44
45/**
46 * Verifies a task still exists.
47 *
48 * @return true on success.
49 */
50bool Task::Verify() { return VerifyTaskId() == TASK_OK; }
51
52/**
53 * Gets the priority of a task.
54 *
55 * @return task priority or 0 if an error occured
56 */
57int Task::GetPriority() {
58 int priority;
59 if (HandleError(GetTaskPriority(&priority)))
60 return priority;
61 else
62 return 0;
63}
64
65/**
66 * This routine changes a task's priority to a specified priority.
67 * Priorities range from 1, the lowest priority, to 99, the highest priority.
68 * Default task priority is 60.
69 *
70 * @param priority The priority at which the internal thread should run.
71 * @return true on success.
72 */
73bool Task::SetPriority(int priority) {
74 return HandleError(SetTaskPriority(priority));
75}
76
77/**
78 * Returns the name of the task.
79 *
80 * @return The name of the task.
81 */
82std::string Task::GetName() const { return m_taskName; }
83
84Task::TASK_STATUS Task::VerifyTaskId() {
85 auto task = m_thread.native_handle();
86 if (pthread_kill(task, 0) == 0) {
87 return TASK_OK;
88 } else {
89 return TASK_ERROR;
90 }
91}
92
93Task::TASK_STATUS Task::GetTaskPriority(int32_t* priority) {
94 auto task = m_thread.native_handle();
95 int32_t policy = 0;
96 struct sched_param param;
97
98 if (VerifyTaskId() == TASK_OK &&
99 pthread_getschedparam(task, &policy, &param) == 0) {
100 *priority = param.sched_priority;
101 return TASK_OK;
102 } else {
103 return TASK_ERROR;
104 }
105}
106
107Task::TASK_STATUS Task::SetTaskPriority(int32_t priority) {
108 auto task = m_thread.native_handle();
109 int32_t policy = 0;
110 struct sched_param param;
111
112 if (VerifyTaskId() == TASK_OK &&
113 pthread_getschedparam(task, &policy, &param) == 0) {
114 param.sched_priority = priority;
115 if (pthread_setschedparam(task, SCHED_FIFO, &param) == 0) {
116 return TASK_OK;
117 } else {
118 return TASK_ERROR;
119 }
120 } else {
121 return TASK_ERROR;
122 }
123}
124
125/**
126 * Handles errors generated by task related code.
127 */
128bool Task::HandleError(TASK_STATUS results) {
129 if (results != TASK_ERROR) return true;
130 int errsv = errno;
131 if (errsv == TaskLib_ILLEGAL_PRIORITY) {
132 wpi_setWPIErrorWithContext(TaskPriorityError, m_taskName.c_str());
133 } else {
134 std::printf("ERROR: errno=%i", errsv);
135 wpi_setWPIErrorWithContext(TaskError, m_taskName.c_str());
136 }
137 return false;
138}
139
140} // namespace frc