F´ Flight Software - C/C++ Documentation  NASA-v2.0.0
A framework for building embedded system applications to NASA flight quality standards.
TaskRoot.cpp
Go to the documentation of this file.
1 #include <Os/Task.hpp>
2 #include <Fw/Types/Assert.hpp>
3 
4 
5 #ifdef TGT_OS_TYPE_VXWORKS
6  #include <vxWorks.h>
7  #include <taskLib.h> // need it for VX_FP_TASK
8 #else
9  #include <sys/types.h>
10  #include <unistd.h>
11 #endif
12 
13 #include <Fw/Logger/Logger.hpp>
14 
15 #include <pthread.h>
16 #include <errno.h>
17 #include <string.h>
18 #include <time.h>
19 #include <stdio.h>
20 
21 //#define DEBUG_PRINT(x,...) Fw::Logger::logMsg(x,##__VA_ARGS__);
22 #define DEBUG_PRINT(x,...)
23 
24 typedef void* (*pthread_func_ptr)(void*);
25 
26 namespace Os {
27  Task::Task() : m_handle(0), m_identifier(0), m_affinity(-1), m_started(false), m_suspendedOnPurpose(false) {
28  }
29 
30  Task::TaskStatus Task::start(const Fw::StringBase &name, NATIVE_INT_TYPE identifier, NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, taskRoutine routine, void* arg, NATIVE_INT_TYPE cpuAffinity) {
31 
32  // for linux, task names can only be of length 15, so just setting it to the name:
33  this->m_name = name;
34  this->m_identifier = identifier;
35 
36  Task::TaskStatus tStat = TASK_OK;
37 
38  pthread_attr_t att;
39  // clear att; can cause issues
40  memset(&att,0,sizeof(att));
41 
42  I32 stat = pthread_attr_init(&att);
43  if (stat != 0) {
44  Fw::Logger::logMsg("pthread_attr_init: (%d)(%d): %s\n",stat,errno,strerror(stat));
45  return TASK_INVALID_PARAMS;
46  }
47 
48  stat = pthread_attr_setstacksize(&att,stackSize);
49  if (stat != 0) {
50  return TASK_INVALID_STACK;
51  }
52 
53  stat = pthread_attr_setschedpolicy(&att,SCHED_RR);
54 
55  if (stat != 0) {
56  Fw::Logger::logMsg("pthread_attr_setschedpolicy: %s\n",strerror(errno));
57  return TASK_INVALID_PARAMS;
58  }
59  stat = pthread_attr_setinheritsched(&att,PTHREAD_EXPLICIT_SCHED); // may not need this
60  if (stat != 0) {
61  Fw::Logger::logMsg("pthread_attr_setinheritsched: %s\n",strerror(errno));
62  return TASK_INVALID_PARAMS;
63  }
64  sched_param schedParam;
65  memset(&schedParam,0,sizeof(sched_param));
66  schedParam.sched_priority = priority;
67  stat = pthread_attr_setschedparam(&att,&schedParam);
68  if (stat != 0) {
69  Fw::Logger::logMsg("pthread_attr_setschedparam: %s\n",strerror(errno));
70  return TASK_INVALID_PARAMS;
71  }
72 
73  // Set affinity before creating thread:
74  if (cpuAffinity != -1) {
75 
76  cpu_set_t cpuset;
77  CPU_ZERO(&cpuset);
78  CPU_SET(cpuAffinity,&cpuset);
79 
80  stat = pthread_attr_setaffinity_np(&att, sizeof(cpu_set_t), &cpuset);
81  if (stat != 0) {
82  Fw::Logger::logMsg("pthread_setaffinity_np: %i %s\n",cpuAffinity,strerror(stat));
83  return TASK_INVALID_PARAMS;
84  }
85  }
86 
87  // If a registry has been registered, register task
88  if (Task::s_taskRegistry) {
89  Task::s_taskRegistry->addTask(this);
90  }
91 
92  pthread_t* tid = new pthread_t;
93 
94  stat = pthread_create(tid,&att,(pthread_func_ptr)routine,arg);
95 
96  switch (stat) {
97  case 0:
98  this->m_handle = (POINTER_CAST)tid;
99  Task::s_numTasks++;
100  break;
101  case EINVAL:
102  delete tid;
103  Fw::Logger::logMsg("pthread_create: %s\n",strerror(errno));
104  tStat = TASK_INVALID_PARAMS;
105  break;
106  default:
107  delete tid;
108  tStat = TASK_UNKNOWN_ERROR;
109  break;
110  }
111 
112  if (tStat == TASK_OK) {
113 
114  stat = pthread_setname_np(*tid,(char*)this->m_name.toChar());
115  if (stat != 0) {
116  Fw::Logger::logMsg("pthread_setname_np: %s %s\n",this->m_name.toChar(),strerror(stat));
117  delete tid;
118  tStat = TASK_INVALID_PARAMS;
119  }
120  }
121 
122  (void)pthread_attr_destroy(&att);
123 
124  return tStat;
125  }
126 
128  {
129  timespec time1;
130 
131  time1.tv_sec = milliseconds/1000;
132  time1.tv_nsec = (milliseconds%1000)*1000000;
133 
134  timespec time2;
135  time2.tv_sec = 0;
136  time2.tv_nsec = 0;
137 
138  timespec* sleepTimePtr = &time1;
139  timespec* remTimePtr = &time2;
140 
141  while (true) {
142  int stat = nanosleep(sleepTimePtr,remTimePtr);
143  if (0 == stat) {
144  return TASK_OK;
145  } else { // check errno
146  if (EINTR == errno) { // swap pointers
147  timespec* temp = remTimePtr;
148  remTimePtr = sleepTimePtr;
149  sleepTimePtr = temp;
150  continue; // if interrupted, just continue
151  } else {
152  return TASK_DELAY_ERROR;
153  }
154  }
155  }
156 
157  return TASK_OK; // for coverage analysis
158 
159  }
160 
161 
162  Task::~Task() {
163  if (this->m_handle) {
164  delete (pthread_t*)this->m_handle;
165  }
166  // If a registry has been registered, remove task
167  if (Task::s_taskRegistry) {
168  Task::s_taskRegistry->removeTask(this);
169  }
170 
171  }
172 
173  // FIXME: Need to find out how to do this for Posix threads
174 
175  void Task::suspend(bool onPurpose) {
176  FW_ASSERT(0);
177  }
178 
179  void Task::resume(void) {
180  FW_ASSERT(0);
181  }
182 
183  bool Task::isSuspended(void) {
184  FW_ASSERT(0);
185  return false;
186  }
187 
188  Task::TaskStatus Task::join(void **value_ptr) {
189  NATIVE_INT_TYPE stat = 0;
190  if (!(this->m_handle)) {
191  return TASK_JOIN_ERROR;
192  }
193  stat = pthread_join(*((pthread_t*) this->m_handle), value_ptr);
194 
195  if (stat != 0) {
196  DEBUG_PRINT("join: %s\n", strerror(errno));
197  return TASK_JOIN_ERROR;
198  }
199  else {
200  return TASK_OK;
201  }
202  }
203 }
Os
Definition: File.cpp:7
Os::Task::suspend
void suspend(bool onPurpose=false)
suspend task
Definition: Task.cpp:57
Os::Task::TASK_UNKNOWN_ERROR
@ TASK_UNKNOWN_ERROR
unexpected error return value
Definition: Task.hpp:22
Fw::StringBase
Definition: StringType.hpp:23
Task.hpp
Os::Task::Task
Task()
constructor
Definition: Task.cpp:8
Os::Task::resume
void resume(void)
resume execution of task
Definition: Task.cpp:62
Assert.hpp
pthread_func_ptr
void *(* pthread_func_ptr)(void *)
Definition: TaskRoot.cpp:24
Os::Task::TASK_OK
@ TASK_OK
message sent/received okay
Definition: Task.hpp:19
Os::Task::TaskStatus
TaskStatus
Definition: Task.hpp:18
NATIVE_UINT_TYPE
unsigned int NATIVE_UINT_TYPE
native unsigned integer type declaration
Definition: BasicTypes.hpp:30
Os::TaskString::toChar
const char * toChar(void) const
get pointer to internal char buffer
Definition: TaskString.cpp:34
Os::Task::TASK_INVALID_PARAMS
@ TASK_INVALID_PARAMS
started task with invalid parameters
Definition: Task.hpp:20
Os::Task::TASK_DELAY_ERROR
@ TASK_DELAY_ERROR
error trying to delay the task
Definition: Task.hpp:24
FW_ASSERT
#define FW_ASSERT(...)
Definition: Assert.hpp:9
Fw::Logger::logMsg
static void logMsg(const char *fmt, POINTER_CAST a0=0, POINTER_CAST a1=0, POINTER_CAST a2=0, POINTER_CAST a3=0, POINTER_CAST a4=0, POINTER_CAST a5=0, POINTER_CAST a6=0, POINTER_CAST a7=0, POINTER_CAST a8=0, POINTER_CAST a9=0)
Definition: Logger.cpp:18
Os::Task::delay
static TaskStatus delay(NATIVE_UINT_TYPE msecs)
delay the task
Definition: Task.cpp:41
Os::Task::start
TaskStatus start(const Fw::StringBase &name, NATIVE_INT_TYPE identifier, NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, taskRoutine routine, void *arg, NATIVE_INT_TYPE cpuAffinity=-1)
start the task
Definition: Task.cpp:16
Os::Task::isSuspended
bool isSuspended(void)
check with OS to see if it is suspended already
Definition: Task.cpp:67
Os::Task::~Task
virtual ~Task()
destructor
Definition: Task.cpp:47
DEBUG_PRINT
#define DEBUG_PRINT(x,...)
Definition: TaskRoot.cpp:22
NATIVE_INT_TYPE
int NATIVE_INT_TYPE
native integer type declaration
Definition: BasicTypes.hpp:29
Os::Task::TASK_INVALID_STACK
@ TASK_INVALID_STACK
started with invalid stack size
Definition: Task.hpp:21
Os::Task::TASK_JOIN_ERROR
@ TASK_JOIN_ERROR
error trying to join the task
Definition: Task.hpp:25
Logger.hpp
Os::Task::join
TaskStatus join(void **value_ptr)
Wait for task to finish.
Definition: Task.cpp:72