os_port_posix.c
Go to the documentation of this file.
1 /**
2  * @file os_port_posix.c
3  * @brief RTOS abstraction layer (POSIX Threads)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  *
23  * @author Oryx Embedded SARL (www.oryx-embedded.com)
24  * @version 1.9.0
25  **/
26 
27 //Switch to the appropriate trace level
28 #define TRACE_LEVEL TRACE_LEVEL_OFF
29 
30 //Dependencies
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <sys/time.h>
34 #include "os_port.h"
35 #include "os_port_posix.h"
36 #include "debug.h"
37 
38 //Pthread start routine
39 typedef void *(*PthreadTaskCode) (void *param);
40 
41 
42 /**
43  * @brief Kernel initialization
44  **/
45 
46 void osInitKernel(void)
47 {
48  //Not implemented
49 }
50 
51 
52 /**
53  * @brief Start kernel
54  **/
55 
56 void osStartKernel(void)
57 {
58  //Not implemented
59 }
60 
61 
62 /**
63  * @brief Create a new task
64  * @param[in] name A name identifying the task
65  * @param[in] taskCode Pointer to the task entry function
66  * @param[in] param A pointer to a variable to be passed to the task
67  * @param[in] stackSize The initial size of the stack, in words
68  * @param[in] priority The priority at which the task should run
69  * @return If the function succeeds, the return value is a pointer to the
70  * new task. If the function fails, the return value is NULL
71  **/
72 
74  void *param, size_t stackSize, int_t priority)
75 {
76  int_t ret;
77  pthread_t thread;
78 
79  //Create a new thread
80  ret = pthread_create(&thread, NULL, (PthreadTaskCode) taskCode, param);
81 
82  //Return a pointer to the newly created thread
83  if(ret == 0)
84  return (OsTask *) thread;
85  else
86  return NULL;
87 }
88 
89 
90 /**
91  * @brief Delete a task
92  * @param[in] task Pointer to the task to be deleted
93  **/
94 
95 void osDeleteTask(OsTask *task)
96 {
97  //Delete the calling thread?
98  if(task == NULL)
99  {
100  //Kill ourselves
101  pthread_exit(NULL);
102  }
103 }
104 
105 
106 /**
107  * @brief Delay routine
108  * @param[in] delay Amount of time for which the calling task should block
109  **/
110 
112 {
113  //Delay the task for the specified duration
114  sleep(delay);
115 }
116 
117 
118 /**
119  * @brief Yield control to the next task
120  **/
121 
122 void osSwitchTask(void)
123 {
124  //Not implemented
125 }
126 
127 
128 /**
129  * @brief Suspend scheduler activity
130  **/
131 
133 {
134  //Not implemented
135 }
136 
137 
138 /**
139  * @brief Resume scheduler activity
140  **/
141 
143 {
144  //Not implemented
145 }
146 
147 
148 /**
149  * @brief Create an event object
150  * @param[in] event Pointer to the event object
151  * @return The function returns TRUE if the event object was successfully
152  * created. Otherwise, FALSE is returned
153  **/
154 
156 {
157  int_t ret;
158 
159  //Create a semaphore object
160  ret = sem_init(event, 0, 0);
161 
162  //Check whether the semaphore was successfully created
163  if(ret == 0)
164  return TRUE;
165  else
166  return FALSE;
167 }
168 
169 
170 /**
171  * @brief Delete an event object
172  * @param[in] event Pointer to the event object
173  **/
174 
175 void osDeleteEvent(OsEvent *event)
176 {
177  //Properly dispose the event object
178  sem_destroy(event);
179 }
180 
181 
182 /**
183  * @brief Set the specified event object to the signaled state
184  * @param[in] event Pointer to the event object
185  **/
186 
187 void osSetEvent(OsEvent *event)
188 {
189  int_t ret;
190  int_t value;
191 
192  //Get the current value of the semaphore
193  ret = sem_getvalue(event, &value);
194 
195  //Nonsignaled state?
196  if(ret == 0 && value == 0)
197  {
198  //Set the specified event to the signaled state
199  sem_post(event);
200  }
201 }
202 
203 
204 /**
205  * @brief Set the specified event object to the nonsignaled state
206  * @param[in] event Pointer to the event object
207  **/
208 
209 void osResetEvent(OsEvent *event)
210 {
211  int_t ret;
212 
213  //Force the specified event to the nonsignaled state
214  do
215  {
216  //Decrement the semaphore's count by one
217  ret = sem_trywait(event);
218 
219  //Check status
220  } while(ret == 0);
221 }
222 
223 
224 /**
225  * @brief Wait until the specified event is in the signaled state
226  * @param[in] event Pointer to the event object
227  * @param[in] timeout Timeout interval
228  * @return The function returns TRUE if the state of the specified object is
229  * signaled. FALSE is returned if the timeout interval elapsed
230  **/
231 
233 {
234  int_t ret;
235  struct timespec ts;
236 
237  //Wait until the specified event is in the signaled
238  //state or the timeout interval elapses
239  if(timeout == 0)
240  {
241  //Non-blocking call
242  ret = sem_trywait(event);
243  }
244  else if(timeout == INFINITE_DELAY)
245  {
246  //Infinite timeout period
247  ret = sem_wait(event);
248  }
249  else
250  {
251  //Get current time
252  clock_gettime(CLOCK_REALTIME, &ts);
253 
254  //Set absolute timeout
255  ts.tv_sec += timeout / 1000;
256  ts.tv_nsec += (timeout % 1000) * 1000000;
257 
258  //Normalize time stamp value
259  if(ts.tv_nsec >= 1000000000)
260  {
261  ts.tv_sec += 1;
262  ts.tv_nsec -= 1000000000;
263  }
264 
265  //Wait until the specified event becomes set
266  ret = sem_timedwait(event, &ts);
267  }
268 
269  //Check whether the specified event is set
270  if(ret == 0)
271  {
272  //Force the event back to the nonsignaled state
273  do
274  {
275  //Decrement the semaphore's count by one
276  ret = sem_trywait(event);
277 
278  //Check status
279  } while(ret == 0);
280 
281  //The specified event is in the signaled state
282  return TRUE;
283  }
284  else
285  {
286  //The timeout interval elapsed
287  return FALSE;
288  }
289 }
290 
291 
292 /**
293  * @brief Set an event object to the signaled state from an interrupt service routine
294  * @param[in] event Pointer to the event object
295  * @return TRUE if setting the event to signaled state caused a task to unblock
296  * and the unblocked task has a priority higher than the currently running task
297  **/
298 
300 {
301  //Not implemented
302  return FALSE;
303 }
304 
305 
306 /**
307  * @brief Create a semaphore object
308  * @param[in] semaphore Pointer to the semaphore object
309  * @param[in] count The maximum count for the semaphore object. This value
310  * must be greater than zero
311  * @return The function returns TRUE if the semaphore was successfully
312  * created. Otherwise, FALSE is returned
313  **/
314 
316 {
317  int_t ret;
318 
319  //Create a semaphore object
320  ret = sem_init(semaphore, 0, count);
321 
322  //Check whether the semaphore was successfully created
323  if(ret == 0)
324  return TRUE;
325  else
326  return FALSE;
327 }
328 
329 
330 /**
331  * @brief Delete a semaphore object
332  * @param[in] semaphore Pointer to the semaphore object
333  **/
334 
336 {
337  //Properly dispose the semaphore object
338  sem_destroy(semaphore);
339 }
340 
341 
342 /**
343  * @brief Wait for the specified semaphore to be available
344  * @param[in] semaphore Pointer to the semaphore object
345  * @param[in] timeout Timeout interval
346  * @return The function returns TRUE if the semaphore is available. FALSE is
347  * returned if the timeout interval elapsed
348  **/
349 
351 {
352  int_t ret;
353  struct timespec ts;
354 
355  //Wait until the semaphore is available or the timeout interval elapses
356  if(timeout == 0)
357  {
358  //Non-blocking call
359  ret = sem_trywait(semaphore);
360  }
361  else if(timeout == INFINITE_DELAY)
362  {
363  //Infinite timeout period
364  ret = sem_wait(semaphore);
365  }
366  else
367  {
368  //Get current time
369  clock_gettime(CLOCK_REALTIME, &ts);
370 
371  //Set absolute timeout
372  ts.tv_sec += timeout / 1000;
373  ts.tv_nsec += (timeout % 1000) * 1000000;
374 
375  //Normalize time stamp value
376  if(ts.tv_nsec >= 1000000000)
377  {
378  ts.tv_sec += 1;
379  ts.tv_nsec -= 1000000000;
380  }
381 
382  //Wait until the specified semaphore becomes available
383  ret = sem_timedwait(semaphore, &ts);
384  }
385 
386  //Check whether the specified semaphore is available
387  if(ret == 0)
388  return TRUE;
389  else
390  return FALSE;
391 }
392 
393 
394 /**
395  * @brief Release the specified semaphore object
396  * @param[in] semaphore Pointer to the semaphore object
397  **/
398 
400 {
401  //Release the semaphore
402  sem_post(semaphore);
403 }
404 
405 
406 /**
407  * @brief Create a mutex object
408  * @param[in] mutex Pointer to the mutex object
409  * @return The function returns TRUE if the mutex was successfully
410  * created. Otherwise, FALSE is returned
411  **/
412 
414 {
415  int_t ret;
416 
417  //Create a mutex object
418  ret = pthread_mutex_init(mutex, NULL);
419 
420  //Check whether the mutex was successfully created
421  if(ret == 0)
422  return TRUE;
423  else
424  return FALSE;
425 }
426 
427 
428 /**
429  * @brief Delete a mutex object
430  * @param[in] mutex Pointer to the mutex object
431  **/
432 
433 void osDeleteMutex(OsMutex *mutex)
434 {
435  //Properly dispose the mutex object
436  pthread_mutex_destroy(mutex);
437 }
438 
439 
440 /**
441  * @brief Acquire ownership of the specified mutex object
442  * @param[in] mutex A handle to the mutex object
443  **/
444 
446 {
447  //Obtain ownership of the mutex object
448  pthread_mutex_lock(mutex);
449 }
450 
451 
452 /**
453  * @brief Release ownership of the specified mutex object
454  * @param[in] mutex Pointer to the mutex object
455  **/
456 
458 {
459  //Release ownership of the mutex object
460  pthread_mutex_unlock(mutex);
461 }
462 
463 
464 /**
465  * @brief Retrieve system time
466  * @return Number of milliseconds elapsed since the system was last started
467  **/
468 
470 {
471  struct timeval tv;
472 
473  //Get current time
474  gettimeofday(&tv, NULL);
475 
476  //Convert resulting value to milliseconds
477  return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
478 }
479 
480 
481 /**
482  * @brief Allocate a memory block
483  * @param[in] size Bytes to allocate
484  * @return A pointer to the allocated memory block or NULL if
485  * there is insufficient memory available
486  **/
487 
488 void *osAllocMem(size_t size)
489 {
490  //Allocate a memory block
491  return malloc(size);
492 }
493 
494 
495 /**
496  * @brief Release a previously allocated memory block
497  * @param[in] p Previously allocated memory block to be freed
498  **/
499 
500 void osFreeMem(void *p)
501 {
502  //Free memory block
503  free(p);
504 }
uint16_t priority
Definition: dns_common.h:219
void osFreeMem(void *p)
Release a previously allocated memory block.
void *(* PthreadTaskCode)(void *param)
Definition: os_port_posix.c:39
uint32_t systime_t
Definition: compiler_port.h:44
char char_t
Definition: compiler_port.h:41
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
Debugging facilities.
uint8_t p
Definition: ndp.h:295
void osStartKernel(void)
Start kernel.
Definition: os_port_posix.c:56
void osResumeAllTasks(void)
Resume scheduler activity.
#define sleep(delay)
Definition: os_port.h:126
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
Event object.
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
#define TRUE
Definition: os_port.h:48
void osInitKernel(void)
Kernel initialization.
Definition: os_port_posix.c:46
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
Task object.
signed int int_t
Definition: compiler_port.h:42
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
char_t name[]
#define INFINITE_DELAY
Definition: os_port.h:72
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
RTOS abstraction layer.
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
bool_t osCreateEvent(OsEvent *event)
Create an event object.
void osDeleteTask(OsTask *task)
Delete a task.
Definition: os_port_posix.c:95
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
Timeout structure.
Definition: bsd_socket.h:251
void osSwitchTask(void)
Yield control to the next task.
void(* OsTaskCode)(void *param)
Task routine.
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
int32_t tv_sec
Definition: bsd_socket.h:253
unsigned int uint_t
Definition: compiler_port.h:43
void osDeleteEvent(OsEvent *event)
Delete an event object.
uint8_t value[]
Definition: dtls_misc.h:141
void osSuspendAllTasks(void)
Suspend scheduler activity.
Mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void osDelayTask(systime_t delay)
Delay routine.
RTOS abstraction layer (POSIX Threads)
OsTask * osCreateTask(const char_t *name, OsTaskCode taskCode, void *param, size_t stackSize, int_t priority)
Create a new task.
Definition: os_port_posix.c:73
systime_t osGetSystemTime(void)
Retrieve system time.
Semaphore object.
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
void * osAllocMem(size_t size)
Allocate a memory block.
int32_t tv_usec
Definition: bsd_socket.h:254