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