F´ Flight Software - C/C++ Documentation  NASA-v1.5.0
A framework for building embedded system applications to NASA flight quality standards.
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