import RT-Thread@9217865c without bsp, libcpu and components/net

This commit is contained in:
Zihao Yu 2023-05-20 16:23:33 +08:00
commit e2376a3709
1414 changed files with 390370 additions and 0 deletions

14
components/libc/Kconfig Normal file
View file

@ -0,0 +1,14 @@
menu "C/C++ and POSIX layer"
config RT_USING_EXTERNAL_LIBC
bool
config RT_LIBC_DEFAULT_TIMEZONE
int "Set the default time zone (UTC+)"
range -12 12
default 8
source "$RTT_DIR/components/libc/posix/Kconfig"
source "$RTT_DIR/components/libc/cplusplus/Kconfig"
endmenu

View file

@ -0,0 +1,15 @@
# RT-Thread building script for bridge
import os
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')

View file

@ -0,0 +1,15 @@
# RT-Thread building script for bridge
import os
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')

View file

@ -0,0 +1,5 @@
# ARMLIB (Keil-MDK) porting for RT-Thread
https://www.keil.com/support/man/docs/armlib/
https://www.keil.com/support/man/docs/armlib/armlib_chr1358938918041.htm

View file

@ -0,0 +1,12 @@
from building import *
Import('rtconfig')
src = Glob('*.c')
group = []
if rtconfig.PLATFORM in ['armcc', 'armclang']:
CPPDEFINES = ['RT_USING_ARMLIBC', 'RT_USING_LIBC', '__STDC_LIMIT_MACROS']
AddDepend(['RT_USING_ARMLIBC', 'RT_USING_LIBC'])
group = DefineGroup('Compiler', src, depend = [''], CPPDEFINES = CPPDEFINES)
Return('group')

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2014-08-03 bernard Add file header
* 2021-11-13 Meco Man implement no-heap warning
*/
#include <rtthread.h>
#include <stddef.h>
#ifndef RT_USING_HEAP
#define DBG_TAG "armlibc.syscall.mem"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#define _NO_HEAP_ERROR() do{LOG_E("Please enable RT_USING_HEAP");\
RT_ASSERT(0);\
}while(0)
#endif /* RT_USING_HEAP */
#ifdef __CC_ARM
/* avoid the heap and heap-using library functions supplied by arm */
#pragma import(__use_no_heap)
#endif /* __CC_ARM */
void *malloc(size_t n)
{
#ifdef RT_USING_HEAP
return rt_malloc(n);
#else
_NO_HEAP_ERROR();
return RT_NULL;
#endif
}
RTM_EXPORT(malloc);
void *realloc(void *rmem, size_t newsize)
{
#ifdef RT_USING_HEAP
return rt_realloc(rmem, newsize);
#else
_NO_HEAP_ERROR();
return RT_NULL;
#endif
}
RTM_EXPORT(realloc);
void *calloc(size_t nelem, size_t elsize)
{
#ifdef RT_USING_HEAP
return rt_calloc(nelem, elsize);
#else
_NO_HEAP_ERROR();
return RT_NULL;
#endif
}
RTM_EXPORT(calloc);
void free(void *rmem)
{
#ifdef RT_USING_HEAP
rt_free(rmem);
#else
_NO_HEAP_ERROR();
#endif
}
RTM_EXPORT(free);

View file

@ -0,0 +1,391 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2012-11-23 Yihui The first version
* 2013-11-24 aozima fixed _sys_read()/_sys_write() issues.
* 2014-08-03 bernard If using msh, use system() implementation
* in msh.
* 2020-08-05 Meco Man fixed _sys_flen() compiling-warning when
* RT_USING_DFS is not defined
* 2020-02-13 Meco Man re-implement exit() and abort()
* 2020-02-14 Meco Man implement _sys_tmpnam()
*/
#include <rt_sys.h>
#include <rtthread.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <compiler_private.h>
#ifdef RT_USING_POSIX_STDIO
#include "libc.h"
#endif /* RT_USING_POSIX_STDIO */
#define DBG_TAG "armlibc.syscalls"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#ifdef __clang__
__asm(".global __use_no_semihosting\n\t");
#else
#pragma import(__use_no_semihosting_swi)
#endif
/* Standard IO device handles. */
#define STDIN 0
#define STDOUT 1
#define STDERR 2
/* Standard IO device name defines. */
const char __stdin_name[] = "STDIN";
const char __stdout_name[] = "STDOUT";
const char __stderr_name[] = "STDERR";
/**
* required by fopen() and freopen().
*
* @param name - file name with path.
* @param openmode - a bitmap hose bits mostly correspond directly to
* the ISO mode specification.
* @return -1 if an error occurs.
*/
FILEHANDLE _sys_open(const char *name, int openmode)
{
#ifdef DFS_USING_POSIX
int fd;
int mode = O_RDONLY;
#endif /* DFS_USING_POSIX */
/* Register standard Input Output devices. */
if (strcmp(name, __stdin_name) == 0)
return (STDIN);
if (strcmp(name, __stdout_name) == 0)
return (STDOUT);
if (strcmp(name, __stderr_name) == 0)
return (STDERR);
#ifndef DFS_USING_POSIX
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
return -1; /* error */
#else
/* Correct openmode from fopen to open */
if (openmode & OPEN_PLUS)
{
if (openmode & OPEN_W)
{
mode |= (O_RDWR | O_TRUNC | O_CREAT);
}
else if (openmode & OPEN_A)
{
mode |= (O_RDWR | O_APPEND | O_CREAT);
}
else
mode |= O_RDWR;
}
else
{
if (openmode & OPEN_W)
{
mode |= (O_WRONLY | O_TRUNC | O_CREAT);
}
else if (openmode & OPEN_A)
{
mode |= (O_WRONLY | O_APPEND | O_CREAT);
}
}
fd = open(name, mode, 0);
if (fd < 0)
return -1; /* error */
else
return fd;
#endif /* DFS_USING_POSIX */
}
int _sys_close(FILEHANDLE fh)
{
#ifdef DFS_USING_POSIX
if (fh <= STDERR)
return 0; /* error */
return close(fh);
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
return 0; /* error */
#endif /* DFS_USING_POSIX */
}
/*
* Read from a file. Can return:
* - zero if the read was completely successful
* - the number of bytes _not_ read, if the read was partially successful
* - the number of bytes not read, plus the top bit set (0x80000000), if
* the read was partially successful due to end of file
* - -1 if some error other than EOF occurred
*
* It is also legal to signal EOF by returning no data but
* signalling no error (i.e. the top-bit-set mechanism need never
* be used).
*
* So if (for example) the user is trying to read 8 bytes at a time
* from a file in which only 5 remain, this routine can do three
* equally valid things:
*
* - it can return 0x80000003 (3 bytes not read due to EOF)
* - OR it can return 3 (3 bytes not read), and then return
* 0x80000008 (8 bytes not read due to EOF) on the next attempt
* - OR it can return 3 (3 bytes not read), and then return
* 8 (8 bytes not read, meaning 0 read, meaning EOF) on the next
* attempt
*
* `mode' exists for historical reasons and must be ignored.
*/
int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, int mode)
{
#ifdef DFS_USING_POSIX
int size;
if (fh == STDIN)
{
#ifdef RT_USING_POSIX_STDIO
if (libc_stdio_get_console() < 0)
{
LOG_W("Do not invoke standard output before initializing Compiler");
return 0; /* error, but keep going */
}
size = read(STDIN_FILENO, buf, len);
return len - size; /* success */
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_STDIO);
return 0; /* error */
#endif /* RT_USING_POSIX_STDIO */
}
else if (fh == STDOUT || fh == STDERR)
{
return -1; /* 100% error */
}
else
{
size = read(fh, buf, len);
if (size >= 0)
{
return len - size; /* success */
}
else
{
return 0; /* error */
}
}
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
return 0; /* error */
#endif /* DFS_USING_POSIX */
}
/*
* Write to a file. Returns 0 on success, negative on error, and
* the number of characters _not_ written on partial success.
* `mode' exists for historical reasons and must be ignored.
* The return value is either:
* A positive number representing the number of characters not written
* (so any nonzero return value denotes a failure of some sort).
* A negative number indicating an error.
*/
int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode)
{
#ifdef DFS_USING_POSIX
int size;
#endif /* DFS_USING_POSIX */
if (fh == STDOUT || fh == STDERR)
{
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
rt_device_t console;
console = rt_console_get_device();
if (console)
{
rt_device_write(console, -1, buf, len);
}
return 0; /* success */
#else
return 0; /* error */
#endif /* defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) */
}
else if (fh == STDIN)
{
return -1; /* 100% error */
}
else
{
#ifdef DFS_USING_POSIX
size = write(fh, buf, len);
if (size >= 0)
{
/*
fflush doesn't have a good solution in Keil-MDK,
so it has to sync/flush when for each writen.
*/
fsync(fh);
return len - size; /* success */
}
else
{
return 0; /* error */
}
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
return 0; /* error */
#endif /* DFS_USING_POSIX */
}
}
/*
* Flush any OS buffers associated with fh, ensuring that the file
* is up to date on disk. Result is >=0 if OK, negative for an
* error.
* This function is deprecated. It is never called by any other library function,
* and you are not required to re-implement it if you are retargeting standard I/O (stdio).
*/
int _sys_ensure(FILEHANDLE fh)
{
#ifdef DFS_USING_POSIX
return fsync(fh);
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
return 0; /* error */
#endif /* DFS_USING_POSIX */
}
/*
* Move the file position to a given offset from the file start.
* Returns >=0 on success, <0 on failure.
*/
int _sys_seek(FILEHANDLE fh, long pos)
{
#ifdef DFS_USING_POSIX
if (fh < STDERR)
return 0; /* error */
/* position is relative to the start of file fh */
return lseek(fh, pos, 0);
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
return 0; /* error */
#endif /* DFS_USING_POSIX */
}
/**
* used by tmpnam() or tmpfile()
*/
#if __ARMCC_VERSION >= 6190000
void _sys_tmpnam(char *name, int fileno, unsigned maxlength)
{
rt_snprintf(name, maxlength, "tem%03d", fileno);
}
#else
int _sys_tmpnam(char *name, int fileno, unsigned maxlength)
{
rt_snprintf(name, maxlength, "tem%03d", fileno);
return 1;
}
#endif /* __ARMCC_VERSION >= 6190000 */
char *_sys_command_string(char *cmd, int len)
{
/* no support */
return RT_NULL;
}
/* This function writes a character to the console. */
void _ttywrch(int ch)
{
#ifdef RT_USING_CONSOLE
rt_kprintf("%c", (char)ch);
#endif /* RT_USING_CONSOLE */
}
/* for exit() and abort() */
rt_weak void _sys_exit(int return_code)
{
extern void __rt_libc_exit(int status);
__rt_libc_exit(return_code);
while (1);
}
/**
* return current length of file.
*
* @param fh - file handle
* @return file length, or -1 on failed
*/
long _sys_flen(FILEHANDLE fh)
{
#ifdef DFS_USING_POSIX
struct stat stat;
if (fh < STDERR)
return 0; /* error */
fstat(fh, &stat);
return stat.st_size;
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
return 0;
#endif /* DFS_USING_POSIX */
}
int _sys_istty(FILEHANDLE fh)
{
if ((STDIN <= fh) && (fh <= STDERR))
return 1;
else
return 0;
}
int remove(const char *filename)
{
#ifdef DFS_USING_POSIX
return unlink(filename);
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
return 0; /* error */
#endif /* DFS_USING_POSIX */
}
#ifdef __MICROLIB
#include <stdio.h>
int fputc(int c, FILE *f)
{
#ifdef RT_USING_CONSOLE
rt_kprintf("%c", (char)c);
return 1;
#else
return 0; /* error */
#endif /* RT_USING_CONSOLE */
}
int fgetc(FILE *f)
{
#ifdef RT_USING_POSIX_STDIO
char ch;
if (libc_stdio_get_console() < 0)
{
LOG_W("Do not invoke standard output before initializing Compiler");
return 0;
}
if (read(STDIN_FILENO, &ch, 1) == 1)
return ch;
#endif /* RT_USING_POSIX_STDIO */
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_STDIO);
return 0; /* error */
}
#endif /* __MICROLIB */

View file

@ -0,0 +1,24 @@
from building import *
Import('rtconfig')
src = []
cwd = GetCurrentDir()
group = []
CPPPATH = [cwd + '/include']
CPPDEFINES = []
if rtconfig.PLATFORM in ['armcc', 'armclang']:
CPPDEFINES += ['__CLK_TCK=RT_TICK_PER_SECOND']
elif rtconfig.PLATFORM in ['iccarm']:
CPPDEFINES += ['CLOCKS_PER_SEC=RT_TICK_PER_SECOND'] # forcly revert to 1 by IAR
src += Glob('*.c')
group = DefineGroup('Compiler', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
group = group + SConscript(os.path.join(item, 'SConscript'))
Return('group')

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-06-07 Meco Man The first version.
*/
#include "posix/ctype.h"
#if !(defined(__ICCARM__) && (__VER__ > 9000000)) /* IAR9.0 has defined */
#ifndef isascii /* some toolchain use macro to define it */
int isascii(int c)
{
return c >= 0x00 && c <= 0x7f;
}
#endif
#endif /* !(defined(__ICCARM__) && (__VER__ > 9000000)) */
#ifndef toascii
int toascii(int c)
{
return (c)&0177;
}
#endif

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2014-05-22 ivanrad implement getline
*/
#include "posix/stdio.h"
#include <stdlib.h>
#include <limits.h>
#include <sys/errno.h>
#ifdef DFS_USING_POSIX
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream)
{
char *cur_pos, *new_lineptr;
size_t new_lineptr_len;
int c;
if (lineptr == NULL || n == NULL || stream == NULL)
{
errno = EINVAL;
return -1;
}
if (*lineptr == NULL)
{
*n = 128; /* init len */
if ((*lineptr = (char *)malloc(*n)) == NULL)
{
errno = ENOMEM;
return -1;
}
}
cur_pos = *lineptr;
for (;;)
{
c = getc(stream);
if (ferror(stream) || (c == EOF && cur_pos == *lineptr))
return -1;
if (c == EOF)
break;
if ((*lineptr + *n - cur_pos) < 2)
{
if (LONG_MAX / 2 < *n)
{
#ifdef EOVERFLOW
errno = EOVERFLOW;
#else
errno = ERANGE; /* no EOVERFLOW defined */
#endif
return -1;
}
new_lineptr_len = *n * 2;
if ((new_lineptr = (char *)realloc(*lineptr, new_lineptr_len)) == NULL)
{
errno = ENOMEM;
return -1;
}
cur_pos = new_lineptr + (cur_pos - *lineptr);
*lineptr = new_lineptr;
*n = new_lineptr_len;
}
*cur_pos++ = (char)c;
if (c == delim)
break;
}
*cur_pos = '\0';
return (ssize_t)(cur_pos - *lineptr);
}
ssize_t getline(char **lineptr, size_t *n, FILE *stream)
{
return getdelim(lineptr, n, '\n', stream);
}
#endif /* DFS_USING_POSIX */

View file

@ -0,0 +1,149 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-02-15 Meco Man first version
*/
#include <rtthread.h>
#define DBG_TAG "stdlib"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
void __rt_libc_exit(int status)
{
rt_thread_t self = rt_thread_self();
if (self != RT_NULL)
{
LOG_W("thread:%s exit:%d!", self->parent.name, status);
#ifdef RT_USING_PTHREADS
if(self->pthread_data != RT_NULL)
{
extern void pthread_exit(void *value);
pthread_exit((void *)status);
}
else
#endif
{
rt_thread_control(self, RT_THREAD_CTRL_CLOSE, RT_NULL);
}
}
}
#ifdef RT_USING_MSH
int system(const char *command)
{
extern int msh_exec(char *cmd, rt_size_t length);
if (command)
{
msh_exec((char *)command, rt_strlen(command));
}
return 0;
}
RTM_EXPORT(system);
#endif /* RT_USING_MSH */
char *ltoa(long value, char *string, int radix)
{
char tmp[33];
char *tp = tmp;
long i;
unsigned long v;
int sign;
char *sp;
if (string == NULL)
{
return 0 ;
}
if (radix > 36 || radix <= 1)
{
return 0 ;
}
sign = (radix == 10 && value < 0);
if (sign)
{
v = -value;
}
else
{
v = (unsigned long)value;
}
while (v || tp == tmp)
{
i = v % radix;
v = v / radix;
if (i < 10)
*tp++ = (char)(i+'0');
else
*tp++ = (char)(i + 'a' - 10);
}
sp = string;
if (sign)
*sp++ = '-';
while (tp > tmp)
*sp++ = *--tp;
*sp = 0;
return string;
}
char *itoa(int value, char *string, int radix)
{
return ltoa(value, string, radix) ;
}
char *ultoa(unsigned long value, char *string, int radix)
{
char tmp[33];
char *tp = tmp;
long i;
unsigned long v = value;
char *sp;
if (string == NULL)
{
return 0;
}
if (radix > 36 || radix <= 1)
{
return 0;
}
while (v || tp == tmp)
{
i = v % radix;
v = v / radix;
if (i < 10)
*tp++ = (char)(i+'0');
else
*tp++ = (char)(i + 'a' - 10);
}
sp = string;
while (tp > tmp)
*sp++ = *--tp;
*sp = 0;
return string;
}
char *utoa(unsigned value, char *string, int radix)
{
return ultoa(value, string, radix) ;
}

View file

