F´ Flight Software - C/C++ Documentation  NASA-v1.5.0
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Task.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 <pthread.h>
14 #include <errno.h>
15 #include <string.h>
16 #include <time.h>
17 #include <stdio.h>
18 #include <Fw/Logger/Logger.hpp>
19 
20 typedef void* (*pthread_func_ptr)(void*);
21 
22 //#define DEBUG_PRINT(x,...) Fw::Logger::logMsg(x,##__VA_ARGS__);
23 #define DEBUG_PRINT(x,...)
24 
25 namespace Os {
26  Task::Task() : m_handle(0), m_identifier(0), m_affinity(-1), m_started(false), m_suspendedOnPurpose(false) {
27  }
28 
29  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) {
30 
31  this->m_name = "TP_";
32  this->m_name += name;
33 #ifndef TGT_OS_TYPE_VXWORKS
34  char pid[40];
35  (void)snprintf(pid,sizeof(pid),".%d",getpid());
36  pid[sizeof(pid)-1] = 0;
37  this->m_name += pid;
38 #endif
39  this->m_identifier = identifier;
40 
41  Task::TaskStatus tStat = TASK_OK;
42 
43  pthread_attr_t att;
44  // clear att; can cause issues
45  memset(&att,0,sizeof(att));
46 
47  I32 stat = pthread_attr_init(&att);
48  if (stat != 0) {
49  Fw::Logger::logMsg("pthread_attr_init: (%d)(%d): %s\n",stat,errno, reinterpret_cast<POINTER_CAST>(strerror(stat)));
50  return TASK_INVALID_PARAMS;
51  }
52 #ifdef TGT_OS_TYPE_VXWORKS
53  stat = pthread_attr_setstacksize(&att,stackSize);
54  if (stat != 0) {
55  return TASK_INVALID_STACK;
56  }
57  stat = pthread_attr_setschedpolicy(&att,SCHED_FIFO);
58  if (stat != 0) {
59  return TASK_INVALID_PARAMS;
60  }
61  stat = pthread_attr_setname(&att,(char*)this->m_name.toChar());
62  if (stat != 0) {
63  return TASK_INVALID_PARAMS;
64  }
65  stat = pthread_attr_setinheritsched(&att,PTHREAD_EXPLICIT_SCHED); // needed to set inheritance according to WR docs
66  if (stat != 0) {
67  return TASK_INVALID_PARAMS;
68  }
69  sched_param schedParam;
70  memset(&schedParam,0,sizeof(sched_param));
71  schedParam.sched_priority = priority;
72  stat = pthread_attr_setschedparam(&att,&schedParam);
73  if (stat != 0) {
74  return TASK_INVALID_PARAMS;
75  }
76  stat = pthread_attr_setopt(&att,VX_FP_TASK);
77  if (stat != 0) {
78  return TASK_INVALID_PARAMS;
79  }
80 #elif defined TGT_OS_TYPE_LINUX
81 #if !defined BUILD_CYGWIN // cygwin doesn't support this call
82  stat = pthread_attr_setschedpolicy(&att,SCHED_RR);
83  if (stat != 0) {
84  Fw::Logger::logMsg("pthread_attr_setschedpolicy: %s\n", reinterpret_cast<POINTER_CAST>(strerror(errno)));
85  return TASK_INVALID_PARAMS;
86  }
87 #endif
88 #elif defined TGT_OS_TYPE_RTEMS
89  stat = pthread_attr_setstacksize(&att,stackSize);
90  if (stat != 0) {
91  return TASK_INVALID_STACK;
92  }
93  stat = pthread_attr_setschedpolicy(&att,SCHED_FIFO);
94  if (stat != 0) {
95  return TASK_INVALID_PARAMS;
96  }
97  stat = pthread_attr_setinheritsched(&att,PTHREAD_EXPLICIT_SCHED); // needed to set inheritance according to WR docs
98  if (stat != 0) {
99  return TASK_INVALID_PARAMS;
100  }
101  sched_param schedParam;
102  memset(&schedParam,0,sizeof(sched_param));
103  schedParam.sched_priority = priority;
104  stat = pthread_attr_setschedparam(&att,&schedParam);
105  if (stat != 0) {
106  return TASK_INVALID_PARAMS;
107  }
108 #elif defined TGT_OS_TYPE_DARWIN
109 #else
110  #error Unsupported OS!
111 #endif
112 
113  // If a registry has been registered, register task
114  if (Task::s_taskRegistry) {
115  Task::s_taskRegistry->addTask(this);
116  }
117 
118  pthread_t* tid = new pthread_t;
119  stat = pthread_create(tid,&att,(pthread_func_ptr)routine,arg);
120 
121  switch (stat) {
122  case 0:
123  this->m_handle = (POINTER_CAST)tid;
124  Task::s_numTasks++;
125  break;
126  case EINVAL:
127  delete tid;
128  Fw::Logger::logMsg("pthread_create: %s\n", reinterpret_cast<POINTER_CAST>(strerror(errno)));
129  tStat = TASK_INVALID_PARAMS;
130  break;
131  default:
132  delete tid;
133  tStat = TASK_UNKNOWN_ERROR;
134  break;
135  }
136 
137  (void)pthread_attr_destroy(&att);
138 
139  return tStat;
140  }
141 
143  {
144  timespec time1;
145 
146  time1.tv_sec = milliseconds/1000;
147  time1.tv_nsec = (milliseconds%1000)*1000000;
148 
149  timespec time2;
150  time2.tv_sec = 0;
151  time2.tv_nsec = 0;
152 
153  timespec* sleepTimePtr = &time1;
154  timespec* remTimePtr = &time2;
155 
156  while (true) {
157  int stat = nanosleep(sleepTimePtr,remTimePtr);
158  if (0 == stat) {
159  return TASK_OK;
160  } else { // check errno
161  if (EINTR == errno) { // swap pointers
162  timespec* temp = remTimePtr;
163  remTimePtr = sleepTimePtr;
164  sleepTimePtr = temp;
165  continue; // if interrupted, just continue
166  } else {
167  return TASK_DELAY_ERROR;
168  }
169  }
170  }
171 
172  return TASK_OK; // for coverage analysis
173 
174  }
175 
176 
177  Task::~Task() {
178  if (this->m_handle) {
179  delete (pthread_t*)this->m_handle;
180  }
181  // If a registry has been registered, remove task
182  if (Task::s_taskRegistry) {
183  Task::s_taskRegistry->removeTask(this);
184  }
185 
186  }
187 
188  // Note: not implemented for Posix threads. Must be manually done using a mutex or other blocking construct as there
189  // is not top-level pthreads support for suspend and resume.
190 
191  void Task::suspend(bool onPurpose) {
192  FW_ASSERT(0);
193  }
194 
195  void Task::resume(void) {
196  FW_ASSERT(0);
197  }
198 
199  bool Task::isSuspended(void) {
200  FW_ASSERT(0);
201  return false;
202  }
203 
205  TaskId T;
206  return T;
207  }
208 
209  Task::TaskStatus Task::join(void **value_ptr) {
210  NATIVE_INT_TYPE stat = 0;
211  if (!(this->m_handle)) {
212  return TASK_JOIN_ERROR;
213  }
214  stat = pthread_join(*((pthread_t*) this->m_handle), value_ptr);
215 
216  if (stat != 0) {
217  DEBUG_PRINT("join: %s\n", strerror(errno));
218  return TASK_JOIN_ERROR;
219  }
220  else {
221  return TASK_OK;
222  }
223  }
224 }
Os
Definition: File.cpp:7
DEBUG_PRINT
#define DEBUG_PRINT(x,...)
Definition: Task.cpp:23
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
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
pthread_func_ptr
void *(* pthread_func_ptr)(void *)
Definition: Task.cpp:20
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
Os::TaskId
Definition: TaskId.hpp:18
Os::Task::getOsIdentifier
static TaskId getOsIdentifier(void)
Definition: Task.cpp:204
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