F´ Flight Software - C/C++ Documentation  NASA-v2.0.1
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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