@ -0,0 +1,225 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-01-12 Meco Man The first version.
*/
#include "posix/string.h"
#include <ctype.h>
#include <rtthread.h>
#include <stdlib.h>
/**
* @brief erases the data in the n bytes of the memory starting at the
* location pointed to by s, by writing zeros (bytes containing '\0') to that area.
*
* @note The bzero() function is deprecated (marked as LEGACY in POSIX. 1-2001).
*/
#ifndef RT_USING_PICOLIBC
void bzero(void* s, size_t n)
{
rt_memset(s, 0, n);
}
#endif
void bcopy(const void* src, void* dest, size_t n)
{
rt_memcpy(dest, src, n);
}
int bcmp(const void* s1, const void* s2, size_t n)
{
return rt_memcmp(s1, s2, n);
}
void explicit_bzero(void* s, size_t n)
{
volatile char* vs = (volatile char*)s;
while (n)
{
*vs++ = 0;
n--;
}
}
char* index(const char* s, int c)
{
return strchr(s, c);
}
char* rindex(const char* s, int c)
{
return strrchr(s, c);
}
int ffs(int i)
{
int bit;
if (0 == i)
return 0;
for (bit = 1; !(i & 1); ++bit)
i >>= 1;
return bit;
}
int ffsl(long i)
{
int bit;
if (0 == i)
return 0;
for (bit = 1; !(i & 1); ++bit)
i >>= 1;
return bit;
}
int ffsll(long long i)
{
int bit;
if (0 == i)
return 0;
for (bit = 1; !(i & 1); ++bit)
i >>= 1;
return bit;
}
/**
* @brief The memchr() function scans the initial n bytes of the memory area pointed to
* by s for the first instance of c. Both c and the bytes of the memory area
* pointed to by s are interpreted as unsigned char.
*
* @note This function is GNU extension, available since glibc 2.1.91.
*/
void* memrchr(const void* ptr, int ch, size_t pos)
{
char* end = (char*)ptr + pos - 1;
while (end != ptr)
{
if (*end == ch)
return end;
end--;
}
return (*end == ch) ? (end) : (NULL);
}
size_t strnlen(const char *s, size_t maxlen)
{
const char *sc;
for (sc = s; maxlen != 0 && *sc != '\0'; maxlen--, ++sc);
return sc - s;
}
char* strchrnul(const char* s, int c)
{
while (*s != '\0' && *s != c)
s++;
return (char*)s;
}
int strcasecmp(const char* s1, const char* s2)
{
const unsigned char* u1 = (const unsigned char*)s1;
const unsigned char* u2 = (const unsigned char*)s2;
int result;
while ((result = tolower(*u1) - tolower(*u2)) == 0 && *u1 != 0)
{
u1++;
u2++;
}
return result;
}
int strncasecmp(const char* s1, const char* s2, size_t n)
{
const unsigned char* u1 = (const unsigned char*)s1;
const unsigned char* u2 = (const unsigned char*)s2;
int result;
for (; n != 0; n--)
{
result = tolower(*u1) - tolower(*u2);
if (result)
return result;
if (*u1 == 0)
return 0;
u1++;
u2++;
}
return 0;
}
char *strdup(const char *s)
{
char *news = (char *)malloc(strlen(s) + 1);
if (news)
{
strcpy(news, s);
}
return news;
}
char *strndup(const char *s, size_t size)
{
size_t nsize = strnlen(s, size);
char *news = (char *)malloc(nsize + 1);
if (news)
{
rt_memcpy(news, s, nsize);
news[nsize] = '\0';
}
return news;
}
rt_weak char *strtok_r(char *str, const char *delim, char **saveptr)
{
char *pbegin;
char *pend = NULL;
if (str)
{
pbegin = str;
}
else if (saveptr && *saveptr)
{
pbegin = *saveptr;
}
else
{
return NULL;
}
for (;*pbegin && strchr(delim, *pbegin) != NULL; pbegin++);
if (!*pbegin)
{
return NULL;
}
for (pend = pbegin + 1; *pend && strchr(delim, *pend) == NULL; pend++);
if (*pend)
{
*pend++ = '\0';
}
if (saveptr)
{
*saveptr = pend;
}
return pbegin;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,140 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2014-01-01 mattn implement wcwidth
*/
#include "posix/wchar.h"
#include <string.h>
struct interval
{
long first;
long last;
};
static int bisearch(wchar_t ucs, const struct interval *table, int max)
{
int min = 0;
int mid;
if (ucs < table[0].first || ucs > table[max].last)
{
return 0;
}
while (max >= min)
{
mid = (min + max) / 2;
if (ucs > table[mid].last)
{
min = mid + 1;
}
else if (ucs < table[mid].first)
{
max = mid - 1;
}
else
{
return 1;
}
}
return 0;
}
int wcwidth(wchar_t ucs)
{
/* sorted list of non-overlapping intervals of non-spacing characters */
static const struct interval combining[] = {
{ 0x0300, 0x034E }, { 0x0360, 0x0362 }, { 0x0483, 0x0486 },
{ 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
{ 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
{ 0x05C4, 0x05C4 }, { 0x064B, 0x0655 }, { 0x0670, 0x0670 },
{ 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
{ 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
{ 0x07A6, 0x07B0 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C },
{ 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 },
{ 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC },
{ 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 },
{ 0x0A02, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 },
{ 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 },
{ 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 },
{ 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 0x0B01, 0x0B01 },
{ 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 },
{ 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 },
{ 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 },
{ 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 },
{ 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
{ 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA },
{ 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 },
{ 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 },
{ 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD },
{ 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 },
{ 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 },
{ 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC },
{ 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, { 0x1032, 0x1032 },
{ 0x1036, 0x1037 }, { 0x1039, 0x1039 }, { 0x1058, 0x1059 },
{ 0x1160, 0x11FF }, { 0x17B7, 0x17BD }, { 0x17C6, 0x17C6 },
{ 0x17C9, 0x17D3 }, { 0x180B, 0x180E }, { 0x18A9, 0x18A9 },
{ 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x206A, 0x206F },
{ 0x20D0, 0x20E3 }, { 0x302A, 0x302F }, { 0x3099, 0x309A },
{ 0xFB1E, 0xFB1E }, { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF },
{ 0xFFF9, 0xFFFB }
};
/* test for 8-bit control characters */
if (ucs == 0)
{
return 0;
}
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
{
return -1;
}
/* binary search in table of non-spacing characters */
if (bisearch(ucs, combining, sizeof(combining) / sizeof(struct interval) - 1))
{
return 0;
}
return 1 +
(ucs >= 0x1100 &&
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
(ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&
ucs != 0x303f) || /* CJK ... Yi */
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
(ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
(ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */
(ucs >= 0xffe0 && ucs <= 0xffe6) // ||
//#ifndef _WIN32
// (ucs >= 0x20000 && ucs <= 0x2ffff)
//#else
// 0
//#endif
));
}
int wcswidth(const wchar_t *pwcs, size_t n)
{
int w, width = 0;
for (;*pwcs && n-- > 0; pwcs++)
{
if ((w = wcwidth(*pwcs)) < 0)
{
return -1;
}
else
{
width += w;
}
}
return width;
}

View file

@ -0,0 +1,21 @@
import os
from building import *
Import('rtconfig')
src = []
cwd = GetCurrentDir()
CPPPATH = [cwd]
group = []
src += Glob('*.c')
if rtconfig.PLATFORM not in ['gcc', 'llvm-arm']:
group = DefineGroup('Compiler', src, depend = [''], CPPPATH = CPPPATH)
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
group = group + SConscript(os.path.join(d, 'SConscript'))
Return('group')

View file

@ -0,0 +1,4 @@
Because of the history issue, flags in fcntl.h, such as O_CREAT, have difference types of value. Some OS use hex flags and others use octal flags.
In terms of RT-Thread, Keil, IAR and MSVC use octal flags, which is located in the `tcntl/octal` folder; newlib uses hex flags; musl uses octal flags.

View file

@ -0,0 +1,15 @@
# RT-Thread building script for bridge
import os
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')

View file

@ -0,0 +1,11 @@
from building import *
Import('rtconfig')
src = []
cwd = GetCurrentDir()
CPPPATH = [cwd]
group = []
if rtconfig.CROSS_TOOL == 'msvc':
group = DefineGroup('Compiler', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-09-02 Meco Man First version
*/
#ifndef __FCNTL_H__
#define __FCNTL_H__
#include "sys/types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* VS fcntl.h interent */
#define O_RDONLY 0x0000 /* open for reading only */
#define O_WRONLY 0x0001 /* open for writing only */
#define O_RDWR 0x0002 /* open for reading and writing */
#define O_APPEND 0x0008 /* writes done at eof */
#define O_CREAT 0x0100 /* create and open file */
#define O_TRUNC 0x0200 /* open and truncate */
#define O_EXCL 0x0400 /* open only if file doesn't already exist */
// O_TEXT files have <cr><lf> sequences translated to <lf> on read()'s and <lf>
// sequences translated to <cr><lf> on write()'s
#define O_TEXT 0x4000 /* file mode is text (translated) */
#define O_BINARY 0x8000 /* file mode is binary (untranslated) */
#define O_RAW O_BINARY
#define O_TEMPORARY 0x0040 /* temporary file bit (file is deleted when last handle is closed) */
#define O_NOINHERIT 0x0080 /* child process doesn't inherit file */
#define O_SEQUENTIAL 0x0020 /* file access is primarily sequential */
#define O_RANDOM 0x0010 /* file access is primarily random */
/* extension */
#define O_ACCMODE 0x0003 /* mask for above modes, from 4.4BSD https://minnie.tuhs.org/cgi-bin/utree.pl?file=4.4BSD/usr/include/sys/fcntl.h */
#define O_NONBLOCK 0x0004 /* non blocking I/O, from BSD apple https://opensource.apple.com/source/xnu/xnu-1228.0.2/bsd/sys/fcntl.h */
#define O_DIRECTORY 0x200000 /* from Newlib */
#define F_DUPFD 0
#define F_GETFD 1
#define F_SETFD 2
#define F_GETFL 3
#define F_SETFL 4
#define F_SETOWN 8
#define F_GETOWN 9
#define F_SETSIG 10
#define F_GETSIG 11
#define F_GETLK 12
#define F_SETLK 13
#define F_SETLKW 14
#define F_SETOWN_EX 15
#define F_GETOWN_EX 16
#define F_GETOWNER_UIDS 17
int open(const char *file, int flags, ...);
int fcntl(int fildes, int cmd, ...);
int creat(const char *path, mode_t mode);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,11 @@
from building import *
Import('rtconfig')
src = []
cwd = GetCurrentDir()
CPPPATH = [cwd]
group = []
if rtconfig.PLATFORM in ['armcc', 'armclang', 'iccarm']:
group = DefineGroup('Compiler', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-09-02 Meco Man First version
*/
#ifndef __FCNTL_H__
#define __FCNTL_H__
#include "sys/types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100
#define O_EXCL 0200
#define O_NOCTTY 0400
#define O_TRUNC 01000
#define O_APPEND 02000
#define O_NONBLOCK 04000
#define O_DSYNC 010000
#define O_SYNC 04010000
#define O_RSYNC 04010000
#define O_BINARY 0100000
#define O_DIRECTORY 0200000
#define O_NOFOLLOW 0400000
#define O_CLOEXEC 02000000
#define O_ASYNC 020000
#define O_DIRECT 040000
#define O_LARGEFILE 0100000
#define O_NOATIME 01000000
#define O_PATH 010000000
#define O_TMPFILE 020200000
#define O_NDELAY O_NONBLOCK
#define O_SEARCH O_PATH
#define O_EXEC O_PATH
#define O_ACCMODE (03|O_SEARCH)
#define F_DUPFD 0
#define F_GETFD 1
#define F_SETFD 2
#define F_GETFL 3
#define F_SETFL 4
#define F_SETOWN 8
#define F_GETOWN 9
#define F_SETSIG 10
#define F_GETSIG 11
#define F_GETLK 12
#define F_SETLK 13
#define F_SETLKW 14
#define F_SETOWN_EX 15
#define F_GETOWN_EX 16
#define F_GETOWNER_UIDS 17
int open(const char *file, int flags, ...);
int fcntl(int fildes, int cmd, ...);
int creat(const char *path, mode_t mode);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,4 @@
## Attentions
This folder is "common" for toolchains, which only support ISO C, as an extension part, such as Keil-MDK and IAR.

View file

@ -0,0 +1,585 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-05-22 Meco Man The first version.
*/
#ifndef __SYS_ERRNO_H__
#define __SYS_ERRNO_H__
#if defined(__ARMCC_VERSION)
/*
defined in armcc/errno.h
#define EDOM 1
#define ERANGE 2
#define EILSEQ 4
#define ESIGNUM 3
#define EINVAL 5
#define ENOMEM 6
*/
#define ERROR_BASE_NO 7
#elif defined(__IAR_SYSTEMS_ICC__)
/* defined in iar/errno.h
#define EDOM 33
#define ERANGE 34
#define EFPOS 35
#define EILSEQ 36
*/
#define ERROR_BASE_NO 36
#else
#define ERROR_BASE_NO 0
#endif
#if defined(__ARMCC_VERSION) || defined(__IAR_SYSTEMS_ICC__)
#include <errno.h>
#ifndef EPERM
#define EPERM (ERROR_BASE_NO + 1)
#endif
#ifndef ENOENT
#define ENOENT (ERROR_BASE_NO + 2)
#endif
#ifndef ESRCH
#define ESRCH (ERROR_BASE_NO + 3)
#endif
#ifndef EINTR
#define EINTR (ERROR_BASE_NO + 4)
#endif
#ifndef EIO
#define EIO (ERROR_BASE_NO + 5)
#endif
#ifndef ENXIO
#define ENXIO (ERROR_BASE_NO + 6)
#endif
#ifndef E2BIG
#define E2BIG (ERROR_BASE_NO + 7)
#endif
#ifndef ENOEXEC
#define ENOEXEC (ERROR_BASE_NO + 8)
#endif
#ifndef EBADF
#define EBADF (ERROR_BASE_NO + 9)
#endif
#ifndef ECHILD
#define ECHILD (ERROR_BASE_NO + 10)
#endif
#ifndef EAGAIN
#define EAGAIN (ERROR_BASE_NO + 11)
#endif
#ifndef ENOMEM
#define ENOMEM (ERROR_BASE_NO + 12)
#endif
#ifndef EACCES
#define EACCES (ERROR_BASE_NO + 13)
#endif
#ifndef EFAULT
#define EFAULT (ERROR_BASE_NO + 14)
#endif
#ifndef ENOTBLK
#define ENOTBLK (ERROR_BASE_NO + 15)
#endif
#ifndef EBUSY
#define EBUSY (ERROR_BASE_NO + 16)
#endif
#ifndef EEXIST
#define EEXIST (ERROR_BASE_NO + 17)
#endif
#ifndef EXDEV
#define EXDEV (ERROR_BASE_NO + 18)
#endif
#ifndef ENODEV
#define ENODEV (ERROR_BASE_NO + 19)
#endif
#ifndef ENOTDIR
#define ENOTDIR (ERROR_BASE_NO + 20)
#endif
#ifndef EISDIR
#define EISDIR (ERROR_BASE_NO + 21)
#endif
#ifndef EINVAL
#define EINVAL (ERROR_BASE_NO + 22)
#endif
#ifndef ENFILE
#define ENFILE (ERROR_BASE_NO + 23)
#endif
#ifndef EMFILE
#define EMFILE (ERROR_BASE_NO + 24)
#endif
#ifndef ENOTTY
#define ENOTTY (ERROR_BASE_NO + 25)
#endif
#ifndef ETXTBSY
#define ETXTBSY (ERROR_BASE_NO + 26)
#endif
#ifndef EFBIG
#define EFBIG (ERROR_BASE_NO + 27)
#endif
#ifndef ENOSPC
#define ENOSPC (ERROR_BASE_NO + 28)
#endif
#ifndef ESPIPE
#define ESPIPE (ERROR_BASE_NO + 29)
#endif
#ifndef EROFS
#define EROFS (ERROR_BASE_NO + 30)
#endif
#ifndef EMLINK
#define EMLINK (ERROR_BASE_NO + 31)
#endif
#ifndef EPIPE
#define EPIPE (ERROR_BASE_NO + 32)
#endif
#ifndef EDOM
#define EDOM (ERROR_BASE_NO + 33)
#endif
#ifndef ERANGE
#define ERANGE (ERROR_BASE_NO + 34)
#endif
#ifndef EDEADLK
#define EDEADLK (ERROR_BASE_NO + 35)
#endif
#ifndef ENAMETOOLONG
#define ENAMETOOLONG (ERROR_BASE_NO + 36)
#endif
#ifndef ENOLCK
#define ENOLCK (ERROR_BASE_NO + 37)
#endif
#ifndef ENOSYS
#define ENOSYS (ERROR_BASE_NO + 38)
#endif
#ifndef ENOTEMPTY
#define ENOTEMPTY (ERROR_BASE_NO + 39)
#endif
#ifndef ELOOP
#define ELOOP (ERROR_BASE_NO + 40)
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
#ifndef ENOMSG
#define ENOMSG (ERROR_BASE_NO + 42)
#endif
#ifndef EIDRM
#define EIDRM (ERROR_BASE_NO + 43)
#endif
#ifndef ECHRNG
#define ECHRNG (ERROR_BASE_NO + 44)
#endif
#ifndef EL2NSYNC
#define EL2NSYNC (ERROR_BASE_NO + 45)
#endif
#ifndef EL3HLT
#define EL3HLT (ERROR_BASE_NO + 46)
#endif
#ifndef EL3RST
#define EL3RST (ERROR_BASE_NO + 47)
#endif
#ifndef ELNRNG
#define ELNRNG (ERROR_BASE_NO + 48)
#endif
#ifndef EUNATCH
#define EUNATCH (ERROR_BASE_NO + 49)
#endif
#ifndef ENOCSI
#define ENOCSI (ERROR_BASE_NO + 50)
#endif
#ifndef EL2HLT
#define EL2HLT (ERROR_BASE_NO + 51)
#endif
#ifndef EBADE
#define EBADE (ERROR_BASE_NO + 52)
#endif
#ifndef EBADR
#define EBADR (ERROR_BASE_NO + 53)
#endif
#ifndef EXFULL
#define EXFULL (ERROR_BASE_NO + 54)
#endif
#ifndef ENOANO
#define ENOANO (ERROR_BASE_NO + 55)
#endif
#ifndef EBADRQC
#define EBADRQC (ERROR_BASE_NO + 56)
#endif
#ifndef EBADSLT
#define EBADSLT (ERROR_BASE_NO + 57)
#endif
#ifndef EDEADLOCK
#define EDEADLOCK EDEADLK
#endif
#ifndef EBFONT
#define EBFONT (ERROR_BASE_NO + 59)
#endif
#ifndef ENOSTR
#define ENOSTR (ERROR_BASE_NO + 60)
#endif
#ifndef ENODATA
#define ENODATA (ERROR_BASE_NO + 61)
#endif
#ifndef ETIME
#define ETIME (ERROR_BASE_NO + 62)
#endif
#ifndef ENOSR
#define ENOSR (ERROR_BASE_NO + 63)
#endif
#ifndef ENONET
#define ENONET (ERROR_BASE_NO + 64)
#endif
#ifndef ENOPKG
#define ENOPKG (ERROR_BASE_NO + 65)
#endif
#ifndef EREMOTE
#define EREMOTE (ERROR_BASE_NO + 66)
#endif
#ifndef ENOLINK
#define ENOLINK (ERROR_BASE_NO + 67)
#endif
#ifndef EADV
#define EADV (ERROR_BASE_NO + 68)
#endif
#ifndef ESRMNT
#define ESRMNT (ERROR_BASE_NO + 69)
#endif
#ifndef ECOMM
#define ECOMM (ERROR_BASE_NO + 70)
#endif
#ifndef EPROTO
#define EPROTO (ERROR_BASE_NO + 71)
#endif
#ifndef EMULTIHOP
#define EMULTIHOP (ERROR_BASE_NO + 72)
#endif
#ifndef EDOTDOT
#define EDOTDOT (ERROR_BASE_NO + 73)
#endif
#ifndef EBADMSG
#define EBADMSG (ERROR_BASE_NO + 74)
#endif
#ifndef EOVERFLOW
#define EOVERFLOW (ERROR_BASE_NO + 75)
#endif
#ifndef ENOTUNIQ
#define ENOTUNIQ (ERROR_BASE_NO + 76)
#endif
#ifndef EBADFD
#define EBADFD (ERROR_BASE_NO + 77)
#endif
#ifndef EREMCHG
#define EREMCHG (ERROR_BASE_NO + 78)
#endif
#ifndef ELIBACC
#define ELIBACC (ERROR_BASE_NO + 79)
#endif
#ifndef ELIBBAD
#define ELIBBAD (ERROR_BASE_NO + 80)
#endif
#ifndef ELIBSCN
#define ELIBSCN (ERROR_BASE_NO + 81)
#endif
#ifndef ELIBMAX
#define ELIBMAX (ERROR_BASE_NO + 82)
#endif
#ifndef ELIBEXEC
#define ELIBEXEC (ERROR_BASE_NO + 83)
#endif
#ifndef EILSEQ
#define EILSEQ (ERROR_BASE_NO + 84)
#endif
#ifndef ERESTART
#define ERESTART (ERROR_BASE_NO + 85)
#endif
#ifndef ESTRPIPE
#define ESTRPIPE (ERROR_BASE_NO + 86)
#endif
#ifndef EUSERS
#define EUSERS (ERROR_BASE_NO + 87)
#endif
#ifndef ENOTSOCK
#define ENOTSOCK (ERROR_BASE_NO + 88)
#endif
#ifndef EDESTADDRREQ
#define EDESTADDRREQ (ERROR_BASE_NO + 89)
#endif
#ifndef EMSGSIZE
#define EMSGSIZE (ERROR_BASE_NO + 90)
#endif
#ifndef EPROTOTYPE
#define EPROTOTYPE (ERROR_BASE_NO + 91)
#endif
#ifndef ENOPROTOOPT
#define ENOPROTOOPT (ERROR_BASE_NO + 92)
#endif
#ifndef EPROTONOSUPPORT
#define EPROTONOSUPPORT (ERROR_BASE_NO + 93)
#endif
#ifndef ESOCKTNOSUPPORT
#define ESOCKTNOSUPPORT (ERROR_BASE_NO + 94)
#endif
#ifndef EOPNOTSUPP
#define EOPNOTSUPP (ERROR_BASE_NO + 95)
#endif
#ifndef ENOTSUP
#define ENOTSUP EOPNOTSUPP
#endif
#ifndef EPFNOSUPPORT
#define EPFNOSUPPORT (ERROR_BASE_NO + 96)
#endif
#ifndef EAFNOSUPPORT
#define EAFNOSUPPORT (ERROR_BASE_NO + 97)
#endif
#ifndef EADDRINUSE
#define EADDRINUSE (ERROR_BASE_NO + 98)
#endif
#ifndef EADDRNOTAVAIL
#define EADDRNOTAVAIL (ERROR_BASE_NO + 99)
#endif
#ifndef ENETDOWN
#define ENETDOWN (ERROR_BASE_NO + 100)
#endif
#ifndef ENETUNREACH
#define ENETUNREACH (ERROR_BASE_NO + 101)
#endif
#ifndef ENETRESET
#define ENETRESET (ERROR_BASE_NO + 102)
#endif
#ifndef ECONNABORTED
#define ECONNABORTED (ERROR_BASE_NO + 103)
#endif
#ifndef ECONNRESET
#define ECONNRESET (ERROR_BASE_NO + 104)
#endif
#ifndef ENOBUFS
#define ENOBUFS (ERROR_BASE_NO + 105)
#endif
#ifndef EISCONN
#define EISCONN (ERROR_BASE_NO + 106)
#endif
#ifndef ENOTCONN
#define ENOTCONN (ERROR_BASE_NO + 107)
#endif
#ifndef ESHUTDOWN
#define ESHUTDOWN (ERROR_BASE_NO + 108)
#endif
#ifndef ETOOMANYREFS
#define ETOOMANYREFS (ERROR_BASE_NO + 109)
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT (ERROR_BASE_NO + 110)
#endif
#ifndef ECONNREFUSED
#define ECONNREFUSED (ERROR_BASE_NO + 111)
#endif
#ifndef EHOSTDOWN
#define EHOSTDOWN (ERROR_BASE_NO + 112)
#endif
#ifndef EHOSTUNREACH
#define EHOSTUNREACH (ERROR_BASE_NO + 113)
#endif
#ifndef EALREADY
#define EALREADY (ERROR_BASE_NO + 114)
#endif
#ifndef EINPROGRESS
#define EINPROGRESS (ERROR_BASE_NO + 115)
#endif
#ifndef ESTALE
#define ESTALE (ERROR_BASE_NO + 116)
#endif
#ifndef EUCLEAN
#define EUCLEAN (ERROR_BASE_NO + 117)
#endif
#ifndef ENOTNAM
#define ENOTNAM (ERROR_BASE_NO + 118)
#endif
#ifndef ENAVAIL
#define ENAVAIL (ERROR_BASE_NO + 119)
#endif
#ifndef EISNAM
#define EISNAM (ERROR_BASE_NO + 120)
#endif
#ifndef EREMOTEIO
#define EREMOTEIO (ERROR_BASE_NO + 121)
#endif
#ifndef EDQUOT
#define EDQUOT (ERROR_BASE_NO + 122)
#endif
#ifndef ENOMEDIUM
#define ENOMEDIUM (ERROR_BASE_NO + 123)
#endif
#ifndef EMEDIUMTYPE
#define EMEDIUMTYPE (ERROR_BASE_NO + 124)
#endif
#ifndef ECANCELED
#define ECANCELED (ERROR_BASE_NO + 125)
#endif
#ifndef ENOKEY
#define ENOKEY (ERROR_BASE_NO + 126)
#endif
#ifndef EKEYEXPIRED
#define EKEYEXPIRED (ERROR_BASE_NO + 127)
#endif
#ifndef EKEYREVOKED
#define EKEYREVOKED (ERROR_BASE_NO + 128)
#endif
#ifndef EKEYREJECTED
#define EKEYREJECTED (ERROR_BASE_NO + 129)
#endif
#ifndef EOWNERDEAD
#define EOWNERDEAD (ERROR_BASE_NO + 130)
#endif
#ifndef ENOTRECOVERABLE
#define ENOTRECOVERABLE (ERROR_BASE_NO + 131)
#endif
#ifndef ERFKILL
#define ERFKILL (ERROR_BASE_NO + 132)
#endif
#ifndef EHWPOISON
#define EHWPOISON (ERROR_BASE_NO + 133)
#endif
#elif defined(_WIN32)
#include <errno.h>
#endif /* defined(__ARMCC_VERSION) || defined(__IAR_SYSTEMS_ICC__) */
#endif /* __SYS_ERRNO_H__ */

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-09-02 Meco Man First version
*/
#ifndef __SYS_STAT_H__
#define __SYS_STAT_H__
#include <sys/types.h>
#include <sys/time.h>
#ifdef __cplusplus
extern "C" {
#endif
#define S_IFMT 00170000
#define S_IFSOCK 0140000
#define S_IFLNK 0120000
#define S_IFREG 0100000
#define S_IFBLK 0060000
#define S_IFDIR 0040000
#define S_IFCHR 0020000
#define S_IFIFO 0010000
#define S_ISUID 0004000
#define S_ISGID 0002000
#define S_ISVTX 0001000
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001
struct stat
{
struct rt_device *st_dev;
uint16_t st_ino;
uint16_t st_mode;
uint16_t st_nlink;
uint16_t st_uid;
uint16_t st_gid;
struct rt_device *st_rdev;
uint32_t st_size;
time_t st_atime;
long st_spare1;
time_t st_mtime;
long st_spare2;
time_t st_ctime;
long st_spare3;
uint32_t st_blksize;
uint32_t st_blocks;
long st_spare4[2];
};
int chmod(const char *, mode_t);
int fchmod(int, mode_t);
int fstat(int, struct stat *);
int lstat(const char *, struct stat *);
int mkdir(const char *, mode_t);
int mkfifo(const char *, mode_t);
int mknod(const char *, mode_t, dev_t);
int stat(const char *, struct stat *);
mode_t umask(mode_t);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-09-05 Meco Man fix bugs
* 2020-12-16 Meco Man add useconds_t
*/
#ifndef __SYS_TYPES_H__
#define __SYS_TYPES_H__
#include <stdint.h>
#include <stddef.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef int32_t clockid_t;
typedef int32_t key_t; /* Used for interprocess communication. */
typedef int pid_t; /* Used for process IDs and process group IDs. */
typedef unsigned short uid_t;
typedef unsigned short gid_t;
typedef signed long off_t;
typedef int mode_t;
typedef signed long ssize_t; /* Used for a count of bytes or an error indication. */
typedef unsigned long __timer_t;
typedef __timer_t timer_t;
typedef long suseconds_t; /* microseconds. */
typedef unsigned long useconds_t; /* microseconds (unsigned) */
typedef unsigned long dev_t;
typedef unsigned int u_int;
typedef unsigned char u_char;
typedef unsigned long u_long;
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-12-26 Meco Man First Version
*/
#ifndef __COMPILER_PRIVATE_H__
#define __COMPILER_PRIVATE_H__
#define _WARNING_WITHOUT_FS "Please enable RT_USING_POSIX_FS"
#define _WARNING_WITHOUT_STDIO "Please enable RT_USING_POSIX_FS and RT_USING_POSIX_STDIO"
#endif /* __COMPILER_PRIVATE_H__ */

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef __DIRENT_H__
#define __DIRENT_H__
#include <rtdef.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* dirent.h - format of directory entries
* Ref: http://www.opengroup.org/onlinepubs/009695399/basedefs/dirent.h.html
*/
/* File types */
#define FT_REGULAR 0 /* regular file */
#define FT_SOCKET 1 /* socket file */
#define FT_DIRECTORY 2 /* directory */
#define FT_USER 3 /* user defined */
#define DT_UNKNOWN 0x00
#define DT_REG 0x01
#define DT_DIR 0x02
#ifndef HAVE_DIR_STRUCTURE
#define HAVE_DIR_STRUCTURE
typedef struct
{
int fd; /* directory file */
char buf[512];
int num;
int cur;
}DIR;
#endif
#ifndef HAVE_DIRENT_STRUCTURE
#define HAVE_DIRENT_STRUCTURE
#define DIRENT_NAME_MAX 256
struct dirent
{
rt_uint8_t d_type; /* The type of the file */
rt_uint8_t d_namlen; /* The length of the not including the terminating null file name */
rt_uint16_t d_reclen; /* length of this record */
char d_name[DIRENT_NAME_MAX]; /* The null-terminated file name */
};
#endif
int closedir(DIR *);
DIR *opendir(const char *);
struct dirent *readdir(DIR *);
int readdir_r(DIR *, struct dirent *, struct dirent **);
void rewinddir(DIR *);
void seekdir(DIR *, long int);
long telldir(DIR *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-06-07 Meco Man The first version.
*/
#ifndef __POSIX_CTYPE_H__
#define __POSIX_CTYPE_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <ctype.h>
#if !(defined(__ICCARM__) && (__VER__ > 9000000)) /* IAR9.0 has defined */
#ifndef isascii /* some toolchain use macro to define it */
int isascii(int c);
#endif
#endif /* !(defined(__ICCARM__) && (__VER__ > 9000000)) */
#ifndef toascii
int toascii(int c);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __POSIX_CTYPE_H__ */

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-06-07 Meco Man first version
*/
#ifndef __POSIX_STDIO_H__
#define __POSIX_STDIO_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <sys/types.h>
#ifdef DFS_USING_POSIX
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
#endif /* DFS_USING_POSIX */
#ifdef __cplusplus
}
#endif
#endif /* __POSIX_STDIO_H__ */

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-06-07 Meco Man The first version.
*/
#ifndef __POSIX_STDLIB_H__
#define __POSIX_STDLIB_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdlib.h>
char *itoa(int n, char *buffer, int radix);
char *lltoa(int64_t ll, char *buffer, int radix);
char *ltoa(long l, char *buffer, int radix);
char *ulltoa(uint64_t ll, char *buffer, int radix);
char *ultoa(unsigned long l, char *buffer, int radix);
char *utoa(unsigned int n, char *buffer, int radix);
#ifdef __cplusplus
}
#endif
#endif /* __POSIX_STDLIB_H__ */

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-01-12 Meco Man The first version.
*/
#ifndef __POSIX_STRING_H__
#define __POSIX_STRING_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <string.h>
void bzero(void * s, size_t n);
void bcopy(const void * src, void * dest, size_t n);
int bcmp(const void * s1, const void * s2, size_t n);
void explicit_bzero(void * s, size_t n);
char *index(const char * s, int c);
char *rindex(const char * s, int c);
int ffs(int i);
int ffsl(long i);
int ffsll(long long i);
void *memrchr(const void* ptr, int ch, size_t pos);
size_t strnlen(const char *s, size_t maxlen);
char* strchrnul(const char *s, int c);
int strcasecmp(const char * s1, const char * s2);
int strncasecmp(const char * s1, const char * s2, size_t n);
char *strdup(const char *s);
char *strndup(const char *s, size_t size);
char *strtok_r(char *str, const char *delim, char **saveptr);
#ifdef __cplusplus
}
#endif
#endif /* __POSIX_STRING_H__ */

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-06-07 Meco Man The first version
*/
#ifndef __POSIX_WCHAR_H__
#define __POSIX_WCHAR_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <wchar.h>
int wcwidth(wchar_t);
int wcswidth(const wchar_t*, size_t);
#ifdef __cplusplus
}
#endif
#endif /* __POSIX_WCHAR_H__ */

View file

@ -0,0 +1,283 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-09-01 Meco Man First Version
*/
#ifndef __SYS_IOCTL_H__
#define __SYS_IOCTL_H__
#ifdef __cplusplus
extern "C" {
#endif
struct winsize
{
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
};
#ifdef RT_USING_MUSLLIBC
#include <bits/ioctl.h>
#else
/*
* Direction bits, which any architecture can choose to override
* before including this file.
*/
#ifndef _IOC_NONE
#define _IOC_NONE 0U
#endif
#ifndef _IOC_WRITE
#define _IOC_WRITE 1U
#endif
#ifndef _IOC_READ
#define _IOC_READ 2U
#endif
#ifndef _IOC
#define _IOC(a,b,c,d) (((a)<<30) | ((b)<<8) | (c) | ((d)<<16))
#endif
#ifndef _IO
#define _IO(a,b) _IOC(_IOC_NONE, (a), (b), 0)
#endif
#ifndef _IOW
#define _IOW(a,b,c) _IOC(_IOC_WRITE, (a), (b), sizeof(c))
#endif
#ifndef _IOR
#define _IOR(a,b,c) _IOC(_IOC_READ, (a), (b), sizeof(c))
#endif
#ifndef _IOWR
#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE, (a), (b), sizeof(c))
#endif
#ifndef FIONREAD
#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */
#endif
#ifndef FIONBIO
#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */
#endif
#ifndef FIOASYNC
#define FIOASYNC _IOW('f', 125, int) /* set/clear async i/o */
#endif
/* Socket I/O Controls */
#ifndef SIOCSHIWAT
#define SIOCSHIWAT _IOW('s', 0, int) /* set high watermark */
#define SIOCGHIWAT _IOR('s', 1, int) /* get high watermark */
#define SIOCSLOWAT _IOW('s', 2, int) /* set low watermark */
#define SIOCGLOWAT _IOR('s', 3, int) /* get low watermark */
#define SIOCATMARK _IOR('s', 7, int) /* at oob mark? */
#endif
#define TCGETS 0x5401
#define TCSETS 0x5402
#define TCSETSW 0x5403
#define TCSETSF 0x5404
#define TCGETA 0x5405
#define TCSETA 0x5406
#define TCSETAW 0x5407
#define TCSETAF 0x5408
#define TCSBRK 0x5409
#define TCXONC 0x540A
#define TCFLSH 0x540B
#define TIOCEXCL 0x540C
#define TIOCNXCL 0x540D
#define TIOCSCTTY 0x540E
#define TIOCGPGRP 0x540F
#define TIOCSPGRP 0x5410
#define TIOCOUTQ 0x5411
#define TIOCSTI 0x5412
#define TIOCGWINSZ 0x5413
#define TIOCSWINSZ 0x5414
#define TIOCMGET 0x5415
#define TIOCMBIS 0x5416
#define TIOCMBIC 0x5417
#define TIOCMSET 0x5418
#define TIOCGSOFTCAR 0x5419
#define TIOCSSOFTCAR 0x541A
#define TIOCINQ FIONREAD
#define TIOCLINUX 0x541C
#define TIOCCONS 0x541D
#define TIOCGSERIAL 0x541E
#define TIOCSSERIAL 0x541F
#define TIOCPKT 0x5420
#define TIOCNOTTY 0x5422
#define TIOCSETD 0x5423
#define TIOCGETD 0x5424
#define TCSBRKP 0x5425
#define TIOCSBRK 0x5427
#define TIOCCBRK 0x5428
#define TIOCGSID 0x5429
#define TIOCGRS485 0x542E
#define TIOCSRS485 0x542F
#define TIOCGPTN 0x80045430
#define TIOCSPTLCK 0x40045431
#define TIOCGDEV 0x80045432
#define TCGETX 0x5432
#define TCSETX 0x5433
#define TCSETXF 0x5434
#define TCSETXW 0x5435
#define TIOCSIG 0x40045436
#define TIOCVHANGUP 0x5437
#define TIOCGPKT 0x80045438
#define TIOCGPTLCK 0x80045439
#define TIOCGEXCL 0x80045440
#define FIONCLEX 0x5450
#define FIOCLEX 0x5451
#define TIOCSERCONFIG 0x5453
#define TIOCSERGWILD 0x5454
#define TIOCSERSWILD 0x5455
#define TIOCGLCKTRMIOS 0x5456
#define TIOCSLCKTRMIOS 0x5457
#define TIOCSERGSTRUCT 0x5458
#define TIOCSERGETLSR 0x5459
#define TIOCSERGETMULTI 0x545A
#define TIOCSERSETMULTI 0x545B
#define TIOCMIWAIT 0x545C
#define TIOCGICOUNT 0x545D
#define FIOQSIZE 0x5460
#define TIOCPKT_DATA 0
#define TIOCPKT_FLUSHREAD 1
#define TIOCPKT_FLUSHWRITE 2
#define TIOCPKT_STOP 4
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01
#define TIOCM_LE 0x001
#define TIOCM_DTR 0x002
#define TIOCM_RTS 0x004
#define TIOCM_ST 0x008
#define TIOCM_SR 0x010
#define TIOCM_CTS 0x020
#define TIOCM_CAR 0x040
#define TIOCM_RNG 0x080
#define TIOCM_DSR 0x100
#define TIOCM_CD TIOCM_CAR
#define TIOCM_RI TIOCM_RNG
#define TIOCM_OUT1 0x2000
#define TIOCM_OUT2 0x4000
#define TIOCM_LOOP 0x8000
#define N_TTY 0
#define N_SLIP 1
#define N_MOUSE 2
#define N_PPP 3
#define N_STRIP 4
#define N_AX25 5
#define N_X25 6
#define N_6PACK 7
#define N_MASC 8
#define N_R3964 9
#define N_PROFIBUS_FDL 10
#define N_IRDA 11
#define N_SMSBLOCK 12
#define N_HDLC 13
#define N_SYNC_PPP 14
#define N_HCI 15
#define FIOSETOWN 0x8901
#define SIOCSPGRP 0x8902
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCGSTAMP 0x8906
#define SIOCGSTAMPNS 0x8907
#endif
#ifndef FIONWRITE
#define FIONWRITE _IOR('f', 121, int) /* get # bytes outstanding in send queue */
#endif
#define SIOCADDRT 0x890B
#define SIOCDELRT 0x890C
#define SIOCRTMSG 0x890D
#define SIOCGIFNAME 0x8910
#define SIOCSIFLINK 0x8911
#define SIOCGIFCONF 0x8912
#define SIOCGIFFLAGS 0x8913
#define SIOCSIFFLAGS 0x8914
#define SIOCGIFADDR 0x8915
#define SIOCSIFADDR 0x8916
#define SIOCGIFDSTADDR 0x8917
#define SIOCSIFDSTADDR 0x8918
#define SIOCGIFBRDADDR 0x8919
#define SIOCSIFBRDADDR 0x891a
#define SIOCGIFNETMASK 0x891b
#define SIOCSIFNETMASK 0x891c
#define SIOCGIFMETRIC 0x891d
#define SIOCSIFMETRIC 0x891e
#define SIOCGIFMEM 0x891f
#define SIOCSIFMEM 0x8920
#define SIOCGIFMTU 0x8921
#define SIOCSIFMTU 0x8922
#define SIOCSIFNAME 0x8923
#define SIOCSIFHWADDR 0x8924
#define SIOCGIFENCAP 0x8925
#define SIOCSIFENCAP 0x8926
#define SIOCGIFHWADDR 0x8927
#define SIOCGIFSLAVE 0x8929
#define SIOCSIFSLAVE 0x8930
#define SIOCADDMULTI 0x8931
#define SIOCDELMULTI 0x8932
#define SIOCGIFINDEX 0x8933
#define SIOGIFINDEX SIOCGIFINDEX
#define SIOCSIFPFLAGS 0x8934
#define SIOCGIFPFLAGS 0x8935
#define SIOCDIFADDR 0x8936
#define SIOCSIFHWBROADCAST 0x8937
#define SIOCGIFCOUNT 0x8938
#define SIOCGIFBR 0x8940
#define SIOCSIFBR 0x8941
#define SIOCGIFTXQLEN 0x8942
#define SIOCSIFTXQLEN 0x8943
#define SIOCDARP 0x8953
#define SIOCGARP 0x8954
#define SIOCSARP 0x8955
#define SIOCDRARP 0x8960
#define SIOCGRARP 0x8961
#define SIOCSRARP 0x8962
#define SIOCGIFMAP 0x8970
#define SIOCSIFMAP 0x8971
#define SIOCADDDLCI 0x8980
#define SIOCDELDLCI 0x8981
#define SIOCDEVPRIVATE 0x89F0
#define SIOCPROTOPRIVATE 0x89E0
int ioctl(int fildes, int cmd, ...);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-07-21 Meco Man The first version
* 2021-12-25 Meco Man Handle newlib 2.2.0 or lower version
*/
#ifndef __SYS_SELECT_H__
#define __SYS_SELECT_H__
#include <rtconfig.h>
#include <sys/types.h>
#include <sys/time.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef FD_SETSIZE
#define FD_SETSIZE 32
#endif
#ifdef SAL_USING_POSIX
#ifdef FD_SETSIZE
#undef FD_SETSIZE
#endif
#define FD_SETSIZE DFS_FD_MAX
#endif /* SAL_USING_POSIX */
typedef long fd_mask;
#ifndef _SYS_TYPES_FD_SET /* Newlib 2.2.0 or lower version */
#define NBBY 8 /* number of bits in a byte */
#define NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */
#ifndef howmany
#define howmany(x,y) (((x)+((y)-1))/(y))
#endif /* howmany */
typedef struct _types_fd_set {
fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
} _types_fd_set;
#define fd_set _types_fd_set
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1L << ((n) % NFDBITS)))
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1L << ((n) % NFDBITS)))
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1L << ((n) % NFDBITS)))
#define FD_ZERO(p) rt_memset((void*)(p), 0, sizeof(*(p)))
#endif /* _SYS_TYPES_FD_SET */
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
#ifdef __cplusplus
}
#endif
#endif /* __SYS_SELECT_H__ */

View file

@ -0,0 +1,251 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-09-12 Bernard The first version
* 2021-07-21 Meco Man move to libc/common
*/
#ifndef __SYS_SIGNAL_H__
#define __SYS_SIGNAL_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef RT_USING_MUSLLIBC
/* this is required for musl <signal.h> */
#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE
#include <signal.h>
/* limiting influence of _POSIX_SOURCE */
#undef _POSIX_SOURCE
#else /* ndef _POSIX_SOURCE */
#include <signal.h>
#endif
#else
#include <stdint.h>
#include <sys/types.h>
/* sigev_notify values
NOTE: P1003.1c/D10, p. 34 adds SIGEV_THREAD. */
#define SIGEV_NONE 1 /* No asynchronous notification shall be delivered */
/* when the event of interest occurs. */
#define SIGEV_SIGNAL 0 /* A queued signal, with an application defined */
/* value, shall be delivered when the event of */
/* interest occurs. */
#define SIGEV_THREAD 2 /* A notification function shall be called to */
/* perform notification. */
/* Signal Generation and Delivery, P1003.1b-1993, p. 63
NOTE: P1003.1c/D10, p. 34 adds sigev_notify_function and
sigev_notify_attributes to the sigevent structure. */
union sigval
{
int sival_int; /* Integer signal value */
void *sival_ptr; /* Pointer signal value */
};
struct sigevent
{
union sigval sigev_value;
int sigev_signo; /* Signal number */
int sigev_notify; /* Notification type */
void (*sigev_notify_function)( union sigval );
/* Notification function */
void *sigev_notify_attributes; /* Notification Attributes, really pthread_attr_t */
};
struct siginfo
{
uint16_t si_signo;
uint16_t si_code;
union sigval si_value;
};
typedef struct siginfo siginfo_t;
#define SI_USER 0x01 /* Signal sent by kill(). */
#define SI_QUEUE 0x02 /* Signal sent by sigqueue(). */
#define SI_TIMER 0x03 /* Signal generated by expiration of a timer set by timer_settime(). */
#define SI_ASYNCIO 0x04 /* Signal generated by completion of an asynchronous I/O request. */
#define SI_MESGQ 0x05 /* Signal generated by arrival of a message on an empty message queue. */
typedef void (*_sig_func_ptr)(int);
typedef unsigned long sigset_t;
struct sigaction
{
_sig_func_ptr sa_handler;
sigset_t sa_mask;
int sa_flags;
};
/*
* Structure used in sigaltstack call.
*/
typedef struct sigaltstack
{
void *ss_sp; /* Stack base or pointer. */
int ss_flags; /* Flags. */
size_t ss_size; /* Stack size. */
} stack_t;
#define SIG_SETMASK 0 /* set mask with sigprocmask() */
#define SIG_BLOCK 1 /* set of signals to block */
#define SIG_UNBLOCK 2 /* set of signals to, well, unblock */
#define sigaddset(what,sig) (*(what) |= (1<<(sig)), 0)
#define sigdelset(what,sig) (*(what) &= ~(1<<(sig)), 0)
#define sigemptyset(what) (*(what) = 0, 0)
#define sigfillset(what) (*(what) = ~(0), 0)
#define sigismember(what,sig) (((*(what)) & (1<<(sig))) != 0)
int sigprocmask (int how, const sigset_t *set, sigset_t *oset);
int sigpending (sigset_t *set);
int sigsuspend (const sigset_t *set);
#include "time.h"
int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout);
int sigwait(const sigset_t *set, int *sig);
int sigwaitinfo(const sigset_t *set, siginfo_t *info);
int raise(int sig);
int sigqueue(pid_t pid, int signo, const union sigval value);
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
#ifdef __ARMCC_VERSION
#define SIGHUP 1
/* #define SIGINT 2 */
#define SIGQUIT 3
/* #define SIGILL 4 */
#define SIGTRAP 5
/* #define SIGABRT 6 */
#define SIGEMT 7
/* #define SIGFPE 8 */
#define SIGKILL 9
#define SIGBUS 10
/* #define SIGSEGV 11 */
#define SIGSYS 12
#define SIGPIPE 13
#define SIGALRM 14
/* #define SIGTERM 15 */
#define SIGURG 16
#define SIGSTOP 17
#define SIGTSTP 18
#define SIGCONT 19
#define SIGCHLD 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGPOLL 23
#define SIGWINCH 24
#define SIGXCPU 24 /* exceeded CPU time limit */
#define SIGXFSZ 25 /* exceeded file size limit */
#define SIGVTALRM 26 /* virtual time alarm */
/* #define SIGUSR1 25 */
/* #define SIGUSR2 26 */
#define SIGRTMIN 27
#define SIGRTMAX 31
#define NSIG 32
#elif defined(__IAR_SYSTEMS_ICC__)
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
/* #define SIGABRT 6 */
#define SIGEMT 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGBUS 10
#define SIGSEGV 11
#define SIGSYS 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGURG 16
#define SIGSTOP 17
#define SIGTSTP 18
#define SIGCONT 19
#define SIGCHLD 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGPOLL 23
#define SIGWINCH 24
#define SIGXCPU 24 /* exceeded CPU time limit */
#define SIGXFSZ 25 /* exceeded file size limit */
#define SIGVTALRM 26 /* virtual time alarm */
#define SIGUSR1 25
#define SIGUSR2 26
#define SIGRTMIN 27
#define SIGRTMAX 31
#define NSIG 32
#elif defined(__GNUC__)
#define SIGHUP 1 /* hangup */
#define SIGINT 2 /* interrupt */
#define SIGQUIT 3 /* quit */
#define SIGILL 4 /* illegal instruction (not reset when caught) */
#define SIGTRAP 5 /* trace trap (not reset when caught) */
#define SIGIOT 6 /* IOT instruction */
#define SIGABRT 6 /* used by abort, replace SIGIOT in the future */
#define SIGEMT 7 /* EMT instruction */
#define SIGFPE 8 /* floating point exception */
#define SIGKILL 9 /* kill (cannot be caught or ignored) */
#define SIGBUS 10 /* bus error */
#define SIGSEGV 11 /* segmentation violation */
#define SIGSYS 12 /* bad argument to system call */
#define SIGPIPE 13 /* write on a pipe with no one to read it */
#define SIGALRM 14 /* alarm clock */
#define SIGTERM 15 /* software termination signal from kill */
#define SIGURG 16 /* urgent condition on IO channel */
#define SIGSTOP 17 /* sendable stop signal not from tty */
#define SIGTSTP 18 /* stop signal from tty */
#define SIGCONT 19 /* continue a stopped process */
#define SIGCHLD 20 /* to parent on child stop or exit */
#define SIGCLD 20 /* System V name for SIGCHLD */
#define SIGTTIN 21 /* to readers pgrp upon background tty read */
#define SIGTTOU 22 /* like TTIN for output if (tp->t_local&LTOSTOP) */
#define SIGIO 23 /* input/output possible signal */
#define SIGPOLL SIGIO /* System V name for SIGIO */
#define SIGXCPU 24 /* exceeded CPU time limit */
#define SIGXFSZ 25 /* exceeded file size limit */
#define SIGVTALRM 26 /* virtual time alarm */
#define SIGPROF 27 /* profiling time alarm */
#define SIGWINCH 28 /* window changed */
#define SIGLOST 29 /* resource lost (eg, record-lock lost) */
#define SIGUSR1 30 /* user defined signal 1 */
#define SIGUSR2 31 /* user defined signal 2 */
#define NSIG 32 /* signal 0 implied */
#endif /* __ARMCC_VERSION */
/* Some applications take advantage of the fact that <sys/signal.h>
* and <signal.h> are equivalent in glibc. Allow for that here. */
#include <signal.h>
#ifndef SIG_ERR
#define SIG_ERR ((void (*)(int))-1)
#endif
#ifndef SIG_DFL
#define SIG_DFL ((void (*)(int)) 0)
#endif
#ifndef SIG_IGN
#define SIG_IGN ((void (*)(int)) 1)
#endif
#endif /* RT_USING_MUSLLIBC */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __SYS_SIGNAL_H__ */

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-27 xqyjlj adapt musl
*/
#ifndef __SYS_STATFS_H__
#define __SYS_STATFS_H__
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef RT_USING_MUSLLIBC
/* this is required for musl <sys/statfs.h> */
#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE
#include_next <sys/statfs.h>
/* limiting influence of _POSIX_SOURCE */
#undef _POSIX_SOURCE
#else /* def _POSIX_SOURCE */
#include_next <sys/statfs.h>
#endif
#else
struct statfs
{
size_t f_bsize; /* block size */
size_t f_blocks; /* total data blocks in file system */
size_t f_bfree; /* free blocks in file system */
size_t f_bavail; /* free blocks available to unprivileged user*/
};
int statfs(const char *path, struct statfs *buf);
int fstatfs(int fd, struct statfs *buf);
#endif
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,166 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-09-07 Meco Man combine gcc armcc iccarm
* 2021-02-12 Meco Man move all definitions located in <clock_time.h> to this file
*/
#ifndef __SYS_TIME_H__
#define __SYS_TIME_H__
#include <rtconfig.h>
#include <sys/types.h>
#include <stdint.h>
#include <time.h>
#ifdef _WIN32
typedef __time64_t time_t;
#endif /* _WIN32 */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#undef CLOCKS_PER_SEC
#define CLOCKS_PER_SEC RT_TICK_PER_SECOND
/* timezone */
#define DST_NONE 0 /* not on dst */
#define DST_USA 1 /* USA style dst */
#define DST_AUST 2 /* Australian style dst */
#define DST_WET 3 /* Western European dst */
#define DST_MET 4 /* Middle European dst */
#define DST_EET 5 /* Eastern European dst */
#define DST_CAN 6 /* Canada */
#define DST_GB 7 /* Great Britain and Eire */
#define DST_RUM 8 /* Rumania */
#define DST_TUR 9 /* Turkey */
#define DST_AUSTALT 10 /* Australian style with shift in 1986 */
struct itimerspec;
struct timezone
{
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of dst correction */
};
#ifndef _TIMEVAL_DEFINED
#define _TIMEVAL_DEFINED
struct timeval
{
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* and microseconds */
};
#endif /* _TIMEVAL_DEFINED */
#if defined(__ARMCC_VERSION) || defined(_WIN32) || (defined(__ICCARM__) && (__VER__ < 8010001))
struct timespec
{
time_t tv_sec; /* seconds */
long tv_nsec; /* and nanoseconds */
};
#endif /* defined(__ARMCC_VERSION) || defined(_WIN32) || (defined(__ICCARM__) && (__VER__ < 8010001)) */
#if !(defined(__GNUC__) && !defined(__ARMCC_VERSION)/*GCC*/)
/*
* Structure defined by POSIX.1b to be like a itimerval, but with
* timespecs. Used in the timer_*() system calls.
*/
struct itimerspec
{
struct timespec it_interval;
struct timespec it_value;
};
#endif /* !(defined(__GNUC__) && !defined(__ARMCC_VERSION)) */
int stime(const time_t *t);
time_t timegm(struct tm * const t);
int gettimeofday(struct timeval *tv, struct timezone *tz);
int settimeofday(const struct timeval *tv, const struct timezone *tz);
#if defined(__ARMCC_VERSION) || defined (__ICCARM__) || defined(_WIN32)
struct tm *gmtime_r(const time_t *timep, struct tm *r);
char* asctime_r(const struct tm *t, char *buf);
char *ctime_r(const time_t * tim_p, char * result);
struct tm* localtime_r(const time_t* t, struct tm* r);
#endif /* defined(__ARMCC_VERSION) || defined (__ICCARM__) || defined(_WIN32) */
#ifdef _WIN32
struct tm* gmtime(const time_t* t);
struct tm* localtime(const time_t* t);
time_t mktime(struct tm* const t);
char* ctime(const time_t* tim_p);
time_t time(time_t* t);
#endif /* _WIN32 */
#ifdef RT_USING_POSIX_DELAY
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
#endif /* RT_USING_POSIX_DELAY */
#define MILLISECOND_PER_SECOND 1000UL
#define MICROSECOND_PER_SECOND 1000000UL
#define NANOSECOND_PER_SECOND 1000000000UL
#define MILLISECOND_PER_TICK (MILLISECOND_PER_SECOND / RT_TICK_PER_SECOND)
#define MICROSECOND_PER_TICK (MICROSECOND_PER_SECOND / RT_TICK_PER_SECOND)
#define NANOSECOND_PER_TICK (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND)
#if defined(RT_USING_POSIX_CLOCK) || defined (RT_USING_POSIX_TIMER)
/* POSIX clock and timer */
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 1
#endif /* CLOCK_REALTIME */
#define CLOCK_CPUTIME_ID 2
#ifndef CLOCK_PROCESS_CPUTIME_ID
#define CLOCK_PROCESS_CPUTIME_ID CLOCK_CPUTIME_ID
#endif /* CLOCK_PROCESS_CPUTIME_ID */
#ifndef CLOCK_THREAD_CPUTIME_ID
#define CLOCK_THREAD_CPUTIME_ID CLOCK_CPUTIME_ID
#endif /* CLOCK_THREAD_CPUTIME_ID */
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC 4
#endif /* CLOCK_MONOTONIC */
#ifdef CLOCK_TAI
#define CLOCK_ID_MAX CLOCK_TAI
#else
#define CLOCK_ID_MAX CLOCK_MONOTONIC
#endif
#endif /* defined(RT_USING_POSIX_CLOCK) || defined (RT_USING_POSIX_TIMER) */
#ifdef RT_USING_POSIX_CLOCK
int clock_getres (clockid_t clockid, struct timespec *res);
int clock_gettime (clockid_t clockid, struct timespec *tp);
int clock_settime (clockid_t clockid, const struct timespec *tp);
int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp, struct timespec *rmtp);
int rt_timespec_to_tick(const struct timespec *time);
#endif /* RT_USING_POSIX_CLOCK */
#ifdef RT_USING_POSIX_TIMER
#include <sys/signal.h>
int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid);
int timer_delete(timer_t timerid);
int timer_getoverrun(timer_t timerid);
int timer_gettime(timer_t timerid, struct itimerspec *its);
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue);
#endif /* RT_USING_POSIX_TIMER */
/* timezone */
void tz_set(int8_t tz);
int8_t tz_get(void);
int8_t tz_is_dst(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _SYS_TIME_H_ */

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-16 Meco Man add usleep
* 2021-09-11 Meco Man move functions from dfs_posix.h to unistd.h
*/
#ifndef __SYS_UNISTD_H__
#define __SYS_UNISTD_H__
#include <stddef.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define STDIN_FILENO 0 /* standard input file descriptor */
#define STDOUT_FILENO 1 /* standard output file descriptor */
#define STDERR_FILENO 2 /* standard error file descriptor */
#define F_OK 0
#define X_OK 1
#define W_OK 2
#define R_OK 4
unsigned alarm(unsigned __secs);
ssize_t read(int fd, void *buf, size_t len);
ssize_t write(int fd, const void *buf, size_t len);
off_t lseek(int fd, off_t offset, int whence);
int pause(void);
int fsync(int fildes);
long sysconf(int __name);
int unlink(const char *pathname);
int close(int d);
int ftruncate(int fd, off_t length);
int rmdir(const char *path);
int chdir(const char *path);
char *getcwd(char *buf, size_t size);
int access(const char *path, int amode);
int pipe(int fildes[2]);
int isatty(int fd);
char *ttyname(int desc);
unsigned int sleep(unsigned int seconds);
int usleep(useconds_t usec);
pid_t gettid(void);
pid_t getpid(void);
pid_t getppid(void);
uid_t getuid(void);
uid_t geteuid(void);
gid_t getgid(void);
gid_t getegid(void);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_UNISTD_H */

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-27 xqyjlj add uname
*/
#ifndef __SYS_UTSNAME_H__
#define __SYS_UTSNAME_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef RT_USING_MUSLLIBC
/* this is required for musl <sys/utsname.h> */
#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE
#include_next <sys/utsname.h>
/* limiting influence of _POSIX_SOURCE */
#undef _POSIX_SOURCE
#else /* def _POSIX_SOURCE */
#include_next <sys/utsname.h>
#endif
#else
struct utsname
{
char sysname[65];
char nodename[65];
char release[65];
char version[65];
char machine[65];
char domainname[65];
};
int uname(struct utsname *);
#endif
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-09-11 Meco Man First version
*/
#ifndef __SYS_VFS_H__
#define __SYS_VFS_H__
#include "statfs.h" /* <sys/statfs.h> */
#endif

View file

@ -0,0 +1,10 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "sys/unistd.h"

View file

@ -0,0 +1 @@
This folder is "common" for all toolchains.

View file

@ -0,0 +1,3 @@
# DLIB (IAR) porting for RT-Thread
http://www.iarsys.co.jp/download/LMS2/arm/7502/ewarm7502doc/arm/doc/EWARM_DevelopmentGuide.ENU.pdf P.130

View file

@ -0,0 +1,21 @@
from building import *
Import('rtconfig')
src = Glob('*.c')
group = []
if rtconfig.PLATFORM in ['iccarm']:
CPPDEFINES = ['RT_USING_DLIBC', 'RT_USING_LIBC', '_DLIB_ADD_EXTRA_SYMBOLS=0']
AddDepend(['RT_USING_DLIBC', 'RT_USING_LIBC'])
if GetDepend('DFS_USING_POSIX'):
from distutils.version import LooseVersion
from iar import IARVersion
CPPDEFINES = CPPDEFINES + ['_DLIB_FILE_DESCRIPTOR']
if LooseVersion(IARVersion()) < LooseVersion("8.20.1"):
CPPDEFINES = CPPDEFINES + ['_DLIB_THREAD_SUPPORT']
group = DefineGroup('Compiler', src, depend = [''], CPPDEFINES = CPPDEFINES)
Return('group')

View file

@ -0,0 +1,12 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-28 Bernard first version
*/
const char *__environ = "OS=RT-Thread";

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-28 Bernard first version
*/
#include <rtthread.h>
#include <LowLevelIOInterface.h>
#include <unistd.h>
#include <compiler_private.h>
#define DBG_TAG "dlib.syscall.close"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
/*
* The "__close" function should close the file corresponding to
* "handle". It should return 0 on success and nonzero on failure.
*/
#pragma module_name = "?__close"
int __close(int handle)
{
if (handle == _LLIO_STDOUT ||
handle == _LLIO_STDERR ||
handle == _LLIO_STDIN)
return _LLIO_ERROR;
#ifdef DFS_USING_POSIX
return close(handle);
#else
LOG_W(_WARNING_WITHOUT_FS);
return _LLIO_ERROR;
#endif /* DFS_USING_POSIX */
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-28 Bernard first version
*/
#include <rtthread.h>
#include <LowLevelIOInterface.h>
#include <unistd.h>
#include <compiler_private.h>
#define DBG_TAG "dlib.syscall.lseek"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
/*
* The "__lseek" function makes the next file operation (__read or
* __write) act on a new location. The parameter "whence" specifies
* how the "offset" parameter should be interpreted according to the
* following table:
*
* 0 (=SEEK_SET) - Goto location "offset".
* 1 (=SEEK_CUR) - Go "offset" bytes from the current location.
* 2 (=SEEK_END) - Go to "offset" bytes from the end.
*
* This function should return the current file position, or -1 on
* failure.
*/
#pragma module_name = "?__lseek"
long __lseek(int handle, long offset, int whence)
{
if (handle == _LLIO_STDOUT ||
handle == _LLIO_STDERR ||
handle == _LLIO_STDIN)
return _LLIO_ERROR;
#ifdef DFS_USING_POSIX
return lseek(handle, offset, whence);
#else
LOG_W(_WARNING_WITHOUT_FS);
return _LLIO_ERROR;
#endif /* DFS_USING_POSIX */
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-28 Bernard first version
* 2021-11-13 Meco Man implement no-heap warning
*/
#include <rtthread.h>
#include <stddef.h>
#ifndef RT_USING_HEAP
#define DBG_TAG "dlib.syscall.mem"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#define _NO_HEAP_ERROR() do{LOG_E("Please enable RT_USING_HEAP");\
RT_ASSERT(0);\
}while(0)
#endif /* RT_USING_HEAP */
void *malloc(size_t n)
{
#ifdef RT_USING_HEAP
return rt_malloc(n);
#else
_NO_HEAP_ERROR();
return RT_NULL;
#endif
}
void *realloc(void *rmem, size_t newsize)
{
#ifdef RT_USING_HEAP
return rt_realloc(rmem, newsize);
#else
_NO_HEAP_ERROR();
return RT_NULL;
#endif
}
void *calloc(size_t nelem, size_t elsize)
{
#ifdef RT_USING_HEAP
return rt_calloc(nelem, elsize);
#else
_NO_HEAP_ERROR();
return RT_NULL;
#endif
}
void free(void *rmem)
{
#ifdef RT_USING_HEAP
rt_free(rmem);
#else
_NO_HEAP_ERROR();
#endif
}

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-28 Bernard first version
*/
#include <rtthread.h>
#include <LowLevelIOInterface.h>
#include <fcntl.h>
#include <compiler_private.h>
#define DBG_TAG "dlib.syscall.open"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
/*
* The "__open" function opens the file named "filename" as specified
* by "mode".
*/
#pragma module_name = "?__open"
int __open(const char *filename, int mode)
{
#ifdef DFS_USING_POSIX
int handle;
int open_mode = O_RDONLY;
if (mode & _LLIO_CREAT)
{
open_mode |= O_CREAT;
/* Check what we should do with it if it exists. */
if (mode & _LLIO_APPEND)
{
/* Append to the existing file. */
open_mode |= O_APPEND;
}
if (mode & _LLIO_TRUNC)
{
/* Truncate the existsing file. */
open_mode |= O_TRUNC;
}
}
if (mode & _LLIO_TEXT)
{
/* we didn't support text mode */
}
switch (mode & _LLIO_RDWRMASK)
{
case _LLIO_RDONLY:
break;
case _LLIO_WRONLY:
open_mode |= O_WRONLY;
break;
case _LLIO_RDWR:
/* The file should be opened for both reads and writes. */
open_mode |= O_RDWR;
break;
default:
return _LLIO_ERROR;
}
handle = open(filename, open_mode, 0);
if (handle < 0)
{
return _LLIO_ERROR;
}
return handle;
#else
LOG_W(_WARNING_WITHOUT_FS);
return _LLIO_ERROR;
#endif /* DFS_USING_POSIX */
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-28 Bernard first version
*/
#include <rtthread.h>
#include <LowLevelIOInterface.h>
#include <unistd.h>
#ifdef RT_USING_POSIX_STDIO
#include "libc.h"
#endif /* RT_USING_POSIX_STDIO */
#include <compiler_private.h>
#define DBG_TAG "dlib.syscall.read"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
/*
* The "__read" function reads a number of bytes, at most "size" into
* the memory area pointed to by "buffer". It returns the number of
* bytes read, 0 at the end of the file, or _LLIO_ERROR if failure
* occurs.
*
* The template implementation below assumes that the application
* provides the function "MyLowLevelGetchar". It should return a
* character value, or -1 on failure.
*/
#pragma module_name = "?__read"
size_t __read(int handle, unsigned char *buf, size_t len)
{
#ifdef DFS_USING_POSIX
int size;
if (handle == _LLIO_STDIN)
{
#ifdef RT_USING_POSIX_STDIO
if (libc_stdio_get_console() < 0)
{
LOG_W("Do not invoke standard input before initializing Compiler");
return 0; /* error, but keep going */
}
return read(STDIN_FILENO, buf, len); /* return the length of the data read */
#else
LOG_W(_WARNING_WITHOUT_STDIO);
return _LLIO_ERROR;
#endif /* RT_USING_POSIX_STDIO */
}
else if ((handle == _LLIO_STDOUT) || (handle == _LLIO_STDERR))
{
return _LLIO_ERROR;
}
size = read(handle, buf, len);
return size; /* return the length of the data read */
#else
LOG_W(_WARNING_WITHOUT_FS);
return _LLIO_ERROR;
#endif /* DFS_USING_POSIX */
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-28 Bernard first version
*/
#include <rtthread.h>
#include <LowLevelIOInterface.h>
#include <unistd.h>
#include <compiler_private.h>
#define DBG_TAG "dlib.syscall.remove"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
/*
* The "remove" function should remove the file named "filename". It
* should return 0 on success and nonzero on failure.
*/
#pragma module_name = "?remove"
int remove(const char *filename)
{
#ifdef DFS_USING_POSIX
return unlink(filename);
#else
LOG_W(_WARNING_WITHOUT_FS);
return _LLIO_ERROR;
#endif /* DFS_USING_POSIX */
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-28 Bernard first version
*/
#include <rtthread.h>
#include <LowLevelIOInterface.h>
#include <unistd.h>
#include <compiler_private.h>
#define DBG_TAG "dlib.syscall.write"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
/*
* The "__write" function should output "size" number of bytes from
* "buffer" in some application-specific way. It should return the
* number of characters written, or _LLIO_ERROR on failure.
*
* If "buffer" is zero then __write should perform flushing of
* internal buffers, if any. In this case "handle" can be -1 to
* indicate that all handles should be flushed.
*
* The template implementation below assumes that the application
* provides the function "MyLowLevelPutchar". It should return the
* character written, or -1 on failure.
*/
#pragma module_name = "?__write"
size_t __write(int handle, const unsigned char *buf, size_t len)
{
#ifdef DFS_USING_POSIX
int size;
#endif /* DFS_USING_POSIX */
if ((handle == _LLIO_STDOUT) || (handle == _LLIO_STDERR))
{
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
rt_device_t console_device;
console_device = rt_console_get_device();
if (console_device)
{
rt_device_write(console_device, 0, buf, len);
}
return len; /* return the length of the data written */
#else
return _LLIO_ERROR;
#endif /* defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) */
}
else if (handle == _LLIO_STDIN)
{
return _LLIO_ERROR;
}
else
{
#ifdef DFS_USING_POSIX
size = write(handle, buf, len);
return size; /* return the length of the data written */
#else
LOG_W(_WARNING_WITHOUT_FS);
return _LLIO_ERROR;
#endif /* DFS_USING_POSIX */
}
}

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-02-13 Meco Man implement exit() and abort()
*/
#include <rtthread.h>
/* for exit() and abort() */
void __exit (int status)
{
extern void __rt_libc_exit(int status);
__rt_libc_exit(status);
while(1);
}

View file

@ -0,0 +1,30 @@
import os
from building import *
from gcc import *
Import('rtconfig')
group = []
musllibc_version = GetMuslVersion(rtconfig)
if musllibc_version:
print('Musl version: ' + musllibc_version)
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
CPPDEFINES = ['RT_USING_MUSLLIBC', 'RT_USING_LIBC']
LIBS = ['c', 'gcc']
LINKFLAGS = ' --specs=kernel.specs'
AddDepend(['RT_USING_MUSLLIBC', 'RT_USING_LIBC'])
group = group + DefineGroup('Compiler', src, depend = [''], CPPPATH = CPPPATH, LINKFLAGS = LINKFLAGS, CPPDEFINES = CPPDEFINES, LIBS = LIBS)
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
group = group + SConscript(os.path.join(d, 'SConscript'))
Return('group')

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-09-02 Meco Man First version
*/
#ifndef __FCNTL_H__
#define __FCNTL_H__
#include_next <fcntl.h>
#ifndef O_DIRECTORY
#define O_DIRECTORY 0x200000
#endif
#ifndef O_BINARY
#define O_BINARY 0x10000
#endif
#endif

View file

@ -0,0 +1,20 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-18 Meco Man first version
*/
#include <rtthread.h>
int *__errno_location(void)
{
return _rt_errno();
}
int *___errno_location(void)
{
return _rt_errno();
}

View file

@ -0,0 +1,4 @@
# NEWLIB (GCC) porting for RT-Thread
https://sourceware.org/newlib/libc.html#Reentrancy

View file

@ -0,0 +1,29 @@
import os
from building import *
from gcc import *
Import('rtconfig')
group = []
newlib_version = GetNewLibVersion(rtconfig)
if newlib_version and not GetDepend('RT_USING_EXTERNAL_LIBC'):
print('Newlib version: ' + newlib_version)
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
CPPDEFINES = ['RT_USING_NEWLIBC', 'RT_USING_LIBC', '_POSIX_C_SOURCE=1'] # identify this is Newlib, and only enable POSIX.1-1990
LIBS = ['c', 'm'] # link libc and libm
AddDepend(['RT_USING_NEWLIBC', 'RT_USING_LIBC'])
group = group + DefineGroup('Compiler', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES, LIBS = LIBS)
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
group = group + SConscript(os.path.join(d, 'SConscript'))
Return('group')

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-09-02 Meco Man First version
*/
#ifndef __FCNTL_H__
#define __FCNTL_H__
#include <sys/_default_fcntl.h>
#ifndef O_DIRECTORY
#define O_DIRECTORY 0x200000
#endif
#ifndef O_BINARY
#define O_BINARY 0x10000
#endif
#endif

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-02-16 Meco Man The first version
*/
#ifndef _MACHTIME_H_
#define _MACHTIME_H_
#include <rtconfig.h>
#define _CLOCKS_PER_SEC_ RT_TICK_PER_SECOND
#endif /* _MACHTIME_H_ */

View file

@ -0,0 +1,338 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-02-11 Meco Man remove _gettimeofday_r() and _times_r()
* 2021-02-13 Meco Man re-implement exit() and abort()
* 2021-02-21 Meco Man improve and beautify syscalls
* 2021-02-24 Meco Man fix bug of _isatty_r()
*/
#include <reent.h>
#include <rtthread.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/errno.h>
#include <sys/stat.h>
#ifdef RT_USING_POSIX_STDIO
#include "libc.h"
#endif /* RT_USING_POSIX_STDIO */
#ifdef RT_USING_MODULE
#include <dlmodule.h>
#endif /* RT_USING_MODULE */
#include <compiler_private.h>
#define DBG_TAG "newlib.syscalls"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#ifdef RT_USING_HEAP /* Memory routine */
void *_malloc_r(struct _reent *ptr, size_t size)
{
void* result;
result = (void*)rt_malloc(size);
if (result == RT_NULL)
{
ptr->_errno = ENOMEM;
}
return result;
}
void *_realloc_r(struct _reent *ptr, void *old, size_t newlen)
{
void* result;
result = (void*)rt_realloc(old, newlen);
if (result == RT_NULL)
{
ptr->_errno = ENOMEM;
}
return result;
}
void *_calloc_r(struct _reent *ptr, size_t size, size_t len)
{
void* result;
result = (void*)rt_calloc(size, len);
if (result == RT_NULL)
{
ptr->_errno = ENOMEM;
}
return result;
}
void _free_r(struct _reent *ptr, void *addr)
{
rt_free(addr);
}
#else
void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr)
{
LOG_E("Please enable RT_USING_HEAP");
RT_ASSERT(0);
return RT_NULL;
}
#endif /*RT_USING_HEAP*/
void __libc_init_array(void)
{
/* we not use __libc init_aray to initialize C++ objects */
/* __libc_init_array is ARM code, not Thumb; it will cause a hardfault. */
}
/* Reentrant versions of system calls. */
#ifndef _REENT_ONLY
int *__errno(void)
{
return _rt_errno();
}
#endif
int _getpid_r(struct _reent *ptr)
{
return 0;
}
int _close_r(struct _reent *ptr, int fd)
{
#ifdef DFS_USING_POSIX
return close(fd);
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
ptr->_errno = ENOTSUP;
return -1;
#endif /* DFS_USING_POSIX */
}
int _execve_r(struct _reent *ptr, const char * name, char *const *argv, char *const *env)
{
ptr->_errno = ENOTSUP;
return -1;
}
int _fcntl_r(struct _reent *ptr, int fd, int cmd, int arg)
{
ptr->_errno = ENOTSUP;
return -1;
}
int _fork_r(struct _reent *ptr)
{
ptr->_errno = ENOTSUP;
return -1;
}
int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat)
{
ptr->_errno = ENOTSUP;
return -1;
}
int _isatty_r(struct _reent *ptr, int fd)
{
if (fd >=0 && fd < 3)
{
return 1;
}
else
{
return 0;
}
}
int _kill_r(struct _reent *ptr, int pid, int sig)
{
ptr->_errno = ENOTSUP;
return -1;
}
int _link_r(struct _reent *ptr, const char *old, const char *new)
{
ptr->_errno = ENOTSUP;
return -1;
}
int _wait_r(struct _reent *ptr, int *status)
{
ptr->_errno = ENOTSUP;
return -1;
}
mode_t umask(mode_t mask)
{
return 022;
}
int flock(int fd, int operation)
{
return 0;
}
_off_t _lseek_r(struct _reent *ptr, int fd, _off_t pos, int whence)
{
#ifdef DFS_USING_POSIX
_off_t rc;
rc = lseek(fd, pos, whence);
return rc;
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
ptr->_errno = ENOTSUP;
return -1;
#endif /* DFS_USING_POSIX */
}
int _mkdir_r(struct _reent *ptr, const char *name, int mode)
{
#ifdef DFS_USING_POSIX
int rc;
rc = mkdir(name, mode);
return rc;
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
ptr->_errno = ENOTSUP;
return -1;
#endif /* DFS_USING_POSIX */
}
int _open_r(struct _reent *ptr, const char *file, int flags, int mode)
{
#ifdef DFS_USING_POSIX
int rc;
rc = open(file, flags, mode);
return rc;
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
ptr->_errno = ENOTSUP;
return -1;
#endif /* DFS_USING_POSIX */
}
_ssize_t _read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes)
{
#ifdef DFS_USING_POSIX
_ssize_t rc;
if (fd == STDIN_FILENO)
{
#ifdef RT_USING_POSIX_STDIO
if (libc_stdio_get_console() < 0)
{
LOG_W("Do not invoke standard input before initializing Compiler");
return 0;
}
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_STDIO);
ptr->_errno = ENOTSUP;
return -1;
#endif /* RT_USING_POSIX_STDIO */
}
else if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
{
ptr->_errno = ENOTSUP;
return -1;
}
rc = read(fd, buf, nbytes);
return rc;
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
ptr->_errno = ENOTSUP;
return -1;
#endif /* DFS_USING_POSIX */
}
int _rename_r(struct _reent *ptr, const char *old, const char *new)
{
#ifdef DFS_USING_POSIX
int rc;
rc = rename(old, new);
return rc;
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
ptr->_errno = ENOTSUP;
return -1;
#endif /* DFS_USING_POSIX */
}
int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat)
{
#ifdef DFS_USING_POSIX
int rc;
rc = stat(file, pstat);
return rc;
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
ptr->_errno = ENOTSUP;
return -1;
#endif /* DFS_USING_POSIX */
}
int _unlink_r(struct _reent *ptr, const char *file)
{
#ifdef DFS_USING_POSIX
return unlink(file);
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
ptr->_errno = ENOTSUP;
return -1;
#endif /* DFS_USING_POSIX */
}
_ssize_t _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes)
{
#ifdef DFS_USING_POSIX
_ssize_t rc;
#endif /* DFS_USING_POSIX */
if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
{
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
rt_device_t console;
console = rt_console_get_device();
if (console)
return rt_device_write(console, -1, buf, nbytes);
#else
ptr->_errno = ENOTSUP;
return -1;
#endif /* defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) */
}
else if (fd == STDIN_FILENO)
{
ptr->_errno = ENOTSUP;
return -1;
}
#ifdef DFS_USING_POSIX
rc = write(fd, buf, nbytes);
return rc;
#else
LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
ptr->_errno = ENOTSUP;
return -1;
#endif /* DFS_USING_POSIX */
}
/* for exit() and abort() */
__attribute__ ((noreturn)) void _exit (int status)
{
extern void __rt_libc_exit(int status);
__rt_libc_exit(status);
while(1);
}
/*
These functions are implemented and replaced by the 'common/time.c' file
int _gettimeofday_r(struct _reent *ptr, struct timeval *__tp, void *__tzp);
_CLOCK_T_ _times_r(struct _reent *ptr, struct tms *ptms);
*/

