dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_semaphore.c
Go to the documentation of this file.
1 
11 /*
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20  * for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, see <http://www.gnu.org/licenses/>
24  */
25 
26 #include <pthread.h>
27 #include <stdlib.h>
28 
29 #include <pios.h>
30 
31 struct pios_semaphore {
32 #define SEMAPHORE_MAGIC 0x616d6553 /* 'Sema' */
33  uint32_t magic;
34 
35  pthread_mutex_t mutex;
36  pthread_cond_t cond;
37 
38  bool given;
39 };
40 
42 {
43  struct pios_semaphore *s = PIOS_malloc(sizeof(*s));
44 
45  if (!s) {
46  return NULL;
47  }
48 
49  pthread_mutexattr_t attr;
50 
51  if (pthread_mutexattr_init(&attr)) {
52  abort();
53  }
54 
55  pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
56 
57  if (pthread_mutex_init(&s->mutex, &attr)) {
58  abort();
59  }
60 
61  if (pthread_cond_init(&s->cond, NULL)) {
62  abort();
63  }
64 
65  s->given = true;
66 
68 
69  return s;
70 }
71 
72 bool PIOS_Semaphore_Take(struct pios_semaphore *sema, uint32_t timeout_ms)
73 {
75 
76  struct timespec abstime;
77 
78  if (timeout_ms != PIOS_QUEUE_TIMEOUT_MAX) {
79  clock_gettime(CLOCK_REALTIME, &abstime);
80 
81  abstime.tv_nsec += (timeout_ms % 1000) * 1000000;
82  abstime.tv_sec += timeout_ms / 1000;
83 
84  if (abstime.tv_nsec > 1000000000) {
85  abstime.tv_nsec -= 1000000000;
86  abstime.tv_sec += 1;
87  }
88  }
89 
90  pthread_mutex_lock(&sema->mutex);
91 
92  while (!sema->given) {
93  if (timeout_ms != PIOS_QUEUE_TIMEOUT_MAX) {
94  if (pthread_cond_timedwait(&sema->cond,
95  &sema->mutex, &abstime)) {
96  pthread_mutex_unlock(&sema->mutex);
97  return false;
98  }
99  } else {
100  pthread_cond_wait(&sema->cond, &sema->mutex);
101  }
102  }
103 
104  sema->given = false;
105 
106  pthread_mutex_unlock(&sema->mutex);
107 
108  return true;
109 }
110 
111 bool PIOS_Semaphore_Give(struct pios_semaphore *sema)
112 {
113  bool old;
114 
116 
117  pthread_mutex_lock(&sema->mutex);
118 
119  old = sema->given;
120 
121  sema->given = true;
122 
123  pthread_cond_signal(&sema->cond);
124 
125  pthread_mutex_unlock(&sema->mutex);
126 
127  return !old;
128 }
129 
130 bool PIOS_Semaphore_Take_FromISR(struct pios_semaphore *sema, bool *woken)
131 {
132  bool ret = PIOS_Semaphore_Take(sema, 0);
133 
134  if (ret && woken) {
135  *woken = true;
136  }
137 
138  return ret;
139 }
140 
141 bool PIOS_Semaphore_Give_FromISR(struct pios_semaphore *sema, bool *woken)
142 {
143  bool ret = PIOS_Semaphore_Give(sema);
144 
145  if (ret && woken) {
146  *woken = true;
147  }
148 
149  return ret;
150 }
151 
int clock_gettime(clockid_t clk_id, struct timespec *t)
Main PiOS header to include all the compiled in PiOS options.
pthread_cond_t cond
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
bool PIOS_Semaphore_Give_FromISR(struct pios_semaphore *sema, bool *woken)
#define PIOS_QUEUE_TIMEOUT_MAX
Definition: pios_queue.h:30
struct pios_semaphore * PIOS_Semaphore_Create(void)
Creates a binary semaphore.
bool PIOS_Semaphore_Take_FromISR(struct pios_semaphore *sema, bool *woken)
bool PIOS_Semaphore_Give(struct pios_semaphore *sema)
Gives binary semaphore.
#define SEMAPHORE_MAGIC
#define CLOCK_REALTIME
Definition: pios_posix.h:63
bool PIOS_Semaphore_Take(struct pios_semaphore *sema, uint32_t timeout_ms)
Takes binary semaphore.
pthread_mutex_t mutex
#define PIOS_Assert(test)
Definition: pios_debug.h:52