sys_arch.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /*
  2. * Copyright (c) 2017 Simon Goldschmidt
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification,
  6. * are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  17. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  19. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  20. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  21. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  24. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  25. * OF SUCH DAMAGE.
  26. *
  27. * This file is part of the lwIP TCP/IP stack.
  28. *
  29. * Author: Simon Goldschmidt
  30. *
  31. */
  32. #include <lwip/opt.h>
  33. #include <lwip/arch.h>
  34. #if !NO_SYS
  35. #include "sys_arch.h"
  36. #endif
  37. #include <lwip/stats.h>
  38. #include <lwip/debug.h>
  39. #include <lwip/sys.h>
  40. #include <string.h>
  41. u32_t lwip_sys_now;
  42. u32_t
  43. sys_jiffies(void)
  44. {
  45. return lwip_sys_now;
  46. }
  47. u32_t
  48. sys_now(void)
  49. {
  50. return lwip_sys_now;
  51. }
  52. void
  53. sys_init(void)
  54. {
  55. }
  56. #if !NO_SYS
  57. test_sys_arch_waiting_fn the_waiting_fn;
  58. void
  59. test_sys_arch_wait_callback(test_sys_arch_waiting_fn waiting_fn)
  60. {
  61. the_waiting_fn = waiting_fn;
  62. }
  63. err_t
  64. sys_sem_new(sys_sem_t *sem, u8_t count)
  65. {
  66. LWIP_ASSERT("sem != NULL", sem != NULL);
  67. *sem = count + 1;
  68. return ERR_OK;
  69. }
  70. void
  71. sys_sem_free(sys_sem_t *sem)
  72. {
  73. LWIP_ASSERT("sem != NULL", sem != NULL);
  74. *sem = 0;
  75. }
  76. void
  77. sys_sem_set_invalid(sys_sem_t *sem)
  78. {
  79. LWIP_ASSERT("sem != NULL", sem != NULL);
  80. *sem = 0;
  81. }
  82. /* semaphores are 1-based because RAM is initialized as 0, which would be valid */
  83. u32_t
  84. sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
  85. {
  86. u32_t ret = 0;
  87. LWIP_ASSERT("sem != NULL", sem != NULL);
  88. LWIP_ASSERT("*sem > 0", *sem > 0);
  89. if (*sem == 1) {
  90. /* need to wait */
  91. if(!timeout)
  92. {
  93. /* wait infinite */
  94. LWIP_ASSERT("cannot wait without waiting callback", the_waiting_fn != NULL);
  95. do {
  96. int expectSomething = the_waiting_fn(sem, NULL);
  97. LWIP_ASSERT("*sem > 0", *sem > 0);
  98. LWIP_ASSERT("expecting a semaphore count but it's 0", !expectSomething || (*sem > 1));
  99. ret++;
  100. if (ret == SYS_ARCH_TIMEOUT) {
  101. ret--;
  102. }
  103. } while(*sem == 1);
  104. }
  105. else
  106. {
  107. if (the_waiting_fn) {
  108. int expectSomething = the_waiting_fn(sem, NULL);
  109. LWIP_ASSERT("expecting a semaphore count but it's 0", !expectSomething || (*sem > 1));
  110. }
  111. LWIP_ASSERT("*sem > 0", *sem > 0);
  112. if (*sem == 1) {
  113. return SYS_ARCH_TIMEOUT;
  114. }
  115. ret = 1;
  116. }
  117. }
  118. LWIP_ASSERT("*sem > 0", *sem > 0);
  119. (*sem)--;
  120. LWIP_ASSERT("*sem > 0", *sem > 0);
  121. /* return the time we waited for the sem */
  122. return ret;
  123. }
  124. void
  125. sys_sem_signal(sys_sem_t *sem)
  126. {
  127. LWIP_ASSERT("sem != NULL", sem != NULL);
  128. LWIP_ASSERT("*sem > 0", *sem > 0);
  129. (*sem)++;
  130. LWIP_ASSERT("*sem > 0", *sem > 0);
  131. }
  132. err_t
  133. sys_mutex_new(sys_mutex_t *mutex)
  134. {
  135. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  136. *mutex = 1; /* 1 allocated */
  137. return ERR_OK;
  138. }
  139. void
  140. sys_mutex_free(sys_mutex_t *mutex)
  141. {
  142. /* parameter check */
  143. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  144. LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
  145. *mutex = 0;
  146. }
  147. void
  148. sys_mutex_set_invalid(sys_mutex_t *mutex)
  149. {
  150. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  151. *mutex = 0;
  152. }
  153. void
  154. sys_mutex_lock(sys_mutex_t *mutex)
  155. {
  156. /* nothing to do, no multithreading supported */
  157. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  158. /* check that the mutext is valid and unlocked (no nested locking) */
  159. LWIP_ASSERT("*mutex >= 1", *mutex == 1);
  160. /* we count up just to check the correct pairing of lock/unlock */
  161. (*mutex)++;
  162. LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
  163. }
  164. void
  165. sys_mutex_unlock(sys_mutex_t *mutex)
  166. {
  167. /* nothing to do, no multithreading supported */
  168. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  169. LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
  170. /* we count down just to check the correct pairing of lock/unlock */
  171. (*mutex)--;
  172. LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
  173. }
  174. sys_thread_t
  175. sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio)
  176. {
  177. LWIP_UNUSED_ARG(name);
  178. LWIP_UNUSED_ARG(function);
  179. LWIP_UNUSED_ARG(arg);
  180. LWIP_UNUSED_ARG(stacksize);
  181. LWIP_UNUSED_ARG(prio);
  182. /* threads not supported */
  183. return 0;
  184. }
  185. err_t
  186. sys_mbox_new(sys_mbox_t *mbox, int size)
  187. {
  188. int mboxsize = size;
  189. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  190. LWIP_ASSERT("size >= 0", size >= 0);
  191. if (size == 0) {
  192. mboxsize = 1024;
  193. }
  194. mbox->head = mbox->tail = 0;
  195. mbox->sem = mbox; /* just point to something for sys_mbox_valid() */
  196. mbox->q_mem = (void**)malloc(sizeof(void*)*mboxsize);
  197. mbox->size = mboxsize;
  198. mbox->used = 0;
  199. memset(mbox->q_mem, 0, sizeof(void*)*mboxsize);
  200. return ERR_OK;
  201. }
  202. void
  203. sys_mbox_free(sys_mbox_t *mbox)
  204. {
  205. /* parameter check */
  206. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  207. LWIP_ASSERT("mbox->sem != NULL", mbox->sem != NULL);
  208. LWIP_ASSERT("mbox->sem == mbox", mbox->sem == mbox);
  209. LWIP_ASSERT("mbox->q_mem != NULL", mbox->q_mem != NULL);
  210. mbox->sem = NULL;
  211. free(mbox->q_mem);
  212. mbox->q_mem = NULL;
  213. }
  214. void
  215. sys_mbox_set_invalid(sys_mbox_t *mbox)
  216. {
  217. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  218. LWIP_ASSERT("mbox->q_mem == NULL", mbox->q_mem == NULL);
  219. mbox->sem = NULL;
  220. mbox->q_mem = NULL;
  221. }
  222. void
  223. sys_mbox_post(sys_mbox_t *q, void *msg)
  224. {
  225. LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
  226. LWIP_ASSERT("q->sem == q", q->sem == q);
  227. LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
  228. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  229. LWIP_ASSERT("q->size > 0", q->size > 0);
  230. LWIP_ASSERT("mbox already full", q->used < q->size);
  231. q->q_mem[q->head] = msg;
  232. q->head++;
  233. if (q->head >= (unsigned int)q->size) {
  234. q->head = 0;
  235. }
  236. LWIP_ASSERT("mbox is full!", q->head != q->tail);
  237. q->used++;
  238. }
  239. err_t
  240. sys_mbox_trypost(sys_mbox_t *q, void *msg)
  241. {
  242. LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
  243. LWIP_ASSERT("q->sem == q", q->sem == q);
  244. LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
  245. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  246. LWIP_ASSERT("q->size > 0", q->size > 0);
  247. LWIP_ASSERT("q->used <= q->size", q->used <= q->size);
  248. if (q->used == q->size) {
  249. return ERR_MEM;
  250. }
  251. sys_mbox_post(q, msg);
  252. return ERR_OK;
  253. }
  254. err_t
  255. sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg)
  256. {
  257. return sys_mbox_trypost(q, msg);
  258. }
  259. u32_t
  260. sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout)
  261. {
  262. u32_t ret = 0;
  263. u32_t ret2;
  264. LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
  265. LWIP_ASSERT("q->sem == q", q->sem == q);
  266. LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
  267. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  268. LWIP_ASSERT("q->size > 0", q->size > 0);
  269. if (q->used == 0) {
  270. /* need to wait */
  271. /* need to wait */
  272. if(!timeout)
  273. {
  274. /* wait infinite */
  275. LWIP_ASSERT("cannot wait without waiting callback", the_waiting_fn != NULL);
  276. do {
  277. int expectSomething = the_waiting_fn(NULL, q);
  278. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  279. LWIP_ASSERT("expecting item available but it's 0", !expectSomething || (q->used > 0));
  280. ret++;
  281. if (ret == SYS_ARCH_TIMEOUT) {
  282. ret--;
  283. }
  284. } while(q->used == 0);
  285. }
  286. else
  287. {
  288. if (the_waiting_fn) {
  289. int expectSomething = the_waiting_fn(NULL, q);
  290. LWIP_ASSERT("expecting item available count but it's 0", !expectSomething || (q->used > 0));
  291. }
  292. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  293. if (q->used == 0) {
  294. if(msg) {
  295. *msg = NULL;
  296. }
  297. return SYS_ARCH_TIMEOUT;
  298. }
  299. ret = 1;
  300. }
  301. }
  302. LWIP_ASSERT("q->used > 0", q->used > 0);
  303. ret2 = sys_arch_mbox_tryfetch(q, msg);
  304. LWIP_ASSERT("got no message", ret2 == 0);
  305. return ret;
  306. }
  307. u32_t
  308. sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg)
  309. {
  310. LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
  311. LWIP_ASSERT("q->sem == q", q->sem == q);
  312. LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
  313. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  314. LWIP_ASSERT("q->size > 0", q->size > 0);
  315. if (!q->used) {
  316. return SYS_ARCH_TIMEOUT;
  317. }
  318. if(msg) {
  319. *msg = q->q_mem[q->tail];
  320. }
  321. q->tail++;
  322. if (q->tail >= (unsigned int)q->size) {
  323. q->tail = 0;
  324. }
  325. q->used--;
  326. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  327. return 0;
  328. }
  329. #if LWIP_NETCONN_SEM_PER_THREAD
  330. /* Simple implementation of this: unit tests only support one thread */
  331. static sys_sem_t global_netconn_sem;
  332. sys_sem_t* sys_arch_netconn_sem_get(void)
  333. {
  334. return &global_netconn_sem;
  335. }
  336. void sys_arch_netconn_sem_alloc(void)
  337. {
  338. sys_sem_new(&global_netconn_sem, 0);
  339. }
  340. void sys_arch_netconn_sem_free(void)
  341. {
  342. sys_sem_free(&global_netconn_sem);
  343. }
  344. #endif /* LWIP_NETCONN_SEM_PER_THREAD */
  345. #endif /* !NO_SYS */