View file

@ -0,0 +1,8 @@
# PICOLIBC (LLVM-ARM) porting for RT-Thread
https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm
https://github.com/picolibc/picolibc

View file

@ -0,0 +1,29 @@
import os
from building import *
from llvm_arm import *
Import('rtconfig')
group = []
picolibc_version = GetPicoLibcVersion(rtconfig)
if picolibc_version and not GetDepend('RT_USING_EXTERNAL_LIBC'):
print('PicoLibc version: ' + picolibc_version)
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
CPPDEFINES = ['RT_USING_PICOLIBC', 'RT_USING_LIBC', '_POSIX_C_SOURCE=1', '__PICOLIBC_ERRNO_FUNCTION=pico_get_errno'] # identify this is Newlib, and only enable POSIX.1-1990
# LIBS = ['c', 'm'] # link libc and libm
AddDepend(['RT_USING_PICOLIBC', 'RT_USING_LIBC'])
group = group + DefineGroup('Compiler', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)#, LIBS = LIBS)
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
group = group + SConscript(os.path.join(d, 'SConscript'))
Return('group')

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-05-17 Flybreak the first version
*/
#include <rtthread.h>
int pico_get_errno(void)
{
return rt_get_errno();
}

View file

@ -0,0 +1 @@
This folder provides uniformed header files crossing different compiler platforms, and supports basic standard C library functions, such as memory management and time management, etc.

