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