sys_arch.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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 sys_jiffies(void)
  42. {
  43. return (u32_t)0; /* todo */
  44. }
  45. u32_t sys_now(void)
  46. {
  47. return (u32_t)0; /* todo */
  48. }
  49. void sys_init(void)
  50. {
  51. }
  52. #if !NO_SYS
  53. test_sys_arch_waiting_fn the_waiting_fn;
  54. void test_sys_arch_wait_callback(test_sys_arch_waiting_fn waiting_fn)
  55. {
  56. the_waiting_fn = waiting_fn;
  57. }
  58. err_t sys_sem_new(sys_sem_t *sem, u8_t count)
  59. {
  60. LWIP_ASSERT("sem != NULL", sem != NULL);
  61. *sem = count + 1;
  62. return ERR_OK;
  63. }
  64. void sys_sem_free(sys_sem_t *sem)
  65. {
  66. LWIP_ASSERT("sem != NULL", sem != NULL);
  67. *sem = 0;
  68. }
  69. void sys_sem_set_invalid(sys_sem_t *sem)
  70. {
  71. LWIP_ASSERT("sem != NULL", sem != NULL);
  72. *sem = 0;
  73. }
  74. /* semaphores are 1-based because RAM is initialized as 0, which would be valid */
  75. u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
  76. {
  77. u32_t ret = 0;
  78. LWIP_ASSERT("sem != NULL", sem != NULL);
  79. LWIP_ASSERT("*sem > 0", *sem > 0);
  80. if (*sem == 1) {
  81. /* need to wait */
  82. if(!timeout)
  83. {
  84. /* wait infinite */
  85. LWIP_ASSERT("cannot wait without waiting callback", the_waiting_fn != NULL);
  86. do {
  87. int expectSomething = the_waiting_fn(sem, NULL);
  88. LWIP_ASSERT("*sem > 0", *sem > 0);
  89. LWIP_ASSERT("expecting a semaphore count but it's 0", !expectSomething || (*sem > 1));
  90. ret++;
  91. if (ret == SYS_ARCH_TIMEOUT) {
  92. ret--;
  93. }
  94. } while(*sem == 1);
  95. }
  96. else
  97. {
  98. if (the_waiting_fn) {
  99. int expectSomething = the_waiting_fn(sem, NULL);
  100. LWIP_ASSERT("expecting a semaphore count but it's 0", !expectSomething || (*sem > 1));
  101. }
  102. LWIP_ASSERT("*sem > 0", *sem > 0);
  103. if (*sem == 1) {
  104. return SYS_ARCH_TIMEOUT;
  105. }
  106. ret = 1;
  107. }
  108. }
  109. LWIP_ASSERT("*sem > 0", *sem > 0);
  110. (*sem)--;
  111. LWIP_ASSERT("*sem > 0", *sem > 0);
  112. /* return the time we waited for the sem */
  113. return ret;
  114. }
  115. void sys_sem_signal(sys_sem_t *sem)
  116. {
  117. LWIP_ASSERT("sem != NULL", sem != NULL);
  118. LWIP_ASSERT("*sem > 0", *sem > 0);
  119. (*sem)++;
  120. LWIP_ASSERT("*sem > 0", *sem > 0);
  121. }
  122. err_t sys_mutex_new(sys_mutex_t *mutex)
  123. {
  124. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  125. *mutex = 1; /* 1 allocated */
  126. return ERR_OK;
  127. }
  128. void sys_mutex_free(sys_mutex_t *mutex)
  129. {
  130. /* parameter check */
  131. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  132. LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
  133. *mutex = 0;
  134. }
  135. void sys_mutex_set_invalid(sys_mutex_t *mutex)
  136. {
  137. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  138. *mutex = 0;
  139. }
  140. void sys_mutex_lock(sys_mutex_t *mutex)
  141. {
  142. /* nothing to do, no multithreading supported */
  143. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  144. /* check that the mutext is valid and unlocked (no nested locking) */
  145. LWIP_ASSERT("*mutex >= 1", *mutex == 1);
  146. /* we count up just to check the correct pairing of lock/unlock */
  147. (*mutex)++;
  148. LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
  149. }
  150. void sys_mutex_unlock(sys_mutex_t *mutex)
  151. {
  152. /* nothing to do, no multithreading supported */
  153. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  154. LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
  155. /* we count down just to check the correct pairing of lock/unlock */
  156. (*mutex)--;
  157. LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
  158. }
  159. sys_thread_t sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio)
  160. {
  161. LWIP_UNUSED_ARG(name);
  162. LWIP_UNUSED_ARG(function);
  163. LWIP_UNUSED_ARG(arg);
  164. LWIP_UNUSED_ARG(stacksize);
  165. LWIP_UNUSED_ARG(prio);
  166. /* threads not supported */
  167. return 0;
  168. }
  169. err_t sys_mbox_new(sys_mbox_t *mbox, int size)
  170. {
  171. int mboxsize = size;
  172. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  173. LWIP_ASSERT("size >= 0", size >= 0);
  174. if (size == 0) {
  175. mboxsize = 1024;
  176. }
  177. mbox->head = mbox->tail = 0;
  178. mbox->sem = mbox; /* just point to something for sys_mbox_valid() */
  179. mbox->q_mem = (void**)malloc(sizeof(void*)*mboxsize);
  180. mbox->size = mboxsize;
  181. mbox->used = 0;
  182. memset(mbox->q_mem, 0, sizeof(void*)*mboxsize);
  183. return ERR_OK;
  184. }
  185. void sys_mbox_free(sys_mbox_t *mbox)
  186. {
  187. /* parameter check */
  188. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  189. LWIP_ASSERT("mbox->sem != NULL", mbox->sem != NULL);
  190. LWIP_ASSERT("mbox->sem == mbox", mbox->sem == mbox);
  191. LWIP_ASSERT("mbox->q_mem != NULL", mbox->q_mem != NULL);
  192. mbox->sem = NULL;
  193. free(mbox->q_mem);
  194. mbox->q_mem = NULL;
  195. }
  196. void sys_mbox_set_invalid(sys_mbox_t *mbox)
  197. {
  198. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  199. LWIP_ASSERT("mbox->q_mem == NULL", mbox->q_mem == NULL);
  200. mbox->sem = NULL;
  201. mbox->q_mem = NULL;
  202. }
  203. void sys_mbox_post(sys_mbox_t *q, void *msg)
  204. {
  205. LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
  206. LWIP_ASSERT("q->sem == q", q->sem == q);
  207. LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
  208. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  209. LWIP_ASSERT("q->size > 0", q->size > 0);
  210. LWIP_ASSERT("mbox already full", q->used < q->size);
  211. q->q_mem[q->head] = msg;
  212. q->head++;
  213. if (q->head >= (unsigned int)q->size) {
  214. q->head = 0;
  215. }
  216. LWIP_ASSERT("mbox is full!", q->head != q->tail);
  217. q->used++;
  218. }
  219. err_t sys_mbox_trypost(sys_mbox_t *q, void *msg)
  220. {
  221. LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
  222. LWIP_ASSERT("q->sem == q", q->sem == q);
  223. LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
  224. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  225. LWIP_ASSERT("q->size > 0", q->size > 0);
  226. LWIP_ASSERT("q->used <= q->size", q->used <= q->size);
  227. if (q->used == q->size) {
  228. return ERR_MEM;
  229. }
  230. sys_mbox_post(q, msg);
  231. return ERR_OK;
  232. }
  233. u32_t sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout)
  234. {
  235. u32_t ret = 0;
  236. u32_t ret2;
  237. LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
  238. LWIP_ASSERT("q->sem == q", q->sem == q);
  239. LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
  240. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  241. LWIP_ASSERT("q->size > 0", q->size > 0);
  242. if (q->used == 0) {
  243. /* need to wait */
  244. /* need to wait */
  245. if(!timeout)
  246. {
  247. /* wait infinite */
  248. LWIP_ASSERT("cannot wait without waiting callback", the_waiting_fn != NULL);
  249. do {
  250. int expectSomething = the_waiting_fn(NULL, q);
  251. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  252. LWIP_ASSERT("expecting item available but it's 0", !expectSomething || (q->used > 0));
  253. ret++;
  254. if (ret == SYS_ARCH_TIMEOUT) {
  255. ret--;
  256. }
  257. } while(q->used == 0);
  258. }
  259. else
  260. {
  261. if (the_waiting_fn) {
  262. int expectSomething = the_waiting_fn(NULL, q);
  263. LWIP_ASSERT("expecting item available count but it's 0", !expectSomething || (q->used > 0));
  264. }
  265. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  266. if (q->used == 0) {
  267. if(msg) {
  268. *msg = NULL;
  269. }
  270. return SYS_ARCH_TIMEOUT;
  271. }
  272. ret = 1;
  273. }
  274. }
  275. LWIP_ASSERT("q->used > 0", q->used > 0);
  276. ret2 = sys_arch_mbox_tryfetch(q, msg);
  277. LWIP_ASSERT("got no message", ret2 == 0);
  278. return ret;
  279. }
  280. u32_t sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg)
  281. {
  282. LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
  283. LWIP_ASSERT("q->sem == q", q->sem == q);
  284. LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
  285. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  286. LWIP_ASSERT("q->size > 0", q->size > 0);
  287. if (!q->used) {
  288. return SYS_ARCH_TIMEOUT;
  289. }
  290. if(msg) {
  291. *msg = q->q_mem[q->tail];
  292. }
  293. q->tail++;
  294. if (q->tail >= (unsigned int)q->size) {
  295. q->tail = 0;
  296. }
  297. q->used--;
  298. LWIP_ASSERT("q->used >= 0", q->used >= 0);
  299. return 0;
  300. }
  301. #if LWIP_NETCONN_SEM_PER_THREAD
  302. #error LWIP_NETCONN_SEM_PER_THREAD==1 not supported
  303. #endif /* LWIP_NETCONN_SEM_PER_THREAD */
  304. #endif /* !NO_SYS */