View file

@ -0,0 +1,15 @@
menuconfig RT_USING_CPLUSPLUS
bool "Enable C++ features"
default n
if RT_USING_CPLUSPLUS
config RT_USING_CPLUSPLUS11
bool "Enable c++11 threading feature support"
default n
select RT_USING_POSIX_FS
select RT_USING_POSIX_STDIO
select RT_USING_PTHREADS
select RT_USING_RTC
endif

View file

@ -0,0 +1,52 @@
# C++ support for RT-Thread #
This is the C++ component in RT-Thread RTOS. In order to support C++ language, this component
implement a basic environment, such as new/delete operators.
Because RT-Thread RTOS is used in embedded system mostly, there are some rules for C++ applications:
1. DOES NOT use exception.
2. DOES NOT use Run-Time Type Information (RTTI).
3. Template is discouraged and it easily causes code text large.
4. Static class variables are discouraged. The time and place to call their constructor function could not be precisely controlled and make multi-threaded programming a nightmare.
5. Multiple inheritance is strongly discouraged, as it can cause intolerable confusion.
About GNU GCC compiler
please add following string in your ld link script:
// in your .text section
PROVIDE(__ctors_start__ = .);
/* old GCC version uses .ctors */
KEEP(*(SORT(.ctors.*)))
KEEP(*(.ctors))
/* new GCC version uses .init_array */
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE(__ctors_end__ = .);
. = ALIGN(4);
// as a standalone section if you use ARM target.
/* The .ARM.exidx section is used for C++ exception handling. */
/* .ARM.exidx is sorted, so has to go in its own output section. */
__exidx_start = .;
ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
/* This is used by the startup in order to initialize the .data secion */
_sidata = .;
} > CODE
__exidx_end = .;
/* .data section which is used for initialized data */
// in your .data section
PROVIDE(__dtors_start__ = .);
KEEP(*(SORT(.dtors.*)))
KEEP(*(.dtors))
PROVIDE(__dtors_end__ = .);
. = ALIGN(4);

