The Pedigree Project  0.1
sys_arch.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <lwip/arch/sys_arch.h>
21 #include <lwip/err.h>
22 #include <lwip/errno.h>
23 #include <lwip/sys.h>
24 
25 #include <pedigree/kernel/Log.h>
26 #include <pedigree/kernel/process/Mutex.h>
27 #include <pedigree/kernel/process/Semaphore.h>
28 #include <pedigree/kernel/process/Thread.h>
29 #include <pedigree/kernel/processor/Processor.h>
30 #include <pedigree/kernel/utilities/RingBuffer.h>
31 #include <pedigree/kernel/utilities/pocketknife.h>
32 
33 
34 #ifdef UTILITY_LINUX
35 #include <time.h>
36 #include <errno.h>
37 
38 static Spinlock g_Protection(false);
39 #else
40 // errno for lwIP usage, this is not ideal as it'll be exposed to ALL modules.
41 int errno;
42 #endif
43 
45 {
46  pedigree_mbox() : buffer(64)
47  {
48  }
49 
50  RingBuffer<void *> buffer;
51 };
52 
53 void sys_init()
54 {
55 }
56 
57 u32_t sys_now()
58 {
59 #ifdef UTILITY_LINUX
60  struct timespec spec;
61  clock_gettime(CLOCK_REALTIME, &spec);
62 
63  return (spec.tv_sec * 1000) + (spec.tv_nsec / 1000000);
64 #else
65  return Time::getTimeNanoseconds() / Time::Multiplier::Millisecond;
66 #endif
67 }
68 
70 {
71  lwip_thread_fn thread;
72  void *arg;
73  char name[64];
74 };
75 
76 static int thread_shim(void *arg)
77 {
78  struct thread_meta *meta = static_cast<struct thread_meta *>(arg);
79  meta->thread(meta->arg);
80  return 0;
81 }
82 
83 sys_thread_t sys_thread_new(
84  const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
85 {
87  auto meta = new struct thread_meta;
88  meta->thread = thread;
89  meta->arg = arg;
90  StringCopy(meta->name, name);
91  pocketknife::runConcurrently(thread_shim, meta);
92  return meta;
93 }
94 
95 err_t sys_sem_new(sys_sem_t *sem, u8_t count)
96 {
97 #ifdef UTILITY_LINUX
98  if (sem_init(sem, 0, count) != 0)
99  {
100  return ERR_ARG;
101  }
102  else
103  {
104  return ERR_OK;
105  }
106 #else
107  Semaphore *newsem = new Semaphore(count);
108  *sem = reinterpret_cast<void *>(newsem);
109  return ERR_OK;
110 #endif
111 }
112 
113 void sys_sem_free(sys_sem_t *sem)
114 {
115 #ifdef UTILITY_LINUX
116  sem_destroy(sem);
117 #else
118  Semaphore *s = reinterpret_cast<Semaphore *>(*sem);
119  delete s;
120  *sem = nullptr;
121 #endif
122 }
123 
124 int sys_sem_valid(sys_sem_t *sem)
125 {
126 #ifdef UTILITY_LINUX
127  return 1;
128 #else
129  if (*sem)
130  {
131  return 1;
132  }
133  else
134  {
135  return 0;
136  }
137 #endif
138 }
139 
140 void sys_sem_set_invalid(sys_sem_t *sem)
141 {
142 #ifndef UTILITY_LINUX
143  *sem = nullptr;
144 #endif
145 }
146 
147 void sys_sem_signal(sys_sem_t *sem)
148 {
149 #ifdef UTILITY_LINUX
150  sem_post(sem);
151 #else
152  Semaphore *s = reinterpret_cast<Semaphore *>(*sem);
153  s->release();
154 #endif
155 }
156 
157 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
158 {
159 #ifdef UTILITY_LINUX
160  if (!timeout)
161  {
162  if (sem_wait(sem) == 0)
163  {
164  return ERR_OK;
165  }
166  else
167  {
168  return ERR_ARG;
169  }
170  }
171 
172  struct timespec now, spec;
173  clock_gettime(CLOCK_REALTIME, &now);
174 
175  int r = 0;
176  if (timeout)
177  {
178  u32_t s = timeout / 1000;
179  u32_t ms = timeout % 1000;
180 
181  spec.tv_sec = now.tv_sec + s;
182  spec.tv_nsec = now.tv_nsec + (ms * 1000000);
183 
184  r = sem_timedwait(sem, &spec);
185  }
186  else
187  {
188  r = sem_wait(sem);
189  }
190 
191  clock_gettime(CLOCK_REALTIME, &spec);
192 
193  if (r == 0)
194  {
195  uint64_t orig_ms = (now.tv_sec * 1000U) + (now.tv_nsec * 1000000U);
196  uint64_t waited_ms = (spec.tv_sec * 1000U) + (spec.tv_nsec * 1000000U);
197 
198  // return time we had to wait for the semaphore
199  return waited_ms - orig_ms;
200  }
201  else
202  {
204  return SYS_ARCH_TIMEOUT;
205  }
206 #else
207  Time::Timestamp begin = Time::getTimeNanoseconds();
208 
209  Semaphore *s = reinterpret_cast<Semaphore *>(*sem);
210  if (!s->acquire(1, timeout * 1000)) // ms -> us
211  {
212  return SYS_ARCH_TIMEOUT;
213  }
214 
215  Time::Timestamp end = Time::getTimeNanoseconds();
216  return (end - begin) / Time::Multiplier::Millisecond;
217 #endif
218 }
219 
220 err_t sys_mbox_new(sys_mbox_t *mbox, int size)
221 {
222  *mbox = new pedigree_mbox;
223  return ERR_OK;
224 }
225 
227 {
228  delete *mbox;
229  *mbox = nullptr;
230 }
231 
232 void sys_mbox_post(sys_mbox_t *mbox, void *msg)
233 {
234  (*mbox)->buffer.write(msg);
235 }
236 
237 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
238 {
239  if (!(*mbox)->buffer.dataReady())
240  {
241  return SYS_MBOX_EMPTY;
242  }
243 
244  *msg = (*mbox)->buffer.read();
245  return 0;
246 }
247 
248 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
249 {
250  Time::Timestamp begin = Time::getTimeNanoseconds();
251 
252  Time::Timestamp timeoutMs = 0;
253  if (timeout == 0)
254  {
255  timeoutMs = Time::Infinity;
256  }
257  else
258  {
259  timeoutMs = timeout * Time::Multiplier::Millisecond;
260  }
261 
262  *msg = (*mbox)->buffer.read(timeoutMs);
263  if (*msg == NULL)
264  {
265  return SYS_ARCH_TIMEOUT;
266  }
267 
268  Time::Timestamp end = Time::getTimeNanoseconds();
269  return (end - begin) / Time::Multiplier::Millisecond;
270 }
271 
273 {
274  if (!(*mbox)->buffer.canWrite())
275  {
276  return ERR_WOULDBLOCK;
277  }
278 
279  (*mbox)->buffer.write(msg);
280 
281  return ERR_OK;
282 }
283 
285 {
286  return *mbox != nullptr ? 1 : 0;
287 }
288 
290 {
291  *mbox = nullptr;
292 }
293 
294 err_t sys_mutex_new(sys_mutex_t *mutex)
295 {
296  Mutex *m = new Mutex;
297  *mutex = m;
298  return ERR_OK;
299 }
300 
301 void sys_mutex_lock(sys_mutex_t *mutex)
302 {
303  Mutex *m = reinterpret_cast<Mutex *>(*mutex);
304  while (!m->acquire())
305  ;
306 }
307 
308 void sys_mutex_unlock(sys_mutex_t *mutex)
309 {
310  Mutex *m = reinterpret_cast<Mutex *>(*mutex);
311  m->release();
312 }
313 
314 void sys_mutex_free(sys_mutex_t *mutex)
315 {
316  Mutex *m = reinterpret_cast<Mutex *>(*mutex);
317  delete m;
318  *mutex = nullptr;
319 }
320 
321 int sys_mutex_valid(sys_mutex_t *mutex)
322 {
323  return *mutex != nullptr ? 1 : 0;
324 }
325 
326 void sys_mutex_set_invalid(sys_mutex_t *mutex)
327 {
328  *mutex = nullptr;
329 }
330 
331 sys_prot_t sys_arch_protect()
332 {
333 #ifdef UTILITY_LINUX
334  while (!g_Protection.acquire(true))
335  ;
336 
337  return 0;
338 #else
339  bool was = Processor::getInterrupts();
341  return was ? 1 : 0;
342 #endif
343 }
344 
345 void sys_arch_unprotect(sys_prot_t pval)
346 {
347 #ifdef UTILITY_LINUX
348  g_Protection.release();
349 #else
351 #endif
352 }
void sys_sem_free(sys_sem_t *sem)
Definition: sys_arch.cc:113
static bool getInterrupts()
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
Definition: Semaphore.h:62
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
Definition: sys_arch.cc:248
#define SYS_ARCH_TIMEOUT
Definition: sys.h:106
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
Definition: sys_arch.cc:157
void sys_mutex_free(sys_mutex_t *mutex)
Definition: sys_arch.cc:314
Definition: Mutex.h:58
void sys_mbox_free(sys_mbox_t *mbox)
Definition: sys_arch.cc:226
void sys_mbox_set_invalid(sys_mbox_t *mbox)
Definition: sys_arch.cc:289
int sys_mbox_valid(sys_mbox_t *mbox)
Definition: sys_arch.cc:284
void sys_mutex_unlock(sys_mutex_t *mutex)
Definition: sys_arch.cc:308
EXPORTED_PUBLIC void runConcurrently(int(*func)(void *), void *param)
Definition: pocketknife.cc:29
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
Definition: sys_arch.cc:83
u32_t sys_now()
Definition: sys_arch.cc:57
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
Definition: sys_arch.cc:220
#define SYS_MBOX_EMPTY
Definition: sys.h:111
void sys_mbox_post(sys_mbox_t *mbox, void *msg)
Definition: sys_arch.cc:232
void(* lwip_thread_fn)(void *arg)
Definition: sys.h:117
Definition: err.h:115
void release(size_t n=1)
Definition: Semaphore.cc:239
void sys_sem_signal(sys_sem_t *sem)
Definition: sys_arch.cc:147
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
Definition: sys_arch.cc:95
s8_t err_t
Definition: err.h:76
int sys_mutex_valid(sys_mutex_t *mutex)
Definition: sys_arch.cc:321
void sys_mutex_lock(sys_mutex_t *mutex)
Definition: sys_arch.cc:301
static void setInterrupts(bool bEnable)
void sys_sem_set_invalid(sys_sem_t *sem)
Definition: sys_arch.cc:140
void sys_mutex_set_invalid(sys_mutex_t *mutex)
Definition: sys_arch.cc:326
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
Definition: sys_arch.cc:272
Definition: err.h:82
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
Definition: sys_arch.cc:237
int sys_sem_valid(sys_sem_t *sem)
Definition: sys_arch.cc:124
err_t sys_mutex_new(sys_mutex_t *mutex)
Definition: sys_arch.cc:294