Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
sys.h
00001 /** 00002 * @file 00003 * OS abstraction layer 00004 */ 00005 00006 /* 00007 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without modification, 00011 * are permitted provided that the following conditions are met: 00012 * 00013 * 1. Redistributions of source code must retain the above copyright notice, 00014 * this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright notice, 00016 * this list of conditions and the following disclaimer in the documentation 00017 * and/or other materials provided with the distribution. 00018 * 3. The name of the author may not be used to endorse or promote products 00019 * derived from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00022 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00024 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00026 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00029 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00030 * OF SUCH DAMAGE. 00031 * 00032 * This file is part of the lwIP TCP/IP stack. 00033 * 00034 * Author: Adam Dunkels <adam@sics.se> 00035 */ 00036 00037 /** 00038 * @defgroup sys_layer System abstraction layer 00039 * @ingroup infrastructure 00040 * @verbinclude "sys_arch.txt" 00041 * 00042 * @defgroup sys_os OS abstraction layer 00043 * @ingroup sys_layer 00044 * No need to implement functions in this section in NO_SYS mode. 00045 * 00046 * @defgroup sys_sem Semaphores 00047 * @ingroup sys_os 00048 * 00049 * @defgroup sys_mutex Mutexes 00050 * @ingroup sys_os 00051 * Mutexes are recommended to correctly handle priority inversion, 00052 * especially if you use LWIP_CORE_LOCKING . 00053 * 00054 * @defgroup sys_mbox Mailboxes 00055 * @ingroup sys_os 00056 * 00057 * @defgroup sys_time Time 00058 * @ingroup sys_layer 00059 * 00060 * @defgroup sys_prot Critical sections 00061 * @ingroup sys_layer 00062 * Used to protect short regions of code against concurrent access. 00063 * - Your system is a bare-metal system (probably with an RTOS) 00064 * and interrupts are under your control: 00065 * Implement this as LockInterrupts() / UnlockInterrupts() 00066 * - Your system uses an RTOS with deferred interrupt handling from a 00067 * worker thread: Implement as a global mutex or lock/unlock scheduler 00068 * - Your system uses a high-level OS with e.g. POSIX signals: 00069 * Implement as a global mutex 00070 * 00071 * @defgroup sys_misc Misc 00072 * @ingroup sys_os 00073 */ 00074 00075 #ifndef LWIP_HDR_SYS_H 00076 #define LWIP_HDR_SYS_H 00077 00078 #include "lwip/opt.h" 00079 00080 #ifdef __cplusplus 00081 extern "C" { 00082 #endif 00083 00084 #if NO_SYS 00085 00086 /* For a totally minimal and standalone system, we provide null 00087 definitions of the sys_ functions. */ 00088 typedef u8_t sys_sem_t; 00089 typedef u8_t sys_mutex_t; 00090 typedef u8_t sys_mbox_t; 00091 00092 #define sys_sem_new(s, c) ERR_OK 00093 #define sys_sem_signal(s) 00094 #define sys_sem_wait(s) 00095 #define sys_arch_sem_wait(s,t) 00096 #define sys_sem_free(s) 00097 #define sys_sem_valid(s) 0 00098 #define sys_sem_valid_val(s) 0 00099 #define sys_sem_set_invalid(s) 00100 #define sys_sem_set_invalid_val(s) 00101 #define sys_mutex_new(mu) ERR_OK 00102 #define sys_mutex_lock(mu) 00103 #define sys_mutex_unlock(mu) 00104 #define sys_mutex_free(mu) 00105 #define sys_mutex_valid(mu) 0 00106 #define sys_mutex_set_invalid(mu) 00107 #define sys_mbox_new(m, s) ERR_OK 00108 #define sys_mbox_fetch(m,d) 00109 #define sys_mbox_tryfetch(m,d) 00110 #define sys_mbox_post(m,d) 00111 #define sys_mbox_trypost(m,d) 00112 #define sys_mbox_free(m) 00113 #define sys_mbox_valid(m) 00114 #define sys_mbox_valid_val(m) 00115 #define sys_mbox_set_invalid(m) 00116 #define sys_mbox_set_invalid_val(m) 00117 00118 #define sys_thread_new(n,t,a,s,p) 00119 00120 #define sys_msleep(t) 00121 00122 #else /* NO_SYS */ 00123 00124 /** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ 00125 #define SYS_ARCH_TIMEOUT 0xffffffffUL 00126 00127 /** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. 00128 * For now we use the same magic value, but we allow this to change in future. 00129 */ 00130 #define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT 00131 00132 #include "lwip/err.h" 00133 #include "arch/sys_arch.h" 00134 00135 /** Function prototype for thread functions */ 00136 typedef void (*lwip_thread_fn)(void *arg); 00137 00138 /* Function prototypes for functions to be implemented by platform ports 00139 (in sys_arch.c) */ 00140 00141 /* Mutex functions: */ 00142 00143 /** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores 00144 should be used instead */ 00145 #ifndef LWIP_COMPAT_MUTEX 00146 #define LWIP_COMPAT_MUTEX 0 00147 #endif 00148 00149 #if LWIP_COMPAT_MUTEX 00150 /* for old ports that don't have mutexes: define them to binary semaphores */ 00151 #define sys_mutex_t sys_sem_t 00152 #define sys_mutex_new(mutex) sys_sem_new(mutex, 1) 00153 #define sys_mutex_lock(mutex) sys_sem_wait(mutex) 00154 #define sys_mutex_unlock(mutex) sys_sem_signal(mutex) 00155 #define sys_mutex_free(mutex) sys_sem_free(mutex) 00156 #define sys_mutex_valid(mutex) sys_sem_valid(mutex) 00157 #define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) 00158 00159 #else /* LWIP_COMPAT_MUTEX */ 00160 00161 /** 00162 * @ingroup sys_mutex 00163 * Create a new mutex 00164 * @param mutex pointer to the mutex to create 00165 * @return a new mutex 00166 */ 00167 err_t sys_mutex_new(sys_mutex_t *mutex); 00168 /** 00169 * @ingroup sys_mutex 00170 * Lock a mutex 00171 * @param mutex the mutex to lock 00172 */ 00173 void sys_mutex_lock(sys_mutex_t *mutex); 00174 /** 00175 * @ingroup sys_mutex 00176 * Unlock a mutex 00177 * @param mutex the mutex to unlock 00178 */ 00179 void sys_mutex_unlock(sys_mutex_t *mutex); 00180 /** 00181 * @ingroup sys_mutex 00182 * Delete a semaphore 00183 * @param mutex the mutex to delete 00184 */ 00185 void sys_mutex_free(sys_mutex_t *mutex); 00186 #ifndef sys_mutex_valid 00187 /** 00188 * @ingroup sys_mutex 00189 * Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid 00190 */ 00191 int sys_mutex_valid(sys_mutex_t *mutex); 00192 #endif 00193 #ifndef sys_mutex_set_invalid 00194 /** 00195 * @ingroup sys_mutex 00196 * Set a mutex invalid so that sys_mutex_valid returns 0 00197 */ 00198 void sys_mutex_set_invalid(sys_mutex_t *mutex); 00199 #endif 00200 #endif /* LWIP_COMPAT_MUTEX */ 00201 00202 /* Semaphore functions: */ 00203 00204 /** 00205 * @ingroup sys_sem 00206 * Create a new semaphore 00207 * @param sem pointer to the semaphore to create 00208 * @param count initial count of the semaphore 00209 * @return ERR_OK if successful, another err_t otherwise 00210 */ 00211 err_t sys_sem_new(sys_sem_t *sem, u8_t count); 00212 /** 00213 * @ingroup sys_sem 00214 * Signals a semaphore 00215 * @param sem the semaphore to signal 00216 */ 00217 void sys_sem_signal(sys_sem_t *sem); 00218 /** 00219 * @ingroup sys_sem 00220 * Wait for a semaphore for the specified timeout 00221 * @param sem the semaphore to wait for 00222 * @param timeout timeout in milliseconds to wait (0 = wait forever) 00223 * @return time (in milliseconds) waited for the semaphore 00224 * or SYS_ARCH_TIMEOUT on timeout 00225 */ 00226 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); 00227 /** 00228 * @ingroup sys_sem 00229 * Delete a semaphore 00230 * @param sem semaphore to delete 00231 */ 00232 void sys_sem_free(sys_sem_t *sem); 00233 /** Wait for a semaphore - forever/no timeout */ 00234 #define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) 00235 #ifndef sys_sem_valid 00236 /** 00237 * @ingroup sys_sem 00238 * Check if a semaphore is valid/allocated: return 1 for valid, 0 for invalid 00239 */ 00240 int sys_sem_valid(sys_sem_t *sem); 00241 #endif 00242 #ifndef sys_sem_set_invalid 00243 /** 00244 * @ingroup sys_sem 00245 * Set a semaphore invalid so that sys_sem_valid returns 0 00246 */ 00247 void sys_sem_set_invalid(sys_sem_t *sem); 00248 #endif 00249 #ifndef sys_sem_valid_val 00250 /** 00251 * Same as sys_sem_valid() but taking a value, not a pointer 00252 */ 00253 #define sys_sem_valid_val(sem) sys_sem_valid(&(sem)) 00254 #endif 00255 #ifndef sys_sem_set_invalid_val 00256 /** 00257 * Same as sys_sem_set_invalid() but taking a value, not a pointer 00258 */ 00259 #define sys_sem_set_invalid_val(sem) sys_sem_set_invalid(&(sem)) 00260 #endif 00261 00262 #ifndef sys_msleep 00263 /** 00264 * @ingroup sys_misc 00265 * Sleep for specified number of ms 00266 */ 00267 void sys_msleep(u32_t ms); /* only has a (close to) 1 ms resolution. */ 00268 #endif 00269 00270 /* Mailbox functions. */ 00271 00272 /** 00273 * @ingroup sys_mbox 00274 * Create a new mbox of specified size 00275 * @param mbox pointer to the mbox to create 00276 * @param size (minimum) number of messages in this mbox 00277 * @return ERR_OK if successful, another err_t otherwise 00278 */ 00279 err_t sys_mbox_new(sys_mbox_t *mbox, int size); 00280 /** 00281 * @ingroup sys_mbox 00282 * Post a message to an mbox - may not fail 00283 * -> blocks if full, only used from tasks not from ISR 00284 * @param mbox mbox to posts the message 00285 * @param msg message to post (ATTENTION: can be NULL) 00286 */ 00287 void sys_mbox_post(sys_mbox_t *mbox, void *msg); 00288 /** 00289 * @ingroup sys_mbox 00290 * Try to post a message to an mbox - may fail if full or ISR 00291 * @param mbox mbox to posts the message 00292 * @param msg message to post (ATTENTION: can be NULL) 00293 */ 00294 err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); 00295 /** 00296 * @ingroup sys_mbox 00297 * Wait for a new message to arrive in the mbox 00298 * @param mbox mbox to get a message from 00299 * @param msg pointer where the message is stored 00300 * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever) 00301 * @return time (in milliseconds) waited for a message, may be 0 if not waited 00302 or SYS_ARCH_TIMEOUT on timeout 00303 * The returned time has to be accurate to prevent timer jitter! 00304 */ 00305 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); 00306 /* Allow port to override with a macro, e.g. special timeout for sys_arch_mbox_fetch() */ 00307 #ifndef sys_arch_mbox_tryfetch 00308 /** 00309 * @ingroup sys_mbox 00310 * Wait for a new message to arrive in the mbox 00311 * @param mbox mbox to get a message from 00312 * @param msg pointer where the message is stored 00313 * @return 0 (milliseconds) if a message has been received 00314 * or SYS_MBOX_EMPTY if the mailbox is empty 00315 */ 00316 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); 00317 #endif 00318 /** 00319 * For now, we map straight to sys_arch implementation. 00320 */ 00321 #define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) 00322 /** 00323 * @ingroup sys_mbox 00324 * Delete an mbox 00325 * @param mbox mbox to delete 00326 */ 00327 void sys_mbox_free(sys_mbox_t *mbox); 00328 #define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) 00329 #ifndef sys_mbox_valid 00330 /** 00331 * @ingroup sys_mbox 00332 * Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid 00333 */ 00334 int sys_mbox_valid(sys_mbox_t *mbox); 00335 #endif 00336 #ifndef sys_mbox_set_invalid 00337 /** 00338 * @ingroup sys_mbox 00339 * Set an mbox invalid so that sys_mbox_valid returns 0 00340 */ 00341 void sys_mbox_set_invalid(sys_mbox_t *mbox); 00342 #endif 00343 #ifndef sys_mbox_valid_val 00344 /** 00345 * Same as sys_mbox_valid() but taking a value, not a pointer 00346 */ 00347 #define sys_mbox_valid_val(mbox) sys_mbox_valid(&(mbox)) 00348 #endif 00349 #ifndef sys_mbox_set_invalid_val 00350 /** 00351 * Same as sys_mbox_set_invalid() but taking a value, not a pointer 00352 */ 00353 #define sys_mbox_set_invalid_val(mbox) sys_mbox_set_invalid(&(mbox)) 00354 #endif 00355 00356 00357 /** 00358 * @ingroup sys_misc 00359 * The only thread function: 00360 * Creates a new thread 00361 * ATTENTION: although this function returns a value, it MUST NOT FAIL (ports have to assert this!) 00362 * @param name human-readable name for the thread (used for debugging purposes) 00363 * @param thread thread-function 00364 * @param arg parameter passed to 'thread' 00365 * @param stacksize stack size in bytes for the new thread (may be ignored by ports) 00366 * @param prio priority of the new thread (may be ignored by ports) */ 00367 sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); 00368 00369 #endif /* NO_SYS */ 00370 00371 /* sys_init() must be called before anything else. */ 00372 void sys_init(void); 00373 00374 #ifndef sys_jiffies 00375 /** 00376 * Ticks/jiffies since power up. 00377 */ 00378 u32_t sys_jiffies(void); 00379 #endif 00380 00381 /** 00382 * @ingroup sys_time 00383 * Returns the current time in milliseconds, 00384 * may be the same as sys_jiffies or at least based on it. 00385 */ 00386 u32_t sys_now(void); 00387 00388 /* Critical Region Protection */ 00389 /* These functions must be implemented in the sys_arch.c file. 00390 In some implementations they can provide a more light-weight protection 00391 mechanism than using semaphores. Otherwise semaphores can be used for 00392 implementation */ 00393 #ifndef SYS_ARCH_PROTECT 00394 /** SYS_LIGHTWEIGHT_PROT 00395 * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection 00396 * for certain critical regions during buffer allocation, deallocation and memory 00397 * allocation and deallocation. 00398 */ 00399 #if SYS_LIGHTWEIGHT_PROT 00400 00401 /** 00402 * @ingroup sys_prot 00403 * SYS_ARCH_DECL_PROTECT 00404 * declare a protection variable. This macro will default to defining a variable of 00405 * type sys_prot_t. If a particular port needs a different implementation, then 00406 * this macro may be defined in sys_arch.h. 00407 */ 00408 #define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev 00409 /** 00410 * @ingroup sys_prot 00411 * SYS_ARCH_PROTECT 00412 * Perform a "fast" protect. This could be implemented by 00413 * disabling interrupts for an embedded system or by using a semaphore or 00414 * mutex. The implementation should allow calling SYS_ARCH_PROTECT when 00415 * already protected. The old protection level is returned in the variable 00416 * "lev". This macro will default to calling the sys_arch_protect() function 00417 * which should be implemented in sys_arch.c. If a particular port needs a 00418 * different implementation, then this macro may be defined in sys_arch.h 00419 */ 00420 #define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() 00421 /** 00422 * @ingroup sys_prot 00423 * SYS_ARCH_UNPROTECT 00424 * Perform a "fast" set of the protection level to "lev". This could be 00425 * implemented by setting the interrupt level to "lev" within the MACRO or by 00426 * using a semaphore or mutex. This macro will default to calling the 00427 * sys_arch_unprotect() function which should be implemented in 00428 * sys_arch.c. If a particular port needs a different implementation, then 00429 * this macro may be defined in sys_arch.h 00430 */ 00431 #define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) 00432 sys_prot_t sys_arch_protect(void); 00433 void sys_arch_unprotect(sys_prot_t pval); 00434 00435 #else 00436 00437 #define SYS_ARCH_DECL_PROTECT(lev) 00438 #define SYS_ARCH_PROTECT(lev) 00439 #define SYS_ARCH_UNPROTECT(lev) 00440 00441 #endif /* SYS_LIGHTWEIGHT_PROT */ 00442 00443 #endif /* SYS_ARCH_PROTECT */ 00444 00445 /* 00446 * Macros to set/get and increase/decrease variables in a thread-safe way. 00447 * Use these for accessing variable that are used from more than one thread. 00448 */ 00449 00450 #ifndef SYS_ARCH_INC 00451 #define SYS_ARCH_INC(var, val) do { \ 00452 SYS_ARCH_DECL_PROTECT(old_level); \ 00453 SYS_ARCH_PROTECT(old_level); \ 00454 var += val; \ 00455 SYS_ARCH_UNPROTECT(old_level); \ 00456 } while(0) 00457 #endif /* SYS_ARCH_INC */ 00458 00459 #ifndef SYS_ARCH_DEC 00460 #define SYS_ARCH_DEC(var, val) do { \ 00461 SYS_ARCH_DECL_PROTECT(old_level); \ 00462 SYS_ARCH_PROTECT(old_level); \ 00463 var -= val; \ 00464 SYS_ARCH_UNPROTECT(old_level); \ 00465 } while(0) 00466 #endif /* SYS_ARCH_DEC */ 00467 00468 #ifndef SYS_ARCH_GET 00469 #define SYS_ARCH_GET(var, ret) do { \ 00470 SYS_ARCH_DECL_PROTECT(old_level); \ 00471 SYS_ARCH_PROTECT(old_level); \ 00472 ret = var; \ 00473 SYS_ARCH_UNPROTECT(old_level); \ 00474 } while(0) 00475 #endif /* SYS_ARCH_GET */ 00476 00477 #ifndef SYS_ARCH_SET 00478 #define SYS_ARCH_SET(var, val) do { \ 00479 SYS_ARCH_DECL_PROTECT(old_level); \ 00480 SYS_ARCH_PROTECT(old_level); \ 00481 var = val; \ 00482 SYS_ARCH_UNPROTECT(old_level); \ 00483 } while(0) 00484 #endif /* SYS_ARCH_SET */ 00485 00486 00487 #ifdef __cplusplus 00488 } 00489 #endif 00490 00491 #endif /* LWIP_HDR_SYS_H */
Generated on Tue Jul 12 2022 18:19:34 by