View file

@ -0,0 +1,21 @@
# RT-Thread building script for component
from building import *
Import('rtconfig')
cwd = GetCurrentDir()
src = Glob('*.cpp') + Glob('*.c')
CPPPATH = [cwd]
if GetDepend('RT_USING_CPLUSPLUS11'):
src += Glob('cpp11/*.cpp') + Glob('cpp11/*.c')
if rtconfig.PLATFORM in ['armclang']:
src += Glob('cpp11/armclang/*.cpp') + Glob('cpp11/armclang/*.c')
CPPPATH += [cwd + '/cpp11/armclang']
elif rtconfig.PLATFORM in ['gcc']:
src += Glob('cpp11/gcc/*.cpp') + Glob('cpp11/gcc/*.c')
CPPPATH += [cwd + '/cpp11/gcc']
group = DefineGroup('CPlusPlus', src, depend = ['RT_USING_CPLUSPLUS'], CPPPATH = CPPPATH)
Return('group')

View file

@ -0,0 +1,49 @@
# C++ 11 support for RT-Thread
## Features
Here are some features about rt-thread c++11 threading futures.
- Atomic.
- Conditional variables.
- Clocks.
- Future.
- Mutexes.
- Threads.
- TLS.
## How To Use
Note that using C++ 11 in rt-thread requires modifying some of the files in the toolchain. Before modifying the tool, back up the tool chain.
1. Enable c++11 support
![](figures/Snipaste_2021-09-02_16-00-09.png)
2. Download toolchain GCC 10.2.1:
```shell
gcc version 10.2.1 20201103 (release) (GNU Arm Embedded Toolchain 10-2020-q4-major)
```
3. Delete the following files:
```shell
rm -f toolchain/arm-none-eabi/include/c++/10.2.1/thread
rm -f toolchain/arm-none-eabi/include/c++/10.2.1/mutex
rm -f toolchain/arm-none-eabi/include/c++/10.2.1/condition_variable
rm -f toolchain/arm-none-eabi/include/c++/10.2.1/future
rm -f toolchain/arm-none-eabi/include/pthread.h
```
4. Clear the contents of the following files and keep them to prevent compilation failures:
```shell
toolchain/arm-none-eabi/include/sys/_pthreadtypes.h
```
5. Update `rtconfig.py` file. add compilation parameters:
```shell
CXXFLAGS = CFLAGS + ' -std=c++11 -fabi-version=0 -MMD -MP -MF'
```

View file

@ -0,0 +1,48 @@
# cpp 11 support for rt-thread
## 特性
下面是 RT-Thread 支持的 C++ 11 线程特性。
- Atomic.
- Conditional variables.
- Clocks.
- Future.
- Mutexes.
- Threads.
- TLS.
## 如何使用
请注意,在 RT-Thread 中使用 C++ 11需要修改工具链中的部分文件。请在修改之前备份好工具链。
1. 使能 c++11
![](figures/Snipaste_2021-09-02_16-00-09.png)
2. 下载 GCC 工具链
```shell
gcc version 10.2.1 20201103 (release) (GNU Arm Embedded Toolchain 10-2020-q4-major)
```
3. 删除下面的文件
```shell
rm -f toolchain/arm-none-eabi/include/c++/10.2.1/thread
rm -f toolchain/arm-none-eabi/include/c++/10.2.1/mutex
rm -f toolchain/arm-none-eabi/include/c++/10.2.1/condition_variable
rm -f toolchain/arm-none-eabi/include/c++/10.2.1/future
rm -f toolchain/arm-none-eabi/include/pthread.h
```
4. 请清除下面文件的内容,保留文件避免编译失败
```shell
toolchain/arm-none-eabi/include/sys/_pthreadtypes.h
```
5. 更新 `rtconfig.py` 文件,添加 c++ 编译参数:
```shell
CXXFLAGS = CFLAGS + ' -std=c++11 -fabi-version=0 -MMD -MP -MF'
```

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#include <arm-tpl.h>
#include <sys/time.h>
#include <rtthread.h>
extern "C" int __ARM_TPL_clock_realtime(__ARM_TPL_timespec_t* __ts)
{
unsigned int t = std::time(nullptr);
__ts->tv_sec = t;
__ts->tv_nsec = 0;
return 0;
}
extern "C" int __ARM_TPL_clock_monotonic(__ARM_TPL_timespec_t* __ts)
{
unsigned int t = rt_tick_get();
__ts->tv_sec = t / RT_TICK_PER_SECOND;
__ts->tv_nsec = (t %RT_TICK_PER_SECOND) * NANOSECOND_PER_TICK ;
return 0;
}

View file

