1 /* 2 * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <string.h> 8 #include <stdbool.h> 9 #include <stdlib.h> 10 #include <stdio.h> 11 #include <sys/reent.h> 12 #include "esp_attr.h" 13 14 /** 15 * This is the replacement for newlib's _REENT_INIT_PTR and __sinit. 16 * The problem with __sinit is that it allocates three FILE structures 17 * (stdin, stdout, stderr). Having individual standard streams for each task 18 * is a bit too much on a small embedded system. So we point streams 19 * to the streams of the global struct _reent, which are initialized in 20 * startup code. 21 */ esp_reent_init(struct _reent * r)22void IRAM_ATTR esp_reent_init(struct _reent* r) 23 { 24 memset(r, 0, sizeof(*r)); 25 r->_stdout = _GLOBAL_REENT->_stdout; 26 r->_stderr = _GLOBAL_REENT->_stderr; 27 r->_stdin = _GLOBAL_REENT->_stdin; 28 r->__cleanup = &_cleanup_r; 29 r->__sdidinit = 1; 30 r->__sglue._next = NULL; 31 r->__sglue._niobs = 0; 32 r->__sglue._iobs = NULL; 33 } 34 35 /* only declared in private stdio header file, local.h */ 36 extern void __sfp_lock_acquire(void); 37 extern void __sfp_lock_release(void); 38 esp_reent_cleanup(void)39void esp_reent_cleanup(void) 40 { 41 struct _reent* r = __getreent(); 42 /* Clean up storage used by mprec functions */ 43 if (r->_mp) { 44 if (_REENT_MP_FREELIST(r)) { 45 for (unsigned int i = 0; i < _Kmax; ++i) { 46 struct _Bigint *cur, *next; 47 next = _REENT_MP_FREELIST(r)[i]; 48 while (next) { 49 cur = next; 50 next = next->_next; 51 free(cur); 52 } 53 } 54 } 55 free(_REENT_MP_FREELIST(r)); 56 free(_REENT_MP_RESULT(r)); 57 } 58 59 /* Clean up "glue" (lazily-allocated FILE objects) */ 60 struct _glue* prev = &_GLOBAL_REENT->__sglue; 61 for (struct _glue* cur = _GLOBAL_REENT->__sglue._next; cur != NULL;) { 62 if (cur->_niobs == 0) { 63 cur = cur->_next; 64 continue; 65 } 66 bool has_open_files = false; 67 for (int i = 0; i < cur->_niobs; ++i) { 68 FILE* fp = &cur->_iobs[i]; 69 if (fp->_flags != 0) { 70 has_open_files = true; 71 break; 72 } 73 } 74 if (has_open_files) { 75 prev = cur; 76 cur = cur->_next; 77 continue; 78 } 79 struct _glue* next = cur->_next; 80 prev->_next = next; 81 free(cur); 82 cur = next; 83 } 84 85 /* Clean up various other buffers */ 86 free(r->_mp); 87 r->_mp = NULL; 88 free(r->_r48); 89 r->_r48 = NULL; 90 free(r->_localtime_buf); 91 r->_localtime_buf = NULL; 92 free(r->_asctime_buf); 93 r->_asctime_buf = NULL; 94 } 95