@ -0,0 +1,178 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#include <arm-tpl.h>
#include "tpl.h"
#include <new>
#include <cstdint>
#include <stdatomic.h>
arm_tpl_cv::arm_tpl_cv()
{
s = rt_sem_create("semxs", 0, RT_IPC_FLAG_PRIO);
if (s == nullptr)
RT_ASSERT(0);
h = rt_sem_create("semxh", 0, RT_IPC_FLAG_PRIO);
if (h == nullptr)
{
rt_sem_delete(s);
RT_ASSERT(0);
}
x = rt_mutex_create("mutx", RT_IPC_FLAG_PRIO);
if (x == nullptr)
{
rt_sem_delete(s);
rt_sem_delete(h);
RT_ASSERT(0);
}
}
arm_tpl_cv::~arm_tpl_cv()
{
rt_mutex_delete(x);
rt_sem_delete(h);
rt_sem_delete(s);
}
void arm_tpl_cv::wait(rt_mutex_t lock, bool recursive)
{
while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0);
rt_sem_release(s);
rt_mutex_release(x);
if (recursive)
rt_mutex_release(lock);
else
rt_mutex_release(lock);
while (rt_sem_take(h, ARM_TPL_MAX_DELAY) != 0);
if (recursive)
while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0);
else
while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0);
}
int arm_tpl_cv::timedwait(rt_mutex_t lock, bool recursive, unsigned int timeout_ms)
{
int result = 0;
while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0);
rt_sem_release(s);
rt_mutex_release(x);
if (recursive)
rt_mutex_release(lock);
else
rt_mutex_release(lock);
if (rt_sem_take(h, rt_tick_from_millisecond(timeout_ms)) != 0)
{
while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0);
if (rt_sem_take(h, 0) != 0)
{
if (rt_sem_take(s, 0) != 0)
result = -1;
else
result = 1;
}
rt_mutex_release(x);
}
if (recursive)
while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0);
else
while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0);
return result;
}
void arm_tpl_cv::signal()
{
while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0);
if (rt_sem_take(s, 0) == 0)
rt_sem_release(h);
rt_mutex_release(x);
}
void arm_tpl_cv::broadcast()
{
while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0);
auto count = s->value;
for (auto i = 0; i < count; i++)
{
while (rt_sem_take(s, ARM_TPL_MAX_DELAY) != 0);
rt_sem_release(h);
}
rt_mutex_release(x);
}
static int check_create(volatile __ARM_TPL_condvar_t *__vcv)
{
if (__vcv->data == 0)
{
uintptr_t cv_new;
cv_new = reinterpret_cast<uintptr_t>(new arm_tpl_cv());
if (cv_new == 0)
{
return -1;
}
uintptr_t cv_null = 0;
if (!atomic_compare_exchange_strong(&__vcv->data, &cv_null, cv_new))
delete reinterpret_cast<arm_tpl_cv *>(cv_new);
}
return 0;
}
extern "C" int __ARM_TPL_condvar_wait(__ARM_TPL_condvar_t *__cv, __ARM_TPL_mutex_t *__m)
{
volatile __ARM_TPL_condvar_t *__vcv = __cv;
if (check_create(__vcv) != 0)
return -1;
struct arm_tpl_mutex_struct *tmutex = (struct arm_tpl_mutex_struct *)(__m->data);
((arm_tpl_cv *) __vcv->data)->wait(tmutex->mutex, tmutex->type == RECURSIVE);
return 0;
}
extern "C" int __ARM_TPL_condvar_timedwait(__ARM_TPL_condvar_t *__cv,
__ARM_TPL_mutex_t *__m,
__ARM_TPL_timespec_t *__ts)
{
volatile __ARM_TPL_condvar_t *__vcv = __cv;
if (check_create(__vcv) != 0)
return -1;
__ARM_TPL_timespec_t now;
if (__ARM_TPL_clock_realtime(&now) != 0)
return -1;
struct arm_tpl_mutex_struct *tmutex = (struct arm_tpl_mutex_struct *)(__m->data);
unsigned int timeout_ms = (__ts->tv_sec - now.tv_sec) * 1000 + (__ts->tv_nsec - now.tv_nsec) / 1000000;
if (((arm_tpl_cv *) __vcv->data)->timedwait(tmutex->mutex, tmutex->type == RECURSIVE, timeout_ms) < 0)
return -1;
return 0;
}
extern "C" int __ARM_TPL_condvar_signal(__ARM_TPL_condvar_t *__cv)
{
volatile __ARM_TPL_condvar_t *__vcv = __cv;
if (__vcv->data != 0)
((arm_tpl_cv *) __vcv->data)->signal();
return 0;
}
extern "C" int __ARM_TPL_condvar_broadcast(__ARM_TPL_condvar_t *__cv)
{
volatile __ARM_TPL_condvar_t *__vcv = __cv;
if (__vcv->data != 0)
((arm_tpl_cv *) __vcv->data)->broadcast();
return 0;
}
extern "C" int __ARM_TPL_condvar_destroy(__ARM_TPL_condvar_t *__cv)
{
volatile __ARM_TPL_condvar_t *__vcv = __cv;
if (__vcv->data != 0)
{
delete (arm_tpl_cv *) __vcv->data;
__vcv->data = 0;
}
return 0;
}

View file

@ -0,0 +1,22 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#include <arm-tpl.h>
extern "C" int __ARM_TPL_execute_once(__ARM_TPL_exec_once_flag *__flag,
void (*__init_routine)(void))
{
if (*__flag == 0)
{
__init_routine();
*__flag = 1;
}
return 0;
}

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#include <arm-tpl.h>
#include <cstdint>
#include <stdatomic.h>
#include "tpl.h"
static int check_create(volatile __ARM_TPL_mutex_t *__vm, bool recursive = false)
{
if (__vm->data == 0)
{
uintptr_t mut_null = 0;
arm_tpl_mutex_struct *mutex_p = (arm_tpl_mutex_struct *)rt_malloc(sizeof(arm_tpl_mutex_struct));
if (mutex_p == nullptr) return -1;
if (recursive)
mutex_p->mutex = rt_mutex_create("mutexx", RT_IPC_FLAG_PRIO);
else
mutex_p->mutex = rt_mutex_create("mutexx", RT_IPC_FLAG_PRIO);
if (mutex_p->mutex == nullptr)
{
rt_free(mutex_p);
return -1;
}
mutex_p->type = recursive ? RECURSIVE : NORMAL;
uintptr_t mut_new = reinterpret_cast<uintptr_t>(mutex_p);
if (!atomic_compare_exchange_strong(&__vm->data, &mut_null, mut_new))
{
rt_mutex_delete(mutex_p->mutex);
rt_free(mutex_p);
}
}
return 0;
}
static int mutexLock(arm_tpl_mutex_struct *mutex_p, rt_tick_t timeOut)
{
if (mutex_p->type == RECURSIVE)
{
if (rt_mutex_take(mutex_p->mutex, timeOut) == 0)
return 0;
}
else
{
if (rt_mutex_take(mutex_p->mutex, timeOut) == 0)
return 0;
}
return -1;
}
static int mutexUnlock(arm_tpl_mutex_struct *mutex_p)
{
if (mutex_p->type == RECURSIVE)
rt_mutex_release(mutex_p->mutex);
else
rt_mutex_release(mutex_p->mutex);
return 0;
}
extern "C" int __ARM_TPL_recursive_mutex_init(__ARM_TPL_mutex_t *__m)
{
volatile __ARM_TPL_mutex_t *__vm = __m;
return check_create(__vm, true);
}
extern "C" int __ARM_TPL_mutex_lock(__ARM_TPL_mutex_t *__m)
{
volatile __ARM_TPL_mutex_t *__vm = __m;
if (check_create(__vm))
return -1;
while (mutexLock((arm_tpl_mutex_struct *)(__vm->data), ARM_TPL_MAX_DELAY) != 0);
return 0;
}
extern "C" int __ARM_TPL_mutex_trylock(__ARM_TPL_mutex_t *__m)
{
volatile __ARM_TPL_mutex_t *__vm = __m;
if (check_create(__vm))
return -1;
return mutexLock((arm_tpl_mutex_struct *)(__vm->data), 0);
}
extern "C" int __ARM_TPL_mutex_unlock(__ARM_TPL_mutex_t *__m)
{
volatile __ARM_TPL_mutex_t *__vm = __m;
return mutexUnlock((arm_tpl_mutex_struct *)(__vm->data));
}
extern "C" int __ARM_TPL_mutex_destroy(__ARM_TPL_mutex_t *__m)
{
volatile __ARM_TPL_mutex_t *__vm = __m;
if (__vm->data != 0)
{
rt_mutex_delete(((arm_tpl_mutex_struct *)(__vm->data))->mutex);
rt_free((void *)(__vm->data));
__vm->data = 0;
}
return 0;
}

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#include <arm-tpl.h>
#include "tpl.h"
#include <cstdio>
#include <pthread.h>
#define CPP11_DEFAULT_ID_OFFSET 1
extern "C" int __ARM_TPL_thread_create(__ARM_TPL_thread_t *__t,
void *(*__func)(void *),
void *__arg)
{
int ret = 0;
pthread_t pid;
ret = pthread_create(&pid, RT_NULL, __func, __arg);
if (ret == 0)
{
__t->data = (std::uintptr_t)pid + CPP11_DEFAULT_ID_OFFSET;
return 0;
}
return -1;
}
extern "C" int __ARM_TPL_thread_id_compare(__ARM_TPL_thread_id __tid1,
__ARM_TPL_thread_id __tid2)
{
if (__tid1 > __tid2)
return 1;
else if (__tid1 < __tid2)
return -1;
else
return 0;
}
extern "C" __ARM_TPL_thread_id __ARM_TPL_thread_get_current_id()
{
return (__ARM_TPL_thread_id)pthread_self();
}
extern "C" __ARM_TPL_thread_id __ARM_TPL_thread_get_id(
const __ARM_TPL_thread_t *__t)
{
return (__ARM_TPL_thread_id)(((pthread_t)__t->data - CPP11_DEFAULT_ID_OFFSET));
}
extern "C" int __ARM_TPL_thread_join(__ARM_TPL_thread_t *__t)
{
pthread_join(((pthread_t)__t->data - CPP11_DEFAULT_ID_OFFSET), RT_NULL);
return 0;
}
extern "C" int __ARM_TPL_thread_detach(__ARM_TPL_thread_t *__t)
{
pthread_detach(((pthread_t)__t->data - CPP11_DEFAULT_ID_OFFSET));
return 0;
}
extern "C" void __ARM_TPL_thread_yield()
{
rt_thread_yield();
}
extern "C" int __ARM_TPL_thread_nanosleep(const __ARM_TPL_timespec_t *__req,
__ARM_TPL_timespec_t *__rem)
{
rt_tick_t tick;
tick = __req->tv_sec * RT_TICK_PER_SECOND + (__req->tv_nsec * RT_TICK_PER_SECOND)/ 1000000000;
rt_thread_delay(tick);
if (__rem)
{
tick = rt_tick_get() - tick;
/* get the passed time */
__rem->tv_sec = tick/RT_TICK_PER_SECOND;
__rem->tv_nsec = (tick%RT_TICK_PER_SECOND) * (1000000000/RT_TICK_PER_SECOND);
}
return 0;
}
extern "C" unsigned __ARM_TPL_thread_hw_concurrency()
{
return 1;
}
extern "C" int __ARM_TPL_tls_create(__ARM_TPL_tls_key *__key,
void (*__at_exit)(void *))
{
pthread_key_t key;
if (pthread_key_create(&key, __at_exit) == 0)
{
*__key = key;
return 0;
}
return -1;
}
extern "C" void *__ARM_TPL_tls_get(__ARM_TPL_tls_key __key)
{
return pthread_getspecific(__key);
}
extern "C" int __ARM_TPL_tls_set(__ARM_TPL_tls_key __key, void *__p)
{
if (pthread_setspecific(__key, (void*)__p) != 0)
{
return -1;
}
return 0;
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#pragma once
#ifndef __cplusplus
void ARMTPLInit();
#else
#include <rtthread.h>
#define ARM_TPL_MAX_DELAY 1000
#define ARM_TPL_THREAD_STACK_SIZE 4096
enum arm_tpl_mutex_type
{
NORMAL,
RECURSIVE,
};
struct arm_tpl_mutex_struct
{
rt_mutex_t mutex;
arm_tpl_mutex_type type;
};
struct arm_tpl_thread_struct
{
rt_thread_t task;
void *(*func)(void *);
void *arg;
rt_sem_t join_sem;
rt_sem_t detach_sem;
};
class arm_tpl_cv
{
public:
arm_tpl_cv();
~arm_tpl_cv();
void wait(rt_mutex_t lock, bool recursive);
int timedwait(rt_mutex_t lock, bool recursive, unsigned int timeout_ms);
void signal();
void broadcast();
private:
rt_sem_t s;
rt_sem_t h;
rt_mutex_t x;
};
#endif

View file

@ -0,0 +1,88 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 peterfan Add copyright header.
*/
#include <rthw.h>
#include <stdint.h>
#include <stdbool.h>
/*
* override gcc builtin atomic function for std::atomic<int64_t>, std::atomic<uint64_t>
* @see https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
*/
uint64_t __atomic_load_8(volatile void *ptr, int memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
rt_base_t level;
uint64_t tmp;
level = rt_hw_interrupt_disable();
tmp = *val_ptr;
rt_hw_interrupt_enable(level);
return tmp;
}
void __atomic_store_8(volatile void *ptr, uint64_t val, int memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
rt_base_t level;
level = rt_hw_interrupt_disable();
*val_ptr = val;
rt_hw_interrupt_enable(level);
}
uint64_t __atomic_exchange_8(volatile void *ptr, uint64_t val, int memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
rt_base_t level;
uint64_t tmp;
level = rt_hw_interrupt_disable();
tmp = *val_ptr;
*val_ptr = val;
rt_hw_interrupt_enable(level);
return tmp;
}
bool __atomic_compare_exchange_8(volatile void *ptr, volatile void *expected, uint64_t desired, bool weak, int success_memorder, int failure_memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
volatile uint64_t *expected_ptr = (volatile uint64_t *)expected;
rt_base_t level;
bool exchanged;
level = rt_hw_interrupt_disable();
if (*val_ptr == *expected_ptr)
{
*val_ptr = desired;
exchanged = true;
}
else
{
*expected_ptr = *val_ptr;
exchanged = false;
}
rt_hw_interrupt_enable(level);
return exchanged;
}
#define __atomic_fetch_op_8(OPNAME, OP) \
uint64_t __atomic_fetch_##OPNAME##_8(volatile void *ptr, uint64_t val, int memorder) {\
volatile uint64_t* val_ptr = (volatile uint64_t*)ptr;\
rt_base_t level;\
uint64_t tmp;\
level = rt_hw_interrupt_disable();\
tmp = *val_ptr;\
*val_ptr OP##= val;\
rt_hw_interrupt_enable(level);\
return tmp;\
}
__atomic_fetch_op_8(add, +)
__atomic_fetch_op_8(sub, -)
__atomic_fetch_op_8( and, &)
__atomic_fetch_op_8( or, |)
__atomic_fetch_op_8(xor, ^)

View file

@ -0,0 +1,208 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 peterfan Add copyright header.
*/
/* ===---------- emutls.c - Implements __emutls_get_address ---------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*/
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
extern int pthread_key_create(pthread_key_t *key, void (*destructor)(void *));
extern int pthread_key_delete(pthread_key_t key);
extern void *pthread_getspecific(pthread_key_t key);
extern int pthread_setspecific(pthread_key_t key, const void *value);
/* Default is not to use posix_memalign, so systems like Android
* can use thread local data without heavier POSIX memory allocators.
*/
#ifndef EMUTLS_USE_POSIX_MEMALIGN
#define EMUTLS_USE_POSIX_MEMALIGN 0
#endif
/* For every TLS variable xyz,
* there is one __emutls_control variable named __emutls_v.xyz.
* If xyz has non-zero initial value, __emutls_v.xyz's "value"
* will point to __emutls_t.xyz, which has the initial value.
*/
typedef struct __emutls_control
{
size_t size; /* size of the object in bytes */
size_t align; /* alignment of the object in bytes */
union
{
uintptr_t index; /* data[index-1] is the object address */
void *address; /* object address, when in single thread env */
} object;
void *value; /* null or non-zero initial value for the object */
} __emutls_control;
static __inline void *emutls_memalign_alloc(size_t align, size_t size)
{
void *base;
#if EMUTLS_USE_POSIX_MEMALIGN
if (posix_memalign(&base, align, size) != 0)
abort();
#else
#define EXTRA_ALIGN_PTR_BYTES (align - 1 + sizeof(void *))
char *object;
if ((object = (char *)malloc(EXTRA_ALIGN_PTR_BYTES + size)) == NULL)
abort();
base = (void *)(((uintptr_t)(object + EXTRA_ALIGN_PTR_BYTES)) & ~(uintptr_t)(align - 1));
((void **)base)[-1] = object;
#endif
return base;
}
static __inline void emutls_memalign_free(void *base)
{
#if EMUTLS_USE_POSIX_MEMALIGN
free(base);
#else
/* The mallocated address is in ((void**)base)[-1] */
free(((void **)base)[-1]);
#endif
}
/* Emulated TLS objects are always allocated at run-time. */
static __inline void *emutls_allocate_object(__emutls_control *control)
{
size_t size = control->size;
size_t align = control->align;
if (align < sizeof(void *))
align = sizeof(void *);
/* Make sure that align is power of 2. */
if ((align & (align - 1)) != 0)
abort();
void *base = emutls_memalign_alloc(align, size);
if (control->value)
memcpy(base, control->value, size);
else
memset(base, 0, size);
return base;
}
static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER;
static size_t emutls_num_object = 0; /* number of allocated TLS objects */
typedef struct emutls_address_array
{
uintptr_t size; /* number of elements in the 'data' array */
void *data[];
} emutls_address_array;
static pthread_key_t emutls_pthread_key;
static void emutls_key_destructor(void *ptr)
{
emutls_address_array *array = (emutls_address_array *)ptr;
uintptr_t i;
for (i = 0; i < array->size; ++i)
{
if (array->data[i])
emutls_memalign_free(array->data[i]);
}
free(ptr);
}
static void emutls_init(void)
{
if (pthread_key_create(&emutls_pthread_key, emutls_key_destructor) != 0)
abort();
}
/* Returns control->object.index; set index if not allocated yet. */
static __inline uintptr_t emutls_get_index(__emutls_control *control)
{
uintptr_t index = __atomic_load_n(&control->object.index, __ATOMIC_ACQUIRE);
if (!index)
{
static pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once(&once, emutls_init);
pthread_mutex_lock(&emutls_mutex);
index = control->object.index;
if (!index)
{
index = ++emutls_num_object;
__atomic_store_n(&control->object.index, index, __ATOMIC_RELEASE);
}
pthread_mutex_unlock(&emutls_mutex);
}
return index;
}
/* Updates newly allocated thread local emutls_address_array. */
static __inline void emutls_check_array_set_size(emutls_address_array *array,
uintptr_t size)
{
if (array == NULL)
abort();
array->size = size;
pthread_setspecific(emutls_pthread_key, (void *)array);
}
/* Returns the new 'data' array size, number of elements,
* which must be no smaller than the given index.
*/
static __inline uintptr_t emutls_new_data_array_size(uintptr_t index)
{
/* Need to allocate emutls_address_array with one extra slot
* to store the data array size.
* Round up the emutls_address_array size to multiple of 16.
*/
return ((index + 1 + 15) & ~((uintptr_t)15)) - 1;
}
/* Returns the thread local emutls_address_array.
* Extends its size if necessary to hold address at index.
*/
static __inline emutls_address_array *
emutls_get_address_array(uintptr_t index)
{
emutls_address_array *array = pthread_getspecific(emutls_pthread_key);
if (array == NULL)
{
uintptr_t new_size = emutls_new_data_array_size(index);
array = (emutls_address_array *)calloc(new_size + 1, sizeof(void *));
emutls_check_array_set_size(array, new_size);
}
else if (index > array->size)
{
uintptr_t orig_size = array->size;
uintptr_t new_size = emutls_new_data_array_size(index);
array = (emutls_address_array *)realloc(array, (new_size + 1) * sizeof(void *));
if (array)
memset(array->data + orig_size, 0,
(new_size - orig_size) * sizeof(void *));
emutls_check_array_set_size(array, new_size);
}
return array;
}
void *__emutls_get_address(void *control)
{
uintptr_t index = emutls_get_index((__emutls_control *)control);
emutls_address_array *array = emutls_get_address_array(index);
if (array->data[index - 1] == NULL)
array->data[index - 1] = emutls_allocate_object((__emutls_control *)control);
return array->data[index - 1];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#pragma once
#include <cstdlib>
#include <system_error>
#include <chrono>
#include <ratio>
#include <rtthread.h>
#define RT_USING_CPP_EXCEPTION
inline void throw_system_error(int err, const char *what_msg)
{
#ifdef RT_USING_CPP_EXCEPTION
throw std::system_error(std::error_code(err, std::system_category()), what_msg);
#else
(void)err;
(void)what_msg;
::abort();
#endif
}
class tick_clock
{
public:
typedef clock_t rep;
typedef std::ratio<1, RT_TICK_PER_SECOND> period;
typedef std::chrono::duration<tick_clock::rep, tick_clock::period> duration;
typedef std::chrono::time_point<tick_clock> time_point;
constexpr static bool is_ready = true;
static time_point now();
};
class real_time_clock
{
public:
typedef std::chrono::nanoseconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef std::chrono::time_point<real_time_clock, duration> time_point;
static constexpr bool is_steady = true;
static time_point
now() noexcept;
};

View file

@ -0,0 +1,222 @@
#pragma once
#if __cplusplus < 201103L
#error "C++ version lower than C++11"
#endif
#include <pthread.h>
#include <system_error>
#include <chrono>
#include <utility>
#include <functional>
#include <memory>
#include "__utils.h"
#include "mutex"
#define rt_cpp_cond_var pthread_cond_t
namespace std
{
enum class cv_status
{
no_timeout,
timeout
};
class condition_variable
{
public:
typedef rt_cpp_cond_var *native_handle_type;
condition_variable(const condition_variable &) = delete;
condition_variable &operator=(const condition_variable &) = delete;
condition_variable() = default;
~condition_variable()
{
pthread_cond_destroy(&_m_cond);
}
void wait(unique_lock<mutex> &lock);
void notify_one() noexcept
{
pthread_cond_signal(&_m_cond);
}
void notify_all() noexcept
{
pthread_cond_broadcast(&_m_cond);
}
template <class Predicate>
void wait(unique_lock<mutex> &lock, Predicate pred)
{
while (!pred())
wait(lock);
}
template <class Clock, class Duration>
cv_status wait_until(unique_lock<mutex> &lock,
const chrono::time_point<Clock, Duration> &abs_time)
{
if (!lock.owns_lock())
throw_system_error((int)errc::operation_not_permitted,
"condition_variable::wailt_until: waiting on unlocked lock");
auto secs = chrono::time_point_cast<chrono::seconds>(abs_time);
auto nano_secs = chrono::duration_cast<chrono::nanoseconds>(abs_time - secs);
struct timespec c_abs_time = {static_cast<time_t>(secs.time_since_epoch().count()),
static_cast<long>(nano_secs.count())};
pthread_cond_timedwait(&_m_cond, lock.mutex()->native_handle(), &c_abs_time);
return (Clock::now() < abs_time) ? cv_status::no_timeout : cv_status::timeout;
}
template <class Clock, class Duration, class Predicate>
bool wait_until(unique_lock<mutex> &lock,
const chrono::time_point<Clock, Duration> &abs_time,
Predicate pred)
{
while (!pred())
if (wait_until(lock, abs_time) == cv_status::timeout)
return pred();
return true;
}
template <class Rep, class Period>
cv_status wait_for(unique_lock<mutex> &lock,
const chrono::duration<Rep, Period> &rel_time)
{
return wait_until(lock, real_time_clock::now() + rel_time);
}
template <class Rep, class Period, class Predicate>
bool wait_for(unique_lock<mutex> &lock,
const chrono::duration<Rep, Period> &rel_time,
Predicate pred)
{
return wait_until(lock, real_time_clock::now() + rel_time, std::move(pred));
}
native_handle_type native_handle()
{
return &_m_cond;
}
private:
rt_cpp_cond_var _m_cond = PTHREAD_COND_INITIALIZER;
};
// Lockable is only required to have `lock()` and `unlock()`
class condition_variable_any
{
private:
condition_variable _m_cond;
shared_ptr<mutex> _m_mtx;
// so that Lockable automatically unlocks when waiting and locks after waiting
template <class Lockable>
struct unlocker
{
Lockable &_m_lock;
explicit unlocker(Lockable &lk)
: _m_lock(lk)
{
_m_lock.unlock();
}
~unlocker()
{
_m_lock.lock();
}
unlocker(const unlocker &) = delete;
unlocker &operator=(const unlocker &) = delete;
};
public:
condition_variable_any() : _m_mtx(std::make_shared<mutex>()) {}
~condition_variable_any() = default;
condition_variable_any(const condition_variable_any &) = delete;
condition_variable_any &operator=(const condition_variable_any &) = delete;
void notify_one() noexcept
{
lock_guard<mutex> lk(*_m_mtx);
_m_cond.notify_one();
}
void notify_all() noexcept
{
lock_guard<mutex> lk(*_m_mtx);
_m_cond.notify_all();
}
template <class Lock>
void wait(Lock &lock)
{
shared_ptr<mutex> mut = _m_mtx;
unique_lock<mutex> lk(*mut);
unlocker<Lock> auto_lk(lock); // unlock here
unique_lock<mutex> lk2(std::move(lk));
_m_cond.wait(lk2);
} // mut.unlock(); lock.lock();
template <class Lock, class Predicate>
void wait(Lock &lock, Predicate pred)
{
while (!pred())
wait(lock);
}
template <class Lock, class Clock, class Duration>
cv_status wait_until(Lock &lock,
const chrono::time_point<Clock, Duration> &abs_time)
{
shared_ptr<mutex> mut = _m_mtx;
unique_lock<mutex> lk(*mut);
unlocker<Lock> auto_lk(lock); // unlock here
unique_lock<mutex> lk2(std::move(lk));
return _m_cond.wait_until(lk2, abs_time);
}
template <class Lock, class Clock, class Duration, class Predicate>
bool wait_until(Lock &lock,
const chrono::time_point<Clock, Duration> &abs_time,
Predicate pred)
{
while (!pred())
if (wait_until(lock, abs_time) == cv_status::timeout)
return pred();
return true;
}
template <class Lock, class Rep, class Period>
cv_status wait_for(Lock &lock,
const chrono::duration<Rep, Period> &rel_time)
{
return wait_until(lock, real_time_clock::now() + rel_time);
}
template <class Lock, class Rep, class Period, class Predicate>
bool wait_for(Lock &lock,
const chrono::duration<Rep, Period> &rel_time,
Predicate pred)
{
return wait_until(lock, real_time_clock::now() + rel_time, std::move(pred));
}
};
void notify_all_at_thread_exit(condition_variable &cond, unique_lock<mutex> lk);
} // namespace std

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#include "condition_variable"
namespace std
{
void condition_variable::wait(unique_lock<mutex>& lock)
{
int err = pthread_cond_wait(&_m_cond, lock.mutex()->native_handle());
if (err)
{
throw_system_error(err, "condition_variable::wait: failed to wait on a condition");
}
}
void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
{
// TLS currently not available
mutex* mut = lk.release();
mut->unlock();
cond.notify_all();
}
} // namespace std

View file

@ -0,0 +1,336 @@
#pragma once
#if __cplusplus < 201103L
#error "C++ version lower than C++11"
#endif
#include <mutex>
#include <condition_variable>
#include <memory>
#include <chrono>
#include <cassert>
namespace std {
enum class future_status {
ready,
timeout,
deferred
};
namespace detail {
class shared_state_base {
protected:
typedef void (*deleter_fn)(void *v);
using scoped_lock = std::lock_guard<std::mutex>;
using unique_lock = std::unique_lock<std::mutex>;
public:
explicit shared_state_base(deleter_fn d) : v_(nullptr), d_(d), valid_(true) {}
~shared_state_base() { d_(v_); }
shared_state_base(shared_state_base &&other) = delete;
shared_state_base(const shared_state_base &other) = delete;
shared_state_base &operator=(shared_state_base &&other) = delete;
shared_state_base &operator=(const shared_state_base &other) = delete;
void wait() {
unique_lock lock(m_);
c_.wait(lock, [this] { return has_value(); });
}
template <class Rep, class Period>
std::future_status
wait_for(const std::chrono::duration<Rep, Period> &rel_time) {
unique_lock lock(m_);
if (c_.wait_for(lock, rel_time, [this] { return has_value(); })) {
return std::future_status::ready;
}
return std::future_status::timeout;
}
template <class Clock, class Duration>
std::future_status
wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) {
unique_lock lock(m_);
if (c_.wait_until(lock, abs_time, [this] { return has_value(); })) {
return std::future_status::ready;
}
return std::future_status::timeout;
}
protected:
bool has_value() { return v_ != nullptr; }
protected:
std::mutex m_;
std::condition_variable c_;
void *v_;
deleter_fn d_;
bool valid_;
};
template <typename R>
class shared_state: public shared_state_base {
public:
shared_state() :shared_state_base(default_deleter_) {}
~shared_state() {}
R &get() {
wait();
scoped_lock lock(m_);
assert(valid_);
valid_ = false;
return *(static_cast<R *>(v_));
}
void set(const R &v) {
scoped_lock lock(m_);
assert(!has_value());
v_ = new R(v);
valid_ = true;
c_.notify_one();
}
void set(R &&v) {
scoped_lock lock(m_);
assert(!has_value());
v_ = new R(std::move(v));
valid_ = true;
c_.notify_one();
}
bool valid() {
scoped_lock lock(m_);
return valid_;
}
private:
static void default_deleter_(void *v) { delete static_cast<R *>(v); }
};
} // namespace detail
template <typename R>
class shared_future {
};
template <typename R>
class future {
using state_type = std::shared_ptr<detail::shared_state<R>>;
public:
future() {}
explicit future(const state_type &state) : state_(state) {}
future(future &&other) noexcept: state_(std::move(other.state_)) {
other.state_.reset();
}
future(const future &other) = delete;
~future() {}
future &operator=(future &&other) noexcept {
if (&other != this) {
state_ = std::move(other.state_);
other.state_.reset();
}
return *this;
}
future &operator=(const future &other) = delete;
void swap(future &other) noexcept {
std::swap(state_, other.state_);
}
std::shared_future<R> share() noexcept { return std::shared_future<R>(); }
R get() { return state_->get(); }
bool valid() const noexcept { return state_->valid(); }
void wait() const { state_->wait(); }
template <class Rep, class Period>
std::future_status
wait_for(const std::chrono::duration<Rep, Period> &rel_time) const {
return state_->wait_for(rel_time);
}
template <class Clock, class Duration>
std::future_status
wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) const {
return state_->wait_until(abs_time);
}
private:
state_type state_;
};
template <>
class future<void> {
using state_type = std::shared_ptr<detail::shared_state<int>>;
public:
future() {}
explicit future(const state_type &state) : state_(state) {}
future(future &&other) noexcept: state_(std::move(other.state_)) {
other.state_.reset();
}
future(const future &other) = delete;
~future() {}
future &operator=(future &&other) noexcept {
if (&other != this) {
state_ = std::move(other.state_);
other.state_.reset();
}
return *this;
}
future &operator=(const future &other) = delete;
void swap(future &other) noexcept {
std::swap(state_, other.state_);
}
std::shared_future<void> share() noexcept { return std::shared_future<void>(); }
void get() { state_->get(); }
bool valid() const noexcept { return state_->valid(); }
void wait() const { state_->wait(); }
template <class Rep, class Period>
std::future_status
wait_for(const std::chrono::duration<Rep, Period> &rel_time) const {
return state_->wait_for(rel_time);
}
template <class Clock, class Duration>
std::future_status
wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) const {
return state_->wait_until(abs_time);
}
private:
state_type state_;
};
template <typename R>
class promise {
using state_type = std::shared_ptr<detail::shared_state<R>>;
public:
promise() : state_(new detail::shared_state<R>()) {}
promise(promise &&other) noexcept: state_(std::move(other.state_)) {
other.state_.reset();
}
promise(const promise &other) = delete;
~promise() {}
promise &operator=(promise &&other) noexcept {
if (&other != this) {
state_ = std::move(other.state_);
other.state_.reset();
}
return *this;
}
promise &operator=(const promise &other) = delete;
void swap(promise &other) noexcept {
std::swap(state_, other.state_);
}
std::future<R> get_future() { return std::future<R>(state_); }
void set_value(const R &value) { state_->set(value); }
void set_value(R &&value) { state_->set(std::move(value)); }
void set_value_at_thread_exit(const R &value);
void set_value_at_thread_exit(R &&value);
void set_exception(std::exception_ptr p);
void set_exception_at_thread_exit(std::exception_ptr p);
private:
state_type state_;
};
template <>
class promise<void> {
using state_type = std::shared_ptr<detail::shared_state<int>>;
public:
promise() : state_(new detail::shared_state<int>()) {}
promise(promise &&other) noexcept: state_(std::move(other.state_)) {
other.state_.reset();
}
promise(const promise &other) = delete;
~promise() {}
promise &operator=(promise &&other) noexcept {
if (&other != this) {
state_ = std::move(other.state_);
other.state_.reset();
}
return *this;
}
promise &operator=(const promise &other) = delete;
void swap(promise &other) noexcept {
std::swap(state_, other.state_);
}
std::future<void> get_future() { return std::future<void>(state_); }
void set_value() { state_->set(0); }
void set_value_at_thread_exit();
void set_exception(std::exception_ptr p);
void set_exception_at_thread_exit(std::exception_ptr p);
private:
state_type state_;
};
template <class R>
void swap(std::future<R> &lhs, std::future<R> &rhs) noexcept {
lhs.swap(rhs);
}
template <class R>
void swap(std::promise<R> &lhs, std::promise<R> &rhs) noexcept {
lhs.swap(rhs);
}
} // namespace std

View file

@ -0,0 +1,512 @@
#pragma once
#if __cplusplus < 201103L
#error "C++ version lower than C++11"
#endif
//#if defined(RT_USING_PTHREADS)
#include <pthread.h>
#include <system_error>
#include <chrono>
#include <utility>
#include <functional>
#include "__utils.h"
#define rt_cpp_mutex_t pthread_mutex_t
namespace std
{
// Base class on which to build std::mutex and std::timed_mutex
class __mutex_base
{
protected:
typedef rt_cpp_mutex_t __native_type;
__native_type _m_mutex = PTHREAD_MUTEX_INITIALIZER;
constexpr __mutex_base() noexcept = default;
__mutex_base(const __mutex_base&) = delete;
__mutex_base& operator=(const __mutex_base&) = delete;
};
class mutex : private __mutex_base
{
public:
constexpr mutex() = default;
~mutex() = default;
mutex(const mutex&) = delete;
mutex& operator=(const mutex&) = delete;
void lock()
{
int err = pthread_mutex_lock(&_m_mutex);
if (err)
{
throw_system_error(err, "mutex:lock failed.");
}
}
bool try_lock() noexcept
{
return !pthread_mutex_trylock(&_m_mutex);
}
void unlock() noexcept
{
pthread_mutex_unlock(&_m_mutex);
}
typedef __native_type* native_handle_type;
native_handle_type native_handle()
{
return &_m_mutex;
};
};
inline int __rt_cpp_recursive_mutex_init(rt_cpp_mutex_t* m)
{
pthread_mutexattr_t attr;
int res;
res = pthread_mutexattr_init(&attr);
if (res)
return res;
res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
if (res)
goto attr_cleanup;
res = pthread_mutex_init(m, &attr);
attr_cleanup:
int err = pthread_mutexattr_destroy(&attr);
return res ? res : err;
}
class __recursive_mutex_base
{
protected:
typedef rt_cpp_mutex_t __native_type;
__native_type _m_recursive_mutex;
__recursive_mutex_base(const __recursive_mutex_base&) = delete;
__recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
__recursive_mutex_base()
{
int err = __rt_cpp_recursive_mutex_init(&_m_recursive_mutex);
if (err)
throw_system_error(err, "Recursive mutex failed to construct");
}
~__recursive_mutex_base()
{
pthread_mutex_destroy(&_m_recursive_mutex);
}
};
class recursive_mutex : private __recursive_mutex_base
{
public:
typedef __native_type* native_handle_type;
recursive_mutex() = default;
~recursive_mutex() = default;
recursive_mutex(const recursive_mutex&) = delete;
recursive_mutex& operator=(const recursive_mutex&) = delete;
void lock()
{
int err = pthread_mutex_lock(&_m_recursive_mutex);
if (err)
throw_system_error(err, "recursive_mutex::lock failed");
}
bool try_lock() noexcept
{
return !pthread_mutex_trylock(&_m_recursive_mutex);
}
void unlock() noexcept
{
pthread_mutex_unlock(&_m_recursive_mutex);
}
native_handle_type native_handle()
{ return &_m_recursive_mutex; }
};
#ifdef RT_PTHREAD_TIMED_MUTEX
class timed_mutex;
class recursive_timed_mutex;
#endif // RT_PTHREAD_TIMED_MUTEX
struct defer_lock_t {};
struct try_to_lock_t {};
struct adopt_lock_t {}; // take ownership of a locked mtuex
constexpr defer_lock_t defer_lock { };
constexpr try_to_lock_t try_to_lock { };
constexpr adopt_lock_t adopt_lock { };
template <class Mutex>
class lock_guard
{
public:
typedef Mutex mutex_type;
explicit lock_guard(mutex_type& m) : pm(m) { pm.lock(); }
lock_guard(mutex_type& m, adopt_lock_t) noexcept : pm(m)
{ }
~lock_guard()
{ pm.unlock(); }
lock_guard(lock_guard const&) = delete;
lock_guard& operator=(lock_guard const&) = delete;
private:
mutex_type& pm;
};
template <class Mutex>
class unique_lock
{
public:
typedef Mutex mutex_type;
unique_lock() noexcept : pm(nullptr), owns(false) { }
explicit unique_lock(mutex_type& m)
: pm(std::addressof(m)), owns(false)
{
lock();
owns = true;
}
unique_lock(mutex_type& m, defer_lock_t) noexcept
: pm(std::addressof(m)), owns(false)
{ }
unique_lock(mutex_type& m, try_to_lock_t) noexcept
: pm(std::addressof(m)), owns(pm->try_lock())
{ }
unique_lock(mutex_type& m, adopt_lock_t) noexcept
: pm(std::addressof(m)), owns(true)
{ }
// any lock-involving timed mutex API is currently only for custom implementations
// the standard ones are not available
template <class Clock, class Duration>
unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time) noexcept
: pm(std::addressof(m)), owns(pm->try_lock_until(abs_time))
{ }
template <class Rep, class Period>
unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time) noexcept
: pm(std::addressof(m)), owns(pm->try_lock_for(rel_time))
{ }
~unique_lock()
{
if (owns)
unlock();
}
unique_lock(unique_lock const&) = delete;
unique_lock& operator=(unique_lock const&) = delete;
unique_lock(unique_lock&& u) noexcept
: pm(u.pm), owns(u.owns)
{
u.pm = nullptr;
u.owns = false;
}
unique_lock& operator=(unique_lock&& u) noexcept
{
if (owns)
unlock();
unique_lock(std::move(u)).swap(*this);
u.pm = nullptr;
u.owns = false;
return *this;
}
void lock()
{
if (!pm)
throw_system_error(int(errc::operation_not_permitted),
"unique_lock::lock: references null mutex");
else if (owns)
throw_system_error(int(errc::resource_deadlock_would_occur),
"unique_lock::lock: already locked" );
else {
pm->lock();
owns = true;
}
}
bool try_lock()
{
if (!pm)
throw_system_error(int(errc::operation_not_permitted),
"unique_lock::try_lock: references null mutex");
else if (owns)
throw_system_error(int(errc::resource_deadlock_would_occur),
"unique_lock::try_lock: already locked" );
else {
owns = pm->try_lock();
}
return owns;
}
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
if (!pm)
throw_system_error(int(errc::operation_not_permitted),
"unique_lock::try_lock_for: references null mutex");
else if (owns)
throw_system_error(int(errc::resource_deadlock_would_occur),
"unique_lock::try_lock_for: already locked");
else {
owns = pm->try_lock_for(rel_time);
}
return owns;
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
{
if (!pm)
throw_system_error(int(errc::operation_not_permitted),
"unique_lock::try_lock_until: references null mutex");
else if (owns)
throw_system_error(int(errc::resource_deadlock_would_occur),
"unique_lock::try_lock_until: already locked");
else {
owns = pm->try_lock_until(abs_time);
}
return owns;
}
void unlock()
{
if (!owns)
throw_system_error(int(errc::operation_not_permitted),
"unique_lock::unlock: not locked");
else {
pm->unlock();
owns = false;
}
}
void swap(unique_lock& u) noexcept
{
std::swap(pm, u.pm);
std::swap(owns, u.owns);
}
mutex_type *release() noexcept
{
mutex_type* ret_mutex = pm;
pm = nullptr;
owns = false;
return ret_mutex;
}
bool owns_lock() const noexcept
{ return owns; }
explicit operator bool() const noexcept
{ return owns_lock(); }
mutex_type* mutex() const noexcept
{ return pm; }
private:
mutex_type *pm;
bool owns;
};
template <class Mutex>
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y)
{
x.swap(y);
}
template <class L0, class L1>
int try_lock(L0& l0, L1& l1)
{
unique_lock<L0> u0(l0, try_to_lock); // try to lock the first Lockable
// using unique_lock since we don't want to unlock l0 manually if l1 fails to lock
if (u0.owns_lock())
{
if (l1.try_lock()) // lock the second one
{
u0.release(); // do not let RAII of a unique_lock unlock l0
return -1;
}
else
return 1;
}
return 0;
}
template <class L0, class L1, class L2, class... L3>
int try_lock(L0& l0, L1& l1, L2& l2, L3&... l3)
{
int r = 0;
unique_lock<L0> u0(l0, try_to_lock);
// automatically unlock is done through RAII of unique_lock
if (u0.owns_lock())
{
r = try_lock(l1, l2, l3...);
if (r == -1)
u0.release();
else
++r;
}
return r;
}
template <class L0, class L1, class L2, class ...L3>
void
__lock_first(int i, L0& l0, L1& l1, L2& l2, L3&... l3)
{
while (true)
{
// we first lock the one that is the most difficult to lock
switch (i)
{
case 0:
{
unique_lock<L0> u0(l0);
i = try_lock(l1, l2, l3...);
if (i == -1)
{
u0.release();
return;
}
}
++i;
sched_yield();
break;
case 1:
{
unique_lock<L1> u1(l1);
i = try_lock(l2, l3..., l0);
if (i == -1)
{
u1.release();
return;
}
}
if (i == sizeof...(L3) + 1) // all except l0 are locked
i = 0;
else
i += 2; // since i was two-based above
sched_yield();
break;
default:
__lock_first(i - 2, l2, l3..., l0, l1);
return;
}
}
}
template <class L0, class L1>
void lock(L0& l0, L1& l1)
{
while (true)
{
{
unique_lock<L0> u0(l0);
if (l1.try_lock())
{
u0.release();
break;
}
}
sched_yield();
// wait and try the other way
{
unique_lock<L1> u1(l1);
if (l0.try_lock())
{
u1.release();
break;
}
}
sched_yield();
}
}
template <class L0, class L1, class... L2>
void lock(L0& l0, L1& l1, L2&... l2)
{
__lock_first(0, l0, l1, l2...);
}
struct once_flag
{
constexpr once_flag() noexcept = default;
once_flag(const once_flag&) = delete;
once_flag& operator=(const once_flag&) = delete;
template <class Callable, class... Args>
friend void call_once(once_flag& flag, Callable&& func, Args&&... args);
private:
pthread_once_t _m_once = PTHREAD_ONCE_INIT;
};
mutex& get_once_mutex();
extern function<void()> once_functor;
extern void set_once_functor_lock_ptr(unique_lock<mutex>*);
extern "C" void once_proxy(); // passed into pthread_once
template <class Callable, class... Args>
void call_once(once_flag& flag, Callable&& func, Args&&... args)
{
// use a lock to ensure the call to the functor
// is exclusive to only the first calling thread
unique_lock<mutex> functor_lock(get_once_mutex());
auto call_wrapper = std::bind(std::forward<Callable>(func), std::forward<Args>(args)...);
once_functor = [&]() { call_wrapper(); };
set_once_functor_lock_ptr(&functor_lock); // so as to unlock when actually calling
int err = pthread_once(&flag._m_once, &once_proxy);
if (functor_lock)
set_once_functor_lock_ptr(nullptr);
if (err)
throw_system_error(err, "call_once failed");
}
}
//#endif //(RT_USING_PTHREADS)

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#include "mutex"
namespace std
{
// use a set of global and static objects
// a proxy function to pthread_once
function<void()> once_functor;
mutex& get_once_mutex()
{
static mutex once_mutex;
return once_mutex;
}
inline unique_lock<mutex>*& get_once_functor_lock_ptr()
{
static unique_lock<mutex>* once_functor_mutex_ptr = nullptr;
return once_functor_mutex_ptr;
}
void set_once_functor_lock_ptr(unique_lock<mutex>* m_ptr)
{
get_once_functor_lock_ptr() = m_ptr;
}
extern "C"
{
void once_proxy()
{
// need to first transfer the functor's ownership so as to call it
function<void()> once_call = std::move(once_functor);
// no need to hold the lock anymore
unique_lock<mutex>* lock_ptr = get_once_functor_lock_ptr();
get_once_functor_lock_ptr() = nullptr;
lock_ptr->unlock();
once_call();
}
}
}

View file

@ -0,0 +1,239 @@
#pragma once
#if __cplusplus < 201103L
#error "C++ version lower than C++11"
#endif
//#if defined(RT_USING_PTHREADS)
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
#include <rtthread.h>
#include <cstddef>
#include <cerrno>
#include <ostream>
#include <functional>
#include <utility>
#include <chrono>
#include <memory>
#define rt_cpp_thread_t pthread_t
#ifndef PTHREAD_NUM_MAX
#define PTHREAD_NUM_MAX 32
#endif
#define CPP_UNJOINABLE_THREAD PTHREAD_NUM_MAX
namespace std
{
#define __STDCPP_THREADS__ __cplusplus
class thread
{
public:
typedef rt_cpp_thread_t native_handle_type;
struct invoker_base;
typedef shared_ptr<invoker_base> invoker_base_ptr;
class id
{
// basically a wrapper around native_handle_type
native_handle_type __cpp_thread_t;
public:
id() noexcept : __cpp_thread_t(CPP_UNJOINABLE_THREAD) {}
explicit id(native_handle_type hid)
: __cpp_thread_t(hid) {}
private:
friend class thread;
friend class hash<thread::id>;
friend bool operator==(thread::id x, thread::id y) noexcept;
friend bool operator<(thread::id x, thread::id y) noexcept;
template <class charT, class traits>
friend basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& out, thread::id id);
};
thread() noexcept = default;
thread(const thread&) = delete;
thread& operator=(const thread&) = delete;
~thread();
template <class F, class ...Args>
explicit thread(F&& f, Args&&... args)
{
start_thread(make_invoker_ptr(std::bind(
std::forward<F>(f),
std::forward<Args>(args)...
)));
}
thread(thread&& t) noexcept
{
swap(t);
}
thread& operator=(thread&& t) noexcept
{
if (joinable())
terminate();
swap(t);
return *this;
}
// member functions
void swap(thread& t) noexcept
{
std::swap(_m_thr, t._m_thr);
}
bool joinable() const noexcept
{
return (_m_thr.__cpp_thread_t < PTHREAD_NUM_MAX);
}
void join();
void detach();
id get_id() const noexcept { return _m_thr; }
native_handle_type native_handle() { return _m_thr.__cpp_thread_t; }
// static members
static unsigned hardware_concurrency() noexcept;
private:
id _m_thr;
void start_thread(invoker_base_ptr b);
public:
struct invoker_base
{
invoker_base_ptr this_ptr;
virtual ~invoker_base() = default;
virtual void invoke() = 0;
};
template<typename Callable>
struct invoker : public invoker_base
{
Callable func;
invoker(Callable&& F) : func(std::forward<Callable>(F)) { }
void invoke() { func(); }
};
template <typename Callable>
shared_ptr<invoker<Callable>> make_invoker_ptr(Callable&& F)
{
return std::make_shared<invoker<Callable>>(std::forward<Callable>(F));
}
};
inline void swap(thread& x, thread& y) noexcept
{
x.swap(y);
}
inline bool operator==(thread::id x, thread::id y) noexcept
{
// From POSIX for pthread_equal:
//"If either t1 or t2 are not valid thread IDs, the behavior is undefined."
return x.__cpp_thread_t == y.__cpp_thread_t;
}
inline bool operator!=(thread::id x, thread::id y) noexcept
{
return !(x == y);
}
inline bool operator<(thread::id x, thread::id y) noexcept
{
return x.__cpp_thread_t < y.__cpp_thread_t;
}
inline bool operator<=(thread::id x, thread::id y) noexcept
{
return !(y < x);
}
inline bool operator>(thread::id x, thread::id y) noexcept
{
return !(x <= y);
}
inline bool operator>=(thread::id x, thread::id y) noexcept
{
return !(x < y);
}
template <class charT, class traits>
inline basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& out, thread::id id)
{
if (id == thread::id()) // id is invalid, representing no pthread
out << "thread::id of a non-executing thread";
else
out << id.__cpp_thread_t;
return out;
}
template <>
struct hash<thread::id>
{
typedef size_t result_type;
typedef thread::id argument_type;
size_t operator()(const thread::id& id) const noexcept
{
return hash<rt_cpp_thread_t>()(id.__cpp_thread_t);
}
};
namespace this_thread
{
inline thread::id get_id() noexcept
{
return thread::id(pthread_self());
}
inline void yield() noexcept
{
sched_yield();
}
template <class Rep, class Period>
inline void sleep_for(const chrono::duration<Rep, Period>& rel_time)
{
if (rel_time <= rel_time.zero()) // less than zero, no need to sleep
return;
auto milli_secs = chrono::duration_cast<chrono::milliseconds>(rel_time);
// the precision is limited by rt-thread thread API
rt_thread_mdelay(milli_secs.count());
}
template <class Clock, class Duration>
inline void sleep_until(const chrono::time_point<Clock, Duration>& abs_time)
{
auto now = Clock::now();
if (abs_time > now)
sleep_for(abs_time - now);
}
}
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#include "thread"
#include "__utils.h"
#define _RT_NPROCS 0
namespace std
{
extern "C"
{
static void* execute_native_thread_routine(void *p)
{
thread::invoker_base* t = static_cast<thread::invoker_base*>(p);
thread::invoker_base_ptr local;
local.swap(t->this_ptr); // tranfer the ownership of the invoker into the thread entry
local->invoke();
return NULL;
}
}
void thread::start_thread(invoker_base_ptr b)
{
auto raw_ptr = b.get();
// transfer the ownership of the invoker to the new thread
raw_ptr->this_ptr = std::move(b);
int err = pthread_create(&_m_thr.__cpp_thread_t, NULL,
&execute_native_thread_routine, raw_ptr);
if (err)
{
raw_ptr->this_ptr.reset();
throw_system_error(err, "Failed to create a thread");
}
}
thread::~thread()
{
if (joinable()) // when either not joined or not detached
terminate();
}
void thread::join()
{
int err = EINVAL;
if (joinable())
err = pthread_join(native_handle(), NULL);
if (err)
{
throw_system_error(err, "thread::join failed");
}
_m_thr = id();
}
void thread::detach()
{
int err = EINVAL;
if (joinable())
err = pthread_detach(native_handle());
if (err)
{
throw_system_error(err, "thread::detach failed");
}
_m_thr = id();
}
// TODO: not yet actually implemented.
// The standard states that the returned value should only be considered a hint.
unsigned thread::hardware_concurrency() noexcept
{
int __n = _RT_NPROCS;
if (__n < 0)
__n = 0;
return __n;
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#include "__utils.h"
#include <sys/time.h>
tick_clock::time_point tick_clock::now()
{
tick_clock::rep cur_tk = clock();
tick_clock::duration cur_time(cur_tk);
return tick_clock::time_point(cur_time);
}
real_time_clock::time_point real_time_clock::now() noexcept
{
timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
return time_point(duration(std::chrono::seconds(tp.tv_sec))
+ std::chrono::nanoseconds(tp.tv_nsec));
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 flybreak the first version.
*/
#include <pthread.h>
#include <cstdlib>
typedef void (*destructor) (void *);
extern "C"
int __cxa_thread_atexit_impl(destructor dtor, void* obj, void* dso_symbol)
{
pthread_key_t key_tmp;
if (pthread_key_create(&key_tmp, dtor) != 0)
abort();
pthread_setspecific(key_tmp, obj);
return 0;
}
#if defined(__GNUC__) && !defined(__ARMCC_VERSION)/*GCC*/
#include <cxxabi.h>
extern"C"
int __cxxabiv1::__cxa_thread_atexit(destructor dtor, void *obj, void *dso_handle)
{
return __cxa_thread_atexit_impl(dtor, obj, dso_handle);
}
#endif

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "cxx_mutex.h"
using namespace rtthread;
Mutex::Mutex(const char *name)
{
rt_mutex_init(&mID, name, RT_IPC_FLAG_PRIO);
}
bool Mutex::lock(int32_t millisec)
{
rt_int32_t tick;
if (millisec < 0)
tick = -1;
else
tick = rt_tick_from_millisecond(millisec);
return rt_mutex_take(&mID, tick) == RT_EOK;
}
bool Mutex::trylock()
{
return lock(0);
}
void Mutex::unlock()
{
rt_mutex_release(&mID);
}
Mutex::~Mutex()
{
rt_mutex_detach(&mID);
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "cxx_semaphore.h"
using namespace rtthread;
Semaphore::Semaphore(const char *name, int32_t count)
{
rt_sem_init(&mID, name, count, RT_IPC_FLAG_FIFO);
}
bool Semaphore::wait(int32_t millisec)
{
rt_int32_t tick;
if (millisec < 0)
tick = -1;
else
tick = rt_tick_from_millisecond(millisec);
return rt_sem_take(&mID, tick) == RT_EOK;
}
void Semaphore::release(void)
{
rt_sem_release(&mID);
}
Semaphore::~Semaphore()
{
rt_sem_detach(&mID);
}

View file

@ -0,0 +1,117 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "cxx_thread.h"
using namespace rtthread;
Thread::Thread(rt_uint32_t stack_size,
rt_uint8_t priority,
rt_uint32_t tick,
const char *name)
: _entry(RT_NULL), _param(RT_NULL), started(false)
{
rt_event_init(&_event, name, 0);
_thread = rt_thread_create(name,
(thread_func_t)func,
this,
stack_size,
priority,
tick);
}
Thread::Thread(void (*entry)(void *p),
void *p,
rt_uint32_t stack_size,
rt_uint8_t priority,
rt_uint32_t tick,
const char *name)
: _entry(entry), _param(p), started(false)
{
rt_event_init(&_event, name, 0);
_thread = rt_thread_create(name,
(thread_func_t)func,
this,
stack_size,
priority,
tick);
}
Thread::~Thread()
{
rt_event_detach(&_event);
rt_thread_delete(_thread);
}
bool Thread::start()
{
if (rt_thread_startup(_thread) == RT_EOK)
{
started = true;
}
return started;
}
void Thread::sleep(int32_t millisec)
{
rt_int32_t tick;
if (millisec < 0)
tick = 1;
else
tick = rt_tick_from_millisecond(millisec);
rt_thread_delay(tick);
}
void Thread::func(Thread *pThis)
{
if (pThis->_entry != RT_NULL)
{
pThis->_entry(pThis->_param);
}
else
{
pThis->run(pThis->_param);
}
rt_event_send(&pThis->_event, 1);
}
void Thread::run(void *parameter)
{
/* please overload this method */
}
rt_err_t Thread::wait(int32_t millisec)
{
return join(millisec);
}
rt_err_t Thread::join(int32_t millisec)
{
if (started)
{
rt_int32_t tick;
if (millisec < 0)
tick = -1;
else
tick = rt_tick_from_millisecond(millisec);
return rt_event_recv(&_event, 1, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, tick, RT_NULL);
}
else
{
return -RT_ENOSYS;
}
}

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-03-07 Bernard Add copyright header.
*/
#include <rtthread.h>
#include "cxx_crt.h"
void *operator new(size_t size)
{
return rt_malloc(size);
}
void *operator new[](size_t size)
{
return rt_malloc(size);
}
void operator delete(void *ptr)
{
rt_free(ptr);
}
void operator delete[](void *ptr)
{
return rt_free(ptr);
}
void __cxa_pure_virtual(void)
{
rt_kprintf("Illegal to call a pure virtual function.\n");
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-03-07 Bernard Add copyright header.
*/
#ifndef CRT_H_
#define CRT_H_
#include <inttypes.h>
#include <stdlib.h>
void *operator new(size_t size);
void *operator new[](size_t size);
void operator delete(void * ptr);
void operator delete[](void *ptr);
extern "C" void __cxa_pure_virtual(void);
extern "C" int cplusplus_system_init(void);
#endif

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2014-12-03 Bernard Add copyright header.
* 2014-12-29 Bernard Add cplusplus initialization for ARMCC.
* 2016-06-28 Bernard Add _init/_fini routines for GCC.
* 2016-10-02 Bernard Add WEAK for cplusplus_system_init routine.
*/
#include <rtthread.h>
#if defined(__ARMCC_VERSION)
extern void $Super$$__cpp_initialize__aeabi_(void);
/* we need to change the cpp_initialize order */
rt_weak void $Sub$$__cpp_initialize__aeabi_(void)
{
/* empty */
}
#elif defined(__GNUC__) && !defined(__CS_SOURCERYGXX_MAJ__)
/* The _init()/_fini() routines has been defined in codesourcery g++ lite */
rt_weak void _init()
{
}
rt_weak void _fini()
{
}
rt_weak void *__dso_handle = 0;
#endif
rt_weak int cplusplus_system_init(void)
{
#if defined(__ARMCC_VERSION)
/* If there is no SHT$$INIT_ARRAY, calling
* $Super$$__cpp_initialize__aeabi_() will cause fault. At least until Keil5.12
* the problem still exists. So we have to initialize the C++ runtime by ourself.
*/
typedef void PROC();
extern const unsigned long SHT$$INIT_ARRAY$$Base[];
extern const unsigned long SHT$$INIT_ARRAY$$Limit[];
const unsigned long *base = SHT$$INIT_ARRAY$$Base;
const unsigned long *lim = SHT$$INIT_ARRAY$$Limit;
for (; base != lim; base++)
{
PROC *proc = (PROC *)((const char *)base + *base);
(*proc)();
}
#elif defined(__GNUC__)
typedef void(*pfunc)();
extern pfunc __ctors_start__[];
extern pfunc __ctors_end__[];
pfunc *p;
for (p = __ctors_start__; p < __ctors_end__; p++)
(*p)();
#endif
return 0;
}
INIT_COMPONENT_EXPORT(cplusplus_system_init);

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016/10/1 Bernard The first version
*/
#pragma once
#include <stdint.h>
#include <string.h>
namespace rtthread {
class Lock
{
public:
Lock(Mutex& mutex) : m(mutex) {m.lock();}
~Lock() {m.unlock();}
protected:
Mutex &m;
};
}

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016/10/1 Bernard The first version
*/
#pragma once
#include <stdint.h>
#include <string.h>
#include <rtthread.h>
namespace rtthread {
/**
* The Mail class allow to control, send, receive, or wait for mail.
* A mail is a memory block that is send to a thread or interrupt service routine.
* @param T data type of a single message element.
* @param queue_sz maximum number of messages in queue.
*/
template<typename T, uint32_t queue_sz>
class Mail {
public:
/** Create and Initialise Mail queue. */
Mail(const char *name = "")
{
rt_mb_init(&mID, name, mPool, queue_sz, RT_IPC_FLAG_FIFO);
}
~Mail()
{
rt_mb_detach(&mID);
}
/** Put a mail in the queue.
@param mptr memory block previously allocated with Mail::alloc or Mail::calloc.
@return status code that indicates the execution status of the function.
*/
bool put(T *mptr, int32_t millisec = 0)
{
rt_int32_t tick;
if (millisec < 0)
tick = -1;
else
tick = rt_tick_from_millisecond(millisec);
return rt_mb_send_wait(&mID, (rt_ubase_t)mptr, tick) == RT_EOK;
}
/** Get a mail from a queue.
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
@return event that contains mail information or error code.
*/
T* get(int32_t millisec = -1)
{
T *t = NULL;
rt_int32_t tick;
if (millisec < 0)
tick = -1;
else
tick = rt_tick_from_millisecond(millisec);
rt_mb_recv(&mID, &t, tick);
return t;
}
private:
struct rt_mailbox mID;
T* mPool[queue_sz];
};
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016/10/1 Bernard The first version
*/
#pragma once
#include <stdint.h>
#include <rtthread.h>
namespace rtthread {
/** The Mutex class is used to synchronise the execution of threads.
This is for example used to protect access to a shared resource.
*/
class Mutex {
public:
/** Create and Initialize a Mutex object */
Mutex(const char *name = "mutex");
~Mutex();
/** Wait until a Mutex becomes available.
@param millisec timeout value or 0 in case of no time-out. (default: WaitForever)
@return true if the mutex was acquired, false otherwise.
*/
bool lock(int32_t millisec = -1);
/** Try to lock the mutex, and return immediately
@return true if the mutex was acquired, false otherwise.
*/
bool trylock();
/** Unlock the mutex that has previously been locked by the same thread
*/
void unlock();
private:
struct rt_mutex mID;
};
}

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016/10/1 Bernard The first version
*/
#pragma once
#include <stdint.h>
#include <string.h>
#include <rtthread.h>
namespace rtthread {
/**
* The Queue class allow to control, send, receive, or wait for messages.
* A message can be a integer or pointer value to a certain type T that is send
* to a thread or interrupt service routine.
* @param T data type of a single message element.
* @param queue_sz maximum number of messages in queue.
*/
template<typename T, uint32_t queue_sz>
class Queue
{
public:
/** Create and initialise a message Queue. */
Queue()
{
rt_mq_init(&mID, "mq", mPool, sizeof(T), sizeof(mPool), RT_IPC_FLAG_FIFO);
};
~Queue()
{
rt_mq_detach(&mID);
};
/** Put a message in a Queue.
@param data message pointer.
@param millisec timeout value or 0 in case of no time-out. (default: 0)
@return status code that indicates the execution status of the function.
*/
rt_err_t put(T& data, int32_t millisec = 0)
{
return rt_mq_send(&mID, &data, sizeof(data));
}
/** Get a message or Wait for a message from a Queue.
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
@return bool .
*/
bool get(T& data, int32_t millisec = WAIT_FOREVER)
{
rt_int32_t tick;
if (millisec < 0)
tick = -1;
else
tick = rt_tick_from_millisecond(millisec);
return rt_mq_recv(&mID, &data, sizeof(data), tick) == RT_EOK;
}
private:
struct rt_messagequeue mID;
char mPool[(sizeof(void *) + RT_ALIGN(sizeof(T), RT_ALIGN_SIZE)) * queue_sz];
};
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016/10/1 Bernard The first version
*/
#pragma once
#include <stdint.h>
#include <rtthread.h>
namespace rtthread {
/** The Semaphore class is used to manage and protect access to a set of shared resources. */
class Semaphore
{
public:
/** Create and Initialize a Semaphore object used for managing resources.
@param number of available resources; maximum index value is (count-1).
*/
Semaphore(const char *name = "sem", int32_t count = 0);
~Semaphore();
/** Wait until a Semaphore resource becomes available.
@param millisec timeout value or 0 in case of no time-out.
@return true on success.
*/
bool wait(int32_t millisec = -1);
/** Release a Semaphore resource that was obtain with Semaphore::wait.
*/
void release(void);
private:
struct rt_semaphore mID;
};
}

Some files were not shown because too many files have changed in this diff Show more