diff options
Diffstat (limited to 'cpukit')
282 files changed, 6938 insertions, 5596 deletions
diff --git a/cpukit/base64/base64-decode.c b/cpukit/base64/base64-decode.c new file mode 100644 index 0000000000..5739266528 --- /dev/null +++ b/cpukit/base64/base64-decode.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSImplBase64 + * + * @brief This source file contains the implementation of + * _Base64_Decode_initialize() and _Base64_Decode(). + */ + +/* + * Copyright (C) 2023 embedded brains GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rtems/base64.h> + +#define SPACE 253 + +#define PAD 254 + +#define INVALID 255 + +const uint8_t _Base64_Decoding[128] = { + ['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, + ['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7, + ['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, + ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15, + ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, + ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, + ['Y'] = 24, ['Z'] = 25, ['a'] = 26, ['b'] = 27, + ['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31, + ['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35, + ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39, + ['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, + ['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47, + ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51, + ['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55, + ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59, + ['8'] = 60, ['9'] = 61, ['+'] = 62, ['-'] = 62, + ['/'] = 63, ['_'] = 63, ['='] = PAD, [' '] = SPACE, + ['\t'] = SPACE, ['\n'] = SPACE, ['\v'] = SPACE, ['\f'] = SPACE, + ['\r'] = SPACE, [0] = INVALID, [1] = INVALID, [2] = INVALID, + [3] = INVALID, [4] = INVALID, [5] = INVALID, [6] = INVALID, + [7] = INVALID, [8] = INVALID, [14] = INVALID, [15] = INVALID, + [16] = INVALID, [17] = INVALID, [18] = INVALID, [19] = INVALID, + [20] = INVALID, [21] = INVALID, [22] = INVALID, [23] = INVALID, + [24] = INVALID, [25] = INVALID, [26] = INVALID, [27] = INVALID, + [28] = INVALID, [29] = INVALID, [30] = INVALID, [31] = INVALID, + [33] = INVALID, [34] = INVALID, [35] = INVALID, [36] = INVALID, + [37] = INVALID, [38] = INVALID, [39] = INVALID, [40] = INVALID, + [41] = INVALID, [42] = INVALID, [44] = INVALID, [46] = INVALID, + [58] = INVALID, [59] = INVALID, [60] = INVALID, [62] = INVALID, + [63] = INVALID, [64] = INVALID, [91] = INVALID, [92] = INVALID, + [93] = INVALID, [94] = INVALID, [96] = INVALID, [123] = INVALID, + [124] = INVALID, [125] = INVALID, [126] = INVALID, [127] = INVALID}; + +void _Base64_Decode_initialize(Base64_Decode_control* self, + uint8_t* target, + size_t target_size) { + self->state = BASE64_DECODE_STATE_0; + self->target = target; + self->target_end = target + target_size; +} + +Base64_Decode_status _Base64_Decode(Base64_Decode_control* self, char ch) { + uint8_t decoded_ch; + uint8_t next_ch; + uint8_t* target; + const uint8_t* target_end; + Base64_Decode_state next_state; + + if ((unsigned char)ch >= 128) { + return BASE64_DECODE_INVALID_INPUT; + } + + decoded_ch = _Base64_Decoding[(unsigned char)ch]; + + if (decoded_ch == SPACE) { + return BASE64_DECODE_SUCCESS; + } + + target = self->target; + + if (decoded_ch == PAD) { + self->target_end = target; + return BASE64_DECODE_SUCCESS; + } + + if (decoded_ch == INVALID) { + return BASE64_DECODE_INVALID_INPUT; + } + + target_end = self->target_end; + + if (target == target_end) { + return BASE64_DECODE_OVERFLOW; + } + + switch (self->state) { + case BASE64_DECODE_STATE_0: + *target = decoded_ch << 2; + next_state = BASE64_DECODE_STATE_1; + break; + + case BASE64_DECODE_STATE_1: + *target |= decoded_ch >> 4; + next_ch = (decoded_ch & 0x0fU) << 4; + ++target; + + if (target != target_end) { + *target = next_ch; + } else if (next_ch != 0) { + return BASE64_DECODE_OVERFLOW; + } + + next_state = BASE64_DECODE_STATE_2; + break; + + case BASE64_DECODE_STATE_2: + *target |= decoded_ch >> 2; + next_ch = (decoded_ch & 0x03U) << 6; + ++target; + + if (target != target_end) { + *target = next_ch; + } else if (next_ch != 0) { + return BASE64_DECODE_OVERFLOW; + } + + next_state = BASE64_DECODE_STATE_3; + break; + + default: /* BASE64_DECODE_STATE_3 */ + *target |= decoded_ch; + ++target; + next_state = BASE64_DECODE_STATE_0; + break; + } + + self->state = next_state; + self->target = target; + return BASE64_DECODE_SUCCESS; +} diff --git a/cpukit/base64/base64-encode.c b/cpukit/base64/base64-encode.c new file mode 100644 index 0000000000..0110f3ff67 --- /dev/null +++ b/cpukit/base64/base64-encode.c @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: ISC */ + +/** + * @file + * + * @ingroup RTEMSImplBase64 + * + * @brief This source file contains the implementation of + * _Base64_Encode() and _Base64url_Encode(). + */ + +/* + * Copyright (C) 2020, 2024 embedded brains GmbH & Co. KG + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1998-2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include <rtems/base64.h> + +static void +_Base64_Put(int c, void *arg, IO_Put_char put_char) +{ + (*put_char)(c, arg); +} + +static int +_Base64_Do_encode(IO_Put_char put_char, void *arg, const void *src, + size_t srclen, const char *wordbreak, int wordlen, const uint8_t *encoding) +{ + unsigned int loops = 0; + const unsigned char *in = src; + int out = 0; + + if (wordlen < 4) { + wordlen = 4; + } + + while (srclen > 2) { + _Base64_Put(encoding[(in[0]>>2)&0x3f], arg, put_char); + _Base64_Put(encoding[((in[0]<<4)&0x30)| + ((in[1]>>4)&0x0f)], arg, put_char); + _Base64_Put(encoding[((in[1]<<2)&0x3c)| + ((in[2]>>6)&0x03)], arg, put_char); + _Base64_Put(encoding[in[2]&0x3f], arg, put_char); + in += 3; + srclen -= 3; + out += 4; + + loops++; + if (srclen != 0 && + (int)((loops + 1) * 4) >= wordlen) + { + const char *w = wordbreak; + loops = 0; + while (*w != '\0') { + _Base64_Put(*w, arg, put_char); + ++w; + ++out; + } + } + } + if (srclen == 2) { + _Base64_Put(encoding[(in[0]>>2)&0x3f], arg, put_char); + _Base64_Put(encoding[((in[0]<<4)&0x30)| + ((in[1]>>4)&0x0f)], arg, put_char); + _Base64_Put(encoding[((in[1]<<2)&0x3c)], arg, put_char); + _Base64_Put('=', arg, put_char); + out += 4; + } else if (srclen == 1) { + _Base64_Put(encoding[(in[0]>>2)&0x3f], arg, put_char); + _Base64_Put(encoding[((in[0]<<4)&0x30)], arg, put_char); + _Base64_Put('=', arg, put_char); + _Base64_Put('=', arg, put_char); + out += 4; + } + return out; +} + +const uint8_t _Base64_Encoding[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +int +_Base64_Encode(IO_Put_char put_char, void *arg, const void *src, size_t srclen, + const char *wordbreak, int wordlen) +{ + return _Base64_Do_encode(put_char, arg, src, srclen, wordbreak, + wordlen, _Base64_Encoding); +} + +const uint8_t _Base64url_Encoding[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '-', '_' +}; + +int +_Base64url_Encode(IO_Put_char put_char, void *arg, const void *src, + size_t srclen, const char *wordbreak, int wordlen) +{ + return _Base64_Do_encode(put_char, arg, src, srclen, wordbreak, + wordlen, _Base64url_Encoding); +} diff --git a/cpukit/libmisc/xz/COPYING b/cpukit/compression/xz/COPYING index fc4fbf798d..fc4fbf798d 100644 --- a/cpukit/libmisc/xz/COPYING +++ b/cpukit/compression/xz/COPYING diff --git a/cpukit/libmisc/xz/README b/cpukit/compression/xz/README index 1d5b9d85b2..1d5b9d85b2 100644 --- a/cpukit/libmisc/xz/README +++ b/cpukit/compression/xz/README diff --git a/cpukit/libmisc/xz/xz_config.h b/cpukit/compression/xz/xz_config.h index eb9dac1a4b..eb9dac1a4b 100644 --- a/cpukit/libmisc/xz/xz_config.h +++ b/cpukit/compression/xz/xz_config.h diff --git a/cpukit/libmisc/xz/xz_crc32.c b/cpukit/compression/xz/xz_crc32.c index 34532d14fd..34532d14fd 100644 --- a/cpukit/libmisc/xz/xz_crc32.c +++ b/cpukit/compression/xz/xz_crc32.c diff --git a/cpukit/libmisc/xz/xz_crc64.c b/cpukit/compression/xz/xz_crc64.c index ca1caee899..ca1caee899 100644 --- a/cpukit/libmisc/xz/xz_crc64.c +++ b/cpukit/compression/xz/xz_crc64.c diff --git a/cpukit/libmisc/xz/xz_dec_lzma2.c b/cpukit/compression/xz/xz_dec_lzma2.c index 6de808c5b3..6de808c5b3 100644 --- a/cpukit/libmisc/xz/xz_dec_lzma2.c +++ b/cpukit/compression/xz/xz_dec_lzma2.c diff --git a/cpukit/libmisc/xz/xz_dec_stream.c b/cpukit/compression/xz/xz_dec_stream.c index d6525506a1..d6525506a1 100644 --- a/cpukit/libmisc/xz/xz_dec_stream.c +++ b/cpukit/compression/xz/xz_dec_stream.c diff --git a/cpukit/libmisc/xz/xz_lzma2.h b/cpukit/compression/xz/xz_lzma2.h index 071d67bee9..071d67bee9 100644 --- a/cpukit/libmisc/xz/xz_lzma2.h +++ b/cpukit/compression/xz/xz_lzma2.h diff --git a/cpukit/libmisc/xz/xz_private.h b/cpukit/compression/xz/xz_private.h index 482b90f363..482b90f363 100644 --- a/cpukit/libmisc/xz/xz_private.h +++ b/cpukit/compression/xz/xz_private.h diff --git a/cpukit/libmisc/xz/xz_stream.h b/cpukit/compression/xz/xz_stream.h index 66cb5a7055..66cb5a7055 100644 --- a/cpukit/libmisc/xz/xz_stream.h +++ b/cpukit/compression/xz/xz_stream.h diff --git a/cpukit/zlib/ChangeLog.zlib b/cpukit/compression/zlib/ChangeLog.zlib index f310bb0fcd..f310bb0fcd 100644 --- a/cpukit/zlib/ChangeLog.zlib +++ b/cpukit/compression/zlib/ChangeLog.zlib diff --git a/cpukit/zlib/FAQ b/cpukit/compression/zlib/FAQ index 99b7cf92e4..99b7cf92e4 100644 --- a/cpukit/zlib/FAQ +++ b/cpukit/compression/zlib/FAQ diff --git a/cpukit/zlib/README b/cpukit/compression/zlib/README index ba34d1894a..ba34d1894a 100644 --- a/cpukit/zlib/README +++ b/cpukit/compression/zlib/README diff --git a/cpukit/zlib/adler32.c b/cpukit/compression/zlib/adler32.c index d0be4380a3..d0be4380a3 100644 --- a/cpukit/zlib/adler32.c +++ b/cpukit/compression/zlib/adler32.c diff --git a/cpukit/zlib/compress.c b/cpukit/compression/zlib/compress.c index 2ad5326c14..2ad5326c14 100644 --- a/cpukit/zlib/compress.c +++ b/cpukit/compression/zlib/compress.c diff --git a/cpukit/zlib/crc32.c b/cpukit/compression/zlib/crc32.c index f8357b083f..f8357b083f 100644 --- a/cpukit/zlib/crc32.c +++ b/cpukit/compression/zlib/crc32.c diff --git a/cpukit/zlib/crc32.h b/cpukit/compression/zlib/crc32.h index 137df68d61..137df68d61 100644 --- a/cpukit/zlib/crc32.h +++ b/cpukit/compression/zlib/crc32.h diff --git a/cpukit/zlib/deflate.c b/cpukit/compression/zlib/deflate.c index 4a689db359..4a689db359 100644 --- a/cpukit/zlib/deflate.c +++ b/cpukit/compression/zlib/deflate.c diff --git a/cpukit/zlib/deflate.h b/cpukit/compression/zlib/deflate.h index 1a06cd5f25..1a06cd5f25 100644 --- a/cpukit/zlib/deflate.h +++ b/cpukit/compression/zlib/deflate.h diff --git a/cpukit/zlib/doc/algorithm.txt b/cpukit/compression/zlib/doc/algorithm.txt index c97f495020..c97f495020 100644 --- a/cpukit/zlib/doc/algorithm.txt +++ b/cpukit/compression/zlib/doc/algorithm.txt diff --git a/cpukit/zlib/doc/rfc1950.txt b/cpukit/compression/zlib/doc/rfc1950.txt index ce6428a0f2..ce6428a0f2 100644 --- a/cpukit/zlib/doc/rfc1950.txt +++ b/cpukit/compression/zlib/doc/rfc1950.txt diff --git a/cpukit/zlib/doc/rfc1951.txt b/cpukit/compression/zlib/doc/rfc1951.txt index 403c8c722f..403c8c722f 100644 --- a/cpukit/zlib/doc/rfc1951.txt +++ b/cpukit/compression/zlib/doc/rfc1951.txt diff --git a/cpukit/zlib/doc/rfc1952.txt b/cpukit/compression/zlib/doc/rfc1952.txt index a8e51b4567..a8e51b4567 100644 --- a/cpukit/zlib/doc/rfc1952.txt +++ b/cpukit/compression/zlib/doc/rfc1952.txt diff --git a/cpukit/zlib/doc/txtvsbin.txt b/cpukit/compression/zlib/doc/txtvsbin.txt index 2a901eaa68..2a901eaa68 100644 --- a/cpukit/zlib/doc/txtvsbin.txt +++ b/cpukit/compression/zlib/doc/txtvsbin.txt diff --git a/cpukit/zlib/gzclose.c b/cpukit/compression/zlib/gzclose.c index caeb99a317..caeb99a317 100644 --- a/cpukit/zlib/gzclose.c +++ b/cpukit/compression/zlib/gzclose.c diff --git a/cpukit/zlib/gzguts.h b/cpukit/compression/zlib/gzguts.h index 57faf37165..57faf37165 100644 --- a/cpukit/zlib/gzguts.h +++ b/cpukit/compression/zlib/gzguts.h diff --git a/cpukit/zlib/gzlib.c b/cpukit/compression/zlib/gzlib.c index 55da46a453..55da46a453 100644 --- a/cpukit/zlib/gzlib.c +++ b/cpukit/compression/zlib/gzlib.c diff --git a/cpukit/zlib/gzread.c b/cpukit/compression/zlib/gzread.c index dd77381596..dd77381596 100644 --- a/cpukit/zlib/gzread.c +++ b/cpukit/compression/zlib/gzread.c diff --git a/cpukit/zlib/gzwrite.c b/cpukit/compression/zlib/gzwrite.c index eb8a0e5893..eb8a0e5893 100644 --- a/cpukit/zlib/gzwrite.c +++ b/cpukit/compression/zlib/gzwrite.c diff --git a/cpukit/zlib/infback.c b/cpukit/compression/zlib/infback.c index babeaf1806..babeaf1806 100644 --- a/cpukit/zlib/infback.c +++ b/cpukit/compression/zlib/infback.c diff --git a/cpukit/zlib/inffast.c b/cpukit/compression/zlib/inffast.c index 1fec7f363f..1fec7f363f 100644 --- a/cpukit/zlib/inffast.c +++ b/cpukit/compression/zlib/inffast.c diff --git a/cpukit/zlib/inffast.h b/cpukit/compression/zlib/inffast.h index e5c1aa4ca8..e5c1aa4ca8 100644 --- a/cpukit/zlib/inffast.h +++ b/cpukit/compression/zlib/inffast.h diff --git a/cpukit/zlib/inffixed.h b/cpukit/compression/zlib/inffixed.h index d628327769..d628327769 100644 --- a/cpukit/zlib/inffixed.h +++ b/cpukit/compression/zlib/inffixed.h diff --git a/cpukit/zlib/inflate.c b/cpukit/compression/zlib/inflate.c index 8acbef44e9..8acbef44e9 100644 --- a/cpukit/zlib/inflate.c +++ b/cpukit/compression/zlib/inflate.c diff --git a/cpukit/zlib/inflate.h b/cpukit/compression/zlib/inflate.h index f127b6b1fa..f127b6b1fa 100644 --- a/cpukit/zlib/inflate.h +++ b/cpukit/compression/zlib/inflate.h diff --git a/cpukit/zlib/inftrees.c b/cpukit/compression/zlib/inftrees.c index 57d2793bec..57d2793bec 100644 --- a/cpukit/zlib/inftrees.c +++ b/cpukit/compression/zlib/inftrees.c diff --git a/cpukit/zlib/inftrees.h b/cpukit/compression/zlib/inftrees.h index f53665311c..f53665311c 100644 --- a/cpukit/zlib/inftrees.h +++ b/cpukit/compression/zlib/inftrees.h diff --git a/cpukit/zlib/trees.c b/cpukit/compression/zlib/trees.c index 5f305c4722..5f305c4722 100644 --- a/cpukit/zlib/trees.c +++ b/cpukit/compression/zlib/trees.c diff --git a/cpukit/zlib/trees.h b/cpukit/compression/zlib/trees.h index d35639d82a..d35639d82a 100644 --- a/cpukit/zlib/trees.h +++ b/cpukit/compression/zlib/trees.h diff --git a/cpukit/zlib/uncompr.c b/cpukit/compression/zlib/uncompr.c index f9532f46c1..f9532f46c1 100644 --- a/cpukit/zlib/uncompr.c +++ b/cpukit/compression/zlib/uncompr.c diff --git a/cpukit/zlib/zutil.c b/cpukit/compression/zlib/zutil.c index 9543ae825e..9543ae825e 100644 --- a/cpukit/zlib/zutil.c +++ b/cpukit/compression/zlib/zutil.c diff --git a/cpukit/zlib/zutil.h b/cpukit/compression/zlib/zutil.h index d3b95f0c27..d3b95f0c27 100644 --- a/cpukit/zlib/zutil.h +++ b/cpukit/compression/zlib/zutil.h diff --git a/cpukit/crc/crc24q.c b/cpukit/crc/crc24q.c new file mode 100644 index 0000000000..c96ec88a47 --- /dev/null +++ b/cpukit/crc/crc24q.c @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSImplCRC + * + * @brief This source file contains the implementation of + * _CRC24Q_Update() and _CRC24Q_Sequence_update(). + * + * The CRC-24Q cyclic redundancy checksum is used for example by Qualcomm, + * RTCM104v3, and LTE-A. + */ + +/* + * Copyright (C) 2023 embedded brains GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rtems/crc.h> + +static const uint32_t _CRC24Q_Table[256] = { + UINT32_C(0x000000), UINT32_C(0x864CFB), UINT32_C(0x8AD50D), + UINT32_C(0x0C99F6), UINT32_C(0x93E6E1), UINT32_C(0x15AA1A), + UINT32_C(0x1933EC), UINT32_C(0x9F7F17), UINT32_C(0xA18139), + UINT32_C(0x27CDC2), UINT32_C(0x2B5434), UINT32_C(0xAD18CF), + UINT32_C(0x3267D8), UINT32_C(0xB42B23), UINT32_C(0xB8B2D5), + UINT32_C(0x3EFE2E), UINT32_C(0xC54E89), UINT32_C(0x430272), + UINT32_C(0x4F9B84), UINT32_C(0xC9D77F), UINT32_C(0x56A868), + UINT32_C(0xD0E493), UINT32_C(0xDC7D65), UINT32_C(0x5A319E), + UINT32_C(0x64CFB0), UINT32_C(0xE2834B), UINT32_C(0xEE1ABD), + UINT32_C(0x685646), UINT32_C(0xF72951), UINT32_C(0x7165AA), + UINT32_C(0x7DFC5C), UINT32_C(0xFBB0A7), UINT32_C(0x0CD1E9), + UINT32_C(0x8A9D12), UINT32_C(0x8604E4), UINT32_C(0x00481F), + UINT32_C(0x9F3708), UINT32_C(0x197BF3), UINT32_C(0x15E205), + UINT32_C(0x93AEFE), UINT32_C(0xAD50D0), UINT32_C(0x2B1C2B), + UINT32_C(0x2785DD), UINT32_C(0xA1C926), UINT32_C(0x3EB631), + UINT32_C(0xB8FACA), UINT32_C(0xB4633C), UINT32_C(0x322FC7), + UINT32_C(0xC99F60), UINT32_C(0x4FD39B), UINT32_C(0x434A6D), + UINT32_C(0xC50696), UINT32_C(0x5A7981), UINT32_C(0xDC357A), + UINT32_C(0xD0AC8C), UINT32_C(0x56E077), UINT32_C(0x681E59), + UINT32_C(0xEE52A2), UINT32_C(0xE2CB54), UINT32_C(0x6487AF), + UINT32_C(0xFBF8B8), UINT32_C(0x7DB443), UINT32_C(0x712DB5), + UINT32_C(0xF7614E), UINT32_C(0x19A3D2), UINT32_C(0x9FEF29), + UINT32_C(0x9376DF), UINT32_C(0x153A24), UINT32_C(0x8A4533), + UINT32_C(0x0C09C8), UINT32_C(0x00903E), UINT32_C(0x86DCC5), + UINT32_C(0xB822EB), UINT32_C(0x3E6E10), UINT32_C(0x32F7E6), + UINT32_C(0xB4BB1D), UINT32_C(0x2BC40A), UINT32_C(0xAD88F1), + UINT32_C(0xA11107), UINT32_C(0x275DFC), UINT32_C(0xDCED5B), + UINT32_C(0x5AA1A0), UINT32_C(0x563856), UINT32_C(0xD074AD), + UINT32_C(0x4F0BBA), UINT32_C(0xC94741), UINT32_C(0xC5DEB7), + UINT32_C(0x43924C), UINT32_C(0x7D6C62), UINT32_C(0xFB2099), + UINT32_C(0xF7B96F), UINT32_C(0x71F594), UINT32_C(0xEE8A83), + UINT32_C(0x68C678), UINT32_C(0x645F8E), UINT32_C(0xE21375), + UINT32_C(0x15723B), UINT32_C(0x933EC0), UINT32_C(0x9FA736), + UINT32_C(0x19EBCD), UINT32_C(0x8694DA), UINT32_C(0x00D821), + UINT32_C(0x0C41D7), UINT32_C(0x8A0D2C), UINT32_C(0xB4F302), + UINT32_C(0x32BFF9), UINT32_C(0x3E260F), UINT32_C(0xB86AF4), + UINT32_C(0x2715E3), UINT32_C(0xA15918), UINT32_C(0xADC0EE), + UINT32_C(0x2B8C15), UINT32_C(0xD03CB2), UINT32_C(0x567049), + UINT32_C(0x5AE9BF), UINT32_C(0xDCA544), UINT32_C(0x43DA53), + UINT32_C(0xC596A8), UINT32_C(0xC90F5E), UINT32_C(0x4F43A5), + UINT32_C(0x71BD8B), UINT32_C(0xF7F170), UINT32_C(0xFB6886), + UINT32_C(0x7D247D), UINT32_C(0xE25B6A), UINT32_C(0x641791), + UINT32_C(0x688E67), UINT32_C(0xEEC29C), UINT32_C(0x3347A4), + UINT32_C(0xB50B5F), UINT32_C(0xB992A9), UINT32_C(0x3FDE52), + UINT32_C(0xA0A145), UINT32_C(0x26EDBE), UINT32_C(0x2A7448), + UINT32_C(0xAC38B3), UINT32_C(0x92C69D), UINT32_C(0x148A66), + UINT32_C(0x181390), UINT32_C(0x9E5F6B), UINT32_C(0x01207C), + UINT32_C(0x876C87), UINT32_C(0x8BF571), UINT32_C(0x0DB98A), + UINT32_C(0xF6092D), UINT32_C(0x7045D6), UINT32_C(0x7CDC20), + UINT32_C(0xFA90DB), UINT32_C(0x65EFCC), UINT32_C(0xE3A337), + UINT32_C(0xEF3AC1), UINT32_C(0x69763A), UINT32_C(0x578814), + UINT32_C(0xD1C4EF), UINT32_C(0xDD5D19), UINT32_C(0x5B11E2), + UINT32_C(0xC46EF5), UINT32_C(0x42220E), UINT32_C(0x4EBBF8), + UINT32_C(0xC8F703), UINT32_C(0x3F964D), UINT32_C(0xB9DAB6), + UINT32_C(0xB54340), UINT32_C(0x330FBB), UINT32_C(0xAC70AC), + UINT32_C(0x2A3C57), UINT32_C(0x26A5A1), UINT32_C(0xA0E95A), + UINT32_C(0x9E1774), UINT32_C(0x185B8F), UINT32_C(0x14C279), + UINT32_C(0x928E82), UINT32_C(0x0DF195), UINT32_C(0x8BBD6E), + UINT32_C(0x872498), UINT32_C(0x016863), UINT32_C(0xFAD8C4), + UINT32_C(0x7C943F), UINT32_C(0x700DC9), UINT32_C(0xF64132), + UINT32_C(0x693E25), UINT32_C(0xEF72DE), UINT32_C(0xE3EB28), + UINT32_C(0x65A7D3), UINT32_C(0x5B59FD), UINT32_C(0xDD1506), + UINT32_C(0xD18CF0), UINT32_C(0x57C00B), UINT32_C(0xC8BF1C), + UINT32_C(0x4EF3E7), UINT32_C(0x426A11), UINT32_C(0xC426EA), + UINT32_C(0x2AE476), UINT32_C(0xACA88D), UINT32_C(0xA0317B), + UINT32_C(0x267D80), UINT32_C(0xB90297), UINT32_C(0x3F4E6C), + UINT32_C(0x33D79A), UINT32_C(0xB59B61), UINT32_C(0x8B654F), + UINT32_C(0x0D29B4), UINT32_C(0x01B042), UINT32_C(0x87FCB9), + UINT32_C(0x1883AE), UINT32_C(0x9ECF55), UINT32_C(0x9256A3), + UINT32_C(0x141A58), UINT32_C(0xEFAAFF), UINT32_C(0x69E604), + UINT32_C(0x657FF2), UINT32_C(0xE33309), UINT32_C(0x7C4C1E), + UINT32_C(0xFA00E5), UINT32_C(0xF69913), UINT32_C(0x70D5E8), + UINT32_C(0x4E2BC6), UINT32_C(0xC8673D), UINT32_C(0xC4FECB), + UINT32_C(0x42B230), UINT32_C(0xDDCD27), UINT32_C(0x5B81DC), + UINT32_C(0x57182A), UINT32_C(0xD154D1), UINT32_C(0x26359F), + UINT32_C(0xA07964), UINT32_C(0xACE092), UINT32_C(0x2AAC69), + UINT32_C(0xB5D37E), UINT32_C(0x339F85), UINT32_C(0x3F0673), + UINT32_C(0xB94A88), UINT32_C(0x87B4A6), UINT32_C(0x01F85D), + UINT32_C(0x0D61AB), UINT32_C(0x8B2D50), UINT32_C(0x145247), + UINT32_C(0x921EBC), UINT32_C(0x9E874A), UINT32_C(0x18CBB1), + UINT32_C(0xE37B16), UINT32_C(0x6537ED), UINT32_C(0x69AE1B), + UINT32_C(0xEFE2E0), UINT32_C(0x709DF7), UINT32_C(0xF6D10C), + UINT32_C(0xFA48FA), UINT32_C(0x7C0401), UINT32_C(0x42FA2F), + UINT32_C(0xC4B6D4), UINT32_C(0xC82F22), UINT32_C(0x4E63D9), + UINT32_C(0xD11CCE), UINT32_C(0x575035), UINT32_C(0x5BC9C3), + UINT32_C(0xDD8538)}; + +static inline uint32_t _CRC24Q_do_update(uint32_t crc, uint8_t byte) { + return (crc << 8) ^ _CRC24Q_Table[byte ^ (uint8_t)(crc >> 16)]; +} + +uint32_t _CRC24Q_Update(uint32_t crc, uint8_t byte) { + return _CRC24Q_do_update(crc, byte); +} + +uint32_t _CRC24Q_Sequence_update(uint32_t crc, + const void* bytes, + size_t size_in_bytes) { + const uint8_t* the_bytes = bytes; + + for (size_t i = 0; i < size_in_bytes; ++i) { + crc = _CRC24Q_do_update(crc, the_bytes[i]); + } + + return crc; +} diff --git a/cpukit/dev/can/can.c b/cpukit/dev/can/can.c deleted file mode 100644 index 9f3fe0db98..0000000000 --- a/cpukit/dev/can/can.c +++ /dev/null @@ -1,507 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup CANBus - * - * @brief Controller Area Network (CAN) Bus Implementation - * - */ - -/* - * Copyright (C) 2022 Prashanth S (fishesprashanth@gmail.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <inttypes.h> -#include <string.h> -#include <stdlib.h> - -#include <fcntl.h> - -#include <rtems/imfs.h> -#include <rtems/thread.h> - -#include <dev/can/canqueueimpl.h> -#include <dev/can/can.h> - -#define can_interrupt_lock_acquire(bus) \ - do { \ - CAN_DEBUG_LOCK("acquiring lock\n"); \ - real_can_interrupt_lock_acquire(bus); \ - } while (0); - -#define can_interrupt_lock_release(bus) \ - do { \ - CAN_DEBUG_LOCK("releasing lock\n"); \ - real_can_interrupt_lock_release(bus); \ - } while (0); - -static int -can_bus_open(rtems_libio_t *iop, const char *path, int oflag, mode_t mode); -static ssize_t -can_bus_read(rtems_libio_t *iop, void *buffer, size_t count); -static ssize_t -can_bus_write(rtems_libio_t *iop, const void *buffer, size_t count); -static int -can_bus_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer); - -static int can_xmit(struct can_bus *bus); - -static int can_bus_create_sem(struct can_bus *); -static int try_sem(struct can_bus *); -static int take_sem(struct can_bus *); -static int give_sem(struct can_bus *); - - -static void can_bus_obtain(can_bus *bus) -{ - CAN_DEBUG("can_bus_obtain Entry\n"); - rtems_mutex_lock(&bus->mutex); - CAN_DEBUG("can_bus_obtain Exit\n"); -} - -static void can_bus_release(can_bus *bus) -{ - CAN_DEBUG("can_bus_release Entry\n"); - rtems_mutex_unlock(&bus->mutex); - CAN_DEBUG("can_bus_release Exit\n"); -} - -static void can_bus_destroy_mutex(struct can_bus *bus) -{ - rtems_mutex_destroy(&bus->mutex); -} - -static int can_bus_create_sem(struct can_bus *bus) -{ - int ret = 0; - - ret = rtems_semaphore_create(rtems_build_name('c', 'a', 'n', bus->index), - CAN_TX_BUF_COUNT, RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE | RTEMS_LOCAL, - 0, &bus->tx_fifo_sem_id); - - if (ret != 0) { - CAN_ERR("can_create_sem: rtems_semaphore_create failed %d\n", ret); - } - - return ret; -} - -static void can_bus_free_tx_semaphore(struct can_bus *bus) -{ - rtems_semaphore_delete(bus->tx_fifo_sem_id); -} - -static void real_can_interrupt_lock_acquire(struct can_bus *bus) -{ - bus->can_dev_ops->dev_int(bus->priv, false); - can_bus_obtain(bus); -} - -static void real_can_interrupt_lock_release(struct can_bus *bus) -{ - can_bus_release(bus); - bus->can_dev_ops->dev_int(bus->priv, true); -} - -static int take_sem(struct can_bus *bus) -{ - int ret = rtems_semaphore_obtain(bus->tx_fifo_sem_id, RTEMS_WAIT, - RTEMS_NO_TIMEOUT); -#ifdef CAN_DEBUG_LOCK - if (ret == RTEMS_SUCCESSFUL) { - bus->sem_count++; - CAN_DEBUG_LOCK("take_sem: Semaphore count = %d\n", bus->sem_count); - if (bus->sem_count > CAN_TX_BUF_COUNT) { - CAN_ERR("take_sem error: sem_count is misleading\n"); - return RTEMS_INTERNAL_ERROR; - } - } -#endif /* CAN_DEBUG_LOCK */ - - return ret; -} - -static int give_sem(struct can_bus *bus) -{ - int ret = rtems_semaphore_release(bus->tx_fifo_sem_id); - -#ifdef CAN_DEBUG_LOCK - if (ret == RTEMS_SUCCESSFUL) { - bus->sem_count--; - CAN_DEBUG_LOCK("give_sem: Semaphore count = %d\n", bus->sem_count); - if (bus->sem_count < 0) { - CAN_ERR("give_sem error: sem_count is misleading\n"); - return RTEMS_INTERNAL_ERROR; - } - } -#endif /* CAN_DEBUG_LOCK */ - - return ret; -} - -static int try_sem(struct can_bus *bus) -{ - int ret = rtems_semaphore_obtain(bus->tx_fifo_sem_id, RTEMS_NO_WAIT, - RTEMS_NO_TIMEOUT); -#ifdef CAN_DEBUG_LOCK - if (ret == RTEMS_SUCCESSFUL) { - bus->sem_count++; - CAN_DEBUG_LOCK("try_sem: Semaphore count = %d\n", bus->sem_count); - if (bus->sem_count > CAN_TX_BUF_COUNT) { - CAN_ERR("take_sem error: sem_count is misleading\n"); - return RTEMS_INTERNAL_ERROR; - } - } -#endif /* CAN_DEBUG_LOCK */ - - return ret; -} - -static int -can_bus_open(rtems_libio_t *iop, const char *path, int oflag, mode_t mode) -{ - CAN_DEBUG("can_bus_open\n"); - - return 0; -} - -/* Should be called only with CAN interrupts disabled */ -int can_receive(struct can_bus *bus, struct can_msg *msg) -{ - memcpy(&bus->can_rx_msg, msg, CAN_MSG_LEN(msg)); - - return CAN_MSG_LEN(msg); -} - -/* FIXME: Should be modified to read count number of bytes, Now sending one can_msg */ -static ssize_t can_bus_read(rtems_libio_t *iop, void *buffer, size_t count) -{ - int len; - - can_bus *bus = IMFS_generic_get_context_by_iop(iop); - if (bus == NULL) { - return -RTEMS_NOT_DEFINED; - } - - struct can_msg *msg = (struct can_msg *)buffer; - - len = CAN_MSG_LEN(&bus->can_rx_msg); - - if (count < len) { - CAN_DEBUG("can_bus_read: buffer size is small min " - "sizeof(struct can_msg) = %" PRIuPTR "\n", - sizeof(struct can_msg)); - return -RTEMS_INVALID_SIZE; - } - - can_interrupt_lock_acquire(bus); - memcpy(msg, &bus->can_rx_msg, len); - can_interrupt_lock_release(bus); - - return len; -} - -/* This function is a critical section and should be called - * with CAN interrupts disabled and mutually exclusive - */ -static int can_xmit(struct can_bus *bus) -{ - int ret = RTEMS_SUCCESSFUL; - - struct can_msg *msg = NULL; - - CAN_DEBUG(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> can_xmit Entry\n"); - - while (1) { - CAN_DEBUG("can_dev_ops->dev_tx_ready\n"); - if (bus->can_dev_ops->dev_tx_ready(bus->priv) != true) { - break; - } - - CAN_DEBUG("can_tx_get_data_buf\n"); - msg = can_bus_tx_get_data_buf(bus); - if (msg == NULL) { - break; - } - - CAN_DEBUG("can_dev_ops->dev_tx\n"); - ret = bus->can_dev_ops->dev_tx(bus->priv, msg); - if (ret != RTEMS_SUCCESSFUL) { - CAN_ERR("can_xmit: dev_send failed\n"); - break; - } - - ret = give_sem(bus); - if (ret != RTEMS_SUCCESSFUL) { - CAN_ERR("can_xmit: rtems_semaphore_release failed = %d\n", ret); - break; - } - } - - CAN_DEBUG(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> can_xmit Exit\n"); - - return ret; -} - -void can_print_msg(struct can_msg const *msg) -{ -#ifdef CAN_DEBUG - CAN_DEBUG("\n----------------------------------------------------------------\n"); - CAN_DEBUG("id = %d len = %d flags = 0x%08X\n", msg->id, msg->len, msg->flags); - - CAN_DEBUG("msg->data[0] = 0x%08x\n", ((uint32_t *)msg->data)[0]); - CAN_DEBUG("msg->data[1] = 0x%08x\n", ((uint32_t *)msg->data)[1]); - - for (int i = 0; i < msg->len; i++) { - CAN_DEBUG("%02x\n", ((char *)msg->data)[i]); - } - - CAN_DEBUG("\n-----------------------------------------------------------------\n"); -#endif /* CAN_DEBUG */ -} - -/* can_tx_done should be called only with CAN interrupts disabled */ -int can_tx_done(struct can_bus *bus) -{ - CAN_DEBUG("------------ can_tx_done Entry\n"); - int ret = RTEMS_SUCCESSFUL; - - if (bus->can_dev_ops->dev_tx_ready(bus->priv) == true) { - ret = can_xmit(bus); - } - CAN_DEBUG("------------ can_tx_done Exit\n"); - - return ret; -} - -/* FIXME: Add support to send multiple CAN msgs for can_bus_write */ -static ssize_t -can_bus_write(rtems_libio_t *iop, const void *buffer, size_t count) -{ - can_bus *bus = IMFS_generic_get_context_by_iop(iop); - - if (bus == NULL || bus->can_dev_ops->dev_tx == NULL) { - return -RTEMS_NOT_DEFINED; - } - - int ret = RTEMS_SUCCESSFUL; - - struct can_msg const *msg = buffer; - struct can_msg *fifo_buf = NULL; - - uint32_t msg_size = CAN_MSG_LEN(msg); - - CAN_DEBUG_TX("can_bus_write: can_msg_size = %u\n", msg_size); - if (msg_size > sizeof(struct can_msg)) { - CAN_ERR("can_bus_write: can message " - "len error msg_size = %u struct can_msg = %" PRIxPTR "\n", - msg_size, sizeof(struct can_msg)); - return -RTEMS_INVALID_SIZE; - } - - if ((iop->flags & O_NONBLOCK) != 0) { - ret = try_sem(bus); - if (ret != RTEMS_SUCCESSFUL) { - return -ret; - } - } else { - ret = take_sem(bus); - if (ret != RTEMS_SUCCESSFUL) { - CAN_ERR("can_bus_write: cannot take semaphore\n"); - return -ret; - } - } - - can_interrupt_lock_acquire(bus); - - fifo_buf = can_bus_tx_get_empty_buf(bus); - if (fifo_buf == NULL) { - /* This error will not happen until buffer counts are not synchronized */ - CAN_ERR("can_bus_write: Buffer counts are not synchronized with semaphore count\n"); - ret = -RTEMS_INTERNAL_ERROR; - goto release_lock_and_return; - } - - CAN_DEBUG_TX("can_bus_write: empty_count = %u\n", bus->tx_fifo.empty_count); - - CAN_DEBUG_TX("can_bus_write: copying msg from application to driver buffer\n"); - memcpy(fifo_buf, msg, msg_size); - - if (bus->can_dev_ops->dev_tx_ready(bus->priv) == true) { - ret = can_xmit(bus); - if (ret != RTEMS_SUCCESSFUL) { - ret = -ret; - goto release_lock_and_return; - } - } - - ret = msg_size; - -release_lock_and_return: - can_interrupt_lock_release(bus); - return ret; -} - -static int -can_bus_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer) -{ - can_bus *bus = IMFS_generic_get_context_by_iop(iop); - - if (bus == NULL || bus->can_dev_ops->dev_ioctl == NULL) { - return -RTEMS_NOT_DEFINED; - } - - can_bus_obtain(bus); - - bus->can_dev_ops->dev_ioctl(bus->priv, NULL, 0); - - can_bus_release(bus); - - return RTEMS_SUCCESSFUL; -} - -static const rtems_filesystem_file_handlers_r can_bus_handler = { - .open_h = can_bus_open, - .close_h = rtems_filesystem_default_close, - .read_h = can_bus_read, - .write_h = can_bus_write, - .ioctl_h = can_bus_ioctl, - .lseek_h = rtems_filesystem_default_lseek, - .fstat_h = IMFS_stat, - .ftruncate_h = rtems_filesystem_default_ftruncate, - .fsync_h = rtems_filesystem_default_fsync_or_fdatasync, - .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .kqfilter_h = rtems_filesystem_default_kqfilter, - .mmap_h = rtems_filesystem_default_mmap, - .poll_h = rtems_filesystem_default_poll, - .readv_h = rtems_filesystem_default_readv, - .writev_h = rtems_filesystem_default_writev -}; - -static void can_bus_node_destroy(IMFS_jnode_t *node) -{ - can_bus *bus; - - bus = IMFS_generic_get_context_by_node(node); - (*bus->destroy)(bus); - - IMFS_node_destroy_default(node); -} - -static const -IMFS_node_control can_bus_node_control = IMFS_GENERIC_INITIALIZER(&can_bus_handler, - IMFS_node_initialize_generic, can_bus_node_destroy); - -rtems_status_code can_bus_register(can_bus *bus, const char *bus_path) -{ - int ret = RTEMS_SUCCESSFUL; - - static uint8_t index = 0; - - if (index == CAN_BUS_REG_MAX) { - CAN_ERR("can_bus_register: can bus registration limit reached\n"); - return RTEMS_TOO_MANY; - } - - bus->index = index++; - CAN_DEBUG("Registering CAN bus index = %u\n", bus->index); - - ret = IMFS_make_generic_node(bus_path, S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, - &can_bus_node_control, bus); - if (ret != RTEMS_SUCCESSFUL) { - CAN_ERR("can_bus_register: Creating node failed = %d\n", ret); - goto fail; - } - - if ((ret = can_bus_create_sem(bus)) != RTEMS_SUCCESSFUL) { - CAN_ERR("can_bus_register: can_create_sem failed = %d\n", ret); - goto fail; - } - - if ((ret = can_bus_create_tx_buffers(bus)) != RTEMS_SUCCESSFUL) { - CAN_ERR("can_bus_register: can_create_tx_buffers failed = %d\n", ret); - goto free_tx_semaphore; - } - - return ret; - -free_tx_semaphore: - rtems_semaphore_delete(bus->tx_fifo_sem_id); - -fail: - can_bus_destroy_mutex(bus); - return ret; - -} - -static void can_bus_destroy(can_bus *bus) -{ - can_bus_free_tx_buffers(bus); - can_bus_free_tx_semaphore(bus); - can_bus_destroy_mutex(bus); -} - -static int can_bus_do_init(can_bus *bus, void (*destroy)(can_bus *bus)) -{ - rtems_mutex_init(&bus->mutex, "CAN Bus"); - bus->destroy = can_bus_destroy; - - return RTEMS_SUCCESSFUL; -} - -static void can_bus_destroy_and_free(can_bus *bus) -{ - can_bus_destroy(bus); - free(bus); -} - -int can_bus_init(can_bus *bus) -{ - memset(bus, 0, sizeof(*bus)); - - return can_bus_do_init(bus, can_bus_destroy); -} - -can_bus *can_bus_alloc_and_init(size_t size) -{ - can_bus *bus = NULL; - - if (size >= sizeof(*bus)) { - bus = calloc(1, size); - if (bus == NULL) { - CAN_ERR("can_bus_alloc_and_init: calloc failed\b"); - return NULL; - } - - int rv = can_bus_do_init(bus, can_bus_destroy_and_free); - if (rv != 0) { - CAN_ERR("can_bus_alloc_and_init: can_bus_do_init failed\n"); - return NULL; - } - } - return bus; -} diff --git a/cpukit/dev/flash/flashdev.c b/cpukit/dev/flash/flashdev.c index 4b7a0560ff..f39f8dde4d 100644 --- a/cpukit/dev/flash/flashdev.c +++ b/cpukit/dev/flash/flashdev.c @@ -135,6 +135,13 @@ static int rtems_flashdev_get_addr( off_t *addr ); +static int rtems_flashdev_get_abs_addr( + rtems_flashdev *flash, + rtems_libio_t *iop, + size_t count, + off_t *addr +); + static int rtems_flashdev_update_and_return( rtems_libio_t *iop, int status, @@ -313,7 +320,7 @@ static int rtems_flashdev_read_write( int status; if ( read_buff == NULL && write_buff == NULL ) { - return 0; + rtems_set_errno_and_return_minus_one( EINVAL ); } /* Get flash address */ @@ -383,6 +390,8 @@ static int rtems_flashdev_ioctl( case RTEMS_FLASHDEV_IOCTL_WRITE_BLOCK_SIZE: err = rtems_flashdev_ioctl_write_block_size( flash, arg ); break; + default: + err = EINVAL; } rtems_flashdev_release( flash ); @@ -565,6 +574,28 @@ static int rtems_flashdev_get_addr( return 0; } +static int rtems_flashdev_get_abs_addr( + rtems_flashdev *flash, + rtems_libio_t *iop, + size_t count, + off_t *addr +) +{ + off_t new_offset; + + /* Check address is in valid region */ + new_offset = *addr + count; + + if (rtems_flashdev_check_offset_region(flash, iop, new_offset)) { + return -1; + } + + /* Get address for operation */ + if ( rtems_flashdev_is_region_defined( iop ) ) { + *addr = ( *addr + rtems_flashdev_get_region_offset( flash, iop ) ); + } + return 0; +} static int rtems_flashdev_update_and_return( rtems_libio_t *iop, int status, @@ -588,7 +619,7 @@ static int rtems_flashdev_ioctl_erase( ) { rtems_flashdev_region *erase_args_1; - off_t check_offset; + off_t new_offset; int status; if ( flash->erase == NULL ) { @@ -597,16 +628,14 @@ static int rtems_flashdev_ioctl_erase( erase_args_1 = (rtems_flashdev_region *) arg; /* Check erasing valid region */ - check_offset = erase_args_1->offset + erase_args_1->size; - if ( rtems_flashdev_is_region_defined( iop ) && ( - rtems_flashdev_check_offset_region(flash, iop, check_offset) || - ( erase_args_1->offset < - rtems_flashdev_get_region_offset( flash, iop ) ) ) ) { - rtems_set_errno_and_return_minus_one( EINVAL ); + new_offset = erase_args_1->offset; + status = rtems_flashdev_get_abs_addr(flash, iop, erase_args_1->size, &new_offset); + if ( status < 0 ) { + return status; } /* Erase flash */ - status = ( *flash->erase )( flash, erase_args_1->offset, erase_args_1->size ); + status = ( *flash->erase )( flash, new_offset, erase_args_1->size ); return status; } diff --git a/cpukit/score/src/ioprintf.c b/cpukit/dev/ioprintf.c index 8ae4213ab1..1f16389b47 100644 --- a/cpukit/score/src/ioprintf.c +++ b/cpukit/dev/ioprintf.c @@ -3,7 +3,7 @@ /** * @file * - * @ingroup RTEMSScoreIO + * @ingroup RTEMSDeviceIO * * @brief This source file contains the implementation of * _IO_Printf(). @@ -38,7 +38,7 @@ #include "config.h" #endif -#include <rtems/score/io.h> +#include <rtems/dev/io.h> int _IO_Printf( IO_Put_char put_char, void *arg, char const *fmt, ... ) { diff --git a/cpukit/score/src/iorelax.c b/cpukit/dev/iorelax.c index 1b155377a9..5fdefac151 100644 --- a/cpukit/score/src/iorelax.c +++ b/cpukit/dev/iorelax.c @@ -3,7 +3,7 @@ /** * @file * - * @ingroup RTEMSScoreIO + * @ingroup RTEMSDeviceIO * * @brief This source file contains the implementation of _IO_Relax(). */ @@ -37,7 +37,7 @@ #include "config.h" #endif -#include <rtems/score/io.h> +#include <rtems/dev/io.h> #include <rtems/score/cpuimpl.h> void _IO_Relax( void ) diff --git a/cpukit/score/src/iovprintf.c b/cpukit/dev/iovprintf.c index 0e8eb0b47b..99b11b691d 100644 --- a/cpukit/score/src/iovprintf.c +++ b/cpukit/dev/iovprintf.c @@ -1,7 +1,7 @@ /** * @file * - * @ingroup RTEMSScoreIO + * @ingroup RTEMSDeviceIO * * @brief This source file contains the implementation of * _IO_Vprintf(). @@ -45,7 +45,7 @@ * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 */ -#include <rtems/score/io.h> +#include <rtems/dev/io.h> #include <sys/cdefs.h> __FBSDID("$FreeBSD: head/sys/kern/subr_prf.c 336417 2018-07-17 14:56:54Z markj $"); diff --git a/cpukit/doxygen.h b/cpukit/doxygen.h index 661955a501..a1ba3ece4a 100644 --- a/cpukit/doxygen.h +++ b/cpukit/doxygen.h @@ -43,7 +43,30 @@ * * @ingroup RTEMSDeviceDrivers * - * @brief Time Test 27 Support + * @brief The Time Test 27 (TM27) support is used to measure the timing of + * the interrupt processing. + * + * The TMS27 support should provide two software generated interrupt requests, + * one low priority request raised by Cause_tm27_intr() and one higher priority + * request raised by Lower_tm27_intr(). Both requests should be cleared by + * Clear_tm27_intr(). A handler provided by the test should be installed + * through Install_tm27_vector(). This function should initialize the system + * so that the software generated interrupt requests can be raised and cleared. + * + * If the raise functions Cause_tm27_intr() and Lower_tm27_intr() do not + * trigger the interrupt immediately, then the TM27 support shall define + * MUST_WAIT_FOR_INTERRUPT to one, otherwise MUST_WAIT_FOR_INTERRUPT shall be + * defined to zero. + * + * The TM27 support may define TM27_INTERRUPT_VECTOR_DEFAULT to indicate the + * interrupt vector of the interrupt request raised by Cause_tm27_intr(). + * + * The TM27 support may define TM27_INTERRUPT_VECTOR_ALTERNATIVE to provide an + * alternative software generated interrupt request which is raised by + * _TM27_Raise_alternative() and cleared by _TM27_Clear_alternative(). Both + * functions shall return an RTEMS status code. This interrupt vector may be + * used to test the interrupt controller support on targets which do not + * provide generic software generated interrupts. */ /** diff --git a/cpukit/doxygen/appl-config.h b/cpukit/doxygen/appl-config.h index 558a40cb0b..de93acbaa7 100644 --- a/cpukit/doxygen/appl-config.h +++ b/cpukit/doxygen/appl-config.h @@ -11,7 +11,7 @@ /* * Copyright (C) 2019, 2023 embedded brains GmbH & Co. KG * Copyright (C) 2010 Gedare Bloom - * Copyright (C) 1988, 2022 On-Line Applications Research Corporation (OAR) + * Copyright (C) 1988, 2023 On-Line Applications Research Corporation (OAR) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -1116,7 +1116,7 @@ * * @par Notes * @parblock - * The application shall define exactly one of the following configuration + * The application shall define at least one of the following configuration * options * * * ``CONFIGURE_RTEMS_INIT_TASKS_TABLE``, @@ -1126,6 +1126,10 @@ * * @ref CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION * * otherwise a compile time error in the configuration file will occur. + * + * The Classic API initialization task performs the <a + * href="https://docs.rtems.org/branches/master/c-user/initialization/operations.html">Global + * Construction</a>. * @endparblock */ #define CONFIGURE_RTEMS_INIT_TASKS_TABLE @@ -2471,6 +2475,34 @@ */ #define CONFIGURE_IMFS_MEMFILE_BYTES_PER_BLOCK +/* Generated from spec:/acfg/if/jffs2-delayed-write-task-priority */ + +/** + * @brief This configuration option is an integer define. + * + * @anchor CONFIGURE_JFFS2_DELAYED_WRITE_TASK_PRIORITY + * + * The value of this configuration option defines the JFFS2 delayed write task + * priority. + * + * @par Default Value + * The default value is 15. + * + * @par Constraints + * @parblock + * The following constraints apply to this configuration option: + * + * * The configuration option is not included in the pre-qualified feature set + * of RTEMS. Applications which are restricted to only use interfaces of the + * pre-qualified feature set of RTEMS shall not use the configuration option. + * + * * The value of the configuration option shall be a valid Classic API task + * priority. The set of valid task priorities depends on the scheduler + * configuration. + * @endparblock + */ +#define CONFIGURE_JFFS2_DELAYED_WRITE_TASK_PRIORITY + /* Generated from spec:/acfg/if/use-devfs-as-base-filesystem */ /** @@ -3281,7 +3313,7 @@ * The following constraints apply to this configuration option: * * * The value of the configuration option shall be greater than or equal to - * zero. + * one. * * * The value of the configuration option shall be less than or equal to <a * href="https://en.cppreference.com/w/c/types/integer">UINT32_MAX</a>. @@ -3504,7 +3536,7 @@ * user IDLE task with the @ref CONFIGURE_IDLE_TASK_BODY configuration option, * otherwise a compile time error in the configuration file will occur. * - * The application shall define exactly one of the following configuration + * The application shall define at least one of the following configuration * options * * * @ref CONFIGURE_RTEMS_INIT_TASKS_TABLE, @@ -3514,6 +3546,11 @@ * * ``CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION`` * * otherwise a compile time error in the configuration file will occur. + * + * If no Classic API initialization task and no POSIX API initialization thread + * is configured, then no <a + * href="https://docs.rtems.org/branches/master/c-user/initialization/operations.html">Global + * Construction</a> is performed. * @endparblock */ #define CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION @@ -4364,7 +4401,7 @@ * * @par Notes * @parblock - * The application shall define exactly one of the following configuration + * The application shall define at least one of the following configuration * options * * * @ref CONFIGURE_RTEMS_INIT_TASKS_TABLE, @@ -4374,6 +4411,11 @@ * * @ref CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION * * otherwise a compile time error in the configuration file will occur. + * + * If no Classic API initialization task is configured, then the POSIX API + * initialization thread performs the <a + * href="https://docs.rtems.org/branches/master/c-user/initialization/operations.html">Global + * Construction</a>. * @endparblock */ #define CONFIGURE_POSIX_INIT_THREAD_TABLE diff --git a/cpukit/score/src/pheapgetblocksize.c b/cpukit/doxygen/build.h index c53a66b5d4..696a6e1723 100644 --- a/cpukit/score/src/pheapgetblocksize.c +++ b/cpukit/doxygen/build.h @@ -3,15 +3,13 @@ /** * @file * - * @ingroup RTEMSScoreProtHeap + * @ingroup RTEMSImplDoxygen * - * @brief This source file contains the implementation of - * _Protected_heap_Get_block_size(). + * @brief This header file defines build system related Doxygen items. */ /* - * COPYRIGHT (c) 1989-2007. - * On-Line Applications Research Corporation (OAR). + * Copyright (C) 2023 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,22 +33,50 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +/** + * @defgroup RTEMSImplBuild Build Options + * + * @ingroup RTEMSImpl + * + * @brief This group contains files generated by the build system. + */ + +/** + * @ingroup RTEMSImplBuild + * + * @file bsps/include/bspopts.h + * + * @brief This header file provides the BSP options definitions. + */ + +/** + * @ingroup RTEMSImplBuild + * + * @file cpukit/include/version-vc-key.h + * + * @brief This header file provides the version control key definitions. + */ -#include <rtems/score/protectedheap.h> +/** + * @ingroup RTEMSImplBuild + * + * @file cpukit/include/config.h + * + * @brief This header file provides system configuration definitions. + */ -bool _Protected_heap_Get_block_size( - Heap_Control *the_heap, - void *starting_address, - uintptr_t *size -) -{ - bool status; +/** + * @ingroup RTEMSImplBuild + * + * @file cpukit/include/rtems/testopts.h + * + * @brief This header file provides test program definitions. + */ - _RTEMS_Lock_allocator(); - status = _Heap_Size_of_alloc_area( the_heap, starting_address, size ); - _RTEMS_Unlock_allocator(); - return status; -} +/** + * @ingroup RTEMSImplBuild + * + * @file cpukit/include/rtems/score/cpuopts.h + * + * @brief This header file provides the CPU options definitions. + */ diff --git a/cpukit/doxygen/mainpage.h b/cpukit/doxygen/mainpage.h new file mode 100644 index 0000000000..6eb0de7b36 --- /dev/null +++ b/cpukit/doxygen/mainpage.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSImplDoxygen + * + * @brief This file exists to provide a top level description of RTEMS for + * Doxygen. + */ + +/* + * Copyright (C) 2021 embedded brains GmbH & Co. KG + * Copyright (C) 1989, 2014 On-Line Applications Research Corporation (OAR) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @mainpage + * + * The Real-Time Executive for Multiprocessor Systems (RTEMS) is a + * multi-threaded, single address-space, real-time operating system with no + * kernel-space/user-space separation. It is capable to operate in an SMP + * configuration providing a state of the art feature set. + * + * RTEMS and all third-party software distributed with RTEMS which may be + * linked to the application is licensed under permissive open source licenses. + * This means that the licenses do not propagate to the application software. + * Most of the original RTEMS code is now under the [BSD 2-Clause + * license](https://git.rtems.org/rtems/tree/LICENSE.BSD-2-Clause). Some + * code of RTEMS is under a legacy license, the [modified GPL 2.0 or later + * license with an exception for static + * linking](https://git.rtems.org/rtems/tree/LICENSE). It exposes no license + * requirements on application code. Everything necessary to build RTEMS + * applications is available as open source software. This makes you + * completely vendor independent. + * + * RTEMS provides the following basic feature set: + * + * - @ref RTEMSAPI + * + * - POSIX with + * [pthreads](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html) + * (enables a broad range of standard software to run on RTEMS) + * + * - @ref RTEMSAPIClassic + * + * - C11 (including + * [thread](https://en.cppreference.com/w/c/thread) support) + * + * - C++11 (including + * [thread](https://en.cppreference.com/w/cpp/thread>) support) + * + * - Newlib and GCC internal + * + * - Programming languages + * + * - C/C++/OpenMP (RTEMS Source Builder, RSB) + * + * - Ada (RSB, ``--with-ada``) + * + * - Erlang + * + * - Fortran (RSB, ``--with-fortran``) + * + * - Python and MicroPython + * + * - Parallel languages + * + * - [Embedded Multicore Building Blocks](https://embb.io/) + * + * - [OpenMP](https://www.openmp.org/) + * + * - Thread synchronization and communication + * + * - Mutexes with and without locking protocols + * + * - Counting semaphores + * + * - Binary semaphores + * + * - Condition variables + * + * - Events + * + * - Message queues + * + * - Barriers + * + * - [Futex](@ref RTEMSScoreFutex) (used by OpenMP barriers) + * + * - Epoch Based Reclamation (libbsd) + * + * - Locking protocols + * + * - Transitive Priority Inheritance + * + * - OMIP (SMP feature) + * + * - Priority Ceiling + * + * - MrsP (SMP feature) + * + * - Scalable timer and timeout support + * + * - Lock-free timestamps (FreeBSD timecounters) + * + * - Responsive interrupt management + * + * - Thread-Local Storage (TLS) as specified by C11/C++11 and later standard + * revisions + * + * - Link-time configurable schedulers + * + * - Fixed-priority + * + * - Job-level fixed-priority (EDF) + * + * - Constant Bandwidth Server (experimental) + * + * - Clustered scheduling (SMP feature) + * + * - Flexible link-time configuration + * + * - Job-level fixed-priority scheduler (EDF) with support for one-to-one + * and one-to-all thread to processor affinities (default SMP scheduler) + * + * - Fixed-priority scheduler + * + * - Proof-of-concept strong APA scheduler + * + * - Focus on link-time application-specific configuration + * + * - Linker-set based initialization (similar to global C++ constructors) + * + * - Operating system uses fine-grained locking (SMP feature) + * + * - Dynamic memory allocators + * + * - First-fit (default) + * + * - Universal Memory Allocator + * ([UMA](https://www.freebsd.org/cgi/man.cgi?query=uma&sektion=9), + * libbsd) + * + * - File systems + * + * - IMFS + * + * - FAT + * + * - RFS + * + * - NFSv2 + * + * - JFFS2 (NOR flashes) + * + * - [YAFFS2](https://git.rtems.org/sebh/rtems-yaffs2.git/) + * (NAND flashes, GPL or commercial license required) + * + * - Device drivers + * + * - Termios (serial interfaces) + * + * - I2C (Linux user-space API compatible) + * + * - SPI (Linux user-space API compatible) + * + * - Network stacks (legacy, libbsd, lwIP) + * + * - USB stack (libbsd) + * + * - SD/MMC card stack (libbsd) + * + * - Framebuffer (Linux user-space API compatible, Qt) + * + * - Application runs in kernel-space and can access hardware directly + * + * - [libbsd](https://git.rtems.org/rtems-libbsd/) + * + * - Port of FreeBSD user-space and kernel-space components to RTEMS + * + * - Easy access to FreeBSD software for RTEMS + * + * - Support to stay in synchronization with FreeBSD + */ diff --git a/cpukit/doxygen/top-level-groups.h b/cpukit/doxygen/top-level-groups.h index fd32db347a..9d34b3e3dd 100644 --- a/cpukit/doxygen/top-level-groups.h +++ b/cpukit/doxygen/top-level-groups.h @@ -41,6 +41,14 @@ */ /** + * @defgroup RTEMSAPISystemLibrary System Library + * + * @ingroup RTEMSAPI + * + * @brief This group contains the system library APIs of RTEMS. + */ + +/** * @defgroup RTEMSDeviceDrivers Device Drivers * * @brief This group contains the device drivers. diff --git a/cpukit/ftpd/ftpd.c b/cpukit/ftpd/ftpd.c index ceb5c5d5b9..a925126dee 100644 --- a/cpukit/ftpd/ftpd.c +++ b/cpukit/ftpd/ftpd.c @@ -576,10 +576,9 @@ send_reply(FTPD_SessionInfo_t *info, int code, const char *text) * Output parameters: * returns 1 on success, 0 on failure. */ -static int +static void set_socket_timeout(int s, int seconds) { - int res = 0; struct timeval tv; int len = sizeof(tv); @@ -591,9 +590,6 @@ set_socket_timeout(int s, int seconds) syslog(LOG_ERR, "ftpd: Can't set send timeout on socket: %s.", serr()); else if(0 != setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, len)) syslog(LOG_ERR, "ftpd: Can't set receive timeout on socket: %s.", serr()); - else - res = 1; - return res; } /* @@ -688,8 +684,7 @@ data_socket(FTPD_SessionInfo_t *info) } info->data_socket = s; info->use_default = 1; - if(s >= 0) - set_socket_timeout(s, info->idle); + set_socket_timeout(s, info->idle); return s; } @@ -1568,8 +1563,8 @@ command_pasv(FTPD_SessionInfo_t *info) syslog(LOG_ERR, "ftpd: Error binding PASV socket: %s", serr()); else if (0 > listen(s, 1)) syslog(LOG_ERR, "ftpd: Error listening on PASV socket: %s", serr()); - else if (set_socket_timeout(s, info->idle)) { + set_socket_timeout(s, info->idle); if (0 == getsockname(s, (struct sockaddr *)&addr, &addrLen)) { char buf[FTPD_BUFSIZE]; @@ -2030,12 +2025,11 @@ ftpd_daemon(rtems_task_argument args RTEMS_UNUSED) ss = accept(s, (struct sockaddr *)&addr, &addrLen); if (0 > ss) syslog(LOG_ERR, "ftpd: Error accepting control connection: %s", serr()); - else if(!set_socket_timeout(ss, ftpd_timeout)) - close_socket(ss); else { FTPD_SessionInfo_t *info; + set_socket_timeout(ss, ftpd_timeout); info = task_pool_obtain(); if (NULL == info) { diff --git a/cpukit/include/dev/can/can-msg.h b/cpukit/include/dev/can/can-msg.h deleted file mode 100644 index 9863e14d84..0000000000 --- a/cpukit/include/dev/can/can-msg.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup CANBus - * - * @brief Controller Area Network (CAN) Bus Implementation - * - */ - -/* - * Copyright (C) 2022 Prashanth S <fishesprashanth@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _DEV_CAN_CAN_MSG_H -#define _DEV_CAN_CAN_MSG_H - -/** - * @defgroup Controller Area Network (CAN) Driver - * - * @ingroup RTEMSDeviceDrivers - * - * @brief Controller Area Network (CAN) bus and device driver support. - * - * @{ - */ - -/** - * @defgroup CANBus CAN Bus Driver - * - * @ingroup CAN - * - * @{ - */ - -/** - * @brief CAN message size - */ -#define CAN_MSG_MAX_SIZE (8u) - -/** - * @brief Number of CAN tx buffers - */ -#define CAN_TX_BUF_COUNT (10u) - -/** - * @brief Number of CAN rx buffers - */ -#define CAN_RX_BUF_COUNT (2u) - -#define CAN_MSGLEN(msg) (sizeof(struct can_msg) - (CAN_MSG_MAX_SIZE - msg->len)) - -/** - * @brief CAN message structure. - */ -struct can_msg { - /** - * @brief CAN message id. - */ - uint32_t id; - /** - * @brief CAN message timestamp. - */ - uint32_t timestamp; - /** - * @brief CAN message flags RTR | BRS | EXT. - */ - uint16_t flags; - /** - * @brief CAN message length. - */ - uint16_t len; - /** - * @brief CAN message. - */ - uint8_t data[CAN_MSG_MAX_SIZE]; -}; - -/** @} */ /* end of CAN message */ - -/** @} */ - -#endif /* _DEV_CAN_CAN_MSG_H */ diff --git a/cpukit/include/dev/can/can.h b/cpukit/include/dev/can/can.h deleted file mode 100644 index 9e55395039..0000000000 --- a/cpukit/include/dev/can/can.h +++ /dev/null @@ -1,284 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup CANBus - * - * @brief Controller Area Network (CAN) Bus Implementation - * - */ - -/* - * Copyright (C) 2022 Prashanth S (fishesprashanth@gmail.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _DEV_CAN_CAN_H -#define _DEV_CAN_CAN_H - -#include <rtems/imfs.h> -#include <rtems/thread.h> -#include <semaphore.h> - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include <dev/can/can-msg.h> - -#define DEBUG(str, ...) \ - do { \ - printf("CAN: %s:%d ID: %08X ", __FILE__, __LINE__, rtems_task_self()); \ - printf(str, ##__VA_ARGS__); \ - } while (false); - -#define CAN_DEBUG(str, ...) DEBUG(str, ##__VA_ARGS__) -#define CAN_DEBUG_BUF(str, ...) CAN_DEBUG(str, ##__VA_ARGS__) -#define CAN_DEBUG_ISR(str, ...) CAN_DEBUG(str, ##__VA_ARGS__) -#define CAN_DEBUG_LOCK(str, ...) CAN_DEBUG(str, ##__VA_ARGS__) -#define CAN_DEBUG_RX(str, ...) CAN_DEBUG(str, ##__VA_ARGS__) -#define CAN_DEBUG_TX(str, ...) CAN_DEBUG(str, ##__VA_ARGS__) -#define CAN_DEBUG_REG(str, ...) //CAN_DEBUG(str, ##__VA_ARGS__) -#define CAN_ERR(str, ...) DEBUG(str, ##__VA_ARGS__) - -#define CAN_MSG_LEN(msg) ((char *)(&((struct can_msg *)msg)->data[(uint16_t)((struct can_msg *)msg)->len]) - (char *)(msg)) - -/* Maximum Bus Reg (255) */ -#define CAN_BUS_REG_MAX (255) - -/** - * @defgroup Controller Area Network (CAN) Driver - * - * @ingroup RTEMSDeviceDrivers - * - * @brief Controller Area Network (CAN) bus and device driver support. - * - * @{ - */ - -/** - * @defgroup CANBus CAN Bus Driver - * - * @ingroup CAN - * - * @{ - */ - -/** - * @brief CAN tx fifo data structure. - */ -struct ring_buf { - /** - * @brief Pointer to array of can_msg structure. - */ - struct can_msg *pbuf; - /** - * @brief Index of the next free buffer. - */ - uint32_t head; - /** - * @brief Index of the produced buffer. - */ - uint32_t tail; - /** - * @brief Number of empty buffers. - */ - uint32_t empty_count; -}; - -/** - * @brief CAN Controller device specific operations. - * These function pointers are initialized by the CAN device driver while - * registering (can_bus_register). - */ -typedef struct can_dev_ops { - /** - * @brief Transfers CAN messages to device fifo. - * - * @param[in] priv device control structure. - * @param[in] msg can_msg message structure. - * - * @retval 0 Successful operation. - * @retval >0 error number in case of an error. - */ - int32_t (*dev_tx)(void *priv, struct can_msg *msg); - /** - * @brief Check device is ready to transfer a CAN message - * - * @param[in] priv device control structure. - * - * @retval true device ready. - * @retval false device not ready. - */ - bool (*dev_tx_ready)(void *priv); - /** - * @brief Enable/Disable CAN interrupts. - * - * @param[in] priv device control structure. - * @param[in] flag true/false to Enable/Disable CAN interrupts. - * - */ - void (*dev_int)(void *priv, bool flag); - /** - * @brief CAN device specific I/O controls. - * - * @param[in] priv device control structure. - * @param[in] buffer This depends on the cmd. - * @param[in] cmd Device specific I/O commands. - * - * @retval 0 Depends on the cmd. - */ - int32_t (*dev_ioctl)(void *priv, void *buffer, size_t cmd); -} can_dev_ops; - -/** - * @name CAN bus control - * - * @{ - */ - -/** - * @brief Obtains the bus. - * - * This command has no argument. - */ -typedef struct can_bus { - /** - * @brief Device specific control. - */ - void *priv; - /** - * @brief Device controller index. - */ - uint8_t index; - /** - * @brief Device specific operations. - */ - struct can_dev_ops *can_dev_ops; - /** - * @brief tx fifo. - */ - struct ring_buf tx_fifo; - /** - * @brief Counting semaphore id (for fifo sync). - */ - rtems_id tx_fifo_sem_id; - - /* FIXME: Using only one CAN msg buffer, Should create a ring buffer */ - /** - * @brief rx fifo. - */ - struct can_msg can_rx_msg; - /** - * @brief Mutex to handle bus concurrency. - */ - rtems_mutex mutex; - /** - * @brief Destroys the bus. - * - * @param[in] bus control structure. - */ - void (*destroy)(struct can_bus *bus); -#ifdef CAN_DEBUG_LOCK - - /** - * @brief For debugging semaphore obtain/release. - */ - int sem_count; - -#endif /* CAN_DEBUG_LOCK */ - -} can_bus; - -/** @} */ - -/** - * @brief Register a CAN node with the CAN bus driver. - * - * @param[in] bus bus control structure. - * @param[in] bus_path path of device node. - * - * @retval >=0 rtems status. - */ -rtems_status_code can_bus_register(can_bus *bus, const char *bus_path); - -/** - * @brief Allocate and initilaize bus control structure. - * - * @param[in] size Size of the bus control structure. - * - * @retval NULL No memory available. - * @retval Address Pointer to the allocated bus control structure. - */ -can_bus *can_bus_alloc_and_init(size_t size); - -/** - * @brief initilaize bus control structure. - * - * @param[in] bus bus control structure. - * - * @retval 0 success. - * @retval >0 error number. - */ -int can_bus_init(can_bus *bus); - -/** - * @brief Initiates CAN message transfer. - * - * Should be called with CAN interrupt disabled. - * - * @param[in] bus Bus control structure. - * - * @retval 0 success. - * @retval >0 error number. - */ -int can_tx_done(struct can_bus *bus); - -/** - * @brief Sends the received CAN message to the application. - * - * Should be called by the device when CAN message should be sent to applicaiton. - * Should be called only with CAN interrupts disabled. - * - * @param[in] bus bus control structure. - * @param[in] msg can_msg structure. - * - * @retval 0 success. - * @retval >0 error number. - */ -int can_receive(struct can_bus *bus, struct can_msg *msg); - -/** - * @brief Prints the can_msg values pointed by msg. - * - * @param[in] msg can_msg structure. - * - */ -void can_print_msg(struct can_msg const *msg); - -/** @} */ /* end of CAN device driver */ - -/** @} */ - -#endif /* _DEV_CAN_CAN_H */ diff --git a/cpukit/include/dev/can/canqueueimpl.h b/cpukit/include/dev/can/canqueueimpl.h deleted file mode 100644 index ef0d56fe31..0000000000 --- a/cpukit/include/dev/can/canqueueimpl.h +++ /dev/null @@ -1,231 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup CANBus - * - * @brief Controller Area Network (CAN) Bus Implementation - * - */ - -/* - * Copyright (C) 2022 Prashanth S <fishesprashanth@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _DEV_CAN_CAN_QUEUE_H -#define _DEV_CAN_CAN_QUEUE_H - -#include <rtems/imfs.h> -#include <rtems/thread.h> - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include <dev/can/can-msg.h> -#include <dev/can/can.h> - -/** - * @defgroup Controller Area Network (CAN) Driver - * - * @ingroup RTEMSDeviceDrivers - * - * @brief Controller Area Network (CAN) bus and device driver support. - * - * @{ - */ - -/** - * @defgroup CANBus CAN Bus Driver - * - * @ingroup CAN - * - * @{ - */ - -/** - * @brief Create CAN tx buffers. - * - * @param[in] bus Bus control structure. - * - * @retval 0 Successful operation. - * @retval >0 error number in case of an error. - */ -static rtems_status_code can_bus_create_tx_buffers(struct can_bus *bus); - -/** - * @brief Free CAN tx buffers. - * - * @param[in] bus Bus control structure. - * - */ -static void can_bus_free_tx_buffers(struct can_bus *bus); - -/** - * @brief Check for atleast one empty CAN tx buffer. - * - * @param[in] bus Bus control structure. - * - * @retval true If atleast one CAN buffer is empty. - * @retval false If no CAN buffer is empty. - */ -static bool can_bus_tx_buf_is_empty(struct can_bus *bus); - -/** - * @brief Get a produced tx buffer to transmit from the tx fifo. - * - * @param[in] bus Bus control structure. - * - * @retval can_msg Pointer to can_msg structure buffer. - * @retval NULL If no can_msg buffer. - */ -static struct can_msg *can_bus_tx_get_data_buf(struct can_bus *bus); - -/** - * @brief Get a empty tx buffer. - * - * @param[in] bus Bus control structure. - * - * @retval can_msg Pointer to can_msg structure buffer. - * @retval NULL If no empty can_msg buffer. - */ -static struct can_msg *can_bus_tx_get_empty_buf(struct can_bus *bus); - -/** - * @brief Creates tx buffers for the CAN bus driver. - * - * @param[in] bus Bus control structure. - * - * @retval rtems_status_code - */ -static rtems_status_code can_bus_create_tx_buffers(struct can_bus *bus) -{ - bus->tx_fifo.pbuf = (struct can_msg *)malloc(CAN_TX_BUF_COUNT * - sizeof(struct can_msg)); - if (bus->tx_fifo.pbuf == NULL) { - CAN_ERR("can_create_tx_buffers: malloc failed\n"); - return RTEMS_NO_MEMORY; - } - - bus->tx_fifo.empty_count = CAN_TX_BUF_COUNT; - - return RTEMS_SUCCESSFUL; -} - -/** - * @brief Free tx buffers for the CAN bus driver. - * - * @param[in] bus Bus control structure. - * - */ -static void can_bus_free_tx_buffers(struct can_bus *bus) -{ - free(bus->tx_fifo.pbuf); -} - -/** - * @brief Check if there is atleast one tx buffer in the CAN - * bus driver. - * - * @param[in] bus Bus control structure. - * - * @retval true - If there is at least one free tx buffer. - * false - If there is no free tx buffer. - */ -static bool can_bus_tx_buf_is_empty(struct can_bus *bus) -{ - if (bus->tx_fifo.empty_count == 0) { - return false; - } - - return true; -} - -/** - * @brief To get a can_msg tx buf which contains valid data to send in - * in the CAN bus. - * - * Note: freeing the returned data buf is done in the same function, - * So the returned buffer should be sent before releasing the - * lock acquired while calling this function. - * - * @param[in] bus Bus control structure. - * - * @retval *can_msg - If there is atleast one tx buffer to send in the CAN bus. - * NULL - If there is no valid tx buffer. - */ -static struct can_msg *can_bus_tx_get_data_buf(struct can_bus *bus) -{ - struct can_msg *msg = NULL; - - if (bus->tx_fifo.empty_count == CAN_TX_BUF_COUNT || - bus->tx_fifo.tail >= CAN_TX_BUF_COUNT) { - CAN_DEBUG_BUF("can_bus_tx_get_data_buf: All buffers are empty\n"); - return NULL; - } - - msg = &bus->tx_fifo.pbuf[bus->tx_fifo.tail]; - bus->tx_fifo.empty_count++; - bus->tx_fifo.tail = (bus->tx_fifo.tail + 1) % CAN_TX_BUF_COUNT; - - return msg; -} - -/** - * @brief To get a can_msg tx buf which is empty (contains no valid data). - * - * Note: marking the returned buf valid is done in the same function - * So a valid CAN message should be copied to the returned buffer before - * releasing the lock acquired while calling this function. - * - * @param[in] bus Bus control structure. - * - * @retval *can_msg - If there is atleast one empty tx buffer. - * NULL - If there is no empty tx buffer. - */ -static struct can_msg *can_bus_tx_get_empty_buf(struct can_bus *bus) -{ - struct can_msg *msg = NULL; - - /* Check whether there is a empty CAN msg buffer */ - if (can_bus_tx_buf_is_empty(bus) == false) { - CAN_DEBUG_BUF("can_bus_tx_get_empty_buf: No empty buffer\n"); - return NULL; - } - - bus->tx_fifo.empty_count--; - - /* tx_fifo.head always points to a empty buffer if there is atleast one */ - msg = &bus->tx_fifo.pbuf[bus->tx_fifo.head]; - bus->tx_fifo.head = (bus->tx_fifo.head + 1) % CAN_TX_BUF_COUNT; - - return msg; -} - -/** @} */ /* end of CAN device driver */ - -/** @} */ - -#endif /*_DEV_CAN_CAN_QUEUE_H */ diff --git a/cpukit/include/dev/flash/flashdev.h b/cpukit/include/dev/flash/flashdev.h index d1dc08a5c4..6759357206 100644 --- a/cpukit/include/dev/flash/flashdev.h +++ b/cpukit/include/dev/flash/flashdev.h @@ -39,6 +39,11 @@ #include <rtems/thread.h> #include <sys/types.h> +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct rtems_flashdev rtems_flashdev; /** @@ -454,6 +459,10 @@ void rtems_flashdev_destroy_and_free( rtems_flashdev *flash ); +#ifdef __cplusplus +} +#endif + /** @} */ #endif /* _DEV_FLASHDEV_H */ diff --git a/cpukit/include/machine/_timecounter.h b/cpukit/include/machine/_timecounter.h index 127e5f6fd3..e20e051f84 100644 --- a/cpukit/include/machine/_timecounter.h +++ b/cpukit/include/machine/_timecounter.h @@ -3,6 +3,8 @@ /** * @file * + * @ingroup RTEMSScoreTimecounter + * * @brief This header file provides timecounter definitions for the kernel space * (_KERNEL is defined before including <sys/time.h>) and RTEMS. */ diff --git a/cpukit/include/pci/irq.h b/cpukit/include/pci/irq.h index 4069f1ffa8..8617dd1680 100644 --- a/cpukit/include/pci/irq.h +++ b/cpukit/include/pci/irq.h @@ -38,18 +38,9 @@ #ifndef __PCI_IRQ_H__ #define __PCI_IRQ_H__ -#include <rtems/irq-extension.h> +#include <rtems/rtems/intr.h> #include <rtems/score/basedefs.h> -/* - * FIXME: This should be available via the IRQ extensions API. - * - * https://devel.rtems.org/ticket/3269 - */ -void BSP_shared_interrupt_clear(int irq); -void BSP_shared_interrupt_unmask(int irq); -void BSP_shared_interrupt_mask(int irq); - /* PCI Handler (ISR) called when IRQ is generated by any of the PCI devices * connected to the same PCI IRQ Pin. This has been defined the same way as * rtems_interrupt_handler in order for BSPs to "direct-map" the register @@ -106,7 +97,7 @@ static inline int pci_interrupt_unregister(int irq, pci_isr isr, */ static inline void pci_interrupt_unmask(int irq) { - BSP_shared_interrupt_unmask(irq); + (void)rtems_interrupt_vector_enable((rtems_vector_number)irq); } /* Disable shared PCI IRQ handler. This function will mask the interrupt @@ -122,7 +113,7 @@ static inline void pci_interrupt_unmask(int irq) */ static inline void pci_interrupt_mask(int irq) { - BSP_shared_interrupt_mask(irq); + (void)rtems_interrupt_vector_disable((rtems_vector_number)irq); } /* Acknowledge the interrupt controller by writing to the interrupt controller. @@ -136,7 +127,7 @@ static inline void pci_interrupt_mask(int irq) */ static inline void pci_interrupt_clear(int irq) { - BSP_shared_interrupt_clear(irq); + (void)rtems_interrupt_clear((rtems_vector_number)irq); } #endif /* !__PCI_IRQ_H__ */ diff --git a/cpukit/include/rtems/score/io.h b/cpukit/include/rtems/base64.h index 9cd401eb1d..58e48a8c33 100644 --- a/cpukit/include/rtems/score/io.h +++ b/cpukit/include/rtems/base64.h @@ -3,14 +3,14 @@ /** * @file * - * @ingroup RTEMSScoreIO + * @ingroup RTEMSImplBase64 * * @brief This header file provides the interfaces of the - * @ref RTEMSScoreIO. + * @ref RTEMSImplBase64. */ /* - * Copyright (c) 2017 embedded brains GmbH & Co. KG + * Copyright (C) 2020, 2024 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,42 +34,35 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _RTEMS_SCORE_IO_H -#define _RTEMS_SCORE_IO_H +#ifndef _RTEMS_BASE64_H +#define _RTEMS_BASE64_H -#include <rtems/score/basedefs.h> - -#include <stdarg.h> +#include <rtems/dev/io.h> #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** - * @defgroup RTEMSScoreIO IO Handler + * @defgroup RTEMSImplBase64 Base64 Encoding and Decoding * - * @ingroup RTEMSScore + * @ingroup RTEMSImpl * - * @brief This group contains the IO Handler implementation. + * @brief This group contains support functions for base64 and base64url + * encoding and decoding. * * @{ */ -typedef void ( *IO_Put_char )( int c, void *arg ); - -int _IO_Printf( - IO_Put_char put_char, - void *arg, - char const *fmt, - ... -) RTEMS_PRINTFLIKE( 3, 4 ); +/** + * @brief Maps a 6-bit integer to the corresponding base64 encoding. + */ +extern const uint8_t _Base64_Encoding[ 64 ]; -int _IO_Vprintf( - IO_Put_char put_char, - void *arg, - char const *fmt, - va_list ap -); +/** + * @brief Maps a 6-bit integer to the corresponding base64url encoding. + */ +extern const uint8_t _Base64url_Encoding[ 64 ]; /** * @brief Outputs the source buffer in base64 encoding. @@ -93,7 +86,7 @@ int _IO_Vprintf( * * @return Returns the count of output characters. */ -int _IO_Base64( +int _Base64_Encode( IO_Put_char put_char, void *arg, const void *src, @@ -124,7 +117,7 @@ int _IO_Base64( * * @return Returns the count of output characters. */ -int _IO_Base64url( +int _Base64url_Encode( IO_Put_char put_char, void *arg, const void *src, @@ -134,17 +127,72 @@ int _IO_Base64url( ); /** - * @brief Issues a couple of no-operation instructions. + * @brief Represents the base64 and base64url decoder state. + */ +typedef enum { + BASE64_DECODE_STATE_0, + BASE64_DECODE_STATE_1, + BASE64_DECODE_STATE_2, + BASE64_DECODE_STATE_3 +} Base64_Decode_state; + +/** + * @brief Contains the base64 and base64url decoder control. + */ +typedef struct { + Base64_Decode_state state; + uint8_t *target; + const uint8_t *target_end; +} Base64_Decode_control; + +/** + * @brief Maps a 7-bit character to the associated 6-bit integer as defined by + * the base64 or base64url encoding or a special value. + */ +extern const uint8_t _Base64_Decoding[ 128 ]; + +/** + * @brief Initializes the base64 decoder. + * + * @param[out] self is the base64 decoder control to initialize. + * + * @param[out] target is the base address of the target area for decoding. + * + * @param target_size is the size in bytes of the target area for decoding. + */ +void _Base64_Decode_initialize( + Base64_Decode_control *self, + uint8_t *target, + size_t target_size +); + +/** + * @brief Represents the base64 and base64url decoder status. + */ +typedef enum { + BASE64_DECODE_SUCCESS, + BASE64_DECODE_OVERFLOW, + BASE64_DECODE_INVALID_INPUT +} Base64_Decode_status; + +/** + * @brief Decodes the character. + * + * The decoder accepts base64 and base64url encodings. White space is ignored. * - * This function may be used to burn a couple of processor cycles with minimum - * impact on the system bus. It may be used in busy wait loops. + * @param[in, out] self is the base64 decoder control. + * + * @param ch is the character to decode. */ -void _IO_Relax( void ); +Base64_Decode_status _Base64_Decode( + Base64_Decode_control *self, + char ch +); -/** @} */ +/** @} */ #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* _RTEMS_SCORE_IO_H */ +#endif /* _RTEMS_BASE64_H */ diff --git a/cpukit/include/rtems/confdefs/clock.h b/cpukit/include/rtems/confdefs/clock.h index 26519cc70b..e57daa899b 100644 --- a/cpukit/include/rtems/confdefs/clock.h +++ b/cpukit/include/rtems/confdefs/clock.h @@ -70,6 +70,11 @@ #warning "The clock ticks per second is not an integer" #endif +#if defined(CONFIGURE_TICKS_PER_TIMESLICE) \ + && CONFIGURE_TICKS_PER_TIMESLICE <= 0 + #error "CONFIGURE_TICKS_PER_TIMESLICE shall be greater than zero" +#endif + #if CONFIGURE_MICROSECONDS_PER_TICK <= 0 #error "CONFIGURE_MICROSECONDS_PER_TICK must be positive" #endif diff --git a/cpukit/include/rtems/config.h b/cpukit/include/rtems/config.h index 40d703d61a..a19d809cf9 100644 --- a/cpukit/include/rtems/config.h +++ b/cpukit/include/rtems/config.h @@ -438,7 +438,7 @@ const char *rtems_get_version_string( void ); * @endparblock */ #define rtems_configuration_get_interrupt_stack_size() \ - ((size_t) _ISR_Stack_size) + ((size_t) _ISR_Stack_size_object) /* Generated from spec:/rtems/config/if/get-maximum-extensions */ diff --git a/cpukit/include/rtems/crc.h b/cpukit/include/rtems/crc.h new file mode 100644 index 0000000000..1158dbcd7b --- /dev/null +++ b/cpukit/include/rtems/crc.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSImplCRC + * + * @brief This header file provides the interfaces of the + * @ref RTEMSImplCRC. + */ + +/* + * Copyright (C) 2024 embedded brains GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTEMS_CRC_H +#define _RTEMS_CRC_H + +#include <stddef.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup RTEMSImplCRC Cyclic Redundancy Check (CRC) Support + * + * @ingroup RTEMSImpl + * + * @brief This group contains functions to calculate + * Cyclic Redundancy Check (CRC) values. + * + * @{ + */ + + +/** + * @brief This constant represents the default CRC-24Q seed state. + */ +#define CRC24Q_SEED 0U + +/** + * @brief This constant provides a mask to get a valid CRC-24Q value from the + * integers returned by _CRC24Q_Update() and _CRC24Q_Sequence_update(). + */ +#define CRC24Q_MASK 0xffffffU + +/** + * @brief Updates the CRC-24Q state using a byte. + * + * @param crc is the input CRC-24Q state. + * + * @param byte is the byte updating the input CRC-24Q state. + * + * @return Returns the updated CRC-24Q state. Use the #CRC24Q_MASK to get a + * valid CRC-24Q value. + */ +uint32_t _CRC24Q_Update( uint32_t crc, uint8_t byte ); + +/** + * @brief Updates the CRC-24Q state using a sequence of bytes. + * + * @param crc is the input CRC-24Q state. + * + * @param bytes[in] is the sequence of bytes updating the input CRC-24Q state. + * + * @param size_in_bytes is the size in bytes of the byte sequence. + * + * @return Returns the updated CRC-24Q state. Use the #CRC24Q_MASK to get a + * valid CRC-24Q value. + */ +uint32_t _CRC24Q_Sequence_update( + uint32_t crc, + const void *bytes, + size_t size_in_bytes +); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_CRC_H */ diff --git a/cpukit/include/rtems/dev/io.h b/cpukit/include/rtems/dev/io.h new file mode 100644 index 0000000000..b8bcde7af4 --- /dev/null +++ b/cpukit/include/rtems/dev/io.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSDeviceIO + * + * @brief This header file provides the interfaces of the + * @ref RTEMSDeviceIO. + */ + +/* + * Copyright (C) 2017, 2023 embedded brains GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTEMS_DEV_IO_H +#define _RTEMS_DEV_IO_H + +#include <rtems/score/basedefs.h> + +#include <stdarg.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup RTEMSDeviceIO Device I/O Support + * + * @ingroup RTEMSDeviceDrivers + * + * @brief This group contains the Device I/O Support API and implementation. + * + * @{ + */ + +/** + * @brief This type defines the put character handler. + * + * @param c is the character to put. + * + * @param arg is the user-provided argument. + */ +typedef void ( *IO_Put_char )( int c, void *arg ); + +/** + * @brief Prints characters using the put character handler according to the + * format string. + * + * @param put_char is the put character handler. + * + * @param arg is the user-provided argument for the put character handler. + * + * @param fmt is the printf()-style format string. + * + * @param ... is the list of parameters required by the format string. + * + * @return Returns the count of put characters. + */ +int _IO_Printf( + IO_Put_char put_char, + void *arg, + char const *fmt, + ... +) RTEMS_PRINTFLIKE( 3, 4 ); + +/** + * @brief Prints characters using the put character handler according to the + * format string. + * + * @param put_char is the put character handler. + * + * @param arg is the user-provided argument for the put character handler. + * + * @param fmt is the printf()-style format string. + * + * @param ap is the argument list required by the format string. + * + * @return Returns the count of put characters. + */ +int _IO_Vprintf( + IO_Put_char put_char, + void *arg, + char const *fmt, + va_list ap +); + +/** + * @brief Issues a couple of no-operation instructions. + * + * This function may be used to burn a couple of processor cycles with minimum + * impact on the system bus. It may be used in busy wait loops. + */ +void _IO_Relax( void ); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_DEV_IO_H */ diff --git a/cpukit/include/rtems/imfs.h b/cpukit/include/rtems/imfs.h index 7db9b4e462..405f489ab3 100644 --- a/cpukit/include/rtems/imfs.h +++ b/cpukit/include/rtems/imfs.h @@ -477,7 +477,7 @@ extern void IMFS_fsunmount( */ extern int rtems_tarfs_load( const char *mountpoint, - uint8_t *tar_image, + const void *tar_image, size_t tar_size ); diff --git a/cpukit/include/rtems/libio.h b/cpukit/include/rtems/libio.h index cb0e6879a9..5424a2a03c 100644 --- a/cpukit/include/rtems/libio.h +++ b/cpukit/include/rtems/libio.h @@ -56,6 +56,7 @@ #include <rtems/fs.h> #include <rtems/chain.h> #include <rtems/score/atomic.h> +#include <rtems/termiosdevice.h> #ifdef __cplusplus extern "C" { @@ -1360,7 +1361,7 @@ typedef struct { /** * @brief Parameter block for open/close. */ -typedef struct { +typedef struct rtems_libio_open_close_args { rtems_libio_t *iop; uint32_t flags; uint32_t mode; @@ -1902,7 +1903,7 @@ typedef struct rtems_termios_callbacks { int (*setAttributes)(int minor, const struct termios *t); int (*stopRemoteTx)(int minor); int (*startRemoteTx)(int minor); - int outputUsesInterrupts; + rtems_termios_device_mode outputUsesInterrupts; } rtems_termios_callbacks; static inline void rtems_termios_initialize( void ) diff --git a/cpukit/include/rtems/linkersets.h b/cpukit/include/rtems/linkersets.h index ef1b0d38d4..a5d7b1b037 100644 --- a/cpukit/include/rtems/linkersets.h +++ b/cpukit/include/rtems/linkersets.h @@ -1,5 +1,13 @@ /* SPDX-License-Identifier: BSD-2-Clause */ +/** + * @file + * + * @ingroup RTEMSAPILinkerSets + * + * @brief This header file provides the linker sets API. + */ + /* * Copyright (C) 2015, 2020 embedded brains GmbH & Co. KG * @@ -34,6 +42,36 @@ extern "C" { #endif /* __cplusplus */ +/** + * @ingroup RTEMSImpl + * + * @brief Obfuscates a pointer to prevent compiler optimizations. + * + * @param ptr is the pointer to obfuscate. + * + * @return Returns the unsigned integer representation of the obfuscated + * pointer. + */ +static inline uintptr_t _Linker_set_Obfuscate( const void *ptr ) +{ + uintptr_t addr; + + addr = (uintptr_t) ptr; + RTEMS_OBFUSCATE_VARIABLE( addr ); + + return addr; +} + +/** + * @defgroup RTEMSAPILinkerSets Linker Sets + * + * @ingroup RTEMSAPI + * + * @brief This group contains the linker sets API. + * + * @{ + */ + #define RTEMS_LINKER_SET_BEGIN( set ) \ _Linker_set_##set##_begin @@ -129,16 +167,6 @@ extern "C" { decl \ RTEMS_SECTION( ".rtemsrwset." #set ".content" ) -static inline uintptr_t _Linker_set_Obfuscate( const void *ptr ) -{ - uintptr_t addr; - - addr = (uintptr_t) ptr; - RTEMS_OBFUSCATE_VARIABLE( addr ); - - return addr; -} - #define RTEMS_LINKER_SET_SIZE( set ) \ ( _Linker_set_Obfuscate( RTEMS_LINKER_SET_END( set ) ) \ - _Linker_set_Obfuscate( RTEMS_LINKER_SET_BEGIN( set ) ) ) @@ -157,6 +185,8 @@ static inline uintptr_t _Linker_set_Obfuscate( const void *ptr ) ++item \ ) +/** @} */ + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/cpukit/include/rtems/posix/posixapi.h b/cpukit/include/rtems/posix/posixapi.h index 24c1dc51e0..5d78573ef7 100644 --- a/cpukit/include/rtems/posix/posixapi.h +++ b/cpukit/include/rtems/posix/posixapi.h @@ -3,10 +3,10 @@ /** * @file * - * @brief POSIX API Implementation + * @ingroup POSIXAPI * - * This include file defines the top level interface to the POSIX API - * implementation in RTEMS. + * @brief This header file provides interfaces used by the POSIX API + * implementation. */ /* diff --git a/cpukit/include/rtems/posix/spinlockimpl.h b/cpukit/include/rtems/posix/spinlockimpl.h index 855e57cc14..10424f1961 100644 --- a/cpukit/include/rtems/posix/spinlockimpl.h +++ b/cpukit/include/rtems/posix/spinlockimpl.h @@ -2,11 +2,11 @@ /** * @file - * - * @brief Inlined Routines from the POSIX Spinlock Manager * - * This file contains the static inlin implementation of the inlined - * routines from the POSIX Spinlock Manager. + * @ingroup POSIXAPI + * + * @brief This header file provides interfaces used by the POSIX Spinlock + * implementation. */ /* diff --git a/cpukit/include/rtems/regulator.h b/cpukit/include/rtems/regulator.h new file mode 100644 index 0000000000..442040a180 --- /dev/null +++ b/cpukit/include/rtems/regulator.h @@ -0,0 +1,502 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RegulatorAPI + * + * @brief This header file defines the Regulator API. + * + */ + +/* + * Copyright (C) 2023 On-Line Applications Research Corporation (OAR) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @defgroup RegulatorAPI Regulator API + * + * @brief Regulator APIs + * + * The Regulator provides a set of APIs to manage input sources which + * produces bursts of message traffic. + * + * The regulator is designed to sit logically between two entities -- a + * source and a destination, where it limits the traffic sent to the + * destination to prevent it from being flooded with messages from the + * source. This can be used to accommodate bursts of input from a source + * and meter it out to a destination. The maximum number of messages + * which can be buffered in the regulator is specified by the + * @a maximum_messages field in the @a rtems_regulator_attributes + * structure passed as an argument to @a rtems_regulator_create(). + * + * The regulator library accepts an input stream of messages from a + * source and delivers them to a destination. The regulator assumes that the + * input stream from the source contains sporadic bursts of data which can + * exceed the acceptable rate of the destination. By limiting the message rate, + * the regulator prevents an overflow of messages. + * + * The regulator can be configured for the input buffering required to manage + * the maximum burst and for the metering rate for the output. The output rate + * is in messages per second. If the sender produces data too fast, the + * regulator will buffer the configured number of messages. + * + * A configuration capability is provided to allow for adaptation to different + * message streams. The regulator can also support running multiple instances, + * which could be used on independent message streams. + * + * The regulator provides a simple interface to the application for avoiding + * bursts of input from a fast source overflowing a slower destination. + * + * It is assumed that the application has a design limit on the number of + * messages which may be buffered. All messages accepted by the regulator, + * assuming no overflow on input, will eventually be output by the Delivery + * thread. + * + * A regulator instance is used as follows from the producer/source side: + * + * @code + * while (1) + * use rtems_regulator_obtain_buffer to obtain a buffer + * input operation to fetch data into the buffer + * rtems_regulator_send(buffer, size of message) + * @endcode + * + * The delivery of message buffers to the Destination and subsequent + * release is performed in the context of the delivery thread by either + * the delivery function or delivery thread. Details are below. + * + * The sequence diagram below shows the interaction between a message Source, + * a Regulator instance, and RTEMS, given the usage described in the above + * paragraphs. + * + * \startuml "Regulator Application Input Source Usage" + * Source -> Regulator : rtems_regulator_obtain_buffer(regulator, buffer) + * Regulator -> RTEMS : rtems_partition_get_buffer(id, buffer) + * RTEMS --> Regulator : rtems_status_code + * Regulator --> Source : rtems_status_code + * Source -> Regulator : rtems_regulator_send(regulator, message, length) + * Regulator -> RTEMS : rtems_message_queue_send(id, message, size) + * RTEMS --> Regulator : rtems_status_code + * Regulator --> Source : rtems_status_code + * \enduml + * + * As illustrated in the sequence diagram, the Source usually corresponds + * to application software reading a system input. The Source obtains a + * buffer from the Regulator instance and fills it with incoming data. + * The application explicitly obtaining a buffer and filling it in allows + * for zero copy operations on the Source side. + * + * The Source then sends the buffer to the Regulator instance. The Regulator + * the sends the buffer via a message queue which to the Delivery thread. + * The Delivery thread executes periodically at a rate specified at + * Regulation creation. At each period, the Delivery thread attempts to + * receive up to a configured number of buffers and invoke the Delivery + * function to deliver them to the Destination. + * + * The Delivery function is provided by the application for this + * specific Regulator instance. Depending on the Destination, it may use + * a function which copies the buffer contents (e.g., write()) or which + * operates directly on the buffer contents (e.g. DMA from buffer). In + * the case of a Destination which copies the buffer contents, the buffer + * can be released via @a rtems_regulator_release_buffer() as soon as the + * function or copying completes. In the case where the delivery uses the + * buffer and returns, the call to @a rtems_regulator_release_buffer() + * will occur when the use of the buffer is complete (e.g. completion + * of DMA transfer). This explicit and deliberate exposure of buffering + * provides the application with the ability to avoid copying the contents. + * + * After the Source has sent the message to the Regulator instance, + * the Source is free to process another input and the Regulator + * instance will ensure that the buffer is delivered to the Delivery + * function and Destination. + * + * The Regulator implementation uses the RTEMS Classic API Partition Manager + * to manage the buffer pool and the RTEMS Classic API Message Queue + * Manager to send the buffer to the Delivery thread. + */ + +#ifndef REGULATOR_H +#define REGULATOR_H + +#include <stdlib.h> + +#include <rtems.h> + +/** + * @ingroup RegulatorAPI + * + * @brief Regulator Delivery Function Type + * + * The user provides a function which is invoked to deliver a message + * to the output. It is invoked by the Delivery thread created as part + * of @a rtems_regulator_create(). The priority and stack size of the + * Delivery thread are specified in the regulator attribute set. + * + * It takes three parameters: + * + * @param[in] context is an untyped pointer to a user context + * @param[in] message points to the message + * @param[in] length is the message size + * + * The following is an example deliverer function. It assumes that the + * application has defined the my_context_t structure and it has at least + * the socket field. The @a message passed in originated with an + * application source which obtained the @a message buffer using + * @a rtems_regulator_obtain_buffer(), filled it in with source data, + * and used @a rtems_regulator_send() to hand to the regulator instance + * for later delivery. + * + * @code + * bool my_deliverer( + * void *context, + * void *message, + * size_t length + * ) + * { + * my_context_t *my_context; + * + * my_context = (my_context_t *)context; + * + * write(my_context->socket, message, length); + * rtems_regulator_release_buffer(message); + * // return false to indicate we released the buffer + * return false; + * } + * @endcode + * + * The delivery function returns true to indicate that the delivery thread + * should release the buffer or false to indicate that it released the + * buffer. If the delivery function invokes a function like @a write() + * to deliver the message to the destination, then the buffer can be + * released immediately after the call. If the delivery function does + * something like setting up a DMA transfer of the buffer, it cannot be + * released until after the DMA is complete. + * + * The following sequence diagram shows the behavior of the Delivery thread + * body and its interaction with the user-supplied deliverer() function. + * + * \startuml "Regulator Delivery Thread Body" + * loop while (1) + * "Delivery Thread" -> RTEMS : rtems_rate_monotonic_period(id, delivery_thread_period) + * loop for 0 : maximum_to_dequeue_per_period + * "Delivery Thread" -> RTEMS : rtems_message_queue_receive(id, message, size, wait, 0) + * RTEMS --> "Delivery Thread" : rtems_status_code + * group if [rtems_status_code != RTEMS_SUCCESSFUL] + * RTEMS -> "Delivery Thread" : break + * end + * "Delivery Thread" -> Application : deliverer(context, buffer, length) + * "Delivery Thread" -> RTEMS : rtems_partition_return_buffer(id, buffer) + * RTEMS --> "Delivery Thread" : rtems_status_code + * end + * end + * \enduml + * + * In the above sequence diagram, the key points are: + * + * -# The Delivery Thread Body is periodically executed. + * -# During each period, up to the instance configuration parameter + * @a maximum_to_dequeue_per_period may be dequeued and + * passed the application's delivery function for processing. + * + * Note that the application explicitly obtains buffers from the + * regulator instance but that the release may be done by Delivery + * Thread, the Delivery function, or later when the buffer contents + * are transferred. + */ +typedef bool (*rtems_regulator_deliverer)( + void *context, + void *message, + size_t length +); + +/** + * @ingroup RegulatorAPI + * + * @brief Attributes for Regulator Instance + * + * An instance of this structure must be populated by the application + * before creating an instance of the regulator. These settings tailor + * the behavior of the regulator instance. + */ +typedef struct { + /** Application function to invoke to output a message to the destination*/ + rtems_regulator_deliverer deliverer; + + /** Context pointer to pass to deliver function */ + void *deliverer_context; + + /** Maximum size message to process */ + size_t maximum_message_size; + + /** Maximum number of messages to be able to buffer */ + size_t maximum_messages; + + /** Priority of Delivery thread */ + rtems_task_priority delivery_thread_priority; + + /** Stack size of Delivery thread */ + size_t delivery_thread_stack_size; + + /** Period (in ticks) of Delivery thread */ + rtems_interval delivery_thread_period; + + /** Maximum messages to dequeue per period */ + size_t maximum_to_dequeue_per_period; + +} rtems_regulator_attributes; + +/** + * @ingroup RegulatorAPI + * + * @brief Statistics for Regulator Instance + * + * An instance of this structure is provided to the directive + * @a rtems_regulator_get_statistics and is filled in by that service. + */ +typedef struct { + /** Number of successfully obtained buffers. */ + size_t obtained; + + /** Number of successfully released buffers. */ + size_t released; + + /** Number of successfully delivered buffers. */ + size_t delivered; + + /** Rate Monotonic Period statistics for Delivery Thread */ + rtems_rate_monotonic_period_statistics period_statistics; + +} rtems_regulator_statistics; + +/** + * @ingroup RegulatorAPI + * + * @brief Regulator Internal Structure + */ +struct _Regulator_Control; + +/** + * @ingroup RegulatorAPI + * + * @brief Regulator Instance + * + * This is used by the application as the handle to a Regulator instance. + */ +typedef struct _Regulator_Control *rtems_regulator_instance; + +/** + * @ingroup RegulatorAPI + * + * @brief Create a regulator + * + * This function creates an instance of a regulator. It uses the provided + * @a attributes to create the instance return in @a regulator. This instance + * will allocate the buffers associated with the regulator instance as well + * as the Delivery thread. + * + * The @a attributes structure defines the priority and stack size of + * the Delivery thread dedicated to this regulator instance. It also + * defines the period of the Delivery thread and the maximum number of + * messages that may be delivered per period via invocation of the + * delivery function. + * + * For each regulator instance, the following resources are allocated: + * + * - A memory area for the regulator control block using @a malloc(). + * - A RTEMS Classic API Message Queue is constructed with message + * buffer memory allocated using @a malloc(). Each message consists + * of a pointer and a length. + * - A RTEMS Classic API Partition. + * - A RTEMS Classic API Rate Monotonic Period. + * + * @param[in] attributes specify the regulator instance attributes + * @param[inout] regulator will point to the regulator instance + * + * @return an RTEMS status code indicating success or failure. + * + * @note This function allocates memory for the buffers holding messages, + * an Delivery thread and an RTEMS partition. When it executes, the + * Delivery thread will create an RTEMS rate monotonic period. + */ +rtems_status_code rtems_regulator_create( + rtems_regulator_attributes *attributes, + rtems_regulator_instance **regulator +); + +/** + * @ingroup RegulatorAPI + * + * @brief Delete a regulator + * + * This function is used to delete the specified @a regulator instance. + * + * It is the responsibility of the user to ensure that any resources + * such as sockets or open file descriptors used by the delivery + * function are also deleted. It is likely safer to delete those + * delivery resources after deleting the regulator instance rather than + * before. + * + * @param[in] regulator is the instance to delete + * @param[in] ticks is the maximum number of ticks to wait for + * the delivery thread to shutdown. + * + * @return an RTEMS status code indicating success or failure. + * + * @note This function deallocates the resources allocated during + * @a rtems_regulator_create(). + */ +rtems_status_code rtems_regulator_delete( + rtems_regulator_instance *regulator, + rtems_interval ticks +); + +/** + * @ingroup RegulatorAPI + * + * @brief Obtain Buffer from Regulator + * + * This function is used to obtain a buffer from the regulator's pool. The + * @a buffer returned is assumed to be filled in with contents and used + * in a subsequent call to @a rtems_regulator_send(). When the @a buffer is + * delivered, it is expected to be released. If the @a buffer is not + * successfully accepted by this function, then it should be returned + * using @a rtems_regulator_release_buffer() or used to send another message. + * + * The @a buffer is of the maximum_message_size specified in the attributes + * passed in to @a rtems_regulator_create(). + * + * @param[in] regulator is the regulator instance to operate upon + * @param[out] buffer will point to the allocated buffer + * + * @return an RTEMS status code indicating success or failure. + * + * @note This function does not perform dynamic allocation. It obtains a + * buffer from the pool allocated during @a rtems_regulator_create(). + * + * @note Any attempt to write outside the buffer area is undefined. + */ +rtems_status_code rtems_regulator_obtain_buffer( + rtems_regulator_instance *regulator, + void **buffer +); + +/** + * @ingroup RegulatorAPI + * + * @brief Release Previously Obtained Regulator Buffer + * + * This function is used to release a buffer to the regulator's pool. It is + * assumed that the @a buffer returned will not be used by the application + * anymore. The @a buffer must have previously been allocated by + * @a rtems_regulator_obtain_buffer() and NOT passed to + * @a rtems_regulator_send(). + * + * If a subsequent @a rtems_regulator_send() using this @a buffer is + * successful, the @a buffer will eventually be processed by the delivery + * thread and released. + * + * @param[in] regulator is the regulator instance to operate upon + * @param[out] buffer will point to the buffer to release + * + * @return an RTEMS status code indicating success or failure. + * + * @note This function does not perform dynamic deallocation. It releases a + * buffer to the pool allocated during @a rtems_regulator_create(). + */ +rtems_status_code rtems_regulator_release_buffer( + rtems_regulator_instance *regulator, + void *buffer +); + +/** + * @ingroup RegulatorAPI + * + * @brief Send to regulator instance + * + * This function is used by the producer to send a @a message to the + * @a regulator for later delivery by the Delivery thread. The message is + * contained in the memory pointed to by @a message and is @a length + * bytes in length. + * + * It is required that the @a message buffer was obtained via + * @a rtems_regulator_obtain_buffer(). + * + * It is assumed that the @a message buffer has been filled in with + * application content to deliver. + * + * If the @a rtems_regulator_send() is successful, the buffer is enqueued + * inside the regulator instance for subsequent delivery. After the + * @a message is delivered, it may be released by either delivery + * function or the application code depending on the implementation. + * + * The status @a RTEMS_TOO_MANY is returned if the regulator's + * internal queue is full. This indicates that the configured + * maximum number of messages was insufficient. It is the + * responsibility of the caller to decide whether to hold messages, + * drop them, or print a message that the maximum number of messages + * should be increased. + * + * If @a rtems_regulator_send() is unsuccessful, it is the application's + * responsibility to release the buffer. If it is successfully sent, + * then it becomes the responsibility of the delivery function to + * release it. + * + * @param[in] regulator is the regulator instance to operate upon + * @param[out] message points to the message to deliver + * @param[out] length is the size of the message in bytes + * + * @return an RTEMS status code indicating success or failure. + * + */ +rtems_status_code rtems_regulator_send( + rtems_regulator_instance *regulator, + void *message, + size_t length +); + +/** + * @ingroup RegulatorAPI + * + * @brief Obtain statistics for regulator instance + * + * This function is used by the application to obtain statistics + * information about the regulator instance. + * + * If the @a obtained and @a released fields in the returned + * @a statistics structure are equal, then there are no buffers + * outstanding from this regulator instance. + * + * @param[in] regulator is the regulator instance to operate upon + * @param[inout] statistics points to the statistics structure to fill in + * + * @return an RTEMS status code indicating success or failure. + * + */ +rtems_status_code rtems_regulator_get_statistics( + rtems_regulator_instance *regulator, + rtems_regulator_statistics *statistics +); + +#endif /* REGULATOR_H */ diff --git a/cpukit/include/rtems/regulatorimpl.h b/cpukit/include/rtems/regulatorimpl.h new file mode 100644 index 0000000000..a5652a764d --- /dev/null +++ b/cpukit/include/rtems/regulatorimpl.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RegulatorInternalAPI + * + * @brief Regulator Library Implementation Support + */ + +/* + * Copyright (C) 2023 On-Line Applications Research Corporation (OAR) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @defgroup RegulatorInternalAPI Regulator API Internals + * + * @brief Regulator Internal Information + * + * This concerns implementation information about the Regulator. + */ + +#ifndef RTEMS_REGULATORIMPL_H +#define RTEMS_REGULATORIMPL_H + +#include <stdatomic.h> + +#include <rtems/chain.h> + + +/** + * @ingroup RegulatorInternalAPI + * + * This constant is used to indicate the regulator instance is initialized. + */ +#define REGULATOR_INITIALIZED 0xDeadF00d + +/** + * @ingroup RegulatorInternalAPI + * + * @brief Regulator Message Instance Management Structure + */ +typedef struct { + /** This points to the message contents. */ + void *buffer; + /** This is the length of the message. */ + size_t length; +} _Regulator_Message_t; + +/** + * @ingroup RegulatorInternalAPI + * + * @brief Regulator Statistics Private Structure + * + * An instance of this structure is allocated per regulator instance. + */ +typedef struct { + /** Number of successfully obtained buffers. */ + atomic_size_t obtained; + + /** Number of successfully released buffers. */ + atomic_size_t released; + + /** Number of successfully delivered buffers. */ + atomic_size_t delivered; +} _Regulator_Statistics; + +/** + * @ingroup RegulatorInternalAPI + * + * @brief Regulator Instance Private Structure + * + * An instance of this structure is allocated per regulator instance. + */ +typedef struct { + /** Has magic value when instance is usable */ + uint32_t initialized; + + /** Attributes for this instance -- copied from user */ + rtems_regulator_attributes Attributes; + + /** Pointer to allocated message memory */ + void *message_memory; + + /** Pointer to allocated memory for RTEMS Message Queue for pending buffers*/ + void *message_queue_storage; + + /** RTEMS Message Queue of pending outgoing messages */ + rtems_id queue_id; + + /** RTEMS Partition for pool of unused messages */ + rtems_id messages_partition_id; + + /** RTEMS Task for performing output */ + rtems_id delivery_thread_id; + + /** Id of period used by output thread */ + rtems_id delivery_thread_period_id; + + /** Indicates Delivery thread is running */ + bool delivery_thread_is_running; + + /** Indicates Delivery thread has been requested to exit */ + bool delivery_thread_request_exit; + + /** Indicates Delivery thread has exited */ + bool delivery_thread_has_exited; + + /** Internal Statistics */ + _Regulator_Statistics Statistics; + +} _Regulator_Control; + +#endif /* RTEMS_REGULATORIMPL_H */ diff --git a/cpukit/include/rtems/rtems/cache.h b/cpukit/include/rtems/rtems/cache.h index 20c630a3eb..d59a3fddca 100644 --- a/cpukit/include/rtems/rtems/cache.h +++ b/cpukit/include/rtems/rtems/cache.h @@ -59,6 +59,7 @@ #include <stddef.h> #include <stdint.h> +#include <rtems/rtems/status.h> #ifdef __cplusplus extern "C" { @@ -89,6 +90,10 @@ extern "C" { * * @param size is the size in bytes of the cache coherent memory area to add. * + * @retval ::RTEMS_SUCCESSFUL The requested operation was successful. + * + * @retval ::RTEMS_UNSATISFIED The requested operation was not successful. + * * @par Constraints * @parblock * The following constraints apply to this directive: @@ -102,7 +107,7 @@ extern "C" { * cause the calling task to be preempted. * @endparblock */ -void rtems_cache_coherent_add_area( void *begin, uintptr_t size ); +rtems_status_code rtems_cache_coherent_add_area( void *begin, uintptr_t size ); /* Generated from spec:/rtems/cache/if/coherent-allocate */ diff --git a/cpukit/include/rtems/rtems/mainpage.h b/cpukit/include/rtems/rtems/mainpage.h deleted file mode 100644 index f168cc3395..0000000000 --- a/cpukit/include/rtems/rtems/mainpage.h +++ /dev/null @@ -1,951 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup RTEMSImplDoxygen - * - * @brief This file exists to provide a top level description of RTEMS for - * Doxygen. - */ - -/* - * COPYRIGHT (c) 1989-2014. - * On-Line Applications Research Corporation (OAR). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @mainpage - * - * The RTEMS real-time operating systems is a layered system with each of the - * public APIs implemented in terms of a common foundation layer called the - * SuperCore. This is the Doxygen generated documentation for the RTEMS CPU - * Kit including the Classic API, POSIX API and SuperCore. - */ - -/** - * @page RTEMSPreface RTEMS History and Introduction - * - * In recent years, the cost required to develop a software product has - * increased significantly while the target hardware costs have decreased. Now - * a larger portion of money is expended in developing, using, and maintaining - * software. The trend in computing costs is the complete dominance of software - * over hardware costs. Because of this, it is necessary that formal - * disciplines be established to increase the probability that software is - * characterized by a high degree of correctness, maintainability, and - * portability. In addition, these disciplines must promote practices that aid - * in the consistent and orderly development of a software system within - * schedule and budgetary constraints. To be effective, these disciplines must - * adopt standards which channel individual software efforts toward a common - * goal. - * - * The push for standards in the software development field has been met with - * various degrees of success. The Microprocessor Operating Systems Interfaces - * (MOSI) effort has experienced only limited success. As popular as the UNIX - * operating system has grown, the attempt to develop a standard interface - * definition to allow portable application development has only recently begun - * to produce the results needed in this area. Unfortunately, very little - * effort has been expended to provide standards addressing the needs of the - * real-time community. Several organizations have addressed this need during - * recent years. - * - * The Real Time Executive Interface Definition (RTEID) was developed by - * Motorola with technical input from Software Components Group. RTEID was - * adopted by the VMEbus International Trade Association (VITA) as a baseline - * draft for their proposed standard multiprocessor, real-time executive - * interface, Open Real-Time Kernel Interface Definition (ORKID). These two - * groups are currently working together with the IEEE P1003.4 committee to - * insure that the functionality of their proposed standards is adopted as the - * real-time extensions to POSIX. - * - * This emerging standard defines an interface for the development of real-time - * software to ease the writing of real-time application programs that are - * directly portable across multiple real-time executive implementations. This - * interface includes both the source code interfaces and run-time behavior as - * seen by a real-time application. It does not include the details of how a - * kernel implements these functions. The standard's goal is to serve as a - * complete definition of external interfaces so that application code that - * conforms to these interfaces will execute properly in all real-time - * executive environments. With the use of a standards compliant executive, - * routines that acquire memory blocks, create and manage message queues, - * establish and use semaphores, and send and receive signals need not be - * redeveloped for a different real-time environment as long as the new - * environment is compliant with the standard. Software developers need only - * concentrate on the hardware dependencies of the real-time system. - * Furthermore, most hardware dependencies for real-time applications can be - * localized to the device drivers. - * - * A compliant executive provides simple and flexible real-time - * multiprocessing. It easily lends itself to both tightly-coupled and - * loosely-coupled configurations (depending on the system hardware - * configuration). Objects such as tasks, queues, events, signals, semaphores, - * and memory blocks can be designated as global objects and accessed by any - * task regardless of which processor the object and the accessing task reside. - * - * The acceptance of a standard for real-time executives will produce the same - * advantages enjoyed from the push for UNIX standardization by AT&T's System V - * Interface Definition and IEEE's POSIX efforts. A compliant multiprocessing - * executive will allow close coupling between UNIX systems and real-time - * executives to provide the many benefits of the UNIX development environment - * to be applied to real-time software development. Together they provide the - * necessary laboratory environment to implement real-time, distributed, - * embedded systems using a wide variety of computer architectures. - * - * A study was completed in 1988, within the Research, Development, and - * Engineering Center, U.S. Army Missile Command, which compared the various - * aspects of the Ada programming language as they related to the application - * of Ada code in distributed and/or multiple processing systems. Several - * critical conclusions were derived from the study. These conclusions have a - * major impact on the way the Army develops application software for embedded - * applications. These impacts apply to both in-house software development and - * contractor developed software. - * - * A conclusion of the analysis, which has been previously recognized by other - * agencies attempting to utilize Ada in a distributed or multiprocessing - * environment, is that the Ada programming language does not adequately - * support multiprocessing. Ada does provide a mechanism for multi-tasking, - * however, this capability exists only for a single processor system. The - * language also does not have inherent capabilities to access global named - * variables, flags or program code. These critical features are essential in - * order for data to be shared between processors. However, these drawbacks do - * have workarounds which are sometimes awkward and defeat the intent of - * software maintainability and portability goals. - * - * Another conclusion drawn from the analysis, was that the run time executives - * being delivered with the Ada compilers were too slow and inefficient to be - * used in modern missile systems. A run time executive is the core part of the - * run time system code, or operating system code, that controls task - * scheduling, input/output management and memory management. Traditionally, - * whenever efficient executive (also known as kernel) code was required by the - * application, the user developed in-house software. This software was usually - * written in assembly language for optimization. - * - * Because of this shortcoming in the Ada programming language, software - * developers in research and development and contractors for project managed - * systems, are mandated by technology to purchase and utilize off-the-shelf - * third party kernel code. The contractor, and eventually the Government, must - * pay a licensing fee for every copy of the kernel code used in an embedded - * system. - * - * The main drawback to this development environment is that the Government - * does not own, nor has the right to modify code contained within the kernel. - * V&V techniques in this situation are more difficult than if the complete - * source code were available. Responsibility for system failures due to faulty - * software is yet another area to be resolved under this environment. - * - * The Guidance and Control Directorate began a software development effort to - * address these problems. A project to develop an experimental run time kernel - * was begun that will eliminate the major drawbacks of the Ada programming - * language mentioned above. The Real Time Executive for Multiprocessor Systems - * (RTEMS) provides full capabilities for management of tasks, interrupts, - * time, and multiple processors in addition to those features typical of - * generic operating systems. The code is Government owned, so no licensing - * fees are necessary. RTEMS has been implemented in both the Ada and C - * programming languages. It has been ported to the following processor - * families: - * - * - Altera NIOS II - * - Analog Devices Blackfin - * - ARM - * - Freescale (formerly Motorola) MC68xxx - * - Freescale (formerly Motorola) MC683xx - * - Freescale (formerly Motorola) ColdFire - * - Intel i386 and above - * - Lattice Semiconductor LM32 - * - MIPS - * - PowerPC - * - Renesas (formerly Hitachi) SuperH - * - Renesas (formerly Hitachi) H8/300 - * - SPARC - * - Texas Instruments C3x/C4x - * - UNIX - * - * Support for other processor families, including RISC, CISC, and DSP, is - * planned. Since almost all of RTEMS is written in a high level language, - * ports to additional processor families require minimal effort. - * - * RTEMS multiprocessor support is capable of handling either homogeneous or - * heterogeneous systems. The kernel automatically compensates for - * architectural differences (byte swapping, etc.) between processors. This - * allows a much easier transition from one processor family to another without - * a major system redesign. - * - * Since the proposed standards are still in draft form, RTEMS cannot and does - * not claim compliance. However, the status of the standard is being carefully - * monitored to guarantee that RTEMS provides the functionality specified in - * the standard. Once approved, RTEMS will be made compliant. - */ - -/** - * @page RTEMSOverview RTEMS Overview - * - * @section RTEMSOverviewSecIntroduction Introduction - * - * RTEMS, Real-Time Executive for Multiprocessor Systems, is a real-time - * executive (kernel) which provides a high performance environment for - * embedded military applications including the following features: - * - * - multitasking capabilities - * - homogeneous and heterogeneous multiprocessor systems - * - event-driven, priority-based, preemptive scheduling - * - optional rate monotonic scheduling - * - intertask communication and synchronization - * - priority inheritance - * - responsive interrupt management - * - dynamic memory allocation - * - high level of user configurability - * - * This manual describes the usage of RTEMS for applications written in the C - * programming language. Those implementation details that are processor - * dependent are provided in the Applications Supplement documents. A - * supplement document which addresses specific architectural issues that - * affect RTEMS is provided for each processor type that is supported. - * - * @section RTEMSOverviewSecRealtimeApplicationSystems Real-time Application Systems - * - * Real-time application systems are a special class of computer applications. - * They have a complex set of characteristics that distinguish them from other - * software problems. Generally, they must adhere to more rigorous - * requirements. The correctness of the system depends not only on the results - * of computations, but also on the time at which the results are produced. The - * most important and complex characteristic of real-time application systems - * is that they must receive and respond to a set of external stimuli within - * rigid and critical time constraints referred to as deadlines. Systems can be - * buried by an avalanche of interdependent, asynchronous or cyclical event - * streams. - * - * Deadlines can be further characterized as either hard or soft based upon the - * value of the results when produced after the deadline has passed. A deadline - * is hard if the results have no value or if their use will result in a - * catastrophic event. In contrast, results which are produced after a soft - * deadline may have some value. - * - * Another distinguishing requirement of real-time application systems is the - * ability to coordinate or manage a large number of concurrent activities. - * Since software is a synchronous entity, this presents special problems. One - * instruction follows another in a repeating synchronous cycle. Even though - * mechanisms have been developed to allow for the processing of external - * asynchronous events, the software design efforts required to process and - * manage these events and tasks are growing more complicated. - * - * The design process is complicated further by spreading this activity over a - * set of processors instead of a single processor. The challenges associated - * with designing and building real-time application systems become very - * complex when multiple processors are involved. New requirements such as - * interprocessor communication channels and global resources that must be - * shared between competing processors are introduced. The ramifications of - * multiple processors complicate each and every characteristic of a real-time - * system. - * - * @section RTEMSOverviewSecRealtimeExecutive Real-time Executive - * - * Fortunately, real-time operating systems or real-time executives serve as a - * cornerstone on which to build the application system. A real-time - * multitasking executive allows an application to be cast into a set of - * logical, autonomous processes or tasks which become quite manageable. Each - * task is internally synchronous, but different tasks execute independently, - * resulting in an asynchronous processing stream. Tasks can be dynamically - * paused for many reasons resulting in a different task being allowed to - * execute for a period of time. The executive also provides an interface to - * other system components such as interrupt handlers and device drivers. - * System components may request the executive to allocate and coordinate - * resources, and to wait for and trigger synchronizing conditions. The - * executive system calls effectively extend the CPU instruction set to support - * efficient multitasking. By causing tasks to travel through well-defined - * state transitions, system calls permit an application to demand-switch - * between tasks in response to real-time events. - * - * By proper grouping of responses to stimuli into separate tasks, a system can - * now asynchronously switch between independent streams of execution, directly - * responding to external stimuli as they occur. This allows the system design - * to meet critical performance specifications which are typically measured by - * guaranteed response time and transaction throughput. The multiprocessor - * extensions of RTEMS provide the features necessary to manage the extra - * requirements introduced by a system distributed across several processors. - * It removes the physical barriers of processor boundaries from the world of - * the system designer, enabling more critical aspects of the system to receive - * the required attention. Such a system, based on an efficient real-time, - * multiprocessor executive, is a more realistic model of the outside world or - * environment for which it is designed. As a result, the system will always be - * more logical, efficient, and reliable. - * - * By using the directives provided by RTEMS, the real-time applications - * developer is freed from the problem of controlling and synchronizing - * multiple tasks and processors. In addition, one need not develop, test, - * debug, and document routines to manage memory, pass messages, or provide - * mutual exclusion. The developer is then able to concentrate solely on the - * application. By using standard software components, the time and cost - * required to develop sophisticated real-time applications is significantly - * reduced. - * - * @section RTEMSOverviewSecApplicationArchitecture RTEMS Application Architecture - * - * One important design goal of RTEMS was to provide a bridge between two - * critical layers of typical real-time systems. As shown in the following - * figure, RTEMS serves as a buffer between the project dependent application - * code and the target hardware. Most hardware dependencies for real-time - * applications can be localized to the low level device drivers. - * - * @todo Image RTEMS Application Architecture - * - * The RTEMS I/O interface manager provides an efficient tool for incorporating - * these hardware dependencies into the system while simultaneously providing a - * general mechanism to the application code that accesses them. A well - * designed real-time system can benefit from this architecture by building a - * rich library of standard application components which can be used repeatedly - * in other real-time projects. - * - * @section RTEMSOverviewSecInternalArchitecture RTEMS Internal Architecture - * - * RTEMS can be viewed as a set of layered components that work in harmony to - * provide a set of services to a real-time application system. The executive - * interface presented to the application is formed by grouping directives into - * logical sets called resource managers. Functions utilized by multiple - * managers such as scheduling, dispatching, and object management are provided - * in the executive core. The executive core depends on a small set of CPU - * dependent routines. Together these components provide a powerful run time - * environment that promotes the development of efficient real-time application - * systems. The following figure illustrates this organization: - * - * @todo Image RTEMS Architecture - * - * Subsequent chapters present a detailed description of the capabilities - * provided by each of the following RTEMS managers: - * - * - initialization - * - task - * - interrupt - * - clock - * - timer - * - semaphore - * - message - * - event - * - signal - * - partition - * - region - * - dual ported memory - * - I/O - * - fatal error - * - rate monotonic - * - user extensions - * - multiprocessing - * - * @section RTEMSOverviewSecUserCustomization User Customization and Extensibility - * - * As 32-bit microprocessors have decreased in cost, they have become - * increasingly common in a variety of embedded systems. A wide range of custom - * and general-purpose processor boards are based on various 32-bit - * processors. RTEMS was designed to make no assumptions concerning the - * characteristics of individual microprocessor families or of specific support - * hardware. In addition, RTEMS allows the system developer a high degree of - * freedom in customizing and extending its features. - * - * RTEMS assumes the existence of a supported microprocessor and sufficient - * memory for both RTEMS and the real-time application. Board dependent - * components such as clocks, interrupt controllers, or I/O devices can be - * easily integrated with RTEMS. The customization and extensibility features - * allow RTEMS to efficiently support as many environments as possible. - * - * @section RTEMSOverviewSecPortability Portability - * - * The issue of portability was the major factor in the creation of RTEMS. - * Since RTEMS is designed to isolate the hardware dependencies in the specific - * board support packages, the real-time application should be easily ported to - * any other processor. The use of RTEMS allows the development of real-time - * applications which can be completely independent of a particular - * microprocessor architecture. - * - * @section RTEMSOverviewSecMemoryRequirements Memory Requirements - * - * Since memory is a critical resource in many real-time embedded systems, - * RTEMS was specifically designed to automatically leave out all services that - * are not required from the run-time environment. Features such as networking, - * various filesystems, and many other features are completely optional. This - * allows the application designer the flexibility to tailor RTEMS to most - * efficiently meet system requirements while still satisfying even the most - * stringent memory constraints. As a result, the size of the RTEMS executive - * is application dependent. - * - * RTEMS requires RAM to manage each instance of an RTEMS object that is - * created. Thus the more RTEMS objects an application needs, the more memory - * that must be reserved. See Configuring a System Determining Memory - * Requirements for more details. - * - * @todo Link to Configuring a SystemDetermining Memory Requirements - * - * RTEMS utilizes memory for both code and data space. Although RTEMS' data - * space must be in RAM, its code space can be located in either ROM or RAM. - * - * @section RTEMSOverviewSecAudience Audience - * - * This manual was written for experienced real-time software developers. - * Although some background is provided, it is assumed that the reader is - * familiar with the concepts of task management as well as intertask - * communication and synchronization. Since directives, user related data - * structures, and examples are presented in C, a basic understanding of the C - * programming language is required to fully understand the material presented. - * However, because of the similarity of the Ada and C RTEMS implementations, - * users will find that the use and behavior of the two implementations is very - * similar. A working knowledge of the target processor is helpful in - * understanding some of RTEMS' features. A thorough understanding of the - * executive cannot be obtained without studying the entire manual because many - * of RTEMS' concepts and features are interrelated. Experienced RTEMS users - * will find that the manual organization facilitates its use as a reference - * document. - */ - -/** - * @addtogroup RTEMSAPIClassic - * - * The facilities provided by RTEMS are built upon a foundation of very - * powerful concepts. These concepts must be understood before the application - * developer can efficiently utilize RTEMS. The purpose of this chapter is to - * familiarize one with these concepts. - * - * @section ClassicRTEMSSecObjects Objects - * - * RTEMS provides directives which can be used to dynamically create, delete, - * and manipulate a set of predefined object types. These types include tasks, - * message queues, semaphores, memory regions, memory partitions, timers, - * ports, and rate monotonic periods. The object-oriented nature of RTEMS - * encourages the creation of modular applications built upon re-usable - * "building block" routines. - * - * All objects are created on the local node as required by the application and - * have an RTEMS assigned ID. All objects have a user-assigned name. Although a - * relationship exists between an object's name and its RTEMS assigned ID, the - * name and ID are not identical. Object names are completely arbitrary and - * selected by the user as a meaningful "tag" which may commonly reflect the - * object's use in the application. Conversely, object IDs are designed to - * facilitate efficient object manipulation by the executive. - * - * @subsection ClassicRTEMSSubSecObjectNames Object Names - * - * An object name is an unsigned 32-bit entity associated with the - * object by the user. The data type @ref rtems_name is used to store object names. - * - * Although not required by RTEMS, object names are often composed of four - * ASCII characters which help identify that object. For example, a task which - * causes a light to blink might be called "LITE". The rtems_build_name() - * routine is provided to build an object name from four ASCII characters. The - * following example illustrates this: - * - * @code - * rtems_name my_name = rtems_build_name('L', 'I', 'T', 'E'); - * @endcode - * - * However, it is not required that the application use ASCII characters to - * build object names. For example, if an application requires one-hundred - * tasks, it would be difficult to assign meaningful ASCII names to each task. - * A more convenient approach would be to name them the binary values one - * through one-hundred, respectively. - * - * RTEMS provides a helper routine, rtems_object_get_name(), which can be used to - * obtain the name of any RTEMS object using just its ID. This routine attempts - * to convert the name into a printable string. - * - * @subsection ClassicRTEMSSubSecObjectIdentifiers Object Identifiers - * - * An object ID is a unique unsigned integer value which uniquely identifies an - * object instance. Object IDs are passed as arguments to many directives in - * RTEMS and RTEMS translates the ID to an internal object pointer. The - * efficient manipulation of object IDs is critical to the performance of RTEMS - * services. Because of this, there are two object ID formats defined. Each - * target architecture specifies which format it will use. There is a 32-bit - * format which is used for most of the supported architectures and supports - * multiprocessor configurations. There is also a simpler 16-bit format which - * is appropriate for smaller target architectures and does not support - * multiprocessor configurations. - * - * @subsubsection ClassicRTEMSSubSec32BitObjectIdentifierFormat 32-Bit Object Identifier Format - * - * The 32-bit format for an object ID is composed of four parts: API, - * object class, node, and index. The data type @ref rtems_id is used to store - * object IDs. - * - * <table> - * <tr> - * <th>Bits</th> - * <td>31</td><td>30</td><td>29</td><td>28</td><td>27</td><td>26</td><td>25</td><td>24</td> - * <td>23</td><td>22</td><td>21</td><td>20</td><td>19</td><td>18</td><td>17</td><td>16</td> - * <td>15</td><td>14</td><td>13</td><td>12</td><td>11</td><td>10</td><td>09</td><td>08</td> - * <td>07</td><td>06</td><td>05</td><td>04</td><td>03</td><td>02</td><td>01</td><td>00</td> - * </tr> - * <tr> - * <th>Contents</th> - * <td colspan=5>Class</td><td colspan=3>API</td><td colspan=8>Node</td><td colspan=16>Object Index</td> - * </tr> - * </table> - * - * The most significant five bits are the object class. The next three bits - * indicate the API to which the object class belongs. The next eight bits - * (16 .. 23) are the number of the node on which this object was created. The - * node number is always one (1) in a single processor system. The least - * significant 16-bits form an identifier within a particular object type. - * This identifier, called the object index, ranges in value from one to the - * maximum number of objects configured for this object type. - * - * @subsubsection ClassicRTEMSSubSec16BitObjectIdentifierFormat 16-Bit Object Identifier Format - * - * The 16-bit format for an object ID is composed of three parts: API, object - * class, and index. The data type @ref rtems_id is used to store object IDs. - * - * <table> - * <tr> - * <th>Bits</th> - * <td>15</td><td>14</td><td>13</td><td>12</td><td>11</td><td>10</td><td>09</td><td>08</td> - * <td>07</td><td>06</td><td>05</td><td>04</td><td>03</td><td>02</td><td>01</td><td>00</td> - * </tr> - * <tr> - * <th>Contents</th> - * <td colspan=5>Class</td><td colspan=3>API</td><td colspan=8>Object Index</td> - * </tr> - * </table> - * - * The 16-bit format is designed to be as similar as possible to the 32-bit - * format. The differences are limited to the elimination of the node field - * and reduction of the index field from 16-bits to 8-bits. Thus the 16-bit - * format only supports up to 255 object instances per API/Class combination - * and single processor systems. As this format is typically utilized by 16-bit - * processors with limited address space, this is more than enough object - * instances. - * - * @subsection ClassicRTEMSSubSecObjectIdentiferDescription Object Identifer Description - * - * The components of an object ID make it possible to quickly locate any object - * in even the most complicated multiprocessor system. Object ID's are - * associated with an object by RTEMS when the object is created and the - * corresponding ID is returned by the appropriate object create directive. The - * object ID is required as input to all directives involving objects, except - * those which create an object or obtain the ID of an object. - * - * The object identification directives can be used to dynamically obtain a - * particular object's ID given its name. This mapping is accomplished by - * searching the name table associated with this object type. If the name is - * non-unique, then the ID associated with the first occurrence of the name - * will be returned to the application. Since object IDs are returned when the - * object is created, the object identification directives are not necessary in - * a properly designed single processor application. - * - * In addition, services are provided to portably examine the subcomponents of - * an RTEMS ID. These services are described in detail later in this manual but - * are prototyped as follows: - * - * - rtems_object_id_get_api() - * - rtems_object_id_get_class() - * - rtems_object_id_get_node() - * - rtems_object_id_get_index() - * - * An object control block is a data structure defined by RTEMS which contains - * the information necessary to manage a particular object type. For efficiency - * reasons, the format of each object type's control block is different. - * However, many of the fields are similar in function. The number of each type - * of control block is application dependent and determined by the values - * specified in the user's Configuration Table. An object control block is - * allocated at object create time and freed when the object is deleted. With - * the exception of user extension routines, object control blocks are not - * directly manipulated by user applications. - * - * @section ClassicRTEMSSecComSync Communication and Synchronization - * - * In real-time multitasking applications, the ability for cooperating - * execution threads to communicate and synchronize with each other is - * imperative. A real-time executive should provide an application with the - * following capabilities - * - * - data transfer between cooperating tasks, - * - data transfer between tasks and ISRs, - * - synchronization of cooperating tasks, and - * - synchronization of tasks and ISRs. - * - * Most RTEMS managers can be used to provide some form of communication and/or - * synchronization. However, managers dedicated specifically to communication - * and synchronization provide well established mechanisms which directly map - * to the application's varying needs. This level of flexibility allows the - * application designer to match the features of a particular manager with the - * complexity of communication and synchronization required. The following - * managers were specifically designed for communication and synchronization: - * - * - @ref ClassicSem - * - @ref ClassicMessageQueue - * - @ref ClassicEvent - * - @ref ClassicSignal - * - * The semaphore manager supports mutual exclusion involving the - * synchronization of access to one or more shared user resources. Binary - * semaphores may utilize the optional priority inheritance algorithm to avoid - * the problem of priority inversion. The message manager supports both - * communication and synchronization, while the event manager primarily - * provides a high performance synchronization mechanism. The signal manager - * supports only asynchronous communication and is typically used for exception - * handling. - * - * @section ClassicRTEMSSecTime Time - * - * The development of responsive real-time applications requires an - * understanding of how RTEMS maintains and supports time-related operations. - * The basic unit of time in RTEMS is known as a tick. The frequency of clock - * ticks is completely application dependent and determines the granularity and - * accuracy of all interval and calendar time operations. - * - * By tracking time in units of ticks, RTEMS is capable of supporting interval - * timing functions such as task delays, timeouts, timeslicing, the delayed - * execution of timer service routines, and the rate monotonic scheduling of - * tasks. An interval is defined as a number of ticks relative to the current - * time. For example, when a task delays for an interval of ten ticks, it is - * implied that the task will not execute until ten clock ticks have occurred. - * All intervals are specified using data type @ref rtems_interval. - * - * A characteristic of interval timing is that the actual interval period may - * be a fraction of a tick less than the interval requested. This occurs - * because the time at which the delay timer is set up occurs at some time - * between two clock ticks. Therefore, the first countdown tick occurs in less - * than the complete time interval for a tick. This can be a problem if the - * clock granularity is large. - * - * The rate monotonic scheduling algorithm is a hard real-time scheduling - * methodology. This methodology provides rules which allows one to guarantee - * that a set of independent periodic tasks will always meet their deadlines -- - * even under transient overload conditions. The rate monotonic manager - * provides directives built upon the Clock Manager's interval timer support - * routines. - * - * Interval timing is not sufficient for the many applications which require - * that time be kept in wall time or true calendar form. Consequently, RTEMS - * maintains the current date and time. This allows selected time operations to - * be scheduled at an actual calendar date and time. For example, a task could - * request to delay until midnight on New Year's Eve before lowering the ball - * at Times Square. The data type @ref rtems_time_of_day is used to specify - * calendar time in RTEMS services. See Clock Manager Time and Date Data - * Structures. - * - * @todo Link to Clock Manager Time and Date Data Structures - * - * Obviously, the directives which use intervals or wall time cannot operate - * without some external mechanism which provides a periodic clock tick. This - * clock tick is typically provided by a real time clock or counter/timer - * device. - * - * @section ClassicRTEMSSecMemoryManagement Memory Management - * - * RTEMS memory management facilities can be grouped into two classes: dynamic - * memory allocation and address translation. Dynamic memory allocation is - * required by applications whose memory requirements vary through the - * application's course of execution. Address translation is needed by - * applications which share memory with another CPU or an intelligent - * Input/Output processor. The following RTEMS managers provide facilities to - * manage memory: - * - * - @ref ClassicRegion - * - @ref ClassicPart - * - @ref ClassicDPMEM - * - * RTEMS memory management features allow an application to create simple - * memory pools of fixed size buffers and/or more complex memory pools of - * variable size segments. The partition manager provides directives to manage - * and maintain pools of fixed size entities such as resource control blocks. - * Alternatively, the region manager provides a more general purpose memory - * allocation scheme that supports variable size blocks of memory which are - * dynamically obtained and freed by the application. The dual-ported memory - * manager provides executive support for address translation between internal - * and external dual-ported RAM address space. - */ - -/** - * @addtogroup RTEMSAPIClassicTasks - * - * @section ClassicTasksSecTaskDefinition Task Definition - * - * Many definitions of a task have been proposed in computer literature. - * Unfortunately, none of these definitions encompasses all facets of the - * concept in a manner which is operating system independent. Several of the - * more common definitions are provided to enable each user to select a - * definition which best matches their own experience and understanding of the - * task concept: - * - * - a "dispatchable" unit. - * - an entity to which the processor is allocated. - * - an atomic unit of a real-time, multiprocessor system. - * - single threads of execution which concurrently compete for resources. - * - a sequence of closely related computations which can execute concurrently - * with other computational sequences. - * - * From RTEMS' perspective, a task is the smallest thread of execution which - * can compete on its own for system resources. A task is manifested by the - * existence of a task control block (TCB). - * - * @section ClassicTasksSecTaskControlBlock Task Control Block - * - * The Task Control Block (TCB) is an RTEMS defined data structure which - * contains all the information that is pertinent to the execution of a task. - * During system initialization, RTEMS reserves a TCB for each task configured. - * A TCB is allocated upon creation of the task and is returned to the TCB free - * list upon deletion of the task. - * - * The TCB's elements are modified as a result of system calls made by the - * application in response to external and internal stimuli. TCBs are the only - * RTEMS internal data structure that can be accessed by an application via - * user extension routines. The TCB contains a task's name, ID, current - * priority, current and starting states, execution mode, TCB user extension - * pointer, scheduling control structures, as well as data required by a - * blocked task. - * - * A task's context is stored in the TCB when a task switch occurs. When the - * task regains control of the processor, its context is restored from the TCB. - * When a task is restarted, the initial state of the task is restored from the - * starting context area in the task's TCB. - * - * @section ClassicTasksSecTaskStates Task States - * - * A task may exist in one of the following five states: - * - * - executing - Currently scheduled to the CPU - * - ready - May be scheduled to the CPU - * - blocked - Unable to be scheduled to the CPU - * - dormant - Created task that is not started - * - non-existent - Uncreated or deleted task - * - * An active task may occupy the executing, ready, blocked or dormant state, - * otherwise the task is considered non-existent. One or more tasks may be - * active in the system simultaneously. Multiple tasks communicate, - * synchronize, and compete for system resources with each other via system - * calls. The multiple tasks appear to execute in parallel, but actually each - * is dispatched to the CPU for periods of time determined by the RTEMS - * scheduling algorithm. The scheduling of a task is based on its current state - * and priority. - * - * @section ClassicTasksSecTaskPriority Task Priority - * - * A task's priority determines its importance in relation to the other tasks - * executing on the same processor. RTEMS supports 255 levels of priority - * ranging from 1 to 255. The data type rtems_task_priority() is used to store - * task priorities. - * - * Tasks of numerically smaller priority values are more important tasks than - * tasks of numerically larger priority values. For example, a task at priority - * level 5 is of higher privilege than a task at priority level 10. There is no - * limit to the number of tasks assigned to the same priority. - * - * Each task has a priority associated with it at all times. The initial value - * of this priority is assigned at task creation time. The priority of a task - * may be changed at any subsequent time. - * - * Priorities are used by the scheduler to determine which ready task will be - * allowed to execute. In general, the higher the logical priority of a task, - * the more likely it is to receive processor execution time. - * - * @section ClassicTasksSecTaskMode Task Mode - * - * A task's execution mode is a combination of the following four components: - * - * - preemption - * - ASR processing - * - timeslicing - * - interrupt level - * - * It is used to modify RTEMS' scheduling process and to alter the execution - * environment of the task. The data type rtems_task_mode() is used to manage - * the task execution mode. - * - * The preemption component allows a task to determine when control of the - * processor is relinquished. If preemption is disabled (@c - * RTEMS_NO_PREEMPT), the task will retain control of the - * processor as long as it is in the executing state -- even if a higher - * priority task is made ready. If preemption is enabled (@c RTEMS_PREEMPT) - * and a higher priority task is made ready, then the processor will be - * taken away from the current task immediately and given to the higher - * priority task. - * - * The timeslicing component is used by the RTEMS scheduler to determine how - * the processor is allocated to tasks of equal priority. If timeslicing is - * enabled (@c RTEMS_TIMESLICE), then RTEMS will limit the amount of time the - * task can execute before the processor is allocated to another ready task of - * equal priority. The length of the timeslice is application dependent and - * specified in the Configuration Table. If timeslicing is disabled (@c - * RTEMS_NO_TIMESLICE), then the task will be allowed to - * execute until a task of higher priority is made ready. If @c - * RTEMS_NO_PREEMPT is selected, then the timeslicing component is ignored by - * the scheduler. - * - * The asynchronous signal processing component is used to determine when - * received signals are to be processed by the task. If signal processing is - * enabled (@c RTEMS_ASR), then signals sent to the task will be processed - * the next time the task executes. If signal processing is disabled (@c - * RTEMS_NO_ASR), then all signals received by the task will - * remain posted until signal processing is enabled. This component affects - * only tasks which have established a routine to process asynchronous signals. - * - * The interrupt level component is used to determine which interrupts will be - * enabled when the task is executing. @c RTEMS_INTERRUPT_LEVEL(n) specifies - * that the task will execute at interrupt level n. - * - * - @ref RTEMS_PREEMPT - enable preemption (default) - * - @ref RTEMS_NO_PREEMPT - disable preemption - * - @ref RTEMS_NO_TIMESLICE - disable timeslicing (default) - * - @ref RTEMS_TIMESLICE - enable timeslicing - * - @ref RTEMS_ASR - enable ASR processing (default) - * - @ref RTEMS_NO_ASR - disable ASR processing - * - @ref RTEMS_INTERRUPT_LEVEL(0) - enable all interrupts (default) - * - @ref RTEMS_INTERRUPT_LEVEL(n) - execute at interrupt level n - * - * The set of default modes may be selected by specifying the @ref - * RTEMS_DEFAULT_MODES constant. - * - * @section ClassicTasksSecAccessingTaskArguments Accessing Task Arguments - * - * All RTEMS tasks are invoked with a single argument which is specified when - * they are started or restarted. The argument is commonly used to communicate - * startup information to the task. The simplest manner in which to define a - * task which accesses it argument is: - * - * @code - * rtems_task user_task( - * rtems_task_argument argument - * ); - * @endcode - * - * Application tasks requiring more information may view this single argument - * as an index into an array of parameter blocks. - * - * @section ClassicTasksSecFloatingPointConsiderations Floating Point Considerations - * - * Creating a task with the @ref RTEMS_FLOATING_POINT attribute flag results in - * additional memory being allocated for the TCB to store the state of the - * numeric coprocessor during task switches. This additional memory is NOT - * allocated for @ref RTEMS_NO_FLOATING_POINT tasks. Saving and restoring the - * context of a @c RTEMS_FLOATING_POINT task takes longer than that of a @c - * RTEMS_NO_FLOATING_POINT task because of the relatively large amount of time - * required for the numeric coprocessor to save or restore its computational - * state. - * - * Since RTEMS was designed specifically for embedded military applications - * which are floating point intensive, the executive is optimized to avoid - * unnecessarily saving and restoring the state of the numeric coprocessor. The - * state of the numeric coprocessor is only saved when a @c - * RTEMS_FLOATING_POINT task is dispatched and that task was not the last task - * to utilize the coprocessor. In a system with only one @c - * RTEMS_FLOATING_POINT task, the state of the numeric coprocessor will never - * be saved or restored. - * - * Although the overhead imposed by @c RTEMS_FLOATING_POINT tasks is minimal, - * some applications may wish to completely avoid the overhead associated with - * @c RTEMS_FLOATING_POINT tasks and still utilize a numeric coprocessor. By - * preventing a task from being preempted while performing a sequence of - * floating point operations, a @c RTEMS_NO_FLOATING_POINT task can utilize - * the numeric coprocessor without incurring the overhead of a @c - * RTEMS_FLOATING_POINT context switch. This approach also avoids the - * allocation of a floating point context area. However, if this approach is - * taken by the application designer, NO tasks should be created as @c - * RTEMS_FLOATING_POINT tasks. Otherwise, the floating point context will not - * be correctly maintained because RTEMS assumes that the state of the numeric - * coprocessor will not be altered by @c RTEMS_NO_FLOATING_POINT tasks. - * - * If the supported processor type does not have hardware floating capabilities - * or a standard numeric coprocessor, RTEMS will not provide built-in support - * for hardware floating point on that processor. In this case, all tasks are - * considered @c RTEMS_NO_FLOATING_POINT whether created as @c - * RTEMS_FLOATING_POINT or @c RTEMS_NO_FLOATING_POINT tasks. A floating point - * emulation software library must be utilized for floating point operations. - * - * On some processors, it is possible to disable the floating point unit - * dynamically. If this capability is supported by the target processor, then - * RTEMS will utilize this capability to enable the floating point unit only - * for tasks which are created with the @c RTEMS_FLOATING_POINT attribute. - * The consequence of a @c RTEMS_NO_FLOATING_POINT task attempting to access - * the floating point unit is CPU dependent but will generally result in an - * exception condition. - * - * @section ClassicTasksSecPerTaskVariables Per Task Variables - * - * Per task variables are no longer available. In particular the - * rtems_task_variable_add(), rtems_task_variable_get() and - * rtems_task_variable_delete() functions are neither declared nor defined - * anymore. Use thread local storage or POSIX Keys instead. - * - * @section ClassicTasksSecBuildingTaskAttributeSet Building a Task Attribute Set - * - * In general, an attribute set is built by a bitwise OR of the desired - * components. The set of valid task attribute components is listed below: - * - * - @ref RTEMS_NO_FLOATING_POINT - does not use coprocessor (default) - * - @ref RTEMS_FLOATING_POINT - uses numeric coprocessor - * - @ref RTEMS_LOCAL - local task (default) - * - @ref RTEMS_GLOBAL - global task - * - * Attribute values are specifically designed to be mutually exclusive, - * therefore bitwise OR and addition operations are equivalent as long as each - * attribute appears exactly once in the component list. A component listed as - * a default is not required to appear in the component list, although it is a - * good programming practice to specify default components. If all defaults are - * desired, then @ref RTEMS_DEFAULT_ATTRIBUTES should be used. This example - * demonstrates the attribute_set parameter needed to create a local task which - * utilizes the numeric coprocessor. The attribute_set parameter could be @c - * RTEMS_FLOATING_POINT or @c RTEMS_LOCAL | @c RTEMS_FLOATING_POINT. The - * attribute_set parameter can be set to @c RTEMS_FLOATING_POINT because @c - * RTEMS_LOCAL is the default for all created tasks. If the task were global - * and used the numeric coprocessor, then the attribute_set parameter would be - * @c RTEMS_GLOBAL | @c RTEMS_FLOATING_POINT. - * - * @section ClassicTasksSecBuildingModeAndMask Building a Mode and Mask - * - * In general, a mode and its corresponding mask is built by a bitwise OR of - * the desired components. The set of valid mode constants and each mode's - * corresponding mask constant is listed below: - * - * <table> - * <tr><th>Mode Constant</th><th>Mask Constant</th><th>Description</th></tr> - * <tr><td>@ref RTEMS_PREEMPT</td><td>@ref RTEMS_PREEMPT_MASK</td><td>enables preemption</td></tr> - * <tr><td>@ref RTEMS_NO_PREEMPT</td><td>@ref RTEMS_PREEMPT_MASK</td><td>disables preemption</td></tr> - * <tr><td>@ref RTEMS_NO_TIMESLICE</td><td>@ref RTEMS_TIMESLICE_MASK</td><td>disables timeslicing</td></tr> - * <tr><td>@ref RTEMS_TIMESLICE</td><td>@ref RTEMS_TIMESLICE_MASK</td><td>enables timeslicing</td></tr> - * <tr><td>@ref RTEMS_ASR</td><td>@ref RTEMS_ASR_MASK</td><td>enables ASR processing</td></tr> - * <tr><td>@ref RTEMS_NO_ASR</td><td>@ref RTEMS_ASR_MASK</td><td>disables ASR processing</td></tr> - * <tr><td>@ref RTEMS_INTERRUPT_LEVEL(0)</td><td>@ref RTEMS_INTERRUPT_MASK</td><td>enables all interrupts</td></tr> - * <tr><td>@ref RTEMS_INTERRUPT_LEVEL(n)</td><td>@ref RTEMS_INTERRUPT_MASK</td><td>sets interrupts level n</td></tr> - * </table> - * - * Mode values are specifically designed to be mutually exclusive, therefore - * bitwise OR and addition operations are equivalent as long as each mode - * appears exactly once in the component list. A mode component listed as a - * default is not required to appear in the mode component list, although it is - * a good programming practice to specify default components. If all defaults - * are desired, the mode @ref RTEMS_DEFAULT_MODES and the mask @ref - * RTEMS_ALL_MODE_MASKS should be used. - * - * The following example demonstrates the mode and mask parameters used with - * the rtems_task_mode() directive to place a task at interrupt level 3 and - * make it non-preemptible. The mode should be set to @c - * RTEMS_INTERRUPT_LEVEL(3) | @c RTEMS_NO_PREEMPT to indicate the desired - * preemption mode and interrupt level, while the mask parameter should be set - * to @c RTEMS_INTERRUPT_MASK | @c RTEMS_PREEMPT_MASK to indicate that - * the calling task's interrupt level and preemption mode are being altered. - */ - - /** - * @defgroup LocalPackages Local Packages - * - * @ingroup RTEMSAPIClassic - * - * @brief Local packages. - */ diff --git a/cpukit/include/rtems/rtems/partdata.h b/cpukit/include/rtems/rtems/partdata.h index 864c47294e..6df4af81c5 100644 --- a/cpukit/include/rtems/rtems/partdata.h +++ b/cpukit/include/rtems/rtems/partdata.h @@ -116,6 +116,8 @@ typedef struct { extern Objects_Information _Partition_Information; #if defined(RTEMS_MULTIPROCESSING) +struct _Thread_Control; + /** * @brief Sends the extract proxy request. * @@ -126,8 +128,8 @@ extern Objects_Information _Partition_Information; * @param id is the partition identifier. */ void _Partition_MP_Send_extract_proxy ( - Thread_Control *the_thread, - Objects_Id id + struct _Thread_Control *the_thread, + Objects_Id id ); #endif diff --git a/cpukit/include/rtems/rtems/tasks.h b/cpukit/include/rtems/rtems/tasks.h index 45be8a8730..84dd646fe7 100644 --- a/cpukit/include/rtems/rtems/tasks.h +++ b/cpukit/include/rtems/rtems/tasks.h @@ -10,7 +10,7 @@ /* * Copyright (C) 2020, 2021 embedded brains GmbH & Co. KG - * Copyright (C) 1988, 2017 On-Line Applications Research Corporation (OAR) + * Copyright (C) 1988, 2023 On-Line Applications Research Corporation (OAR) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -234,7 +234,7 @@ typedef void rtems_task; /** * @ingroup RTEMSAPIClassicTasks * - * @brief This type defines the entry point of an RTEMS task. + * @brief This type defines the task entry point of an RTEMS task. */ typedef rtems_task ( *rtems_task_entry )( rtems_task_argument ); @@ -897,8 +897,8 @@ rtems_id rtems_task_self( void ); * * This directive readies the task, specified by ``id``, for execution based on * the priority and execution mode specified when the task was created. The - * entry point of the task is given in ``entry_point``. The task's entry point - * argument is contained in ``argument``. + * task entry point of the task is given in ``entry_point``. The task's entry + * point argument is contained in ``argument``. * * @retval ::RTEMS_SUCCESSFUL The requested operation was successful. * @@ -1544,15 +1544,16 @@ rtems_status_code rtems_task_mode( /** * @ingroup RTEMSAPIClassicTasks * - * @brief Wakes up after an interval in clock ticks or yields the processor. + * @brief Wakes up after a count of clock ticks have occurred or yields the + * processor. * - * @param ticks is the interval in clock ticks to delay the task or + * @param ticks is the count of clock ticks to delay the task or * #RTEMS_YIELD_PROCESSOR to yield the processor. * - * This directive blocks the calling task for the specified ``ticks`` of clock - * ticks if the value is not equal to #RTEMS_YIELD_PROCESSOR. When the - * requested interval has elapsed, the task is made ready. The clock tick - * directives automatically updates the delay period. The calling task may + * This directive blocks the calling task for the specified ``ticks`` count of + * clock ticks if the value is not equal to #RTEMS_YIELD_PROCESSOR. When the + * requested count of ticks have occurred, the task is made ready. The clock + * tick directives automatically update the delay period. The calling task may * give up the processor and remain in the ready state by specifying a value of * #RTEMS_YIELD_PROCESSOR in ``ticks``. * @@ -1561,7 +1562,11 @@ rtems_status_code rtems_task_mode( * @par Notes * Setting the system date and time with the rtems_clock_set() directive and * similar directives which set CLOCK_REALTIME have no effect on a - * rtems_task_wake_after() blocked task. + * rtems_task_wake_after() blocked task. The delay until first clock tick will + * never be a whole clock tick interval since this directive will never execute + * exactly on a clock tick. Applications requiring use of a clock + * (CLOCK_REALTIME or CLOCK_MONOTONIC) instead of clock ticks should make use + * of clock_nanosleep(). * * @par Constraints * @parblock diff --git a/cpukit/include/rtems/rtl/rtl-allocator.h b/cpukit/include/rtems/rtl/rtl-allocator.h index 8ffaf58c3c..7d291c65f4 100644 --- a/cpukit/include/rtems/rtl/rtl-allocator.h +++ b/cpukit/include/rtems/rtl/rtl-allocator.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* - * COPYRIGHT (c) 2012, 2018 Chris Johns <chrisj@rtems.org> + * COPYRIGHT (c) 2012, 2018, 2023 Chris Johns <chrisj@rtems.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -69,6 +69,7 @@ typedef enum rtems_rtl_alloc_tags rtems_rtl_alloc_tag; enum rtems_rtl_alloc_cmd { RTEMS_RTL_ALLOC_NEW, /**< Allocate new memory. */ RTEMS_RTL_ALLOC_DEL, /**< Delete allocated memory. */ + RTEMS_RTL_ALLOC_RESIZE, /**< Resize allocated memory. */ RTEMS_RTL_ALLOC_LOCK, /**< Lock the allocator. */ RTEMS_RTL_ALLOC_UNLOCK, /**< Unlock the allocator. */ RTEMS_RTL_ALLOC_WR_ENABLE, /**< Enable writes to the memory. */ @@ -143,6 +144,25 @@ void* rtems_rtl_alloc_new (rtems_rtl_alloc_tag tag, size_t size, bool zero); void rtems_rtl_alloc_del (rtems_rtl_alloc_tag tag, void* address); /** + * The Runtime Loader allocator resize resizes allocated memory. + * + * This call resizes a previously allocated block of memory. If the + * provided address cannot be resized it is deleted and a new block is + * allocated and the contents of the existing memory is copied. + * + * + * @param tag The type of allocation request. + * @param address The memory address to resize. A NULL is ignored. + * @param size The size of the allocation. + * @param zero If true the memory is cleared. + * @return void* The memory address or NULL is not memory available. + */ +void* rtems_rtl_alloc_resize (rtems_rtl_alloc_tag tag, + void* address, + size_t size, + bool zero); + +/** * The Runtime Loader allocator lock. An allocator that depends on a * separate allocation process, for example the heap, may need to be * locked during loading of an object file to make sure the locality @@ -267,6 +287,30 @@ bool rtems_rtl_alloc_module_new (void** text_base, size_t text_size, void** bss_base, size_t bss_size); /** + * Resize the allocated memory for a module given the new size of the text, + * const, data and bss sections. If any part of the allocation fails the + * allocated is deleted. + * + * @param text_base Pointer to the text base pointer. + * @param text_size The size of the read/exec section. + * @param const_base Pointer to the const base pointer. + * @param const_size The size of the read only section. + * @param eh_base Pointer to the eh base pointer. + * @param eh_size The size of the eh section. + * @param data_base Pointer to the data base pointer. + * @param data_size The size of the read/write secton. + * @param bss_base Pointer to the bss base pointer. + * @param bss_size The size of the read/write. + * @retval true The memory has been allocated. + * @retval false The allocation of memory has failed. + */ +bool rtems_rtl_alloc_module_resize (void** text_base, size_t text_size, + void** const_base, size_t const_size, + void** eh_base, size_t eh_size, + void** data_base, size_t data_size, + void** bss_base, size_t bss_size); + +/** * Free the memory allocated to a module. * * @param text_base Pointer to the text base pointer. diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h index 6b47eb1205..3523958bfd 100644 --- a/cpukit/include/rtems/rtl/rtl-obj.h +++ b/cpukit/include/rtems/rtl/rtl-obj.h @@ -198,65 +198,66 @@ typedef bool (*rtems_rtl_obj_depends_iterator) (rtems_rtl_obj* obj, */ struct rtems_rtl_obj { - rtems_chain_node link; /**< The node's link in the chain. */ - uint32_t flags; /**< The status of the object file. */ - size_t users; /**< Users of this object file, number of loads. */ - size_t refs; /**< References to the object file. */ - int format; /**< The format of the object file. */ - const char* fname; /**< The file name for the object. */ - const char* oname; /**< The object file name. Can be - * relative. */ - const char* aname; /**< The archive name containing the - * object. NULL means the object is not - * in a lib */ - off_t ooffset; /**< The object offset in the archive. */ - size_t fsize; /**< Size of the object file. */ - rtems_chain_control sections; /**< The sections of interest in the object - * file. */ - rtems_chain_control dependents; /**< The dependent object files. */ - rtems_rtl_obj_sym* local_table; /**< Local symbol table. */ - size_t local_syms; /**< Local symbol count. */ - size_t local_size; /**< Local symbol memory usage. */ - rtems_rtl_obj_sym* global_table; /**< Global symbol table. */ - size_t global_syms; /**< Global symbol count. */ - size_t global_size; /**< Global symbol memory usage. */ - size_t unresolved; /**< The number of unresolved relocations. */ - void* text_base; /**< The base address of the text section - * in memory. */ - size_t text_size; /**< The size of the text section. */ - void* const_base; /**< The base address of the const section - * in memory. */ - size_t const_size; /**< The size of the const section. */ - void* eh_base; /**< The base address of the eh section in - * memory. */ - size_t eh_size; /**< The size of the eh section. */ - void* data_base; /**< The base address of the data section - * in memory. */ - size_t data_size; /**< The size of the data section. */ - void* bss_base; /**< The base address of the bss section in - * memory. */ - size_t bss_size; /**< The size of the bss section. */ - size_t exec_size; /**< The amount of executable memory - * allocated */ - void* entry; /**< The entry point of the module. */ - uint32_t checksum; /**< The checksum of the text sections. A - * zero means do not checksum. */ - uint32_t* sec_num; /**< The sec nums of each obj. */ - uint32_t obj_num; /**< The count of elf files in an rtl - * obj. */ - void* trampoline; /**< Trampoline memory. Used for fixups or - * veneers */ - size_t tramp_size; /**< Size of a tramopline slot. */ - size_t tramps_size; /**< Size of the trampoline memory. */ - void* tramp_brk; /**< Trampoline memory allocator. MD - * relocators can take memory from the - * break up to the size. */ - size_t tramp_relocs; /**< Number of slots reserved for - * relocs. The remainder are for - * unresolved symbols. */ - struct link_map* linkmap; /**< For GDB. */ - void* loader; /**< The file details specific to a - * loader. */ + rtems_chain_node link; /**< The node's link in the chain. */ + uint32_t flags; /**< The status of the object file. */ + size_t users; /**< Users of this object file, number of loads. */ + size_t refs; /**< References to the object file. */ + int format; /**< The format of the object file. */ + const char* fname; /**< The file name for the object. */ + const char* oname; /**< The object file name. Can be + * relative. */ + const char* aname; /**< The archive name containing the + * object. NULL means the object is not + * in a lib */ + off_t ooffset; /**< The object offset in the archive. */ + size_t fsize; /**< Size of the object file. */ + rtems_chain_control sections; /**< The sections of interest in the object + * file. */ + rtems_chain_control dependents; /**< The dependent object files. */ + rtems_rtl_obj_sym* local_table; /**< Local symbol table. */ + size_t local_syms; /**< Local symbol count. */ + size_t local_size; /**< Local symbol memory usage. */ + rtems_rtl_obj_sym* global_table; /**< Global symbol table. */ + size_t global_syms; /**< Global symbol count. */ + size_t global_size; /**< Global symbol memory usage. */ + size_t unresolved; /**< The number of unresolved relocations. */ + void* text_base; /**< The base address of the text section + * in memory. */ + size_t text_size; /**< The size of the text section. */ + void* const_base; /**< The base address of the const section + * in memory. */ + size_t const_size; /**< The size of the const section. */ + void* eh_base; /**< The base address of the eh section in + * memory. */ + size_t eh_size; /**< The size of the eh section. */ + void* data_base; /**< The base address of the data section + * in memory. */ + size_t data_size; /**< The size of the data section. */ + void* bss_base; /**< The base address of the bss section in + * memory. */ + size_t bss_size; /**< The size of the bss section. */ + size_t exec_size; /**< The amount of executable memory + * allocated */ + void* entry; /**< The entry point of the module. */ + uint32_t checksum; /**< The checksum of the text sections. A + * zero means do not checksum. */ + uint32_t* sec_num; /**< The sec nums of each obj. */ + uint32_t obj_num; /**< The count of elf files in an rtl + * obj. */ + void* tramp_base; /**< Trampoline memory. Used for fixups or + * veneers */ + size_t tramp_size; /**< Size of a trampoline memory. */ + size_t tramp_slots; /**< The number of tampoline slots. */ + size_t tramp_slot_size; /**< The number of tampoline slots. */ + void* tramp_brk; /**< Trampoline memory allocator. MD + * relocators can take memory from the + * break up to the size. */ + size_t tramp_relocs; /**< Number of slots reserved for + * relocs. The remainder are for + * unresolved symbols. */ + struct link_map* linkmap; /**< For GDB. */ + void* loader; /**< The file details specific to a + * loader. */ }; /** @@ -387,6 +388,17 @@ static inline bool rtems_rtl_obj_has_symbol (const rtems_rtl_obj* obj, } /** + * Does the object file have any trampolines? + * + * @param obj The object file's descriptor to check for available space. + * @retval bool Returns @true if the object file has trampolines + */ +static inline size_t rtems_rtl_obj_has_trampolines (const rtems_rtl_obj* obj) +{ + return obj->tramp_slot_size != 0 && obj->tramp_slots != 0; +} + +/** * Is there space in the trampoline memory for a trapoline. * * @param obj The object file's descriptor to check for available space. @@ -395,7 +407,7 @@ static inline bool rtems_rtl_obj_has_symbol (const rtems_rtl_obj* obj, */ static inline size_t rtems_rtl_obj_tramp_avail_space (const rtems_rtl_obj* obj) { - return (char*) obj->tramp_brk - (char*) obj->trampoline; + return (char*) obj->tramp_brk - (char*) obj->tramp_base; } /** @@ -408,8 +420,8 @@ static inline size_t rtems_rtl_obj_tramp_avail_space (const rtems_rtl_obj* obj) static inline bool rtems_rtl_obj_has_tramp_space (const rtems_rtl_obj* obj, const size_t size) { - return (obj->trampoline != NULL && - (rtems_rtl_obj_tramp_avail_space (obj) + size) <= obj->tramps_size); + return (obj->tramp_base != NULL && + (rtems_rtl_obj_tramp_avail_space (obj) + size) <= obj->tramp_size); } /** @@ -420,20 +432,19 @@ static inline bool rtems_rtl_obj_has_tramp_space (const rtems_rtl_obj* obj, */ static inline size_t rtems_rtl_obj_trampoline_slots (const rtems_rtl_obj* obj) { - return obj->trampoline == NULL || obj->tramp_size == 0 ? - 0 : obj->tramps_size / obj->tramp_size; + return obj->tramp_slots; } /** - * Number of trampolines. + * Number of trampoline slot available. * * @param obj The object file's descriptor. - * @retval size_t The number of trampolines. + * @retval size_t The number of trampoline slots available. */ static inline size_t rtems_rtl_obj_trampolines (const rtems_rtl_obj* obj) { - return obj->trampoline == NULL || obj->tramp_size == 0 ? - 0 : rtems_rtl_obj_tramp_avail_space (obj) / obj->tramp_size; + return obj->tramp_base == NULL || obj->tramp_slots == 0 ? + 0 : rtems_rtl_obj_tramp_avail_space (obj) / obj->tramp_slot_size; } /** @@ -572,22 +583,6 @@ rtems_rtl_obj_sect* rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj uint32_t mask); /** - * Allocate a table for trampoline fixup calls. - * - * @param obj The object file's descriptor. - * @retval true The table was allocated. - * @retval false The alloction failed. - */ -bool rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj); - -/** - * Erase the object file descriptor's trampoline table.. - * - * @param obj The object file's descriptor. - */ -void rtems_rtl_obj_erase_trampoline (rtems_rtl_obj* obj); - -/** * Allocate a table for dependent objects. * * @param obj The object file's descriptor. @@ -750,6 +745,24 @@ size_t rtems_rtl_obj_bss_size (const rtems_rtl_obj* obj); uint32_t rtems_rtl_obj_bss_alignment (const rtems_rtl_obj* obj); /** + * The trampoline size. + * + * @param obj The object file's descriptor. + * @return size_t The size of the trampoline memory of the object file. + */ +size_t rtems_rtl_obj_tramp_size (const rtems_rtl_obj* obj); + +/** + * The trampolinme alignment for the architecture. + * + * This is implemented and set in the architecture backend. + * + * @param obj The object file's descriptor. + * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. + */ +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj); + +/** * Relocate the object file. The object file's section are parsed for any * relocation type sections. * @@ -810,11 +823,19 @@ bool rtems_rtl_obj_load_symbols (rtems_rtl_obj* obj, * @retval true The object has been sucessfully loaded. * @retval false The load failed. The RTL error has been set. */ -bool -rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, - int fd, - rtems_rtl_obj_sect_handler handler, - void* data); +bool rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, + int fd, + rtems_rtl_obj_sect_handler handler, + void* data); + +/** + * Resize the sections. + * + * @param obj The object file's descriptor. + * @retval true The object has been sucessfully loaded. + * @retval false The load failed. The RTL error has been set. + */ +bool rtems_rtl_obj_resize_sections (rtems_rtl_obj* obj); /** * Load the sections that have been allocated memory in the target. The bss diff --git a/cpukit/include/rtems/rtl/rtl-sym.h b/cpukit/include/rtems/rtl/rtl-sym.h index 0d29a6ae40..3502b303b8 100644 --- a/cpukit/include/rtems/rtl/rtl-sym.h +++ b/cpukit/include/rtems/rtl/rtl-sym.h @@ -63,6 +63,22 @@ typedef struct rtems_rtl_symbols } rtems_rtl_symbols; /** + * A TLS variable offset call. There is one per base image TLS + * variable. + */ +typedef size_t (*rtems_rtl_tls_offset_func)(void); + +/** + * A TLS symbol offset entry. It is used with an exported symbol table + * to find a TSL table offset for a variable at runtime. + */ +typedef struct rtems_rtl_tls_offset +{ + size_t index; /** exported symbol table index */ + rtems_rtl_tls_offset_func offset; /** TLS offset function */ +} rtems_rtl_tls_offset; + +/** * Open a symbol table with the specified number of buckets. * * @param symbols The symbol table to open. @@ -101,10 +117,14 @@ void rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols); * @param obj The object table the symbols are for. * @param esyms The exported symbol table. * @param size The size of the table in bytes. + * @param tls_offsets The TLS offsets table. If NULL none provided. + * @param tls_size The number TLS offset entries in the table. */ -bool rtems_rtl_symbol_global_add (rtems_rtl_obj* obj, - const unsigned char* esyms, - unsigned int size); +bool rtems_rtl_symbol_global_add (rtems_rtl_obj* obj, + const unsigned char* esyms, + unsigned int size, + rtems_rtl_tls_offset* tls_offsets, + unsigned int tls_size); /** * Find a symbol given the symbol label in the global symbol table. diff --git a/cpukit/include/rtems/rtl/rtl.h b/cpukit/include/rtems/rtl/rtl.h index 0fd4e74cdf..bd3dce588a 100644 --- a/cpukit/include/rtems/rtl/rtl.h +++ b/cpukit/include/rtems/rtl/rtl.h @@ -393,9 +393,13 @@ bool rtems_rtl_path_prepend (const char* path); * * @param esyms The exported symbol table. * @param count The size of the exported symbol table. + * @param tls_offsets The TLS offsets table. If NULL none provided. + * @param tls_size The number TLS offset entries in the table. */ -void rtems_rtl_base_sym_global_add (const unsigned char* esyms, - unsigned int count); +void rtems_rtl_base_sym_global_add (const unsigned char* esyms, + unsigned int count, + rtems_rtl_tls_offset* tls_offsets, + unsigned int tls_size); /** * Return the object file descriptor for the base image. The object file diff --git a/cpukit/include/rtems/score/atomic.h b/cpukit/include/rtems/score/atomic.h index 161b0ec03e..9ef1779e60 100644 --- a/cpukit/include/rtems/score/atomic.h +++ b/cpukit/include/rtems/score/atomic.h @@ -10,6 +10,7 @@ */ /* + * Copyright (C) 2015 embedded brains GmbH & Co. KG * COPYRIGHT (c) 2012-2013 Deng Hengyi. * * Redistribution and use in source and binary forms, with or without @@ -37,7 +38,7 @@ #ifndef _RTEMS_SCORE_ATOMIC_H #define _RTEMS_SCORE_ATOMIC_H -#include <rtems/score/cpuatomic.h> +#include <rtems/score/basedefs.h> /** * @defgroup RTEMSScoreAtomic Atomic Operations @@ -54,122 +55,935 @@ * @{ */ -typedef CPU_atomic_Uint Atomic_Uint; +#ifdef RTEMS_SMP + #if defined(__cplusplus) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) + /* + * The GCC 4.9 ships its own <stdatomic.h> which is not C++ compatible. The + * suggested solution was to include <atomic> in case C++ is used. This works + * at least with GCC 4.9. See also: + * + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60932 + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60940 + */ + #include <atomic> + #define _RTEMS_SCORE_ATOMIC_USE_ATOMIC + #else + #include <stdatomic.h> + #define _RTEMS_SCORE_ATOMIC_USE_STDATOMIC + #endif +#else + #include <rtems/score/isrlevel.h> +#endif -typedef CPU_atomic_Ulong Atomic_Ulong; +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) -typedef CPU_atomic_Uintptr Atomic_Uintptr; +typedef std::atomic_uint Atomic_Uint; -typedef CPU_atomic_Flag Atomic_Flag; +typedef std::atomic_ulong Atomic_Ulong; -typedef CPU_atomic_Order Atomic_Order; +typedef std::atomic_uintptr_t Atomic_Uintptr; -#define ATOMIC_ORDER_RELAXED CPU_ATOMIC_ORDER_RELAXED +typedef std::atomic_flag Atomic_Flag; -#define ATOMIC_ORDER_ACQUIRE CPU_ATOMIC_ORDER_ACQUIRE +typedef std::memory_order Atomic_Order; -#define ATOMIC_ORDER_RELEASE CPU_ATOMIC_ORDER_RELEASE +#define ATOMIC_ORDER_RELAXED std::memory_order_relaxed -#define ATOMIC_ORDER_ACQ_REL CPU_ATOMIC_ORDER_ACQ_REL +#define ATOMIC_ORDER_ACQUIRE std::memory_order_acquire -#define ATOMIC_ORDER_SEQ_CST CPU_ATOMIC_ORDER_SEQ_CST +#define ATOMIC_ORDER_RELEASE std::memory_order_release -#define ATOMIC_INITIALIZER_UINT( value ) CPU_ATOMIC_INITIALIZER_UINT( value ) +#define ATOMIC_ORDER_ACQ_REL std::memory_order_acq_rel -#define ATOMIC_INITIALIZER_ULONG( value ) CPU_ATOMIC_INITIALIZER_ULONG( value ) +#define ATOMIC_ORDER_SEQ_CST std::memory_order_seq_cst -#define ATOMIC_INITIALIZER_UINTPTR( value ) CPU_ATOMIC_INITIALIZER_UINTPTR( value ) +#define ATOMIC_INITIALIZER_UINT( value ) ATOMIC_VAR_INIT( value ) -#define ATOMIC_INITIALIZER_FLAG CPU_ATOMIC_INITIALIZER_FLAG +#define ATOMIC_INITIALIZER_ULONG( value ) ATOMIC_VAR_INIT( value ) -#define _Atomic_Fence( order ) _CPU_atomic_Fence( order ) +#define ATOMIC_INITIALIZER_UINTPTR( value ) ATOMIC_VAR_INIT( value ) -#define _Atomic_Init_uint( obj, desired ) \ - _CPU_atomic_Init_uint( obj, desired ) +#define ATOMIC_INITIALIZER_FLAG ATOMIC_FLAG_INIT -#define _Atomic_Init_ulong( obj, desired ) \ - _CPU_atomic_Init_ulong( obj, desired ) +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) -#define _Atomic_Init_uintptr( obj, desired ) \ - _CPU_atomic_Init_uintptr( obj, desired ) +typedef atomic_uint Atomic_Uint; -#define _Atomic_Load_uint( obj, order ) \ - _CPU_atomic_Load_uint( obj, order ) +typedef atomic_ulong Atomic_Ulong; -#define _Atomic_Load_ulong( obj, order ) \ - _CPU_atomic_Load_ulong( obj, order ) +typedef atomic_uintptr_t Atomic_Uintptr; -#define _Atomic_Load_uintptr( obj, order ) \ - _CPU_atomic_Load_uintptr( obj, order ) +typedef atomic_flag Atomic_Flag; -#define _Atomic_Store_uint( obj, desr, order ) \ - _CPU_atomic_Store_uint( obj, desr, order ) +typedef memory_order Atomic_Order; -#define _Atomic_Store_ulong( obj, desr, order ) \ - _CPU_atomic_Store_ulong( obj, desr, order ) +#define ATOMIC_ORDER_RELAXED memory_order_relaxed -#define _Atomic_Store_uintptr( obj, desr, order ) \ - _CPU_atomic_Store_uintptr( obj, desr, order ) +#define ATOMIC_ORDER_ACQUIRE memory_order_acquire -#define _Atomic_Fetch_add_uint( obj, arg, order ) \ - _CPU_atomic_Fetch_add_uint( obj, arg, order ) +#define ATOMIC_ORDER_RELEASE memory_order_release -#define _Atomic_Fetch_add_ulong( obj, arg, order ) \ - _CPU_atomic_Fetch_add_ulong( obj, arg, order ) +#define ATOMIC_ORDER_ACQ_REL memory_order_acq_rel -#define _Atomic_Fetch_add_uintptr( obj, arg, order ) \ - _CPU_atomic_Fetch_add_uintptr( obj, arg, order ) +#define ATOMIC_ORDER_SEQ_CST memory_order_seq_cst -#define _Atomic_Fetch_sub_uint( obj, arg, order ) \ - _CPU_atomic_Fetch_sub_uint( obj, arg, order ) +#define ATOMIC_INITIALIZER_UINT( value ) ATOMIC_VAR_INIT( value ) -#define _Atomic_Fetch_sub_ulong( obj, arg, order ) \ - _CPU_atomic_Fetch_sub_ulong( obj, arg, order ) +#define ATOMIC_INITIALIZER_ULONG( value ) ATOMIC_VAR_INIT( value ) -#define _Atomic_Fetch_sub_uintptr( obj, arg, order ) \ - _CPU_atomic_Fetch_sub_uintptr( obj, arg, order ) +#define ATOMIC_INITIALIZER_UINTPTR( value ) ATOMIC_VAR_INIT( value ) -#define _Atomic_Fetch_or_uint( obj, arg, order ) \ - _CPU_atomic_Fetch_or_uint( obj, arg, order ) +#define ATOMIC_INITIALIZER_FLAG ATOMIC_FLAG_INIT -#define _Atomic_Fetch_or_ulong( obj, arg, order ) \ - _CPU_atomic_Fetch_or_ulong( obj, arg, order ) +#else -#define _Atomic_Fetch_or_uintptr( obj, arg, order ) \ - _CPU_atomic_Fetch_or_uintptr( obj, arg, order ) +typedef unsigned int Atomic_Uint; -#define _Atomic_Fetch_and_uint( obj, arg, order ) \ - _CPU_atomic_Fetch_and_uint( obj, arg, order ) +typedef unsigned long Atomic_Ulong; -#define _Atomic_Fetch_and_ulong( obj, arg, order ) \ - _CPU_atomic_Fetch_and_ulong( obj, arg, order ) +typedef uintptr_t Atomic_Uintptr; -#define _Atomic_Fetch_and_uintptr( obj, arg, order ) \ - _CPU_atomic_Fetch_and_uintptr( obj, arg, order ) +typedef bool Atomic_Flag; -#define _Atomic_Exchange_uint( obj, desr, order ) \ - _CPU_atomic_Exchange_uint( obj, desr, order ) +typedef int Atomic_Order; -#define _Atomic_Exchange_ulong( obj, desr, order ) \ - _CPU_atomic_Exchange_ulong( obj, desr, order ) +#define ATOMIC_ORDER_RELAXED 0 -#define _Atomic_Exchange_uintptr( obj, desr, order ) \ - _CPU_atomic_Exchange_uintptr( obj, desr, order ) +#define ATOMIC_ORDER_ACQUIRE 2 -#define _Atomic_Compare_exchange_uint( obj, expected, desired, succ, fail ) \ - _CPU_atomic_Compare_exchange_uint( obj, expected, desired, succ, fail ) +#define ATOMIC_ORDER_RELEASE 3 -#define _Atomic_Compare_exchange_ulong( obj, expected, desired, succ, fail ) \ - _CPU_atomic_Compare_exchange_ulong( obj, expected, desired, succ, fail ) +#define ATOMIC_ORDER_ACQ_REL 4 -#define _Atomic_Compare_exchange_uintptr( obj, expected, desired, succ, fail ) \ - _CPU_atomic_Compare_exchange_uintptr( obj, expected, desired, succ, fail ) +#define ATOMIC_ORDER_SEQ_CST 5 -#define _Atomic_Flag_clear( obj, order ) \ - _CPU_atomic_Flag_clear( obj, order ) +#define ATOMIC_INITIALIZER_UINT( value ) ( value ) -#define _Atomic_Flag_test_and_set( obj, order ) \ - _CPU_atomic_Flag_test_and_set( obj, order ) +#define ATOMIC_INITIALIZER_ULONG( value ) ( value ) + +#define ATOMIC_INITIALIZER_UINTPTR( value ) ( value ) + +#define ATOMIC_INITIALIZER_FLAG false + +#endif + +/** + * @brief Sets up a cpu fence. + * + * @param[out] order The order for the fence. + */ +static inline void _Atomic_Fence( Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + std::atomic_thread_fence( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_thread_fence( order ); +#else + (void) order; + RTEMS_COMPILER_MEMORY_BARRIER(); +#endif +} + +/** + * @brief Initializes Uint. + * + * @param[out] obj The CPU atomic Uint to initialize. + * @param desired The desired value for @a obj. + */ +static inline void _Atomic_Init_uint( Atomic_Uint *obj, unsigned int desired ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_init( obj, desired ); +#else + *obj = desired; +#endif +} + +/** + * @brief Initializes Ulong. + * + * @param[out] obj The CPU atomic Ulong to initialize. + * @param desired The desired value for @a obj. + */ +static inline void _Atomic_Init_ulong( Atomic_Ulong *obj, unsigned long desired ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_init( obj, desired ); +#else + *obj = desired; +#endif +} + +/** + * @brief Initializes Uintptr. + * + * @param[out] obj The CPU atomic Uintptr to initialize. + * @param desired The desired value for @a obj. + */ +static inline void _Atomic_Init_uintptr( Atomic_Uintptr *obj, uintptr_t desired ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_init( obj, desired ); +#else + *obj = desired; +#endif +} + +/** + * @brief Loads value of Uint considering the order. + * + * @param obj The CPU atomic Uint to get the value from. + * @param order The atomic order for getting the value. + * + * @return The value of @a obj considering the @a order. + */ +static inline unsigned int _Atomic_Load_uint( const Atomic_Uint *obj, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->load( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_load_explicit( obj, order ); +#else + unsigned int val; + + (void) order; + val = *obj; + RTEMS_COMPILER_MEMORY_BARRIER(); + + return val; +#endif +} + +/** + * @brief Loads value of Ulong considering the order. + * + * @param obj The CPU atomic Ulong to get the value from. + * @param order The atomic order for getting the value. + * + * @return The value of @a obj considering the @a order. + */ +static inline unsigned long _Atomic_Load_ulong( const Atomic_Ulong *obj, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->load( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_load_explicit( obj, order ); +#else + unsigned long val; + + (void) order; + val = *obj; + RTEMS_COMPILER_MEMORY_BARRIER(); + + return val; +#endif +} + +/** + * @brief Loads value of Uintptr considering the order. + * + * @param obj The CPU atomic Uintptr to get the value from. + * @param order The atomic order for getting the value. + * + * @return The value of @a obj considering the @a order. + */ +static inline uintptr_t _Atomic_Load_uintptr( const Atomic_Uintptr *obj, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->load( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_load_explicit( obj, order ); +#else + uintptr_t val; + + (void) order; + val = *obj; + RTEMS_COMPILER_MEMORY_BARRIER(); + + return val; +#endif +} + +/** + * @brief Stores a value to Uint considering the order. + * + * @param[out] obj The CPU atomic Uint to store a value in. + * @param desired The desired value for @a obj. + * @param order The atomic order for storing the value. + */ +static inline void _Atomic_Store_uint( Atomic_Uint *obj, unsigned int desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_store_explicit( obj, desired, order ); +#else + (void) order; + RTEMS_COMPILER_MEMORY_BARRIER(); + *obj = desired; +#endif +} + +/** + * @brief Stores a value to Ulong considering the order. + * + * @param[out] obj The CPU atomic Ulong to store a value in. + * @param desired The desired value for @a obj. + * @param order The atomic order for storing the value. + */ +static inline void _Atomic_Store_ulong( Atomic_Ulong *obj, unsigned long desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_store_explicit( obj, desired, order ); +#else + (void) order; + RTEMS_COMPILER_MEMORY_BARRIER(); + *obj = desired; +#endif +} + +/** + * @brief Stores a value to Uintptr considering the order. + * + * @param[out] obj The CPU atomic Uintptr to store a value in. + * @param desired The desired value for @a obj. + * @param order The atomic order for storing the value. + */ +static inline void _Atomic_Store_uintptr( Atomic_Uintptr *obj, uintptr_t desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_store_explicit( obj, desired, order ); +#else + (void) order; + RTEMS_COMPILER_MEMORY_BARRIER(); + *obj = desired; +#endif +} + +/** + * @brief Fetches current value of Uint and adds a value to the stored value. + * + * @param[in, out] obj The CPU atomic Uint to get the value from and add @a arg to. + * @param arg The value to add to @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the addition of @a arg. + */ +static inline unsigned int _Atomic_Fetch_add_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_add( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_add_explicit( obj, arg, order ); +#else + unsigned int val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val + arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Ulong and adds a value to the stored value. + * + * @param[in, out] obj The CPU atomic Ulong to get the value from and add @a arg to. + * @param arg The value to add to @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the addition of @a arg. + */ +static inline unsigned long _Atomic_Fetch_add_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_add( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_add_explicit( obj, arg, order ); +#else + unsigned long val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val + arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uintptr and adds a value to the stored value. + * + * @param[in, out] obj The CPU atomic Uintptr to get the value from and add @a arg to. + * @param arg The value to add to @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the addition of @a arg. + */ +static inline uintptr_t _Atomic_Fetch_add_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_add( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_add_explicit( obj, arg, order ); +#else + uintptr_t val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val + arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uint and subtracts a value from the stored value. + * + * @param[in, out] obj The CPU atomic Uint to get the value from and subtract @a arg from. + * @param arg The value to subtract from @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the subtraction of @a arg. + */ +static inline unsigned int _Atomic_Fetch_sub_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_sub( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_sub_explicit( obj, arg, order ); +#else + unsigned int val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val - arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Ulong and subtracts a value from the stored value. + * + * @param[in, out] obj The CPU atomic Ulong to get the value from and subtract @a arg from. + * @param arg The value to subtract from @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the subtraction of @a arg. + */ +static inline unsigned long _Atomic_Fetch_sub_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_sub( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_sub_explicit( obj, arg, order ); +#else + unsigned long val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val - arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uintptr and subtracts a value from the stored value. + * + * @param[in, out] obj The CPU atomic Uintptr to get the value from and subtract @a arg from. + * @param arg The value to subtract from @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the subtraction of @a arg. + */ +static inline uintptr_t _Atomic_Fetch_sub_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_sub( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_sub_explicit( obj, arg, order ); +#else + uintptr_t val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val - arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uint and ORs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Uint to get the value from and OR @a arg to. + * @param arg The value to OR with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the OR operation with @a arg. + */ +static inline unsigned int _Atomic_Fetch_or_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_or( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_or_explicit( obj, arg, order ); +#else + unsigned int val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val | arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Ulong and ORs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Ulong to get the value from and OR @a arg to. + * @param arg The value to OR with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the OR operation with @a arg. + */ +static inline unsigned long _Atomic_Fetch_or_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_or( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_or_explicit( obj, arg, order ); +#else + unsigned long val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val | arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uintptr and ORs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Uintptr to get the value from and OR @a arg to. + * @param arg The value to OR with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the OR operation with @a arg. + */ +static inline uintptr_t _Atomic_Fetch_or_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_or( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_or_explicit( obj, arg, order ); +#else + uintptr_t val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val | arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uint and ANDs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Uint to get the value from and AND @a arg to. + * @param arg The value to AND with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the AND operation with @a arg. + */ +static inline unsigned int _Atomic_Fetch_and_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_and( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_and_explicit( obj, arg, order ); +#else + unsigned int val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val & arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Ulong and ANDs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Ulong to get the value from and AND @a arg to. + * @param arg The value to AND with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the AND operation with @a arg. + */ +static inline unsigned long _Atomic_Fetch_and_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_and( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_and_explicit( obj, arg, order ); +#else + unsigned long val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val & arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uintptr and ANDs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Uintptr to get the value from and AND @a arg to. + * @param arg The value to AND with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the AND operation with @a arg. + */ +static inline uintptr_t _Atomic_Fetch_and_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_and( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_and_explicit( obj, arg, order ); +#else + uintptr_t val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val & arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uint and sets its value. + * + * @param[in, out] obj The CPU atomic Uint to get the value from and set the value to @a desired. + * @param arg The value to set for @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the exchange with @a desired. + */ +static inline unsigned int _Atomic_Exchange_uint( Atomic_Uint *obj, unsigned int desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->exchange( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_exchange_explicit( obj, desired, order ); +#else + unsigned int val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = desired; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Ulong and sets its value. + * + * @param[in, out] obj The CPU atomic Ulong to get the value from and set the value to @a desired. + * @param arg The value to set for @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the exchange with @a desired. + */ +static inline unsigned long _Atomic_Exchange_ulong( Atomic_Ulong *obj, unsigned long desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->exchange( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_exchange_explicit( obj, desired, order ); +#else + unsigned long val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = desired; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uintptr and sets its value. + * + * @param[in, out] obj The CPU atomic Uintptr to get the value from and set the value to @a desired. + * @param arg The value to set for @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the exchange with @a desired. + */ +static inline uintptr_t _Atomic_Exchange_uintptr( Atomic_Uintptr *obj, uintptr_t desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->exchange( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_exchange_explicit( obj, desired, order ); +#else + uintptr_t val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = desired; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Checks if value of Uint is as expected. + * + * This method checks if the value of @a obj is equal to the value of @a expected. If + * this is the case, the value of @a obj is changed to @a desired. Otherwise, the value + * of @a obj is changed to @a expected. + * + * @param[in, out] obj The CPU atomic Uint to operate upon. + * @param[in, out] expected The expected value of @a obj. If @a obj has a different + * value, @a expected is changed to the actual value of @a obj. + * @param desired The new value of @a obj if the old value of @a obj was as expected. + * @param succ The order if it is successful. + * @param fail The order if it fails. + * + * @retval true The old value of @a obj was as expected. + * @retval false The old value of @a obj was not as expected. + */ +static inline bool _Atomic_Compare_exchange_uint( Atomic_Uint *obj, unsigned int *expected, unsigned int desired, Atomic_Order succ, Atomic_Order fail ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->compare_exchange_strong( *expected, desired, succ, fail ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail ); +#else + bool success; + ISR_Level level; + unsigned int actual; + + (void) succ; + (void) fail; + _ISR_Local_disable( level ); + actual = *obj; + success = ( actual == *expected ); + if ( success ) { + *obj = desired; + } else { + *expected = actual; + } + _ISR_Local_enable( level ); + + return success; +#endif +} + +/** + * @brief Checks if value of Ulong is as expected. + * + * This method checks if the value of @a obj is equal to the value of @a expected. If + * this is the case, the value of @a obj is changed to @a desired. Otherwise, the value + * of @a obj is changed to @a expected. + * + * @param[in, out] obj The CPU atomic Ulong to operate upon. + * @param[in, out] expected The expected value of @a obj. If @a obj has a different + * value, @a expected is changed to the actual value of @a obj. + * @param desired The new value of @a obj if the old value of @a obj was as expected. + * @param succ The order if it is successful. + * @param fail The order if it fails. + * + * @retval true The old value of @a obj was as expected. + * @retval false The old value of @a obj was not as expected. + */ +static inline bool _Atomic_Compare_exchange_ulong( Atomic_Ulong *obj, unsigned long *expected, unsigned long desired, Atomic_Order succ, Atomic_Order fail ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->compare_exchange_strong( *expected, desired, succ, fail ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail ); +#else + bool success; + ISR_Level level; + unsigned long actual; + + (void) succ; + (void) fail; + _ISR_Local_disable( level ); + actual = *obj; + success = ( actual == *expected ); + if ( success ) { + *obj = desired; + } else { + *expected = actual; + } + _ISR_Local_enable( level ); + + return success; +#endif +} + +/** + * @brief Checks if value of Uintptr is as expected. + * + * This method checks if the value of @a obj is equal to the value of @a expected. If + * this is the case, the value of @a obj is changed to @a desired. Otherwise, the value + * of @a obj is changed to @a expected. + * + * @param[in, out] obj The CPU atomic Uintptr to operate upon. + * @param[in, out] expected The expected value of @a obj. If @a obj has a different + * value, @a expected is changed to the actual value of @a obj. + * @param desired The new value of @a obj if the old value of @a obj was as expected. + * @param succ The order if it is successful. + * @param fail The order if it fails. + * + * @retval true The old value of @a obj was as expected. + * @retval false The old value of @a obj was not as expected. + */ +static inline bool _Atomic_Compare_exchange_uintptr( Atomic_Uintptr *obj, uintptr_t *expected, uintptr_t desired, Atomic_Order succ, Atomic_Order fail ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->compare_exchange_strong( *expected, desired, succ, fail ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail ); +#else + bool success; + ISR_Level level; + uintptr_t actual; + + (void) succ; + (void) fail; + _ISR_Local_disable( level ); + actual = *obj; + success = ( actual == *expected ); + if ( success ) { + *obj = desired; + } else { + *expected = actual; + } + _ISR_Local_enable( level ); + + return success; +#endif +} + +/** + * @brief Clears the atomic flag. + * + * @param[out] obj The atomic flag to be cleared. + * @param order The atomic order for the operation. + */ +static inline void _Atomic_Flag_clear( Atomic_Flag *obj, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->clear( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_flag_clear_explicit( obj, order ); +#else + (void) order; + *obj = false; +#endif +} + +/** + * @brief Returns current flag state and sets it. + * + * @param[in, out] obj The atomic flag to be set. + * @param order The atomic order for the operation. + * + * @retval true @a obj was set prior to this operation. + * @retval false @a obj was not set prior to this operation. + */ +static inline bool _Atomic_Flag_test_and_set( Atomic_Flag *obj, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->test_and_set( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_flag_test_and_set_explicit( obj, order ); +#else + bool flag; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + flag = *obj; + *obj = true; + _ISR_Local_enable( level ); + + return flag; +#endif +} /** @} */ diff --git a/cpukit/include/rtems/score/basedefs.h b/cpukit/include/rtems/score/basedefs.h index 99fda67e8c..010728d795 100644 --- a/cpukit/include/rtems/score/basedefs.h +++ b/cpukit/include/rtems/score/basedefs.h @@ -10,7 +10,7 @@ */ /* - * Copyright (C) 2014 Paval Pisa + * Copyright (C) 2014 Pavel Pisa * Copyright (C) 2011, 2013 On-Line Applications Research Corporation (OAR) * Copyright (C) 2009, 2023 embedded brains GmbH & Co. KG * @@ -168,9 +168,9 @@ extern "C" { * * @return Returns the alignment requirement of the type. */ -#if __cplusplus >= 201103L +#if defined( __cplusplus ) && __cplusplus >= 201103L #define RTEMS_ALIGNOF( _type_name ) alignof( _type_name ) -#elif __STDC_VERSION__ >= 201112L +#elif defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 201112L #define RTEMS_ALIGNOF( _type_name ) _Alignof( _type_name ) #else #define RTEMS_ALIGNOF( _type_name ) sizeof( _type_name ) @@ -376,9 +376,9 @@ extern "C" { * @brief Tells the compiler in a function declaration that this function does * not return. */ -#if __cplusplus >= 201103L +#if defined( __cplusplus ) && __cplusplus >= 201103L #define RTEMS_NO_RETURN [[noreturn]] -#elif __STDC_VERSION__ >= 201112L +#elif defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 201112L #define RTEMS_NO_RETURN _Noreturn #elif defined(__GNUC__) #define RTEMS_NO_RETURN __attribute__(( __noreturn__ )) @@ -833,9 +833,9 @@ extern "C" { * * @param _msg is the error message in case the static assertion fails. */ -#if __cplusplus >= 201103L +#if defined( __cplusplus ) && __cplusplus >= 201103L #define RTEMS_STATIC_ASSERT( _cond, _msg ) static_assert( _cond, # _msg ) -#elif __STDC_VERSION__ >= 201112L +#elif defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 201112L #define RTEMS_STATIC_ASSERT( _cond, _msg ) _Static_assert( _cond, # _msg ) #else #define RTEMS_STATIC_ASSERT( _cond, _msg ) \ @@ -999,11 +999,12 @@ extern "C" { * * @param _value is the value of the symbol. On the value a macro expansion is * performed and afterwards it is stringified. It shall expand to an integer - * expression understood by the assembler. + * expression understood by the assembler. The value shall be representable + * in the code model of the target architecture. * * This macro shall be placed at file scope. */ -#if defined(__USER_LABEL_PREFIX__) +#if defined(__GNUC__) #define RTEMS_DEFINE_GLOBAL_SYMBOL( _name, _value ) \ __asm__( \ "\t.globl " RTEMS_XSTRING( RTEMS_SYMBOL_NAME( _name ) ) \ diff --git a/cpukit/include/rtems/score/cpustdatomic.h b/cpukit/include/rtems/score/cpustdatomic.h deleted file mode 100644 index f1afa6bec2..0000000000 --- a/cpukit/include/rtems/score/cpustdatomic.h +++ /dev/null @@ -1,986 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup RTEMSScoreAtomicCPU - * - * @brief This header file provides the interfaces of the - * @ref RTEMSScoreAtomicCPU. - */ - -/* - * COPYRIGHT (c) 2013 Deng Hengyi. - * Copyright (c) 2015 embedded brains GmbH & Co. KG - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_CPUSTDATOMIC_H -#define _RTEMS_SCORE_CPUSTDATOMIC_H - -#include <rtems/score/basedefs.h> - -/** - * @defgroup RTEMSScoreAtomicCPU C11/C++11 Atomic Operations - * - * @ingroup RTEMSScoreAtomic - * - * @brief This group contains the atomic operations implementation using - * functions provided by the C11/C++11. - * - * @{ - */ - -#ifdef RTEMS_SMP - #if defined(__cplusplus) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) - /* - * The GCC 4.9 ships its own <stdatomic.h> which is not C++ compatible. The - * suggested solution was to include <atomic> in case C++ is used. This works - * at least with GCC 4.9. See also: - * - * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60932 - * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60940 - */ - #include <atomic> - #define _RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC - #else - #include <stdatomic.h> - #define _RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC - #endif -#else - #include <rtems/score/isrlevel.h> -#endif - -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - -typedef std::atomic_uint CPU_atomic_Uint; - -typedef std::atomic_ulong CPU_atomic_Ulong; - -typedef std::atomic_uintptr_t CPU_atomic_Uintptr; - -typedef std::atomic_flag CPU_atomic_Flag; - -typedef std::memory_order CPU_atomic_Order; - -#define CPU_ATOMIC_ORDER_RELAXED std::memory_order_relaxed - -#define CPU_ATOMIC_ORDER_ACQUIRE std::memory_order_acquire - -#define CPU_ATOMIC_ORDER_RELEASE std::memory_order_release - -#define CPU_ATOMIC_ORDER_ACQ_REL std::memory_order_acq_rel - -#define CPU_ATOMIC_ORDER_SEQ_CST std::memory_order_seq_cst - -#define CPU_ATOMIC_INITIALIZER_UINT( value ) ATOMIC_VAR_INIT( value ) - -#define CPU_ATOMIC_INITIALIZER_ULONG( value ) ATOMIC_VAR_INIT( value ) - -#define CPU_ATOMIC_INITIALIZER_UINTPTR( value ) ATOMIC_VAR_INIT( value ) - -#define CPU_ATOMIC_INITIALIZER_FLAG ATOMIC_FLAG_INIT - -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - -typedef atomic_uint CPU_atomic_Uint; - -typedef atomic_ulong CPU_atomic_Ulong; - -typedef atomic_uintptr_t CPU_atomic_Uintptr; - -typedef atomic_flag CPU_atomic_Flag; - -typedef memory_order CPU_atomic_Order; - -#define CPU_ATOMIC_ORDER_RELAXED memory_order_relaxed - -#define CPU_ATOMIC_ORDER_ACQUIRE memory_order_acquire - -#define CPU_ATOMIC_ORDER_RELEASE memory_order_release - -#define CPU_ATOMIC_ORDER_ACQ_REL memory_order_acq_rel - -#define CPU_ATOMIC_ORDER_SEQ_CST memory_order_seq_cst - -#define CPU_ATOMIC_INITIALIZER_UINT( value ) ATOMIC_VAR_INIT( value ) - -#define CPU_ATOMIC_INITIALIZER_ULONG( value ) ATOMIC_VAR_INIT( value ) - -#define CPU_ATOMIC_INITIALIZER_UINTPTR( value ) ATOMIC_VAR_INIT( value ) - -#define CPU_ATOMIC_INITIALIZER_FLAG ATOMIC_FLAG_INIT - -#else - -typedef unsigned int CPU_atomic_Uint; - -typedef unsigned long CPU_atomic_Ulong; - -typedef uintptr_t CPU_atomic_Uintptr; - -typedef bool CPU_atomic_Flag; - -typedef int CPU_atomic_Order; - -#define CPU_ATOMIC_ORDER_RELAXED 0 - -#define CPU_ATOMIC_ORDER_ACQUIRE 2 - -#define CPU_ATOMIC_ORDER_RELEASE 3 - -#define CPU_ATOMIC_ORDER_ACQ_REL 4 - -#define CPU_ATOMIC_ORDER_SEQ_CST 5 - -#define CPU_ATOMIC_INITIALIZER_UINT( value ) ( value ) - -#define CPU_ATOMIC_INITIALIZER_ULONG( value ) ( value ) - -#define CPU_ATOMIC_INITIALIZER_UINTPTR( value ) ( value ) - -#define CPU_ATOMIC_INITIALIZER_FLAG false - -#endif - -/** - * @brief Sets up a cpu fence. - * - * @param[out] order The order for the fence. - */ -static inline void _CPU_atomic_Fence( CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - std::atomic_thread_fence( order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - atomic_thread_fence( order ); -#else - (void) order; - RTEMS_COMPILER_MEMORY_BARRIER(); -#endif -} - -/** - * @brief Initializes Uint. - * - * @param[out] obj The CPU atomic Uint to initialize. - * @param desired The desired value for @a obj. - */ -static inline void _CPU_atomic_Init_uint( CPU_atomic_Uint *obj, unsigned int desired ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - obj->store( desired ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - atomic_init( obj, desired ); -#else - *obj = desired; -#endif -} - -/** - * @brief Initializes Ulong. - * - * @param[out] obj The CPU atomic Ulong to initialize. - * @param desired The desired value for @a obj. - */ -static inline void _CPU_atomic_Init_ulong( CPU_atomic_Ulong *obj, unsigned long desired ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - obj->store( desired ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - atomic_init( obj, desired ); -#else - *obj = desired; -#endif -} - -/** - * @brief Initializes Uintptr. - * - * @param[out] obj The CPU atomic Uintptr to initialize. - * @param desired The desired value for @a obj. - */ -static inline void _CPU_atomic_Init_uintptr( CPU_atomic_Uintptr *obj, uintptr_t desired ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - obj->store( desired ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - atomic_init( obj, desired ); -#else - *obj = desired; -#endif -} - -/** - * @brief Loads value of Uint considering the order. - * - * @param obj The CPU atomic Uint to get the value from. - * @param order The atomic order for getting the value. - * - * @return The value of @a obj considering the @a order. - */ -static inline unsigned int _CPU_atomic_Load_uint( const CPU_atomic_Uint *obj, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->load( order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_load_explicit( obj, order ); -#else - unsigned int val; - - (void) order; - val = *obj; - RTEMS_COMPILER_MEMORY_BARRIER(); - - return val; -#endif -} - -/** - * @brief Loads value of Ulong considering the order. - * - * @param obj The CPU atomic Ulong to get the value from. - * @param order The atomic order for getting the value. - * - * @return The value of @a obj considering the @a order. - */ -static inline unsigned long _CPU_atomic_Load_ulong( const CPU_atomic_Ulong *obj, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->load( order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_load_explicit( obj, order ); -#else - unsigned long val; - - (void) order; - val = *obj; - RTEMS_COMPILER_MEMORY_BARRIER(); - - return val; -#endif -} - -/** - * @brief Loads value of Uintptr considering the order. - * - * @param obj The CPU atomic Uintptr to get the value from. - * @param order The atomic order for getting the value. - * - * @return The value of @a obj considering the @a order. - */ -static inline uintptr_t _CPU_atomic_Load_uintptr( const CPU_atomic_Uintptr *obj, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->load( order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_load_explicit( obj, order ); -#else - uintptr_t val; - - (void) order; - val = *obj; - RTEMS_COMPILER_MEMORY_BARRIER(); - - return val; -#endif -} - -/** - * @brief Stores a value to Uint considering the order. - * - * @param[out] obj The CPU atomic Uint to store a value in. - * @param desired The desired value for @a obj. - * @param order The atomic order for storing the value. - */ -static inline void _CPU_atomic_Store_uint( CPU_atomic_Uint *obj, unsigned int desired, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - obj->store( desired, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - atomic_store_explicit( obj, desired, order ); -#else - (void) order; - RTEMS_COMPILER_MEMORY_BARRIER(); - *obj = desired; -#endif -} - -/** - * @brief Stores a value to Ulong considering the order. - * - * @param[out] obj The CPU atomic Ulong to store a value in. - * @param desired The desired value for @a obj. - * @param order The atomic order for storing the value. - */ -static inline void _CPU_atomic_Store_ulong( CPU_atomic_Ulong *obj, unsigned long desired, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - obj->store( desired, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - atomic_store_explicit( obj, desired, order ); -#else - (void) order; - RTEMS_COMPILER_MEMORY_BARRIER(); - *obj = desired; -#endif -} - -/** - * @brief Stores a value to Uintptr considering the order. - * - * @param[out] obj The CPU atomic Uintptr to store a value in. - * @param desired The desired value for @a obj. - * @param order The atomic order for storing the value. - */ -static inline void _CPU_atomic_Store_uintptr( CPU_atomic_Uintptr *obj, uintptr_t desired, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - obj->store( desired, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - atomic_store_explicit( obj, desired, order ); -#else - (void) order; - RTEMS_COMPILER_MEMORY_BARRIER(); - *obj = desired; -#endif -} - -/** - * @brief Fetches current value of Uint and adds a value to the stored value. - * - * @param[in, out] obj The CPU atomic Uint to get the value from and add @a arg to. - * @param arg The value to add to @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the addition of @a arg. - */ -static inline unsigned int _CPU_atomic_Fetch_add_uint( CPU_atomic_Uint *obj, unsigned int arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_add( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_add_explicit( obj, arg, order ); -#else - unsigned int val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val + arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Ulong and adds a value to the stored value. - * - * @param[in, out] obj The CPU atomic Ulong to get the value from and add @a arg to. - * @param arg The value to add to @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the addition of @a arg. - */ -static inline unsigned long _CPU_atomic_Fetch_add_ulong( CPU_atomic_Ulong *obj, unsigned long arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_add( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_add_explicit( obj, arg, order ); -#else - unsigned long val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val + arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Uintptr and adds a value to the stored value. - * - * @param[in, out] obj The CPU atomic Uintptr to get the value from and add @a arg to. - * @param arg The value to add to @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the addition of @a arg. - */ -static inline uintptr_t _CPU_atomic_Fetch_add_uintptr( CPU_atomic_Uintptr *obj, uintptr_t arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_add( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_add_explicit( obj, arg, order ); -#else - uintptr_t val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val + arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Uint and subtracts a value from the stored value. - * - * @param[in, out] obj The CPU atomic Uint to get the value from and subtract @a arg from. - * @param arg The value to subtract from @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the subtraction of @a arg. - */ -static inline unsigned int _CPU_atomic_Fetch_sub_uint( CPU_atomic_Uint *obj, unsigned int arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_sub( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_sub_explicit( obj, arg, order ); -#else - unsigned int val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val - arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Ulong and subtracts a value from the stored value. - * - * @param[in, out] obj The CPU atomic Ulong to get the value from and subtract @a arg from. - * @param arg The value to subtract from @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the subtraction of @a arg. - */ -static inline unsigned long _CPU_atomic_Fetch_sub_ulong( CPU_atomic_Ulong *obj, unsigned long arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_sub( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_sub_explicit( obj, arg, order ); -#else - unsigned long val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val - arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Uintptr and subtracts a value from the stored value. - * - * @param[in, out] obj The CPU atomic Uintptr to get the value from and subtract @a arg from. - * @param arg The value to subtract from @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the subtraction of @a arg. - */ -static inline uintptr_t _CPU_atomic_Fetch_sub_uintptr( CPU_atomic_Uintptr *obj, uintptr_t arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_sub( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_sub_explicit( obj, arg, order ); -#else - uintptr_t val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val - arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Uint and ORs a value with the stored value. - * - * @param[in, out] obj The CPU atomic Uint to get the value from and OR @a arg to. - * @param arg The value to OR with @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the OR operation with @a arg. - */ -static inline unsigned int _CPU_atomic_Fetch_or_uint( CPU_atomic_Uint *obj, unsigned int arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_or( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_or_explicit( obj, arg, order ); -#else - unsigned int val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val | arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Ulong and ORs a value with the stored value. - * - * @param[in, out] obj The CPU atomic Ulong to get the value from and OR @a arg to. - * @param arg The value to OR with @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the OR operation with @a arg. - */ -static inline unsigned long _CPU_atomic_Fetch_or_ulong( CPU_atomic_Ulong *obj, unsigned long arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_or( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_or_explicit( obj, arg, order ); -#else - unsigned long val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val | arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Uintptr and ORs a value with the stored value. - * - * @param[in, out] obj The CPU atomic Uintptr to get the value from and OR @a arg to. - * @param arg The value to OR with @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the OR operation with @a arg. - */ -static inline uintptr_t _CPU_atomic_Fetch_or_uintptr( CPU_atomic_Uintptr *obj, uintptr_t arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_or( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_or_explicit( obj, arg, order ); -#else - uintptr_t val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val | arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Uint and ANDs a value with the stored value. - * - * @param[in, out] obj The CPU atomic Uint to get the value from and AND @a arg to. - * @param arg The value to AND with @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the AND operation with @a arg. - */ -static inline unsigned int _CPU_atomic_Fetch_and_uint( CPU_atomic_Uint *obj, unsigned int arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_and( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_and_explicit( obj, arg, order ); -#else - unsigned int val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val & arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Ulong and ANDs a value with the stored value. - * - * @param[in, out] obj The CPU atomic Ulong to get the value from and AND @a arg to. - * @param arg The value to AND with @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the AND operation with @a arg. - */ -static inline unsigned long _CPU_atomic_Fetch_and_ulong( CPU_atomic_Ulong *obj, unsigned long arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_and( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_and_explicit( obj, arg, order ); -#else - unsigned long val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val & arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Uintptr and ANDs a value with the stored value. - * - * @param[in, out] obj The CPU atomic Uintptr to get the value from and AND @a arg to. - * @param arg The value to AND with @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the AND operation with @a arg. - */ -static inline uintptr_t _CPU_atomic_Fetch_and_uintptr( CPU_atomic_Uintptr *obj, uintptr_t arg, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->fetch_and( arg, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_fetch_and_explicit( obj, arg, order ); -#else - uintptr_t val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = val & arg; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Uint and sets its value. - * - * @param[in, out] obj The CPU atomic Uint to get the value from and set the value to @a desired. - * @param arg The value to set for @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the exchange with @a desired. - */ -static inline unsigned int _CPU_atomic_Exchange_uint( CPU_atomic_Uint *obj, unsigned int desired, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->exchange( desired, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_exchange_explicit( obj, desired, order ); -#else - unsigned int val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = desired; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Ulong and sets its value. - * - * @param[in, out] obj The CPU atomic Ulong to get the value from and set the value to @a desired. - * @param arg The value to set for @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the exchange with @a desired. - */ -static inline unsigned long _CPU_atomic_Exchange_ulong( CPU_atomic_Ulong *obj, unsigned long desired, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->exchange( desired, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_exchange_explicit( obj, desired, order ); -#else - unsigned long val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = desired; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Fetches current value of Uintptr and sets its value. - * - * @param[in, out] obj The CPU atomic Uintptr to get the value from and set the value to @a desired. - * @param arg The value to set for @a obj. - * @param order The atomic order for the operation. - * - * @return The value of @a obj prior to the exchange with @a desired. - */ -static inline uintptr_t _CPU_atomic_Exchange_uintptr( CPU_atomic_Uintptr *obj, uintptr_t desired, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->exchange( desired, order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_exchange_explicit( obj, desired, order ); -#else - uintptr_t val; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - val = *obj; - *obj = desired; - _ISR_Local_enable( level ); - - return val; -#endif -} - -/** - * @brief Checks if value of Uint is as expected. - * - * This method checks if the value of @a obj is equal to the value of @a expected. If - * this is the case, the value of @a obj is changed to @a desired. Otherwise, the value - * of @a obj is changed to @a expected. - * - * @param[in, out] obj The CPU atomic Uint to operate upon. - * @param[in, out] expected The expected value of @a obj. If @a obj has a different - * value, @a expected is changed to the actual value of @a obj. - * @param desired The new value of @a obj if the old value of @a obj was as expected. - * @param succ The order if it is successful. - * @param fail The order if it fails. - * - * @retval true The old value of @a obj was as expected. - * @retval false The old value of @a obj was not as expected. - */ -static inline bool _CPU_atomic_Compare_exchange_uint( CPU_atomic_Uint *obj, unsigned int *expected, unsigned int desired, CPU_atomic_Order succ, CPU_atomic_Order fail ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->compare_exchange_strong( *expected, desired, succ, fail ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail ); -#else - bool success; - ISR_Level level; - unsigned int actual; - - (void) succ; - (void) fail; - _ISR_Local_disable( level ); - actual = *obj; - success = ( actual == *expected ); - if ( success ) { - *obj = desired; - } else { - *expected = actual; - } - _ISR_Local_enable( level ); - - return success; -#endif -} - -/** - * @brief Checks if value of Ulong is as expected. - * - * This method checks if the value of @a obj is equal to the value of @a expected. If - * this is the case, the value of @a obj is changed to @a desired. Otherwise, the value - * of @a obj is changed to @a expected. - * - * @param[in, out] obj The CPU atomic Ulong to operate upon. - * @param[in, out] expected The expected value of @a obj. If @a obj has a different - * value, @a expected is changed to the actual value of @a obj. - * @param desired The new value of @a obj if the old value of @a obj was as expected. - * @param succ The order if it is successful. - * @param fail The order if it fails. - * - * @retval true The old value of @a obj was as expected. - * @retval false The old value of @a obj was not as expected. - */ -static inline bool _CPU_atomic_Compare_exchange_ulong( CPU_atomic_Ulong *obj, unsigned long *expected, unsigned long desired, CPU_atomic_Order succ, CPU_atomic_Order fail ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->compare_exchange_strong( *expected, desired, succ, fail ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail ); -#else - bool success; - ISR_Level level; - unsigned long actual; - - (void) succ; - (void) fail; - _ISR_Local_disable( level ); - actual = *obj; - success = ( actual == *expected ); - if ( success ) { - *obj = desired; - } else { - *expected = actual; - } - _ISR_Local_enable( level ); - - return success; -#endif -} - -/** - * @brief Checks if value of Uintptr is as expected. - * - * This method checks if the value of @a obj is equal to the value of @a expected. If - * this is the case, the value of @a obj is changed to @a desired. Otherwise, the value - * of @a obj is changed to @a expected. - * - * @param[in, out] obj The CPU atomic Uintptr to operate upon. - * @param[in, out] expected The expected value of @a obj. If @a obj has a different - * value, @a expected is changed to the actual value of @a obj. - * @param desired The new value of @a obj if the old value of @a obj was as expected. - * @param succ The order if it is successful. - * @param fail The order if it fails. - * - * @retval true The old value of @a obj was as expected. - * @retval false The old value of @a obj was not as expected. - */ -static inline bool _CPU_atomic_Compare_exchange_uintptr( CPU_atomic_Uintptr *obj, uintptr_t *expected, uintptr_t desired, CPU_atomic_Order succ, CPU_atomic_Order fail ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->compare_exchange_strong( *expected, desired, succ, fail ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail ); -#else - bool success; - ISR_Level level; - uintptr_t actual; - - (void) succ; - (void) fail; - _ISR_Local_disable( level ); - actual = *obj; - success = ( actual == *expected ); - if ( success ) { - *obj = desired; - } else { - *expected = actual; - } - _ISR_Local_enable( level ); - - return success; -#endif -} - -/** - * @brief Clears the atomic flag. - * - * @param[out] obj The atomic flag to be cleared. - * @param order The atomic order for the operation. - */ -static inline void _CPU_atomic_Flag_clear( CPU_atomic_Flag *obj, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - obj->clear( order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - atomic_flag_clear_explicit( obj, order ); -#else - (void) order; - *obj = false; -#endif -} - -/** - * @brief Returns current flag state and sets it. - * - * @param[in, out] obj The atomic flag to be set. - * @param order The atomic order for the operation. - * - * @retval true @a obj was set prior to this operation. - * @retval false @a obj was not set prior to this operation. - */ -static inline bool _CPU_atomic_Flag_test_and_set( CPU_atomic_Flag *obj, CPU_atomic_Order order ) -{ -#if defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_ATOMIC) - return obj->test_and_set( order ); -#elif defined(_RTEMS_SCORE_CPUSTDATOMIC_USE_STDATOMIC) - return atomic_flag_test_and_set_explicit( obj, order ); -#else - bool flag; - ISR_Level level; - - (void) order; - _ISR_Local_disable( level ); - flag = *obj; - *obj = true; - _ISR_Local_enable( level ); - - return flag; -#endif -} - -/** @} */ - -#endif /* _RTEMS_SCORE_CPUSTDATOMIC_H */ diff --git a/cpukit/include/rtems/score/isr.h b/cpukit/include/rtems/score/isr.h index bb1f3cee50..96ad816245 100644 --- a/cpukit/include/rtems/score/isr.h +++ b/cpukit/include/rtems/score/isr.h @@ -98,7 +98,11 @@ extern ISR_Handler_entry _ISR_Vector_table[ CPU_INTERRUPT_NUMBER_OF_VECTORS ]; #endif /** - * @brief Global symbol with a value equal to the configure interrupt stack size. + * @brief Provides the configured interrupt stack size through an address. + * + * The address of this global symbol is equal to the configured interrupt stack + * size. The address of this symbol has an arbitrary value an may not be + * representable in the code model used by the compiler. * * This global symbol is defined by the application configuration option * CONFIGURE_INIT_TASK_STACK_SIZE via <rtems/confdefs.h>. @@ -106,6 +110,14 @@ extern ISR_Handler_entry _ISR_Vector_table[ CPU_INTERRUPT_NUMBER_OF_VECTORS ]; RTEMS_DECLARE_GLOBAL_SYMBOL( _ISR_Stack_size ); /** + * @brief Provides the configured interrupt stack size through an object. + * + * This object is provided to avoid issues with the _ISR_Stack_size symbol + * address and the code model used by the compiler. + */ +extern const char * const volatile _ISR_Stack_size_object; + +/** * @brief The interrupt stack area begin. * * The interrupt stack area is defined by the application configuration via diff --git a/cpukit/include/rtems/score/mpci.h b/cpukit/include/rtems/score/mpci.h index 874c195e95..796c881929 100644 --- a/cpukit/include/rtems/score/mpci.h +++ b/cpukit/include/rtems/score/mpci.h @@ -40,9 +40,6 @@ #define _RTEMS_SCORE_MPCI_H #include <rtems/score/mppkt.h> -#include <rtems/score/thread.h> -#include <rtems/score/threadq.h> -#include <rtems/score/watchdog.h> #ifdef __cplusplus extern "C" { diff --git a/cpukit/include/rtems/score/mpciimpl.h b/cpukit/include/rtems/score/mpciimpl.h index b646d4be4d..d0c2d0558a 100644 --- a/cpukit/include/rtems/score/mpciimpl.h +++ b/cpukit/include/rtems/score/mpciimpl.h @@ -39,6 +39,9 @@ #define _RTEMS_SCORE_MPCIIMPL_H #include <rtems/score/mpci.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/watchdog.h> #include <rtems/score/status.h> #ifdef __cplusplus diff --git a/cpukit/include/rtems/score/mrspimpl.h b/cpukit/include/rtems/score/mrspimpl.h index 7a6c86d57c..fd783bf2a0 100644 --- a/cpukit/include/rtems/score/mrspimpl.h +++ b/cpukit/include/rtems/score/mrspimpl.h @@ -130,6 +130,7 @@ static inline Priority_Control _MRSP_Get_priority( uint32_t scheduler_index; scheduler_index = _Scheduler_Get_index( scheduler ); + _Assert( scheduler_index < _Scheduler_Count ); return mrsp->ceiling_priorities[ scheduler_index ]; } @@ -149,6 +150,7 @@ static inline void _MRSP_Set_priority( uint32_t scheduler_index; scheduler_index = _Scheduler_Get_index( scheduler ); + _Assert( scheduler_index < _Scheduler_Count ); mrsp->ceiling_priorities[ scheduler_index ] = new_priority; } diff --git a/cpukit/include/rtems/score/processormask.h b/cpukit/include/rtems/score/processormask.h index ce23f6c10d..71ed37cd0e 100644 --- a/cpukit/include/rtems/score/processormask.h +++ b/cpukit/include/rtems/score/processormask.h @@ -39,9 +39,7 @@ #include <rtems/score/cpu.h> -#include <sys/cpuset.h> - -#include <strings.h> +#include <sys/_bitset.h> #ifdef __cplusplus extern "C" { @@ -123,381 +121,6 @@ extern "C" { */ typedef __BITSET_DEFINE( Processor_mask, CPU_MAXIMUM_PROCESSORS ) Processor_mask; -/** - * @brief Sets the bits of the mask to zero, also considers CPU_MAXIMUM_PROCESSORS. - * - * @param[out] mask The mask to set to zero. - */ -static inline void _Processor_mask_Zero( Processor_mask *mask ) -{ - __BIT_ZERO( CPU_MAXIMUM_PROCESSORS, mask ); -} - -/** - * @brief Checks if the mask is zero, also considers CPU_MAXIMUM_PROCESSORS. - * - * @param mask The mask to check whether is is zero - * - * @retval true The mask is zero. - * @retval false The mask is not zero. - */ -static inline bool _Processor_mask_Is_zero( const Processor_mask *mask ) -{ - return __BIT_EMPTY( CPU_MAXIMUM_PROCESSORS, mask ); -} - -/** - * @brief Fills the mask, also considers CPU_MAXIMUM_PROCESSORS. - * - * @param[out] mask The mask to fill - */ -static inline void _Processor_mask_Fill( Processor_mask *mask ) -{ - __BIT_FILL( CPU_MAXIMUM_PROCESSORS, mask ); -} - -/** - * @brief Copies the mask to another mask, also considers CPU_MAXIMUM_PROCESSORS. - * - * @param[out] dst The mask to copy @a src to. - * @param src The mask to copy to @a dst. - */ -static inline void _Processor_mask_Assign( - Processor_mask *dst, const Processor_mask *src -) -{ - __BIT_COPY( CPU_MAXIMUM_PROCESSORS, src, dst ); -} - -/** - * @brief Sets the specified index bit of the mask. - * - * @param[out] mask The mask to set the bit of. - * @param index The index of the bit that shall be set. - */ -static inline void _Processor_mask_Set( - Processor_mask *mask, - uint32_t index -) -{ - __BIT_SET( CPU_MAXIMUM_PROCESSORS, index, mask ); -} - -/** - * @brief Clears the specified index bit of the mask. - * - * @param[out] mask The mask to clear the bit of. - * @param index The index of the bit that shall be cleared. - */ -static inline void _Processor_mask_Clear( - Processor_mask *mask, - uint32_t index -) -{ - __BIT_CLR( CPU_MAXIMUM_PROCESSORS, index, mask ); -} - -/** - * @brief Checks if the specified index bit of the mask is set. - * - * @param mask The mask to check if the specified bit is set. - * @param index The index of the bit that is checked. - * - * @retval true The specified index bit is set. - * @retval false The specified index bit is not set. - */ -static inline bool _Processor_mask_Is_set( - const Processor_mask *mask, - uint32_t index -) -{ - return __BIT_ISSET( CPU_MAXIMUM_PROCESSORS, index, mask ); -} - -/** - * @brief Checks if the processor sets a and b are equal. - * - * @param a The first processor set. - * @param b The seconde processor set. - * - * @retval true The processor sets a and b are equal. - * @retval false The processor sets a and b are not equal. - */ -static inline bool _Processor_mask_Is_equal( - const Processor_mask *a, - const Processor_mask *b -) -{ - return !__BIT_CMP( CPU_MAXIMUM_PROCESSORS, a, b ); -} - -/** - * @brief Checks if the intersection of the processor sets a and b is - * non-empty. - * - * @param a The first processor set. - * @param b The second processor set. - * - * @retval true The intersection of the processor sets a and b is non-empty. - * @retval false The intersection of the processor sets a and b is empty. - */ -static inline bool _Processor_mask_Has_overlap( - const Processor_mask *a, - const Processor_mask *b -) -{ - return __BIT_OVERLAP( CPU_MAXIMUM_PROCESSORS, a, b ); -} - -/** - * @brief Checks if the processor set small is a subset of processor set - * big. - * - * @param big The bigger processor set. - * @param small The smaller processor set. - * - * @retval true @a small is a subset of @a big. - * @retval false @a small is not a subset of @a big. - */ -static inline bool _Processor_mask_Is_subset( - const Processor_mask *big, - const Processor_mask *small -) -{ - return __BIT_SUBSET( CPU_MAXIMUM_PROCESSORS, big, small ); -} - -/** - * @brief Performs a bitwise a = b & c. - * - * @param[out] a The processor mask that is set by this operation. - * @param b The first parameter of the AND-operation. - * @param c The second parameter of the AND-operation. - */ -static inline void _Processor_mask_And( - Processor_mask *a, - const Processor_mask *b, - const Processor_mask *c -) -{ - __BIT_AND2( CPU_MAXIMUM_PROCESSORS, a, b, c ); -} - -/** - * @brief Performs a bitwise a = b | c. - * - * @param[out] a The processor mask that is set by this operation. - * @param b The first parameter of the OR-operation. - * @param c The second parameter of the OR-operation. - */ -static inline void _Processor_mask_Or( - Processor_mask *a, - const Processor_mask *b, - const Processor_mask *c -) -{ - __BIT_OR2( CPU_MAXIMUM_PROCESSORS, a, b, c ); -} - -/** - * @brief Performs a bitwise a = b ^ c. - * - * @param[out] a The processor mask that is set by this operation. - * @param b The first parameter of the XOR-operation. - * @param c The second parameter of the XOR-operation. - */ -static inline void _Processor_mask_Xor( - Processor_mask *a, - const Processor_mask *b, - const Processor_mask *c -) -{ - __BIT_XOR2( CPU_MAXIMUM_PROCESSORS, a, b, c ); -} - -/** - * @brief Gets the number of set bits in the processor mask. - * - * @param a The processor mask of which the set bits are counted. - * - * @return The number of set bits in @a a. - */ -static inline uint32_t _Processor_mask_Count( const Processor_mask *a ) -{ - return (uint32_t) __BIT_COUNT( CPU_MAXIMUM_PROCESSORS, a ); -} - -/** - * @brief Finds the last set of the processor mask. - * - * @param a The processor mask wo find the last set of. - * - * @return The last set of @a a. - */ -static inline uint32_t _Processor_mask_Find_last_set( const Processor_mask *a ) -{ - return (uint32_t) __BIT_FLS( CPU_MAXIMUM_PROCESSORS, a ); -} - -/** - * @brief Returns the subset of 32 processors containing the specified index as - * an unsigned 32-bit integer. - * - * @param mask The processor mask. - * @param index The specified index. - * - * @return The subset containing the specified index as an unsigned 32-bit integer. - */ -static inline uint32_t _Processor_mask_To_uint32_t( - const Processor_mask *mask, - uint32_t index -) -{ - long bits = mask->__bits[ index / _BITSET_BITS ]; - - return (uint32_t) ( bits >> ( 32 * ( ( index % _BITSET_BITS ) / 32 ) ) ); -} - -/** - * @brief Creates a processor set from an unsigned 32-bit integer relative to - * the specified index. - * - * @param[out] mask The mask that is created. - * @param bits The bits for creating the mask. - * @param index The index to which the mask is relative. - */ -static inline void _Processor_mask_From_uint32_t( - Processor_mask *mask, - uint32_t bits, - uint32_t index -) -{ - _Processor_mask_Zero( mask ); - mask->__bits[ __bitset_words( index ) ] = ((long) bits) << (32 * (index % _BITSET_BITS) / 32); -} - -/** - * @brief Creates a processor set from the specified index. - * - * @param[out] The mask that is created. - * @param index The specified index. - */ -static inline void _Processor_mask_From_index( - Processor_mask *mask, - uint32_t index -) -{ - __BIT_SETOF( CPU_MAXIMUM_PROCESSORS, (int) index, mask ); -} - -typedef enum { - PROCESSOR_MASK_COPY_LOSSLESS, - PROCESSOR_MASK_COPY_PARTIAL_LOSS, - PROCESSOR_MASK_COPY_COMPLETE_LOSS, - PROCESSOR_MASK_COPY_INVALID_SIZE -} Processor_mask_Copy_status; - -/** - * @brief Checks if the copy status guarantees at most partial loss. - * - * @param status The copy status to check. - * - * @retval true At most partial loss can be guaranteed. - * @retval false The status indicates more than partial loss. - */ -static inline bool _Processor_mask_Is_at_most_partial_loss( - Processor_mask_Copy_status status -) -{ - return (unsigned int) status <= PROCESSOR_MASK_COPY_PARTIAL_LOSS; -} - -/** - * @brief Copies one mask to another. - * - * @param[out] dst The destination of the copy operation. - * @param dst_size The size of @a dst. - * @param src The source of the copy operation. - * @param src_size The size of @a src. - * - * @retval PROCESSOR_MASK_COPY_LOSSLESS It is guaranteed that the copy - * operation is lossless. - * @retval PROCESSOR_MASK_COPY_PARTIAL_LOSS Partial loss happened due - * to the sizes of @a src and @a dst. - * @retval PROCESSOR_MASK_COPY_COMPLETE_LOSS Complete loss happened due - * to the sizes of @a src and @a dst. - * @retval PROCESSOR_MASK_COPY_INVALID_SIZE One of the arguments sizes - * is invalid (bigger than the size of a long). - */ -Processor_mask_Copy_status _Processor_mask_Copy( - long *dst, - size_t dst_size, - const long *src, - size_t src_size -); - -/** - * @brief Copies one mask to another. - * - * @param src The source for the copy operation. - * @param dst_size The size of @a dst. - * @param[out] dst The destination for the copy operation. - * - * @retval PROCESSOR_MASK_COPY_LOSSLESS It is guaranteed that the copy - * operation is lossless. - * @retval PROCESSOR_MASK_COPY_PARTIAL_LOSS Partial loss happened due - * to the sizes of @a src and @a dst. - * @retval PROCESSOR_MASK_COPY_COMPLETE_LOSS Complete loss happened due - * to the sizes of @a src and @a dst. - * @retval PROCESSOR_MASK_COPY_INVALID_SIZE One of the arguments sizes - * is invalid (bigger than the size of a long). - */ -static inline Processor_mask_Copy_status _Processor_mask_To_cpu_set_t( - const Processor_mask *src, - size_t dst_size, - cpu_set_t *dst -) -{ - return _Processor_mask_Copy( - &dst->__bits[ 0 ], - dst_size, - &src->__bits[ 0 ], - sizeof( *src ) - ); -} - -/** - * @brief Copies one mask to another. - * - * @param src The source for the copy operation. - * @param src_size The size of @a src. - * @param[out] dst The destination for the copy operation. - * - * @retval PROCESSOR_MASK_COPY_LOSSLESS It is guaranteed that the copy - * operation is lossless. - * @retval PROCESSOR_MASK_COPY_PARTIAL_LOSS Partial loss happened due - * to the sizes of @a src and @a dst. - * @retval PROCESSOR_MASK_COPY_COMPLETE_LOSS Complete loss happened due - * to the sizes of @a src and @a dst. - * @retval PROCESSOR_MASK_COPY_INVALID_SIZE One of the arguments sizes - * is invalid (bigger than the size of a long). - */ -static inline Processor_mask_Copy_status _Processor_mask_From_cpu_set_t( - Processor_mask *dst, - size_t src_size, - const cpu_set_t *src -) -{ - return _Processor_mask_Copy( - &dst->__bits[ 0 ], - sizeof( *dst ), - &src->__bits[ 0 ], - src_size - ); -} - -extern const Processor_mask _Processor_mask_The_one_and_only; - /** @} */ #ifdef __cplusplus diff --git a/cpukit/include/rtems/score/processormaskimpl.h b/cpukit/include/rtems/score/processormaskimpl.h new file mode 100644 index 0000000000..bc997edfd4 --- /dev/null +++ b/cpukit/include/rtems/score/processormaskimpl.h @@ -0,0 +1,437 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSScoreProcessorMask + * + * @brief This header file provides the interfaces of the + * @ref RTEMSScoreProcessorMask. + */ + +/* + * Copyright (C) 2016, 2017 embedded brains GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTEMS_SCORE_PROCESSORMASKIMPL_H +#define _RTEMS_SCORE_PROCESSORMASKIMPL_H + +#include <rtems/score/processormask.h> + +#include <sys/cpuset.h> + +#include <strings.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @addtogroup RTEMSScoreProcessorMask + * + * @{ + */ + +/** + * @brief Sets the bits of the mask to zero, also considers CPU_MAXIMUM_PROCESSORS. + * + * @param[out] mask The mask to set to zero. + */ +static inline void _Processor_mask_Zero( Processor_mask *mask ) +{ + __BIT_ZERO( CPU_MAXIMUM_PROCESSORS, mask ); +} + +/** + * @brief Checks if the mask is zero, also considers CPU_MAXIMUM_PROCESSORS. + * + * @param mask The mask to check whether is is zero + * + * @retval true The mask is zero. + * @retval false The mask is not zero. + */ +static inline bool _Processor_mask_Is_zero( const Processor_mask *mask ) +{ + return __BIT_EMPTY( CPU_MAXIMUM_PROCESSORS, mask ); +} + +/** + * @brief Fills the mask, also considers CPU_MAXIMUM_PROCESSORS. + * + * @param[out] mask The mask to fill + */ +static inline void _Processor_mask_Fill( Processor_mask *mask ) +{ + __BIT_FILL( CPU_MAXIMUM_PROCESSORS, mask ); +} + +/** + * @brief Copies the mask to another mask, also considers CPU_MAXIMUM_PROCESSORS. + * + * @param[out] dst The mask to copy @a src to. + * @param src The mask to copy to @a dst. + */ +static inline void _Processor_mask_Assign( + Processor_mask *dst, const Processor_mask *src +) +{ + __BIT_COPY( CPU_MAXIMUM_PROCESSORS, src, dst ); +} + +/** + * @brief Sets the specified index bit of the mask. + * + * @param[out] mask The mask to set the bit of. + * @param index The index of the bit that shall be set. + */ +static inline void _Processor_mask_Set( + Processor_mask *mask, + uint32_t index +) +{ + __BIT_SET( CPU_MAXIMUM_PROCESSORS, index, mask ); +} + +/** + * @brief Clears the specified index bit of the mask. + * + * @param[out] mask The mask to clear the bit of. + * @param index The index of the bit that shall be cleared. + */ +static inline void _Processor_mask_Clear( + Processor_mask *mask, + uint32_t index +) +{ + __BIT_CLR( CPU_MAXIMUM_PROCESSORS, index, mask ); +} + +/** + * @brief Checks if the specified index bit of the mask is set. + * + * @param mask The mask to check if the specified bit is set. + * @param index The index of the bit that is checked. + * + * @retval true The specified index bit is set. + * @retval false The specified index bit is not set. + */ +static inline bool _Processor_mask_Is_set( + const Processor_mask *mask, + uint32_t index +) +{ + return __BIT_ISSET( CPU_MAXIMUM_PROCESSORS, index, mask ); +} + +/** + * @brief Checks if the processor sets a and b are equal. + * + * @param a The first processor set. + * @param b The seconde processor set. + * + * @retval true The processor sets a and b are equal. + * @retval false The processor sets a and b are not equal. + */ +static inline bool _Processor_mask_Is_equal( + const Processor_mask *a, + const Processor_mask *b +) +{ + return !__BIT_CMP( CPU_MAXIMUM_PROCESSORS, a, b ); +} + +/** + * @brief Checks if the intersection of the processor sets a and b is + * non-empty. + * + * @param a The first processor set. + * @param b The second processor set. + * + * @retval true The intersection of the processor sets a and b is non-empty. + * @retval false The intersection of the processor sets a and b is empty. + */ +static inline bool _Processor_mask_Has_overlap( + const Processor_mask *a, + const Processor_mask *b +) +{ + return __BIT_OVERLAP( CPU_MAXIMUM_PROCESSORS, a, b ); +} + +/** + * @brief Checks if the processor set small is a subset of processor set + * big. + * + * @param big The bigger processor set. + * @param small The smaller processor set. + * + * @retval true @a small is a subset of @a big. + * @retval false @a small is not a subset of @a big. + */ +static inline bool _Processor_mask_Is_subset( + const Processor_mask *big, + const Processor_mask *small +) +{ + return __BIT_SUBSET( CPU_MAXIMUM_PROCESSORS, big, small ); +} + +/** + * @brief Performs a bitwise a = b & c. + * + * @param[out] a The processor mask that is set by this operation. + * @param b The first parameter of the AND-operation. + * @param c The second parameter of the AND-operation. + */ +static inline void _Processor_mask_And( + Processor_mask *a, + const Processor_mask *b, + const Processor_mask *c +) +{ + __BIT_AND2( CPU_MAXIMUM_PROCESSORS, a, b, c ); +} + +/** + * @brief Performs a bitwise a = b | c. + * + * @param[out] a The processor mask that is set by this operation. + * @param b The first parameter of the OR-operation. + * @param c The second parameter of the OR-operation. + */ +static inline void _Processor_mask_Or( + Processor_mask *a, + const Processor_mask *b, + const Processor_mask *c +) +{ + __BIT_OR2( CPU_MAXIMUM_PROCESSORS, a, b, c ); +} + +/** + * @brief Performs a bitwise a = b ^ c. + * + * @param[out] a The processor mask that is set by this operation. + * @param b The first parameter of the XOR-operation. + * @param c The second parameter of the XOR-operation. + */ +static inline void _Processor_mask_Xor( + Processor_mask *a, + const Processor_mask *b, + const Processor_mask *c +) +{ + __BIT_XOR2( CPU_MAXIMUM_PROCESSORS, a, b, c ); +} + +/** + * @brief Gets the number of set bits in the processor mask. + * + * @param a The processor mask of which the set bits are counted. + * + * @return The number of set bits in @a a. + */ +static inline uint32_t _Processor_mask_Count( const Processor_mask *a ) +{ + return (uint32_t) __BIT_COUNT( CPU_MAXIMUM_PROCESSORS, a ); +} + +/** + * @brief Finds the last set of the processor mask. + * + * @param a The processor mask wo find the last set of. + * + * @return The last set of @a a. + */ +static inline uint32_t _Processor_mask_Find_last_set( const Processor_mask *a ) +{ + return (uint32_t) __BIT_FLS( CPU_MAXIMUM_PROCESSORS, a ); +} + +/** + * @brief Returns the subset of 32 processors containing the specified index as + * an unsigned 32-bit integer. + * + * @param mask The processor mask. + * @param index The specified index. + * + * @return The subset containing the specified index as an unsigned 32-bit integer. + */ +static inline uint32_t _Processor_mask_To_uint32_t( + const Processor_mask *mask, + uint32_t index +) +{ + long bits = mask->__bits[ index / _BITSET_BITS ]; + + return (uint32_t) ( bits >> ( 32 * ( ( index % _BITSET_BITS ) / 32 ) ) ); +} + +/** + * @brief Creates a processor set from an unsigned 32-bit integer relative to + * the specified index. + * + * @param[out] mask The mask that is created. + * @param bits The bits for creating the mask. + * @param index The index to which the mask is relative. + */ +static inline void _Processor_mask_From_uint32_t( + Processor_mask *mask, + uint32_t bits, + uint32_t index +) +{ + _Processor_mask_Zero( mask ); + mask->__bits[ __bitset_words( index ) ] = ((long) bits) << (32 * (index % _BITSET_BITS) / 32); +} + +/** + * @brief Creates a processor set from the specified index. + * + * @param[out] The mask that is created. + * @param index The specified index. + */ +static inline void _Processor_mask_From_index( + Processor_mask *mask, + uint32_t index +) +{ + __BIT_SETOF( CPU_MAXIMUM_PROCESSORS, (int) index, mask ); +} + +typedef enum { + PROCESSOR_MASK_COPY_LOSSLESS, + PROCESSOR_MASK_COPY_PARTIAL_LOSS, + PROCESSOR_MASK_COPY_COMPLETE_LOSS, + PROCESSOR_MASK_COPY_INVALID_SIZE +} Processor_mask_Copy_status; + +/** + * @brief Checks if the copy status guarantees at most partial loss. + * + * @param status The copy status to check. + * + * @retval true At most partial loss can be guaranteed. + * @retval false The status indicates more than partial loss. + */ +static inline bool _Processor_mask_Is_at_most_partial_loss( + Processor_mask_Copy_status status +) +{ + return (unsigned int) status <= PROCESSOR_MASK_COPY_PARTIAL_LOSS; +} + +/** + * @brief Copies one mask to another. + * + * @param[out] dst The destination of the copy operation. + * @param dst_size The size of @a dst. + * @param src The source of the copy operation. + * @param src_size The size of @a src. + * + * @retval PROCESSOR_MASK_COPY_LOSSLESS It is guaranteed that the copy + * operation is lossless. + * @retval PROCESSOR_MASK_COPY_PARTIAL_LOSS Partial loss happened due + * to the sizes of @a src and @a dst. + * @retval PROCESSOR_MASK_COPY_COMPLETE_LOSS Complete loss happened due + * to the sizes of @a src and @a dst. + * @retval PROCESSOR_MASK_COPY_INVALID_SIZE One of the arguments sizes + * is invalid (bigger than the size of a long). + */ +Processor_mask_Copy_status _Processor_mask_Copy( + long *dst, + size_t dst_size, + const long *src, + size_t src_size +); + +/** + * @brief Copies one mask to another. + * + * @param src The source for the copy operation. + * @param dst_size The size of @a dst. + * @param[out] dst The destination for the copy operation. + * + * @retval PROCESSOR_MASK_COPY_LOSSLESS It is guaranteed that the copy + * operation is lossless. + * @retval PROCESSOR_MASK_COPY_PARTIAL_LOSS Partial loss happened due + * to the sizes of @a src and @a dst. + * @retval PROCESSOR_MASK_COPY_COMPLETE_LOSS Complete loss happened due + * to the sizes of @a src and @a dst. + * @retval PROCESSOR_MASK_COPY_INVALID_SIZE One of the arguments sizes + * is invalid (bigger than the size of a long). + */ +static inline Processor_mask_Copy_status _Processor_mask_To_cpu_set_t( + const Processor_mask *src, + size_t dst_size, + cpu_set_t *dst +) +{ + return _Processor_mask_Copy( + &dst->__bits[ 0 ], + dst_size, + &src->__bits[ 0 ], + sizeof( *src ) + ); +} + +/** + * @brief Copies one mask to another. + * + * @param src The source for the copy operation. + * @param src_size The size of @a src. + * @param[out] dst The destination for the copy operation. + * + * @retval PROCESSOR_MASK_COPY_LOSSLESS It is guaranteed that the copy + * operation is lossless. + * @retval PROCESSOR_MASK_COPY_PARTIAL_LOSS Partial loss happened due + * to the sizes of @a src and @a dst. + * @retval PROCESSOR_MASK_COPY_COMPLETE_LOSS Complete loss happened due + * to the sizes of @a src and @a dst. + * @retval PROCESSOR_MASK_COPY_INVALID_SIZE One of the arguments sizes + * is invalid (bigger than the size of a long). + */ +static inline Processor_mask_Copy_status _Processor_mask_From_cpu_set_t( + Processor_mask *dst, + size_t src_size, + const cpu_set_t *src +) +{ + return _Processor_mask_Copy( + &dst->__bits[ 0 ], + sizeof( *dst ), + &src->__bits[ 0 ], + src_size + ); +} + +extern const Processor_mask _Processor_mask_The_one_and_only; + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_SCORE_PROCESSORMASKIMPL_H */ diff --git a/cpukit/include/rtems/score/protectedheap.h b/cpukit/include/rtems/score/protectedheap.h index 884d7e1c47..287108568a 100644 --- a/cpukit/include/rtems/score/protectedheap.h +++ b/cpukit/include/rtems/score/protectedheap.h @@ -163,59 +163,6 @@ static inline void *_Protected_heap_Allocate( } /** - * @brief Returns the size of the allocatable memory area. - * - * The size value may be greater than the initially requested size in - * _Heap_Allocate_aligned_with_boundary(). - * - * Inappropriate values for @a addr will not corrupt the heap, but may yield - * invalid size values. - * - * This method first locks the allocator and after the operation, unlocks it again. - * - * @param heap The heap to operate upon. - * @param addr The starting address of the allocatable memory area. - * @param[out] size Stores the size of the allocatable memory area after the method call. - * - * @retval true The operation was successful. - * @retval false The operation was not successful. - */ -bool _Protected_heap_Get_block_size( - Heap_Control *heap, - void *addr, - uintptr_t *size -); - -/** - * @brief Resizes the block of the allocated memory area. - * - * Inappropriate values for @a addr may corrupt the heap. - * - * This method first locks the allocator and after the resize, unlocks it again. - * - * @param[in, out] heap The heap to operate upon. - * @param addr The starting address of the allocated memory area to be resized. - * @param size The least possible size for the new memory area. Resize may be - * impossible and depends on the current heap usage. - * @param[out] old_size Stores the size available for allocation in the current - * block before the resize after the method call. - * @param[out] new_size Stores the size available for allocation in the resized - * block after the method call. In the case of an unsuccessful resize, - * zero is returned in this parameter - * - * @retval HEAP_RESIZE_SUCCESSFUL The resize was successful. - * @retval HEAP_RESIZE_UNSATISFIED The least possible size @a size was too big. - * Resize not possible. - * @retval HEAP_RESIZE_FATAL_ERROR The block starting at @a addr is not part of - * the heap. - */ -bool _Protected_heap_Resize_block( - Heap_Control *heap, - void *addr, - uintptr_t size -); - -/** * @brief Frees the allocated memory area. * * Inappropriate values for @a addr may corrupt the heap. This method first locks @@ -245,22 +192,6 @@ bool _Protected_heap_Free( Heap_Control *heap, void *addr ); bool _Protected_heap_Walk( Heap_Control *heap, int source, bool dump ); /** - * @brief Iterates over all blocks of the heap. - * - * This method first locks the allocator and after the operation, unlocks it again. - * - * @param[in, out] heap The heap to iterate over. - * @param visitor This will be called for each heap block with - * the argument @a visitor_arg. - * @param[in, out] visitor_arg The argument for all calls of @a visitor. - */ -void _Protected_heap_Iterate( - Heap_Control *heap, - Heap_Block_visitor visitor, - void *visitor_arg -); - -/** * @brief Returns information about used and free blocks for the heap. * * This method first locks the allocator and after the operation, unlocks it again. diff --git a/cpukit/include/rtems/score/smpimpl.h b/cpukit/include/rtems/score/smpimpl.h index 2ffc047070..a8e3a3be15 100644 --- a/cpukit/include/rtems/score/smpimpl.h +++ b/cpukit/include/rtems/score/smpimpl.h @@ -40,7 +40,7 @@ #include <rtems/score/smp.h> #include <rtems/score/percpu.h> -#include <rtems/score/processormask.h> +#include <rtems/score/processormaskimpl.h> #include <rtems/fatal.h> #ifdef __cplusplus diff --git a/cpukit/include/rtems/score/thread.h b/cpukit/include/rtems/score/thread.h index 9a9d2e038f..8ca7d85205 100644 --- a/cpukit/include/rtems/score/thread.h +++ b/cpukit/include/rtems/score/thread.h @@ -719,50 +719,50 @@ typedef struct { * The individual state flags must be a power of two to allow use of bit * operations to manipulate and evaluate the thread life state. */ -typedef enum { - /** - * @brief Indicates that the thread life is protected. - * - * If this flag is set, then the thread restart or delete requests are deferred - * until the protection and deferred change flags are cleared. It is used by - * _Thread_Set_life_protection(). - */ - THREAD_LIFE_PROTECTED = 0x1, +typedef unsigned int Thread_Life_state; - /** - * @brief Indicates that thread is restarting. - * - * If this flag is set, then a thread restart request is in pending. See - * _Thread_Restart_self() and _Thread_Restart_other(). - */ - THREAD_LIFE_RESTARTING = 0x2, +/** + * @brief Indicates that the thread life is protected. + * + * If this flag is set, then the thread restart or delete requests are deferred + * until the protection and deferred change flags are cleared. It is used by + * _Thread_Set_life_protection(). + */ +#define THREAD_LIFE_PROTECTED 0x1U - /** - * @brief Indicates that thread is terminating. - * - * If this flag is set, then a thread termination request is in pending. See - * _Thread_Exit() and _Thread_Cancel(). - */ - THREAD_LIFE_TERMINATING = 0x4, +/** + * @brief Indicates that thread is restarting. + * + * If this flag is set, then a thread restart request is in pending. See + * _Thread_Restart_self() and _Thread_Restart_other(). + */ +#define THREAD_LIFE_RESTARTING 0x2U - /** - * @brief Indicates that thread life changes are deferred. - * - * If this flag is set, then the thread restart or delete requests are deferred - * until the protection and deferred change flags are cleared. It is used by - * pthread_setcanceltype(). - */ - THREAD_LIFE_CHANGE_DEFERRED = 0x8, +/** + * @brief Indicates that thread is terminating. + * + * If this flag is set, then a thread termination request is in pending. See + * _Thread_Exit() and _Thread_Cancel(). + */ +#define THREAD_LIFE_TERMINATING 0x4U - /** - * @brief Indicates that thread is detached. - * - * If this flag is set, then the thread is detached. Detached threads do not - * wait during termination for other threads to join. See rtems_task_delete(), - * rtems_task_exit(), and pthread_detach(). - */ - THREAD_LIFE_DETACHED = 0x10 -} Thread_Life_state; +/** + * @brief Indicates that thread life changes are deferred. + * + * If this flag is set, then the thread restart or delete requests are deferred + * until the protection and deferred change flags are cleared. It is used by + * pthread_setcanceltype(). + */ +#define THREAD_LIFE_CHANGE_DEFERRED 0x8U + +/** + * @brief Indicates that thread is detached. + * + * If this flag is set, then the thread is detached. Detached threads do not + * wait during termination for other threads to join. See rtems_task_delete(), + * rtems_task_exit(), and pthread_detach(). + */ +#define THREAD_LIFE_DETACHED 0x10U /** * @brief Thread life control. diff --git a/cpukit/include/rtems/score/threadimpl.h b/cpukit/include/rtems/score/threadimpl.h index a82f412887..36ddb785e9 100644 --- a/cpukit/include/rtems/score/threadimpl.h +++ b/cpukit/include/rtems/score/threadimpl.h @@ -1598,12 +1598,12 @@ static inline Scheduler_Node *_Thread_Scheduler_get_node_by_index( size_t scheduler_index ) { + _Assert( scheduler_index < _Scheduler_Count ); #if defined(RTEMS_SMP) return (Scheduler_Node *) ( (uintptr_t) the_thread->Scheduler.nodes + scheduler_index * _Scheduler_Node_size ); #else - _Assert( scheduler_index == 0 ); (void) scheduler_index; return the_thread->Scheduler.nodes; #endif diff --git a/cpukit/include/rtems/score/tls.h b/cpukit/include/rtems/score/tls.h index fa3ee0afa2..8716c5230c 100644 --- a/cpukit/include/rtems/score/tls.h +++ b/cpukit/include/rtems/score/tls.h @@ -10,7 +10,7 @@ */ /* - * Copyright (C) 2014, 2022 embedded brains GmbH & Co. KG + * Copyright (C) 2014, 2023 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -59,31 +59,51 @@ extern "C" { * @{ */ -extern char _TLS_Data_begin[]; - -extern char _TLS_Data_end[]; +/** + * @brief Represents the TLS configuration. + */ +typedef struct { + /** + * @brief This member is initialized to _TLS_Data_begin. + */ + const char *data_begin; -extern char _TLS_Data_size[]; + /** + * @brief This member is initialized to _TLS_Data_size. + */ + const char *data_size; -extern char _TLS_BSS_begin[]; + /** + * @brief This member is initialized to _TLS_BSS_begin. + */ + const char *bss_begin; -extern char _TLS_BSS_end[]; + /** + * @brief This member is initialized to _TLS_BSS_size. + */ + const char *bss_size; -extern char _TLS_BSS_size[]; + /** + * @brief This member is initialized to _TLS_Size. + */ + const char *size; -extern char _TLS_Size[]; + /** + * @brief This member is initialized to _TLS_Alignment. + */ + const char *alignment; +} TLS_Configuration; /** - * @brief The TLS section alignment. + * @brief Provides the TLS configuration. * - * This symbol is provided by the linker command file as the maximum alignment - * of the .tdata and .tbss sections. The linker ensures that the first TLS - * output section is aligned to the maximum alignment of all TLS output - * sections, see function _bfd_elf_tls_setup() in bfd/elflink.c of the GNU - * Binutils sources. The linker command file must take into account the case - * that the .tdata section is empty and the .tbss section is non-empty. + * Directly using symbols with an arbitrary absolute address such as + * _TLS_Alignment may not work with all code models (for example the AArch64 + * tiny and small code models). Store the addresses in a read-only object. + * Using the volatile qualifier ensures that the compiler actually loads the + * address from the object. */ -extern char _TLS_Alignment[]; +extern const volatile TLS_Configuration _TLS_Configuration; typedef struct { /* @@ -116,38 +136,24 @@ typedef struct { } TLS_Index; /** - * @brief Gets the size of the thread-local storage data in bytes. - * - * @return Returns the size of the thread-local storage data in bytes. - */ -static inline uintptr_t _TLS_Get_size( void ) -{ - uintptr_t size; - - /* - * We must be careful with using _TLS_Size here since this could lead GCC to - * assume that this symbol is not 0 and the tests for 0 will be optimized - * away. - */ - size = (uintptr_t) _TLS_Size; - RTEMS_OBFUSCATE_VARIABLE( size ); - return size; -} - -/** * @brief Gets the size of the thread control block area in bytes. * + * @param config is the TLS configuration. + * * @return Returns the size of the thread control block area in bytes. */ -static inline uintptr_t _TLS_Get_thread_control_block_area_size( void ) +static inline uintptr_t _TLS_Get_thread_control_block_area_size( + const volatile TLS_Configuration *config +) { #if CPU_THREAD_LOCAL_STORAGE_VARIANT == 11 uintptr_t alignment; - alignment = (uintptr_t) _TLS_Alignment; + alignment = (uintptr_t) config->alignment; return RTEMS_ALIGN_UP( sizeof( TLS_Thread_control_block ), alignment ); #else + (void) config; return sizeof( TLS_Thread_control_block ); #endif } @@ -163,17 +169,23 @@ uintptr_t _TLS_Get_allocation_size( void ); /** * @brief Initializes the thread-local storage data. * + * @param config is the TLS configuration. + * * @param[out] tls_data is the thread-local storage data to initialize. */ -static inline void _TLS_Copy_and_clear( void *tls_data ) +static inline void _TLS_Copy_and_clear( + const volatile TLS_Configuration *config, + void *tls_data +) { - tls_data = memcpy( tls_data, _TLS_Data_begin, (uintptr_t) _TLS_Data_size ); + tls_data = + memcpy( tls_data, config->data_begin, (uintptr_t) config->data_size ); memset( (char *) tls_data + - (uintptr_t) _TLS_BSS_begin - (uintptr_t) _TLS_Data_begin, + (uintptr_t) config->bss_begin - (uintptr_t) config->data_begin, 0, - (uintptr_t) _TLS_BSS_size + (uintptr_t) config->bss_size ); } @@ -213,20 +225,22 @@ static inline void _TLS_Initialize_TCB_and_DTV( */ static inline void *_TLS_Initialize_area( void *tls_area ) { - uintptr_t alignment; - void *tls_data; - TLS_Thread_control_block *tcb; - TLS_Dynamic_thread_vector *dtv; - void *return_value; + const volatile TLS_Configuration *config; + uintptr_t alignment; + void *tls_data; + TLS_Thread_control_block *tcb; + TLS_Dynamic_thread_vector *dtv; + void *return_value; #if CPU_THREAD_LOCAL_STORAGE_VARIANT == 11 - uintptr_t tcb_size; + uintptr_t tcb_size; #endif #if CPU_THREAD_LOCAL_STORAGE_VARIANT == 20 - uintptr_t size; - uintptr_t alignment_2; + uintptr_t size; + uintptr_t alignment_2; #endif - alignment = (uintptr_t) _TLS_Alignment; + config = &_TLS_Configuration; + alignment = (uintptr_t) config->alignment; #ifdef __i386__ dtv = NULL; @@ -249,7 +263,7 @@ static inline void *_TLS_Initialize_area( void *tls_area ) #elif CPU_THREAD_LOCAL_STORAGE_VARIANT == 20 alignment_2 = RTEMS_ALIGN_UP( alignment, CPU_SIZEOF_POINTER ); tls_area = (void *) RTEMS_ALIGN_UP( (uintptr_t) tls_area, alignment_2 ); - size = _TLS_Get_size(); + size = (uintptr_t) config->size; tcb = (TLS_Thread_control_block *) ((char *) tls_area + RTEMS_ALIGN_UP( size, alignment_2 )); tls_data = (char *) tcb - RTEMS_ALIGN_UP( size, alignment ); @@ -259,7 +273,7 @@ static inline void *_TLS_Initialize_area( void *tls_area ) #endif _TLS_Initialize_TCB_and_DTV( tls_data, tcb, dtv ); - _TLS_Copy_and_clear( tls_data ); + _TLS_Copy_and_clear( config, tls_data ); return return_value; } diff --git a/cpukit/include/rtems/sysinit.h b/cpukit/include/rtems/sysinit.h index b973ecfc91..3e6f4d9933 100644 --- a/cpukit/include/rtems/sysinit.h +++ b/cpukit/include/rtems/sysinit.h @@ -1,7 +1,15 @@ /* SPDX-License-Identifier: BSD-2-Clause */ +/** + * @file + * + * @ingroup RTEMSAPISystemInit + * + * @brief This header file provides the API of the @ref RTEMSAPISystemInit. + */ + /* - * Copyright (C) 2015, 2020 embedded brains GmbH & Co. KG + * Copyright (C) 2015, 2023 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,6 +42,54 @@ extern "C" { #endif /* __cplusplus */ +/** + * @ingroup RTEMSImpl + * + * @brief Enables a verbose system initialization. + */ +void _Sysinit_Verbose( void ); + +/** + * @ingroup RTEMSImpl + * + * @brief Creates the system initialization item associated with the handler + * and index. + * + * The enum helps to detect typos in the module and order parameters of + * RTEMS_SYSINIT_ITEM(). + */ +#define _RTEMS_SYSINIT_INDEX_ITEM( handler, index ) \ + enum { _Sysinit_##handler = index }; \ + RTEMS_LINKER_ROSET_ITEM_ORDERED( \ + _Sysinit, \ + rtems_sysinit_item, \ + handler, \ + index \ + ) = { handler } + +/** + * @ingroup RTEMSImpl + * + * @brief Creates the system initialization item associated with the handler, + * module, and order. + * + * This helper macro is used to perform parameter expansion in + * RTEMS_SYSINIT_ITEM(). + */ +#define _RTEMS_SYSINIT_ITEM( handler, module, order ) \ + _RTEMS_SYSINIT_INDEX_ITEM( handler, 0x##module##order ) + +/** + * @defgroup RTEMSAPISystemInit System Initialization Support + * + * @ingroup RTEMSAPI + * + * @brief The system initialization support provides an ordered invocation of + * system initialization handlers registered in a linker set. + * + * @{ + */ + /* * The value of each module define must consist of exactly six hexadecimal * digits without a 0x-prefix. A 0x-prefix is concatenated with the module and @@ -133,29 +189,22 @@ typedef struct { rtems_sysinit_handler handler; } rtems_sysinit_item; -/* The enum helps to detect typos in the module and order parameters */ -#define _RTEMS_SYSINIT_INDEX_ITEM( handler, index ) \ - enum { _Sysinit_##handler = index }; \ - RTEMS_LINKER_ROSET_ITEM_ORDERED( \ - _Sysinit, \ - rtems_sysinit_item, \ - handler, \ - index \ - ) = { handler } - -/* Create index from module and order */ -#define _RTEMS_SYSINIT_ITEM( handler, module, order ) \ - _RTEMS_SYSINIT_INDEX_ITEM( handler, 0x##module##order ) - -/* Perform parameter expansion */ +/** + * @brief Creates the system initialization item associated with the handler, + * module, and order. + * + * @param handler is the system initialization handler. + * + * @param module is the system initialization module. It shall be a 6-digit + * hex number without a 0x-prefix. + * + * @param order is the system initialization order with respect to the module. + * It shall be a 2-digit hex number without a 0x-prefix. + */ #define RTEMS_SYSINIT_ITEM( handler, module, order ) \ _RTEMS_SYSINIT_ITEM( handler, module, order ) -/** - * @brief System initialization handler to enable a verbose system - * initialization. - */ -void _Sysinit_Verbose( void ); +/** @} */ #ifdef __cplusplus } diff --git a/cpukit/include/rtems/termiosdevice.h b/cpukit/include/rtems/termiosdevice.h new file mode 100644 index 0000000000..17d05e61f6 --- /dev/null +++ b/cpukit/include/rtems/termiosdevice.h @@ -0,0 +1,300 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup TermiostypesSupport + * + * @brief This header file provides the interfaces of the + * @ref TermiostypesSupport. + */ + +/* + * Copyright (C) 2014, 2017 embedded brains GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTEMS_TERMIOSDEVICE_H +#define _RTEMS_TERMIOSDEVICE_H + +#include <rtems/thread.h> +#include <rtems/rtems/intr.h> + +#include <sys/ioccom.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct rtems_libio_open_close_args; +struct rtems_termios_tty; +struct termios; + +/** + * @defgroup TermiostypesSupport RTEMS Termios Device Support + * + * @ingroup libcsupport + * + * @brief This group contains the Termios Device Support provided by RTEMS. + */ + +/** + * @brief Termios device context. + * + * @see RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER(), + * rtems_termios_device_context_initialize() and + * rtems_termios_device_install(). + */ +typedef struct rtems_termios_device_context { + union { + /* Used for TERMIOS_POLLED and TERMIOS_IRQ_DRIVEN */ + rtems_interrupt_lock interrupt; + + /* Used for TERMIOS_IRQ_SERVER_DRIVEN and TERMIOS_TASK_DRIVEN */ + rtems_mutex mutex; + } lock; + + void ( *lock_acquire )( + struct rtems_termios_device_context *, + rtems_interrupt_lock_context * + ); + + void ( *lock_release )( + struct rtems_termios_device_context *, + rtems_interrupt_lock_context * + ); +} rtems_termios_device_context; + +typedef enum { + TERMIOS_POLLED, + TERMIOS_IRQ_DRIVEN, + TERMIOS_TASK_DRIVEN, + TERMIOS_IRQ_SERVER_DRIVEN +} rtems_termios_device_mode; + +/** + * @brief Termios device handler. + * + * @see rtems_termios_device_install(). + */ +typedef struct { + /** + * @brief First open of this device. + * + * @param[in] tty The Termios control. This parameter may be passed to + * interrupt service routines since it must be provided for the + * rtems_termios_enqueue_raw_characters() and + * rtems_termios_dequeue_characters() functions. + * @param[in] context The Termios device context. + * @param[in] term The current Termios attributes. + * @param[in] args The open/close arguments. This is parameter provided to + * support legacy drivers. It must not be used by new drivers. + * + * @retval true Successful operation. + * @retval false Cannot open device. + * + * @see rtems_termios_get_device_context() and rtems_termios_set_best_baud(). + */ + bool (*first_open)( + struct rtems_termios_tty *tty, + rtems_termios_device_context *context, + struct termios *term, + struct rtems_libio_open_close_args *args + ); + + /** + * @brief Last close of this device. + * + * @param[in] tty The Termios control. + * @param[in] context The Termios device context. + * @param[in] args The open/close arguments. This is parameter provided to + * support legacy drivers. It must not be used by new drivers. + */ + void (*last_close)( + struct rtems_termios_tty *tty, + rtems_termios_device_context *context, + struct rtems_libio_open_close_args *args + ); + + /** + * @brief Polled read. + * + * In case mode is TERMIOS_IRQ_DRIVEN, TERMIOS_IRQ_SERVER_DRIVEN or + * TERMIOS_TASK_DRIVEN, then data is received via + * rtems_termios_enqueue_raw_characters(). + * + * @param[in] context The Termios device context. + * + * @retval char The received data encoded as unsigned char. + * @retval -1 No data currently available. + */ + int (*poll_read)(rtems_termios_device_context *context); + + /** + * @brief Polled write in case mode is TERMIOS_POLLED or write support + * otherwise. + * + * @param[in] context The Termios device context. + * @param[in] buf The output buffer. + * @param[in] len The output buffer length in characters. + */ + void (*write)( + rtems_termios_device_context *context, + const char *buf, + size_t len + ); + + /** + * @brief Set attributes after a Termios settings change. + * + * @param[in] context The Termios device context. + * @param[in] term The new Termios attributes. + * + * @retval true Successful operation. + * @retval false Invalid attributes. + */ + bool (*set_attributes)( + rtems_termios_device_context *context, + const struct termios *term + ); + + /** + * @brief IO control handler. + * + * Invoked in case the Termios layer cannot deal with the IO request. + * + * @param[in] context The Termios device context. + * @param[in] request The IO control request. + * @param[in] buffer The IO control buffer. + */ + int (*ioctl)( + rtems_termios_device_context *context, + ioctl_command_t request, + void *buffer + ); + + /** + * @brief Termios device mode. + */ + rtems_termios_device_mode mode; +} rtems_termios_device_handler; + +/** + * @brief Termios device flow control handler. + * + * @see rtems_termios_device_install(). + */ +typedef struct { + /** + * @brief Indicate to stop remote transmitter. + * + * @param[in] context The Termios device context. + */ + void (*stop_remote_tx)(rtems_termios_device_context *context); + + /** + * @brief Indicate to start remote transmitter. + * + * @param[in] context The Termios device context. + */ + void (*start_remote_tx)(rtems_termios_device_context *context); +} rtems_termios_device_flow; + +void rtems_termios_device_lock_acquire_default( + rtems_termios_device_context *ctx, + rtems_interrupt_lock_context *lock_context +); + +void rtems_termios_device_lock_release_default( + rtems_termios_device_context *ctx, + rtems_interrupt_lock_context *lock_context +); + +/** + * @brief Initializes a device context. + * + * @param[in] context The Termios device context. + * @param[in] name The name for the interrupt lock. This name must be a + * string persistent throughout the life time of this lock. The name is only + * used if profiling is enabled. + */ +static inline void rtems_termios_device_context_initialize( + rtems_termios_device_context *context, + const char *name +) +{ + rtems_interrupt_lock_initialize( &context->lock.interrupt, name ); + context->lock_acquire = rtems_termios_device_lock_acquire_default; + context->lock_release = rtems_termios_device_lock_release_default; +} + +/** + * @brief Initializer for static initialization of Termios device contexts. + * + * @param name The name for the interrupt lock. It must be a string. The name + * is only used if profiling is enabled. + */ +#define RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( name ) \ + { \ + { RTEMS_INTERRUPT_LOCK_INITIALIZER( name ) }, \ + rtems_termios_device_lock_acquire_default, \ + rtems_termios_device_lock_release_default \ + } + +/** + * @brief Acquires the device lock. + * + * @param[in] context The device context. + * @param[in] lock_context The local interrupt lock context for an acquire and + * release pair. + */ +static inline void rtems_termios_device_lock_acquire( + rtems_termios_device_context *context, + rtems_interrupt_lock_context *lock_context +) +{ + ( *context->lock_acquire )( context, lock_context ); +} + +/** + * @brief Releases the device lock. + * + * @param[in] context The device context. + * @param[in] lock_context The local interrupt lock context for an acquire and + * release pair. + */ +static inline void rtems_termios_device_lock_release( + rtems_termios_device_context *context, + rtems_interrupt_lock_context *lock_context +) +{ + ( *context->lock_release )( context, lock_context ); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_TERMIOSDEVICE_H */ diff --git a/cpukit/include/rtems/termiostypes.h b/cpukit/include/rtems/termiostypes.h index 67f3461b1f..5cf418a5eb 100644 --- a/cpukit/include/rtems/termiostypes.h +++ b/cpukit/include/rtems/termiostypes.h @@ -39,8 +39,7 @@ #include <rtems/libio.h> #include <rtems/assoc.h> #include <rtems/chain.h> -#include <rtems/thread.h> -#include <sys/ioccom.h> +#include <rtems/termiosdevice.h> #include <stdint.h> #include <termios.h> @@ -49,11 +48,9 @@ extern "C" { #endif /** - * @defgroup TermiostypesSupport RTEMS Termios Device Support + * @addtogroup TermiostypesSupport * - * @ingroup libcsupport - * - * @brief RTEMS Termios Device Support Internal Data Structures + * @{ */ /* @@ -75,211 +72,6 @@ struct rtems_termios_rawbuf { rtems_binary_semaphore Semaphore; }; -typedef enum { - TERMIOS_POLLED, - TERMIOS_IRQ_DRIVEN, - TERMIOS_TASK_DRIVEN, - TERMIOS_IRQ_SERVER_DRIVEN -} rtems_termios_device_mode; - -struct rtems_termios_tty; - -/** - * @brief Termios device context. - * - * @see RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER(), - * rtems_termios_device_context_initialize() and - * rtems_termios_device_install(). - */ -typedef struct rtems_termios_device_context { - union { - /* Used for TERMIOS_POLLED and TERMIOS_IRQ_DRIVEN */ - rtems_interrupt_lock interrupt; - - /* Used for TERMIOS_IRQ_SERVER_DRIVEN or TERMIOS_TASK_DRIVEN */ - rtems_mutex mutex; - } lock; - - void ( *lock_acquire )( - struct rtems_termios_device_context *, - rtems_interrupt_lock_context * - ); - - void ( *lock_release )( - struct rtems_termios_device_context *, - rtems_interrupt_lock_context * - ); -} rtems_termios_device_context; - -void rtems_termios_device_lock_acquire_default( - rtems_termios_device_context *ctx, - rtems_interrupt_lock_context *lock_context -); - -void rtems_termios_device_lock_release_default( - rtems_termios_device_context *ctx, - rtems_interrupt_lock_context *lock_context -); - -/** - * @brief Initializes a device context. - * - * @param[in] context The Termios device context. - * @param[in] name The name for the interrupt lock. This name must be a - * string persistent throughout the life time of this lock. The name is only - * used if profiling is enabled. - */ -static inline void rtems_termios_device_context_initialize( - rtems_termios_device_context *context, - const char *name -) -{ - rtems_interrupt_lock_initialize( &context->lock.interrupt, name ); - context->lock_acquire = rtems_termios_device_lock_acquire_default; - context->lock_release = rtems_termios_device_lock_release_default; -} - -/** - * @brief Initializer for static initialization of Termios device contexts. - * - * @param name The name for the interrupt lock. It must be a string. The name - * is only used if profiling is enabled. - */ -#define RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( name ) \ - { \ - { RTEMS_INTERRUPT_LOCK_INITIALIZER( name ) }, \ - rtems_termios_device_lock_acquire_default, \ - rtems_termios_device_lock_release_default \ - } - -/** - * @brief Termios device handler. - * - * @see rtems_termios_device_install(). - */ -typedef struct { - /** - * @brief First open of this device. - * - * @param[in] tty The Termios control. This parameter may be passed to - * interrupt service routines since it must be provided for the - * rtems_termios_enqueue_raw_characters() and - * rtems_termios_dequeue_characters() functions. - * @param[in] context The Termios device context. - * @param[in] term The current Termios attributes. - * @param[in] args The open/close arguments. This is parameter provided to - * support legacy drivers. It must not be used by new drivers. - * - * @retval true Successful operation. - * @retval false Cannot open device. - * - * @see rtems_termios_get_device_context() and rtems_termios_set_best_baud(). - */ - bool (*first_open)( - struct rtems_termios_tty *tty, - rtems_termios_device_context *context, - struct termios *term, - rtems_libio_open_close_args_t *args - ); - - /** - * @brief Last close of this device. - * - * @param[in] tty The Termios control. - * @param[in] context The Termios device context. - * @param[in] args The open/close arguments. This is parameter provided to - * support legacy drivers. It must not be used by new drivers. - */ - void (*last_close)( - struct rtems_termios_tty *tty, - rtems_termios_device_context *context, - rtems_libio_open_close_args_t *args - ); - - /** - * @brief Polled read. - * - * In case mode is TERMIOS_IRQ_DRIVEN, TERMIOS_IRQ_SERVER_DRIVEN or - * TERMIOS_TASK_DRIVEN, then data is received via - * rtems_termios_enqueue_raw_characters(). - * - * @param[in] context The Termios device context. - * - * @retval char The received data encoded as unsigned char. - * @retval -1 No data currently available. - */ - int (*poll_read)(rtems_termios_device_context *context); - - /** - * @brief Polled write in case mode is TERMIOS_POLLED or write support - * otherwise. - * - * @param[in] context The Termios device context. - * @param[in] buf The output buffer. - * @param[in] len The output buffer length in characters. - */ - void (*write)( - rtems_termios_device_context *context, - const char *buf, - size_t len - ); - - /** - * @brief Set attributes after a Termios settings change. - * - * @param[in] context The Termios device context. - * @param[in] term The new Termios attributes. - * - * @retval true Successful operation. - * @retval false Invalid attributes. - */ - bool (*set_attributes)( - rtems_termios_device_context *context, - const struct termios *term - ); - - /** - * @brief IO control handler. - * - * Invoked in case the Termios layer cannot deal with the IO request. - * - * @param[in] context The Termios device context. - * @param[in] request The IO control request. - * @param[in] buffer The IO control buffer. - */ - int (*ioctl)( - rtems_termios_device_context *context, - ioctl_command_t request, - void *buffer - ); - - /** - * @brief Termios device mode. - */ - rtems_termios_device_mode mode; -} rtems_termios_device_handler; - -/** - * @brief Termios device flow control handler. - * - * @see rtems_termios_device_install(). - */ -typedef struct { - /** - * @brief Indicate to stop remote transmitter. - * - * @param[in] context The Termios device context. - */ - void (*stop_remote_tx)(rtems_termios_device_context *context); - - /** - * @brief Indicate to start remote transmitter. - * - * @param[in] context The Termios device context. - */ - void (*start_remote_tx)(rtems_termios_device_context *context); -} rtems_termios_device_flow; - /** * @brief Termios device node for installed devices. * @@ -456,36 +248,6 @@ static inline void *rtems_termios_get_device_context( } /** - * @brief Acquires the device lock. - * - * @param[in] context The device context. - * @param[in] lock_context The local interrupt lock context for an acquire and - * release pair. - */ -static inline void rtems_termios_device_lock_acquire( - rtems_termios_device_context *context, - rtems_interrupt_lock_context *lock_context -) -{ - ( *context->lock_acquire )( context, lock_context ); -} - -/** - * @brief Releases the device lock. - * - * @param[in] context The device context. - * @param[in] lock_context The local interrupt lock context for an acquire and - * release pair. - */ -static inline void rtems_termios_device_lock_release( - rtems_termios_device_context *context, - rtems_interrupt_lock_context *lock_context -) -{ - ( *context->lock_release )( context, lock_context ); -} - -/** * @brief Sets the best baud value in the Termios control. * * The valid Termios baud values are between 0 and 460800. The Termios baud diff --git a/cpukit/include/rtems/score/gcov.h b/cpukit/include/rtems/test-gcov.h index 35e0480f6b..3664e91c64 100644 --- a/cpukit/include/rtems/score/gcov.h +++ b/cpukit/include/rtems/test-gcov.h @@ -3,10 +3,9 @@ /** * @file * - * @ingroup RTEMSScoreGcov + * @ingroup RTEMSImplGcov * - * @brief This header file provides the interfaces of the - * @ref RTEMSScoreGcov. + * @brief This header file provides the interfaces of the @ref RTEMSImplGcov. */ /* @@ -34,22 +33,22 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _RTEMS_SCORE_GCOV_H -#define _RTEMS_SCORE_GCOV_H +#ifndef _RTEMS_TEST_GCOV_H +#define _RTEMS_TEST_GCOV_H #include <gcov.h> #include <rtems/linkersets.h> -#include <rtems/score/io.h> +#include <rtems/dev/io.h> #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** - * @defgroup RTEMSScoreGcov Gcov Support + * @defgroup RTEMSImplGcov Gcov Support * - * @ingroup RTEMSScore + * @ingroup RTEMSTestFrameworkImpl * * @brief This group contains the gocv support. * @@ -84,4 +83,4 @@ void _Gcov_Dump_info_base64( IO_Put_char put_char, void *arg ); } #endif /* __cplusplus */ -#endif /* _RTEMS_SCORE_GCOV_H */ +#endif /* _RTEMS_TEST_GCOV_H */ diff --git a/cpukit/include/rtems/test-info.h b/cpukit/include/rtems/test-info.h index 055ed4f25b..a5c00c423a 100644 --- a/cpukit/include/rtems/test-info.h +++ b/cpukit/include/rtems/test-info.h @@ -1,5 +1,13 @@ /* SPDX-License-Identifier: BSD-2-Clause */ +/** + * @file + * + * @ingroup RTEMSTest + * + * @brief This header file provides interfaces of the RTEMS Test Support. + */ + /* * Copyright (C) 2014, 2018 embedded brains GmbH & Co. KG * @@ -29,7 +37,6 @@ #define _RTEMS_TEST_H #include <rtems.h> -#include <rtems/printer.h> #include <rtems/score/atomic.h> #include <rtems/score/smpbarrier.h> @@ -53,11 +60,6 @@ extern "C" { extern const char rtems_test_name[]; /** - * @brief Each test must define a printer. - */ -extern rtems_printer rtems_test_printer; - -/** * @brief Fatal extension for tests. */ void rtems_test_fatal_extension( @@ -125,13 +127,6 @@ int rtems_test_end(const char* name); */ RTEMS_NO_RETURN void rtems_test_exit(int status); -/** - * @brief Prints via the RTEMS printer. - * - * @return As specified by printf(). - */ -int rtems_test_printf(const char* format, ...) RTEMS_PRINTFLIKE(1, 2); - #define RTEMS_TEST_PARALLEL_PROCESSOR_MAX 32 typedef struct rtems_test_parallel_job rtems_test_parallel_job; diff --git a/cpukit/score/src/pheapresizeblock.c b/cpukit/include/rtems/test-printer.h index ffd765e860..6625aa5a29 100644 --- a/cpukit/score/src/pheapresizeblock.c +++ b/cpukit/include/rtems/test-printer.h @@ -3,15 +3,13 @@ /** * @file * - * @ingroup RTEMSScoreProtHeap + * @ingroup RTEMSTest * - * @brief This source file contains the implementation of - * _Protected_heap_Resize_block(). + * @brief This header file provides interfaces of the RTEMS Test Support. */ /* - * COPYRIGHT (c) 1989-2007. - * On-Line Applications Research Corporation (OAR). + * Copyright (C) 2014, 2023 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,26 +33,37 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <rtems/score/protectedheap.h> - -bool _Protected_heap_Resize_block( - Heap_Control *the_heap, - void *starting_address, - uintptr_t size -) -{ - Heap_Resize_status status; - uintptr_t old_mem_size; - uintptr_t avail_mem_size; - - _RTEMS_Lock_allocator(); - status = _Heap_Resize_block( - the_heap, starting_address, size, &old_mem_size, &avail_mem_size ); - _RTEMS_Unlock_allocator(); - return (status == HEAP_RESIZE_SUCCESSFUL); +#ifndef _RTEMS_TEST_PRINTER_H +#define _RTEMS_TEST_PRINTER_H + +#include <rtems/printer.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @addtogroup RTEMSTest + * + * @{ + */ + +/** + * @brief Provides an RTEMS printer for tests. + */ +extern rtems_printer rtems_test_printer; + +/** + * @brief Prints via the RTEMS test printer. + * + * @return Returns the count of output characters as specified by printf(). + */ +int rtems_test_printf( const char *format, ... ) RTEMS_PRINTFLIKE( 1, 2 ); + +/** @} */ + +#ifdef __cplusplus } +#endif /* __cplusplus */ +#endif /* _RTEMS_TEST_PRINTER_H */ diff --git a/cpukit/include/rtems/test.h b/cpukit/include/rtems/test.h index 79313343a0..b8e7934883 100644 --- a/cpukit/include/rtems/test.h +++ b/cpukit/include/rtems/test.h @@ -1,6 +1,15 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file * + * @ingroup RTEMSTestFramework + * + * @brief This header file provides interfaces of the + * RTEMS Test Framework. + */ + +/* * Copyright (C) 2017, 2021 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without @@ -77,6 +86,11 @@ typedef struct T_fixture_node { unsigned int failures; } T_fixture_node; +typedef struct T_remark { + struct T_remark *next; + const char *remark; +} T_remark; + #define T_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) /* @@ -98,7 +112,7 @@ typedef struct T_fixture_node { /** * @defgroup RTEMSTestFrameworkImpl RTEMS Test Framework Implementation * - * @ingroup RTEMSTestFramework + * @ingroup RTEMSImpl * * @brief Implementation details. * @@ -2318,6 +2332,8 @@ void *T_fixture_context(void); void T_set_fixture_context(void *); +void T_add_remark(T_remark *); + void *T_push_fixture(T_fixture_node *, const T_fixture *); void T_pop_fixture(void); diff --git a/cpukit/include/rtems/thread.h b/cpukit/include/rtems/thread.h index 739744b4e0..c3d7de67f4 100644 --- a/cpukit/include/rtems/thread.h +++ b/cpukit/include/rtems/thread.h @@ -1,5 +1,14 @@ /* SPDX-License-Identifier: BSD-2-Clause */ +/** + * @file + * + * @ingroup RTEMSAPISelfContainedObjects + * + * @brief This header file provides the API of + * @ref RTEMSAPISelfContainedObjects. + */ + /* * Copyright (c) 2017 embedded brains GmbH & Co. KG * @@ -45,6 +54,16 @@ void _Semaphore_Post_binary(struct _Semaphore_Control *); typedef struct _Mutex_Control rtems_mutex; +/** + * @defgroup RTEMSAPISelfContainedObjects Self-Contained Objects + * + * @ingroup RTEMSAPI + * + * @brief This group contains the self-contained objects API. + * + * @{ + */ + #define RTEMS_MUTEX_INITIALIZER( name ) _MUTEX_NAMED_INITIALIZER( name ) static __inline void rtems_mutex_init( rtems_mutex *mutex, const char *name ) @@ -309,6 +328,8 @@ static __inline void rtems_binary_semaphore_destroy( _Semaphore_Destroy( &binary_semaphore->Semaphore ); } +/** @} */ + __END_DECLS #endif /* _RTEMS_THREAD_H */ diff --git a/cpukit/include/sys/_ffcounter.h b/cpukit/include/sys/_ffcounter.h index d83c48cd44..802c7d3224 100644 --- a/cpukit/include/sys/_ffcounter.h +++ b/cpukit/include/sys/_ffcounter.h @@ -1,3 +1,12 @@ +/** + * @file + * + * @ingroup RTEMSScoreTimecounter + * + * @brief This header file provides interfaces of the feed-forward clock + * counter. + */ + /*- * Copyright (c) 2011 The University of Melbourne * All rights reserved. diff --git a/cpukit/include/sys/endian.h b/cpukit/include/sys/endian.h index 0849a6a90b..cdd6201736 100644 --- a/cpukit/include/sys/endian.h +++ b/cpukit/include/sys/endian.h @@ -1,3 +1,12 @@ +/** + * @file + * + * @ingroup RTEMSAPISystemLibrary + * + * @brief This header file provides interfaces of the system endianness + * support. + */ + /*- * Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org> * All rights reserved. diff --git a/cpukit/include/sys/priority.h b/cpukit/include/sys/priority.h index 855edb63c2..37d0d938dc 100644 --- a/cpukit/include/sys/priority.h +++ b/cpukit/include/sys/priority.h @@ -1,3 +1,11 @@ +/** + * @file + * + * @ingroup RTEMSAPISystemLibrary + * + * @brief This header file provides interfaces of the process priority support. + */ + /*- * SPDX-License-Identifier: BSD-4-Clause * diff --git a/cpukit/include/sys/statvfs.h b/cpukit/include/sys/statvfs.h index 52d8e9d3fa..655f9a596c 100644 --- a/cpukit/include/sys/statvfs.h +++ b/cpukit/include/sys/statvfs.h @@ -3,10 +3,11 @@ /** * @file * - * @brief Interface to the statvfs() Set of API Methods + * @ingroup RTEMSAPISystemLibrary * - * This include file defines the interface to the statvfs() set of - * API methods. The statvfs as defined by the SUS: + * @brief This header file provides the statvfs() and fstatvfs() interfaces. + * + * The statvfs() is defined by the SUS: * * - http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html */ diff --git a/cpukit/include/sys/timeffc.h b/cpukit/include/sys/timeffc.h index c04de97f1d..13abd37a2b 100644 --- a/cpukit/include/sys/timeffc.h +++ b/cpukit/include/sys/timeffc.h @@ -1,3 +1,12 @@ +/** + * @file + * + * @ingroup RTEMSScoreTimecounter + * + * @brief This header file provides interfaces of the feed-back and + * feed-forward clock implementations. + */ + /*- * Copyright (c) 2011 The University of Melbourne * All rights reserved. diff --git a/cpukit/include/sys/timepps.h b/cpukit/include/sys/timepps.h index 030c734477..502d93833e 100644 --- a/cpukit/include/sys/timepps.h +++ b/cpukit/include/sys/timepps.h @@ -1,3 +1,12 @@ +/** + * @file + * + * @ingroup RTEMSScoreTimecounter + * + * @brief This header file provides interfaces of the Pulse Per Second (PPS) + * support. + */ + /*- * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): diff --git a/cpukit/include/sys/timetc.h b/cpukit/include/sys/timetc.h index 1ef58b378d..8f2537692c 100644 --- a/cpukit/include/sys/timetc.h +++ b/cpukit/include/sys/timetc.h @@ -1,3 +1,12 @@ +/** + * @file + * + * @ingroup RTEMSScoreTimecounter + * + * @brief This header file provides interfaces of the timecounter + * implementation. + */ + /*- * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): diff --git a/cpukit/include/sys/timex.h b/cpukit/include/sys/timex.h index 8e763bb30f..36b1fcdb5a 100644 --- a/cpukit/include/sys/timex.h +++ b/cpukit/include/sys/timex.h @@ -1,3 +1,12 @@ +/** + * @file + * + * @ingroup RTEMSScoreTimecounter + * + * @brief This header file provides interfaces of the Network Time Protocol + * (NTP) support. + */ + /*- *********************************************************************** * * diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c index 06b756272f..ee6f1d9347 100644 --- a/cpukit/libblock/src/bdbuf.c +++ b/cpukit/libblock/src/bdbuf.c @@ -39,7 +39,6 @@ #include <pthread.h> #include <rtems.h> -#include <rtems/error.h> #include <rtems/thread.h> #include <rtems/score/assert.h> @@ -2902,7 +2901,7 @@ rtems_bdbuf_set_block_size (rtems_disk_device *dd, * device later. */ if (sync) - rtems_bdbuf_syncdev (dd); + (void) rtems_bdbuf_syncdev (dd); rtems_bdbuf_lock_cache (); diff --git a/cpukit/libblock/src/blkdev-imfs.c b/cpukit/libblock/src/blkdev-imfs.c index 67f7c98c9d..e562619d4d 100644 --- a/cpukit/libblock/src/blkdev-imfs.c +++ b/cpukit/libblock/src/blkdev-imfs.c @@ -269,7 +269,7 @@ static void rtems_blkdev_imfs_destroy(IMFS_jnode_t *node) rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_node(node); rtems_disk_device *dd = &ctx->dd; - rtems_bdbuf_syncdev(dd); + (void) rtems_bdbuf_syncdev(dd); rtems_bdbuf_purge_dev(dd); if (ctx->fd >= 0) { diff --git a/cpukit/libblock/src/media.c b/cpukit/libblock/src/media.c index 3ab01602ae..cc6bb70f91 100644 --- a/cpukit/libblock/src/media.c +++ b/cpukit/libblock/src/media.c @@ -194,7 +194,7 @@ static void error( const char *dest ) { - notify(RTEMS_MEDIA_EVENT_ERROR, state, src, dest); + (void) notify(RTEMS_MEDIA_EVENT_ERROR, state, src, dest); } static media_item *get_media_item( @@ -434,7 +434,7 @@ static rtems_status_code process_event( { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc_retry = RTEMS_SUCCESSFUL; - rtems_media_state state = RTEMS_MEDIA_STATE_FAILED; + rtems_media_state state; char *dest = NULL; do { @@ -519,7 +519,7 @@ static rtems_status_code mount_worker( &mount_options ); if (rv != 0) { - rmdir(mount_path); + (void) rmdir(mount_path); free(mount_path); (*mount_options.converter->handler->destroy)(mount_options.converter); diff --git a/cpukit/libcsupport/src/cachecoherentalloc.c b/cpukit/libcsupport/src/cachecoherentalloc.c index 198eb907b5..ed17ebffcb 100644 --- a/cpukit/libcsupport/src/cachecoherentalloc.c +++ b/cpukit/libcsupport/src/cachecoherentalloc.c @@ -97,7 +97,7 @@ void rtems_cache_coherent_free( void *ptr ) _RTEMS_Unlock_allocator(); } -static void add_area( +static rtems_status_code add_area( void *area_begin, uintptr_t area_size ) @@ -105,31 +105,37 @@ static void add_area( Heap_Control *heap = cache_coherent_heap; if ( heap == NULL ) { - bool ok; - heap = &cache_coherent_heap_instance; - ok = _Heap_Initialize( heap, area_begin, area_size, 0 ); - if ( ok ) { - cache_coherent_heap = heap; + if ( _Heap_Initialize( heap, area_begin, area_size, 0 ) == 0 ) { + return RTEMS_UNSATISFIED; } + cache_coherent_heap = heap; } else { - _Heap_Extend( heap, area_begin, area_size, 0 ); + if (_Heap_Extend( heap, area_begin, area_size, 0 ) == 0) { + return RTEMS_UNSATISFIED; + } } + return RTEMS_SUCCESSFUL; } -void rtems_cache_coherent_add_area( +rtems_status_code rtems_cache_coherent_add_area( void *area_begin, uintptr_t area_size ) { - if ( _System_state_Is_up( _System_state_Get()) ) { + rtems_status_code sc; + bool needs_locking = _System_state_Is_up( _System_state_Get()); + + if ( needs_locking ) { _RTEMS_Lock_allocator(); + } - add_area( area_begin, area_size ); + sc = add_area( area_begin, area_size ); + if ( needs_locking ) { _RTEMS_Unlock_allocator(); - } else { - add_area( area_begin, area_size ); } + + return sc; } diff --git a/cpukit/libcsupport/src/getpid.c b/cpukit/libcsupport/src/getpid.c index 84cab91a39..464504de7e 100644 --- a/cpukit/libcsupport/src/getpid.c +++ b/cpukit/libcsupport/src/getpid.c @@ -40,7 +40,6 @@ #include <unistd.h> #include <rtems.h> -#include <rtems/seterr.h> /** * 4.1.1 Get Process and Parent Process IDs, P1003.1b-1993, p. 83 diff --git a/cpukit/libcsupport/src/getppid.c b/cpukit/libcsupport/src/getppid.c index 46d1cc8e08..2ca7a8f900 100644 --- a/cpukit/libcsupport/src/getppid.c +++ b/cpukit/libcsupport/src/getppid.c @@ -46,8 +46,6 @@ #include <unistd.h> -#include <rtems/seterr.h> - pid_t _POSIX_types_Ppid = 0; /** diff --git a/cpukit/libcsupport/src/isatty_r.c b/cpukit/libcsupport/src/isatty_r.c index 7a758c54a8..3ae285fb26 100644 --- a/cpukit/libcsupport/src/isatty_r.c +++ b/cpukit/libcsupport/src/isatty_r.c @@ -44,7 +44,6 @@ */ #include <unistd.h> #include <reent.h> -#include <sys/stat.h> int _isatty_r( struct _reent *ptr, diff --git a/cpukit/libcsupport/src/malloc_p.h b/cpukit/libcsupport/src/malloc_p.h index ac25cd31d1..115198cb40 100644 --- a/cpukit/libcsupport/src/malloc_p.h +++ b/cpukit/libcsupport/src/malloc_p.h @@ -1,8 +1,15 @@ /* SPDX-License-Identifier: BSD-2-Clause */ -/* - * RTEMS Malloc Family Internal Header +/** + * @file + * + * @ingroup libcsupport * + * @brief This header file provides interfaces used by the memory allocator + * implementation. + */ + +/* * COPYRIGHT (c) 1989-2007. * On-Line Applications Research Corporation (OAR). * diff --git a/cpukit/libcsupport/src/sup_fs_location.c b/cpukit/libcsupport/src/sup_fs_location.c index 1f533f37f4..a121b252fb 100644 --- a/cpukit/libcsupport/src/sup_fs_location.c +++ b/cpukit/libcsupport/src/sup_fs_location.c @@ -39,7 +39,6 @@ #include <stdlib.h> #include <rtems/libio_.h> -#include <rtems/score/threaddispatch.h> rtems_interrupt_lock rtems_filesystem_mt_entry_lock_control = RTEMS_INTERRUPT_LOCK_INITIALIZER("mount table entry"); diff --git a/cpukit/libcsupport/src/termiosinitialize.c b/cpukit/libcsupport/src/termiosinitialize.c index 35aa1eb955..ae80243b2a 100644 --- a/cpukit/libcsupport/src/termiosinitialize.c +++ b/cpukit/libcsupport/src/termiosinitialize.c @@ -1,8 +1,11 @@ /** - * @file + * @file * - * @brief Termios Initialization - * @ingroup Termios + * @ingroup TermiostypesSupport + * + * @brief This source file contains the implementation of + * rtems_termios_device_lock_acquire_default() and + * rtems_termios_device_lock_release_default(). */ /* @@ -17,7 +20,7 @@ #include "config.h" #endif -#include <rtems/termiostypes.h> +#include <rtems/termiosdevice.h> void rtems_termios_device_lock_acquire_default( diff --git a/cpukit/libcsupport/src/vprintk.c b/cpukit/libcsupport/src/vprintk.c index e46cdad60f..f4ac81c5fc 100644 --- a/cpukit/libcsupport/src/vprintk.c +++ b/cpukit/libcsupport/src/vprintk.c @@ -38,7 +38,7 @@ #endif #include <rtems/bspIo.h> -#include <rtems/score/io.h> +#include <rtems/dev/io.h> int vprintk( const char *fmt, va_list ap ) { diff --git a/cpukit/libdl/rtl-alloc-heap.c b/cpukit/libdl/rtl-alloc-heap.c index 10150a0753..f90233874e 100644 --- a/cpukit/libdl/rtl-alloc-heap.c +++ b/cpukit/libdl/rtl-alloc-heap.c @@ -9,7 +9,7 @@ */ /* - * COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org> + * COPYRIGHT (c) 2012,2023 Chris Johns <chrisj@rtems.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -54,6 +54,9 @@ rtems_rtl_alloc_heap (rtems_rtl_alloc_cmd cmd, free (*address); *address = NULL; break; + case RTEMS_RTL_ALLOC_RESIZE: + *address = realloc (*address, size); + break; case RTEMS_RTL_ALLOC_LOCK: _RTEMS_Lock_allocator(); break; diff --git a/cpukit/libdl/rtl-allocator.c b/cpukit/libdl/rtl-allocator.c index f09690d71a..7503183367 100644 --- a/cpukit/libdl/rtl-allocator.c +++ b/cpukit/libdl/rtl-allocator.c @@ -9,7 +9,7 @@ */ /* - * COPYRIGHT (c) 2012, 2018 Chris Johns <chrisj@rtems.org> + * COPYRIGHT (c) 2012, 2018, 2023 Chris Johns <chrisj@rtems.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -110,6 +110,39 @@ rtems_rtl_alloc_del (rtems_rtl_alloc_tag tag, void* address) rtems_rtl_unlock (); } +void* rtems_rtl_alloc_resize (rtems_rtl_alloc_tag tag, + void* address, + size_t size, + bool zero) +{ + rtems_rtl_data* rtl = rtems_rtl_lock (); + const void* prev_address = address; + + /* + * Resize memory of an existing allocation. The address field is set + * by the allocator and may change. + */ + if (rtl != NULL) + rtl->allocator.allocator (RTEMS_RTL_ALLOC_RESIZE, tag, &address, size); + + rtems_rtl_unlock (); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR)) + printf ("rtl: alloc: resize: %s%s prev-addr=%p addr=%p size=%zu\n", + rtems_rtl_trace_tag_label (tag), prev_address == address ? "" : " MOVED", + prev_address, address, size); + + /* + * Only zero the memory if asked to and the resize was successful. We + * cannot clear the resized area if bigger than the previouis allocation + * because we do not have the original size. + */ + if (address != NULL && zero) + memset (address, 0, size); + + return address; +} + void rtems_rtl_alloc_wr_enable (rtems_rtl_alloc_tag tag, void* address) { @@ -277,21 +310,23 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, { *text_base = *const_base = *data_base = *bss_base = NULL; - if (text_size) + if (data_size != 0) { - *text_base = rtems_rtl_alloc_new (rtems_rtl_alloc_text_tag (), - text_size, false); - if (!*text_base) + *data_base = rtems_rtl_alloc_new (rtems_rtl_alloc_data_tag (), + data_size, false); + if (*data_base == NULL) { + rtems_rtl_alloc_module_del (text_base, const_base, eh_base, + data_base, bss_base); return false; } } - if (const_size) + if (bss_size != 0) { - *const_base = rtems_rtl_alloc_new (rtems_rtl_alloc_const_tag (), - const_size, false); - if (!*const_base) + *bss_base = rtems_rtl_alloc_new (rtems_rtl_alloc_bss_tag (), + bss_size, false); + if (*bss_base == NULL) { rtems_rtl_alloc_module_del (text_base, const_base, eh_base, data_base, bss_base); @@ -299,11 +334,11 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, } } - if (eh_size) + if (eh_size != 0) { *eh_base = rtems_rtl_alloc_new (rtems_rtl_alloc_eh_tag (), eh_size, false); - if (!*eh_base) + if (*eh_base == NULL) { rtems_rtl_alloc_module_del (text_base, const_base, eh_base, data_base, bss_base); @@ -311,11 +346,11 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, } } - if (data_size) + if (const_size != 0) { - *data_base = rtems_rtl_alloc_new (rtems_rtl_alloc_data_tag (), - data_size, false); - if (!*data_base) + *const_base = rtems_rtl_alloc_new (rtems_rtl_alloc_const_tag (), + const_size, false); + if (*const_base == NULL) { rtems_rtl_alloc_module_del (text_base, const_base, eh_base, data_base, bss_base); @@ -323,14 +358,72 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, } } - if (bss_size) + if (text_size != 0) { - *bss_base = rtems_rtl_alloc_new (rtems_rtl_alloc_bss_tag (), - bss_size, false); - if (!*bss_base) + *text_base = rtems_rtl_alloc_new (rtems_rtl_alloc_text_tag (), + text_size, false); + if (*text_base == NULL) + { + return false; + } + } + + return true; +} + +bool +rtems_rtl_alloc_module_resize (void** text_base, size_t text_size, + void** const_base, size_t const_size, + void** eh_base, size_t eh_size, + void** data_base, size_t data_size, + void** bss_base, size_t bss_size) +{ + if (data_size != 0) + { + *data_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_data_tag (), + *data_base, data_size, false); + if (*data_base == NULL) + { + return false; + } + } + + if (bss_size != 0) + { + *bss_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_bss_tag (), + *bss_base, bss_size, false); + if (*bss_base == NULL) + { + return false; + } + } + + if (eh_size != 0) + { + *eh_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_eh_tag (), + *eh_base, eh_size, false); + if (*eh_base == NULL) + { + return false; + } + } + + if (const_size != 0) + { + *const_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_const_tag (), + *const_base, const_size, false); + if (*const_base == NULL) + { + return false; + } + } + + if (text_size != 0) + { + *text_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_text_tag (), + *text_base, text_size, false); + if (*text_base == NULL) { - rtems_rtl_alloc_module_del (text_base, const_base, eh_base, - data_base, bss_base); return false; } } diff --git a/cpukit/libdl/rtl-archive.c b/cpukit/libdl/rtl-archive.c index f916336f7c..4a6d2cbf0b 100644 --- a/cpukit/libdl/rtl-archive.c +++ b/cpukit/libdl/rtl-archive.c @@ -1174,6 +1174,7 @@ rtems_rtl_obj_archive_find_obj (int fd, */ if (header[0] == '/') { + const char* name_ = *name; off_t extended_off; switch (header[1]) @@ -1190,7 +1191,7 @@ rtems_rtl_obj_archive_find_obj (int fd, * return the result. */ *extended_file_names = *ooffset + RTEMS_RTL_AR_FHDR_SIZE; - if (*name[0] == '/' && *name[1] == '/') + if (name_[0] == '/' && name_[1] == '/') { *ooffset = *ooffset + RTEMS_RTL_AR_FHDR_SIZE; return true; diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c index 5754070518..dd6d8617bb 100644 --- a/cpukit/libdl/rtl-elf.c +++ b/cpukit/libdl/rtl-elf.c @@ -178,12 +178,19 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj, /* * If the symbol type is STT_NOTYPE the symbol references a global - * symbol. The gobal symbol table is searched to find it and that value + * symbol. The global symbol table is searched to find it and that value * returned. If the symbol is local to the object module the section for the * symbol is located and it's base added to the symbol's value giving an * absolute location. + * + * If the symbols type of TLS return the symbols value. It is the + * offset from the thread's TLS area base. The offset is set by the + * linker for the base image and by the TLS allocator for loaded + * modules. There is no section and no absolute base. */ - if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE || sym->st_shndx == SHN_COMMON) + if (ELF_ST_TYPE (sym->st_info) == STT_NOTYPE || + sym->st_shndx == SHN_COMMON || + ELF_ST_TYPE (sym->st_info) == STT_TLS) { /* * Search the object file then the global table for the symbol. @@ -247,6 +254,13 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj, rtems_rtl_elf_rel_status rs; /* + * TLS are not parsed. + */ + if (ELF_ST_TYPE (sym->st_info) == STT_TLS) { + return true; + } + + /* * Check the reloc record to see if a trampoline is needed. */ if (is_rela) @@ -302,7 +316,7 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj, * Find the symbol's object file. It cannot be NULL so ignore that result * if returned, it means something is corrupted. We are in an iterator. */ - rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol); + rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol); if (sobj != NULL) { /* @@ -791,7 +805,7 @@ rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec, } if (unresolved || rs == rtems_rtl_elf_rel_tramp_add) - tramp->obj->tramps_size += tramp->obj->tramp_size; + ++tramp->obj->tramp_slots; if (rs == rtems_rtl_elf_rel_failure) { *failure = true; @@ -804,7 +818,7 @@ rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec, } static bool -rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved) +rtems_rtl_elf_find_trampolines (rtems_rtl_obj* obj, size_t unresolved) { rtems_rtl_tramp_data td = { 0 }; td.obj = obj; @@ -815,21 +829,20 @@ rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved) if (td.failure) return false; rtems_rtl_trampoline_remove (obj); - obj->tramp_relocs = obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size; + obj->tramp_relocs = obj->tramp_slots; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: tramp:elf: tramps: %zu count:%zu total:%zu\n", + printf ("rtl: tramp:elf: tramps: slots:%zu count:%zu total:%zu\n", obj->tramp_relocs, td.count, td.total); /* * Add on enough space to handle the unresolved externals that need to be * resolved at some point in time. They could all require fixups and * trampolines. */ - obj->tramps_size += obj->tramp_size * unresolved; + obj->tramp_slots += unresolved; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: tramp:elf: slots: %zu (%zu)\n", - obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size, - obj->tramps_size); - return rtems_rtl_obj_alloc_trampoline (obj); + printf ("rtl: tramp:elf: slots:%zu (%zu)\n", + obj->tramp_slots, obj->tramp_slots * obj->tramp_slot_size); + return true; } static bool @@ -1716,7 +1729,7 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd) /* * Set the format's architecture's maximum tramp size. */ - obj->tramp_size = rtems_rtl_elf_relocate_tramp_max_size (); + obj->tramp_slot_size = rtems_rtl_elf_relocate_tramp_max_size (); /* * Parse the section information first so we have the memory map of the object @@ -1765,13 +1778,23 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd) if (!rtems_rtl_obj_alloc_sections (obj, fd, rtems_rtl_elf_arch_alloc, &ehdr)) return false; - if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr)) + if (!rtems_rtl_elf_dependents (obj, &relocs)) return false; - if (!rtems_rtl_elf_dependents (obj, &relocs)) + if (!rtems_rtl_elf_find_trampolines (obj, relocs.unresolved)) return false; - if (!rtems_rtl_elf_alloc_trampoline (obj, relocs.unresolved)) + /* + * Resize the sections to allocate the trampoline memory as part of + * the text section. + */ + if (rtems_rtl_obj_has_trampolines (obj)) + { + if (!rtems_rtl_obj_resize_sections (obj)) + return false; + } + + if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr)) return false; /* diff --git a/cpukit/libdl/rtl-mdreloc-aarch64.c b/cpukit/libdl/rtl-mdreloc-aarch64.c index 46f87e9178..1eb1d1e87d 100644 --- a/cpukit/libdl/rtl-mdreloc-aarch64.c +++ b/cpukit/libdl/rtl-mdreloc-aarch64.c @@ -78,9 +78,11 @@ __RCSID("$NetBSD: mdreloc.c,v 1.14 2020/06/16 21:01:30 joerg Exp $"); #include "rtl-elf.h" #include "rtl-error.h" #include <rtems/rtl/rtl-trace.h> -#include "rtl-unwind-arm.h" #include <rtems/score/tls.h> +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" + struct tls_data { size_t td_tlsindex; Elf_Addr td_tlsoffs; @@ -161,6 +163,12 @@ get_veneer_size(int type) return 16; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint64_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { @@ -309,11 +317,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, } if (!parsing) { - target = (Elf_Addr)symvalue + rela->r_addend; - /* Calculate offset accounting for the DTV */ - target -= (uintptr_t)_TLS_Data_begin; - target += sizeof(TLS_Dynamic_thread_vector); - + target = (Elf_Addr)symvalue; target >>= shift; target &= WIDTHMASK(12); if (of_check && target >= of_check) { @@ -388,6 +392,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, target -= (uintptr_t)where >> 12; if (checkoverflow(target, 21, raddr, " x 4k", where, off)) { + printf("]] %d\n", __LINE__); return rtems_rtl_elf_rel_failure; } @@ -418,6 +423,13 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, return rtems_rtl_elf_rel_failure; } + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ( + "rtl: JUMP26/PC26/CALL: insn=%p where=%p target=%p raddr=%p parsing=%d\n", + insn, (void*) where, (void*)(uintptr_t) target, (void*)(uintptr_t) raddr, + parsing + ); + target = (intptr_t)target >> 2; if (((Elf_Sword)target > 0x1FFFFFF) || ((Elf_Sword)target < -0x2000000)) { @@ -437,9 +449,8 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, return rtems_rtl_elf_rel_failure; } - tramp_addr = ((Elf_Addr)(uintptr_t)obj->tramp_brk) | (symvalue & 1); + tramp_addr = ((Elf_Addr)(uintptr_t) obj->tramp_brk) | (symvalue & 1); obj->tramp_brk = set_veneer(obj->tramp_brk, symvalue); - target = tramp_addr + rela->r_addend - (uintptr_t)where; target = (uintptr_t)target >> 2; } @@ -464,6 +475,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, raddr = (Elf_Addr)symvalue + rela->r_addend; target = raddr - (uintptr_t)where; if (checkoverflow(target, 32, raddr, "", where, off)) { + printf("]] %d\n", __LINE__); return rtems_rtl_elf_rel_failure; } *where32 = target; @@ -561,3 +573,20 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj, rtems_rtl_set_error (EINVAL, "rela type record not supported"); return rtems_rtl_elf_rel_failure; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj, + const char* name, + uint32_t flags) { + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj) { + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj* obj) { + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c index fbfd42dc58..16efbe79da 100644 --- a/cpukit/libdl/rtl-mdreloc-arm.c +++ b/cpukit/libdl/rtl-mdreloc-arm.c @@ -108,6 +108,12 @@ get_veneer_size(int type) return 8; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { @@ -526,7 +532,6 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj, break; case R_TYPE(TLS_LE32): -#if ALLOW_UNTESTED_RELOCS if (!parsing) { addend = *where; *where = symvalue + addend; @@ -535,7 +540,7 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj, (void *)*where, where, rtems_rtl_obj_oname (obj)); } break; -#endif + case R_TYPE(TLS_GD32): case R_TYPE(TLS_LDM32): case R_TYPE(TLS_LDO32): diff --git a/cpukit/libdl/rtl-mdreloc-bfin.c b/cpukit/libdl/rtl-mdreloc-bfin.c index f46b86ce34..cf3f3f88c0 100644 --- a/cpukit/libdl/rtl-mdreloc-bfin.c +++ b/cpukit/libdl/rtl-mdreloc-bfin.c @@ -99,6 +99,12 @@ load_ptr(void *where) return (res); } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-i386.c b/cpukit/libdl/rtl-mdreloc-i386.c index 40b09d4be2..09cbe4f42f 100644 --- a/cpukit/libdl/rtl-mdreloc-i386.c +++ b/cpukit/libdl/rtl-mdreloc-i386.c @@ -64,6 +64,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-lm32.c b/cpukit/libdl/rtl-mdreloc-lm32.c index de0609345f..af904cd126 100644 --- a/cpukit/libdl/rtl-mdreloc-lm32.c +++ b/cpukit/libdl/rtl-mdreloc-lm32.c @@ -92,6 +92,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-m68k.c b/cpukit/libdl/rtl-mdreloc-m68k.c index 873574ef7c..a88d612c28 100644 --- a/cpukit/libdl/rtl-mdreloc-m68k.c +++ b/cpukit/libdl/rtl-mdreloc-m68k.c @@ -77,6 +77,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-microblaze.c b/cpukit/libdl/rtl-mdreloc-microblaze.c new file mode 100644 index 0000000000..0956e22bc7 --- /dev/null +++ b/cpukit/libdl/rtl-mdreloc-microblaze.c @@ -0,0 +1,298 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (C) 2023 On-Line Applications Research Corporation (OAR) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> + +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <rtems/rtl/rtl.h> +#include "rtl-elf.h" +#include "rtl-error.h" +#include <rtems/rtl/rtl-trace.h> +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" + +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj, + const Elf_Shdr* shdr) { + (void) obj; + (void) shdr; + return 0; +} + +uint32_t +rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj, + int section, + const char* name, + const Elf_Shdr* shdr, + const uint32_t flags) { + (void) obj; + (void) section; + (void) name; + (void) shdr; + return flags; +} + +bool +rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj, + rtems_rtl_obj_sect* sect) { + (void) obj; + (void) sect; + return false; +} + +bool +rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj, + rtems_rtl_obj_sect* sect) { + (void) obj; + (void) sect; + return false; +} + +bool +rtems_rtl_elf_rel_resolve_sym (Elf_Word type) { + return type != 0; +} + +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + +size_t +rtems_rtl_elf_relocate_tramp_max_size (void) { + /* + * Disable by returning 0. + */ + return 0; +} + +rtems_rtl_elf_rel_status +rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj, + const Elf_Rel* rel, + const rtems_rtl_obj_sect* sect, + const char* symname, + const Elf_Byte syminfo, + const Elf_Word symvalue) { + (void) obj; + (void) rel; + (void) sect; + (void) symname; + (void) syminfo; + (void) symvalue; + return rtems_rtl_elf_rel_no_error; +} + +static void write16le(void *loc, uint16_t val) { + *((uint16_t *) loc) = val; +} + +static void write32le(void *loc, uint32_t val) { + *((uint32_t *) loc) = val; +} + +static uint16_t read16le(void *loc) { + return *((uint16_t *) loc); +} + +static uint32_t read32le(void *loc) { + return *((uint32_t *) loc); +} + +static rtems_rtl_elf_rel_status +rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, + const Elf_Rela* rela, + const rtems_rtl_obj_sect* sect, + const char* symname, + const Elf_Byte syminfo, + const Elf_Word symvalue, + const bool parsing) { + Elf_Word *where; + Elf_Word addend = (Elf_Word)rela->r_addend; + Elf_Addr target; + + where = (Elf_Addr *)(sect->base + rela->r_offset); + + /* Target value */ + target = (Elf_Addr)symvalue + addend; + /* Final PCREL value */ + Elf_Word pcrel_val = target - ((Elf_Word)where); + + if (parsing) { + return rtems_rtl_elf_rel_no_error; + } + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(NONE): + break; + + case R_TYPE(64): + /* Set the lower 16 bits of where to the upper 16 bits of target */ + write16le(where, + (read16le(where) & 0xFFFF0000) | (target >> 16)); + /* Set the lower 16 bits of where + 4 to the lower 16 bits of target */ + write16le(where + 1, + (read16le(where + 1) & 0xFFFF0000) | (target & 0xFFFF)); + break; + + case R_TYPE(32): + { + uintptr_t addr = (uintptr_t)where; + if ((uintptr_t)where & 3) { + /* `where` is not aligned to a 4-byte boundary. */ + uintptr_t addr_down = addr & ~3; + uintptr_t addr_up = (addr + 3) & ~3; + + uint32_t value_down = read32le((void*)addr_down); + uint32_t value_up = read32le((void*)addr_up); + + /* + * Calculate how many bytes `where` is offset from the previous 4-byte + * boundary. + */ + unsigned offset = addr & 3; + + /* + * Combine `target` with `value_down` and `value_up` to form the new + * values to write. + */ + uint32_t new_value_down = (value_down & ((1 << (offset * 8)) - 1)) | + (target << (offset * 8)); + uint32_t new_value_up = (value_up & ~((1 << (offset * 8)) - 1)) | + (target >> ((4 - offset) * 8)); + + write32le((void*)addr_down, new_value_down); + write32le((void*)addr_up, new_value_up); + } else { + write32le(where, target); + } + } + break; + + case R_TYPE(32_PCREL): + write32le(where, pcrel_val); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: R_MICROBLAZE_32_PCREL %p @ %p in %s\n", + (void *) * (where), where, rtems_rtl_obj_oname (obj)); + break; + + case R_TYPE(64_PCREL): + /* + * Compensate for the fact that the PC is 4 bytes ahead of the instruction + */ + pcrel_val -= 4; + /* Set the lower 16 bits of where to the upper 16 bits of target */ + write16le(where, + (read16le(where) & 0xFFFF0000) | (pcrel_val >> 16)); + /* Set the lower 16 bits of where + 4 to the lower 16 bits of target */ + write16le(where + 1, + (read16le(where + 1) & 0xFFFF0000) | (pcrel_val & 0xFFFF)); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: R_MICROBLAZE_64_PCREL %p @ %p in %s\n", + (void *) * (where), where, rtems_rtl_obj_oname (obj)); + break; + + case R_TYPE(32_PCREL_LO): + write16le(where, (read16le(where) & 0xFFFF0000) | (pcrel_val & 0xFFFF)); + break; + + default: + rtems_rtl_set_error (EINVAL, + "%s: Unsupported relocation type %d " + "in non-PLT relocations", + sect->name, (uint32_t) ELF_R_TYPE(rela->r_info)); + return rtems_rtl_elf_rel_failure; + } + + return rtems_rtl_elf_rel_no_error; +} + +rtems_rtl_elf_rel_status +rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj, + const Elf_Rela* rela, + const rtems_rtl_obj_sect* sect, + const char* symname, + const Elf_Byte syminfo, + const Elf_Word symvalue) { + return rtems_rtl_elf_reloc_rela (obj, + rela, + sect, + symname, + syminfo, + symvalue, + false); +} + +rtems_rtl_elf_rel_status +rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, + const Elf_Rela* rela, + const rtems_rtl_obj_sect* sect, + const char* symname, + const Elf_Byte syminfo, + const Elf_Word symvalue) { + return rtems_rtl_elf_reloc_rela (obj, + rela, + sect, + symname, + syminfo, + symvalue, + true); +} + +rtems_rtl_elf_rel_status +rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj, + const Elf_Rel* rel, + const rtems_rtl_obj_sect* sect, + const char* symname, + const Elf_Byte syminfo, + const Elf_Word symvalue) { + rtems_rtl_set_error (EINVAL, "rel type record not supported"); + return rtems_rtl_elf_rel_failure; +} + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj, + const char* name, + uint32_t flags) { + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj) { + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj* obj) { + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-mips.c b/cpukit/libdl/rtl-mdreloc-mips.c index d43b144895..91d88c9986 100644 --- a/cpukit/libdl/rtl-mdreloc-mips.c +++ b/cpukit/libdl/rtl-mdreloc-mips.c @@ -93,6 +93,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-moxie.c b/cpukit/libdl/rtl-mdreloc-moxie.c index 6238ac99d2..a3cfe63b6a 100644 --- a/cpukit/libdl/rtl-mdreloc-moxie.c +++ b/cpukit/libdl/rtl-mdreloc-moxie.c @@ -93,6 +93,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-powerpc.c b/cpukit/libdl/rtl-mdreloc-powerpc.c index c6062c872a..09c2ab1512 100644 --- a/cpukit/libdl/rtl-mdreloc-powerpc.c +++ b/cpukit/libdl/rtl-mdreloc-powerpc.c @@ -207,6 +207,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { @@ -348,37 +354,47 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, break; case R_TYPE(16_HA): + case R_TYPE(TPREL16_HA): /* * value:6; Field:half16; Expression: #ha(S+A) + * value:72; Field:half16; Expression: #ha(S+A) */ if (!parsing) { tmp = symvalue + rela->r_addend; *(uint16_t *)where = (((tmp >> 16) + ((tmp & 0x8000) ? 1: 0)) & 0xffff); if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: 16_HA %p @ %p in %s\n", + printf ("rtl: %s16_HA %p @ %p in %s\n", + ELF_R_TYPE(rela->r_info) == R_TYPE(TPREL16_HA) ? "TPREL" : "", (void *)*(where), where, rtems_rtl_obj_oname (obj)); } break; case R_TYPE(16_HI): + case R_TYPE(TPREL16_HI): /* * value:5; Field:half16; Expression: #hi(S+A) + * value:71; Field:half16; Expression: #hi(S+A) */ if (!parsing) { *(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: 16_HI %p @ %p in %s\n", + printf ("rtl: %s16_HI %p @ %p in %s\n", + ELF_R_TYPE(rela->r_info) == R_TYPE(TPREL16_HI) ? "TPREL" : "", (void *)*where, where, rtems_rtl_obj_oname (obj)); } break; + case R_TYPE(16_LO): + case R_TYPE(TPREL16_LO): /* * value:4; Field:half16; Expression: #lo(S+A) + * value:71; Field:half16; Expression: #lo(S+A) */ if (!parsing) { *(uint16_t *)where = (symvalue + (rela->r_addend)) & 0xffff; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: 16_LO %p @ %p in %s\n", + printf ("rtl: %s16_LO %p @ %p in %s\n", + ELF_R_TYPE(rela->r_info) == R_TYPE(TPREL16_LO) ? "TPREL" : "", (void *)*where, where, rtems_rtl_obj_oname (obj)); } break; @@ -484,7 +500,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, (void *)rela->r_offset, (void *)*where); rtems_rtl_set_error (EINVAL, "%s: Unsupported relocation type %" PRId32 - "in non-PLT relocations", + " in non-PLT relocations", sect->name, (uint32_t) ELF_R_TYPE(rela->r_info)); return rtems_rtl_elf_rel_failure; } diff --git a/cpukit/libdl/rtl-mdreloc-riscv.c b/cpukit/libdl/rtl-mdreloc-riscv.c index e6778dcc90..c0b7556366 100644 --- a/cpukit/libdl/rtl-mdreloc-riscv.c +++ b/cpukit/libdl/rtl-mdreloc-riscv.c @@ -89,6 +89,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) { return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { /* diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c index f8a4312a8a..9810de988e 100644 --- a/cpukit/libdl/rtl-mdreloc-sparc.c +++ b/cpukit/libdl/rtl-mdreloc-sparc.c @@ -87,46 +87,66 @@ static const uint32_t reloc_target_flags[] = { _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ - _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ - _RF_SZ(32) | _RF_RS(0), /* COPY */ + _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ + _RF_SZ(32) | _RF_RS(0), /* COPY */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_DAT */ - _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ - _RF_A| _RF_B|_RF_SZ(32) | _RF_RS(0), /* RELATIVE */ - _RF_S|_RF_A| _RF_U|_RF_SZ(32) | _RF_RS(0), /* UA_32 */ + _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ + _RF_A| _RF_B| _RF_SZ(32) | _RF_RS(0), /* RELATIVE */ + _RF_S|_RF_A|_RF_U| _RF_SZ(32) | _RF_RS(0), /* UA_32 */ + + /* TLS and 64 bit relocs not listed here... */ }; +#define RELOC_TARGET_FLAGS_SIZE \ + (sizeof(reloc_target_flags) / sizeof(reloc_target_flags[0])) -#define NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL -#ifdef NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL +#define RTLD_DEBUG_RELOC +#ifdef RTLD_DEBUG_RELOC static const char *reloc_names[] = { "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8", "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22", "22", "13", "LO10", "GOT10", "GOT13", "GOT22", "PC10", "PC22", "WPLT30", "COPY", - "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32" + "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32", + + /* not used with 32bit userland, besides a few of the TLS ones */ + "PLT32", + "HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", "PCPLT32", + "10", "11", "64", "OLO10", "HH22", + "HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22", + "WDISP16", "WDISP19", "GLOB_JMP", "7", "5", "6", + "DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44", + "L44", "REGISTER", "UA64", "UA16", + "TLS_GD_HI22", "TLS_GD_LO10", "TLS_GD_ADD", "TLS_GD_CALL", + "TLS_LDM_HI22", "TLS_LDM_LO10", "TLS_LDM_ADD", "TLS_LDM_CALL", + "TLS_LDO_HIX22", "TLS_LDO_LOX10", "TLS_LDO_ADD", "TLS_IE_HI22", + "TLS_IE_LO10", "TLS_IE_LD", "TLS_IE_LDX", "TLS_IE_ADD", "TLS_LE_HIX22", + "TLS_LE_LOX10", "TLS_DTPMOD32", "TLS_DTPMOD64", "TLS_DTPOFF32", + "TLS_DTPOFF64", "TLS_TPOFF32", "TLS_TPOFF64", }; #endif -#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) -#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) -#define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) -#define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) -#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) -#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) -#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) +#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) +#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) +#define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) +#define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) +#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) +#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) +#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) +#define RELOC_TLS(t) (t >= R_TYPE(TLS_GD_HI22)) static const int reloc_target_bitmask[] = { #define _BM(x) (~(-(1ULL << (x)))) - 0, /* NONE */ - _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */ - _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ - _BM(30), _BM(22), /* WDISP30, WDISP22 */ - _BM(22), _BM(22), /* HI22, _22 */ - _BM(13), _BM(10), /* RELOC_13, _LO10 */ - _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ - _BM(10), _BM(22), /* _PC10, _PC22 */ - _BM(30), 0, /* _WPLT30, _COPY */ - -1, -1, -1, /* _GLOB_DAT, JMP_SLOT, _RELATIVE */ - _BM(32) /* _UA32 */ + 0, /* NONE */ + _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */ + _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ + _BM(30), _BM(22), /* WDISP30, WDISP22 */ + _BM(22), _BM(22), /* HI22, _22 */ + _BM(13), _BM(10), /* RELOC_13, _LO10 */ + _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ + _BM(10), _BM(22), /* _PC10, _PC22 */ + _BM(30), 0, /* _WPLT30, _COPY */ + -1, -1, -1, /* _GLOB_DAT, JMP_SLOT, _RELATIVE */ + _BM(32) /* _UA32 */ #undef _BM }; #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) @@ -173,7 +193,26 @@ rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj, bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) { - return RELOC_RESOLVE_SYMBOL (type) ? true : false; + bool r = false; + if (type < RELOC_TARGET_FLAGS_SIZE) { + r = RELOC_RESOLVE_SYMBOL (type) ? true : false; + } + switch (type) { + case R_TYPE(TLS_DTPOFF32): + case R_TYPE(TLS_LE_HIX22): + case R_TYPE(TLS_LE_LOX10): + r = true; + break; + default: + break; + } + return r; +} + +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); } size_t @@ -241,6 +280,73 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj, value = rela->r_addend; /* + * Handle TLS relocations here, they are different. + */ + if (RELOC_TLS(type)) { + switch (type) { + case R_TYPE(TLS_DTPMOD32): + #if NETBSD_CODE__NOT_USED + *where = (Elf_Addr)defobj->tlsindex; + #endif + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf("rtl: reloc: TLS_DTPMOD32 %s in %s --> %p\n", + symname, rtems_rtl_obj_oname (obj), (void *)*where); + break; + + case R_TYPE(TLS_DTPOFF32): + *where = (Elf_Addr)(symvalue + rela->r_addend); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf("rtl: reloc: TLS_DTPOFF32 %s in %s --> %p\n", + symname, rtems_rtl_obj_oname (obj), (void *)*where); + break; + + case R_TYPE(TLS_TPOFF32): + #if NETBSD_CODE__NOT_USED + if (!defobj->tls_static && + _rtld_tls_offset_allocate(__UNCONST(defobj))) + return ; + + *where = (Elf_Addr)(def->st_value - + defobj->tlsoffset + rela->r_addend); + #endif + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf("rtl: reloc: TLS_TPOFF32 %s in %s --> %p\n", + symname, rtems_rtl_obj_oname (obj), (void *)*where); + return rtems_rtl_elf_rel_failure; + + case R_TYPE(TLS_LE_HIX22): + *where |= ((symvalue + rela->r_addend) ^ 0xffffffff) >> 10; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf("rtl: reloc: R_SPARC_TLS_LE_HIX22 %s in %s --> %p\n", + symname, rtems_rtl_obj_oname (obj), (void *)*where); + break; + + case R_TYPE(TLS_LE_LOX10): + *where |= ((symvalue + rela->r_addend) & 0x3ff) | 0x1c00; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf("rtl: reloc: R_SPARC_TLS_LE_LOX10 %s in %s --> %p\n", + symname, rtems_rtl_obj_oname (obj), (void *)*where); + break; + + default: + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf("rtl: reloc: unknown TLS relo: %d for %s in %s --> %p\n", + type, symname, rtems_rtl_obj_oname (obj), (void *)*where); + return rtems_rtl_elf_rel_failure; + } + return rtems_rtl_elf_rel_no_error; + } + + /* + * If it is no TLS relocation (handled above), we can not + * deal with it if it is beyond R_SPARC_6. + */ + if (type > R_TYPE(6)) + return rtems_rtl_elf_rel_failure; + + /* * Handle relative relocs here, as an optimization. */ if (type == R_TYPE (RELATIVE)) { diff --git a/cpukit/libdl/rtl-mdreloc-v850.c b/cpukit/libdl/rtl-mdreloc-v850.c index 8d1f3c02a7..826763a2b5 100644 --- a/cpukit/libdl/rtl-mdreloc-v850.c +++ b/cpukit/libdl/rtl-mdreloc-v850.c @@ -93,6 +93,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c index 24d1e09048..c99e9f703f 100644 --- a/cpukit/libdl/rtl-obj.c +++ b/cpukit/libdl/rtl-obj.c @@ -137,7 +137,6 @@ rtems_rtl_obj_free (rtems_rtl_obj* obj) rtems_rtl_obj_erase_sections (obj); rtems_rtl_obj_erase_dependents (obj); rtems_rtl_symbol_obj_erase (obj); - rtems_rtl_obj_erase_trampoline (obj); rtems_rtl_obj_free_names (obj); if (obj->sec_num != NULL) free (obj->sec_num); @@ -600,26 +599,6 @@ rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj, } bool -rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj) -{ - if (obj->tramps_size == 0) - return true; - obj->trampoline = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, - obj->tramps_size, - true); - if (obj->trampoline == NULL) - rtems_rtl_set_error (ENOMEM, "no memory for the trampoline"); - obj->tramp_brk = obj->trampoline; - return obj->trampoline != NULL; -} - -void -rtems_rtl_obj_erase_trampoline (rtems_rtl_obj* obj) -{ - rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj->trampoline); -} - -bool rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents) { rtems_rtl_obj_depends* depends; @@ -828,6 +807,12 @@ rtems_rtl_obj_bss_size (const rtems_rtl_obj* obj) return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_BSS); } +size_t +rtems_rtl_obj_tramp_size (const rtems_rtl_obj* obj) +{ + return obj->tramp_slots * obj->tramp_slot_size; +} + uint32_t rtems_rtl_obj_bss_alignment (const rtems_rtl_obj* obj) { @@ -919,10 +904,10 @@ rtems_rtl_obj_synchronize_cache (rtems_rtl_obj* obj) size); } - if (obj->trampoline != NULL) + if (obj->tramp_base != NULL) { - rtems_cache_instruction_sync_after_code_change(obj->trampoline, - obj->tramps_size); + rtems_cache_instruction_sync_after_code_change(obj->tramp_base, + obj->tramp_size); } } @@ -1047,6 +1032,7 @@ rtems_rtl_obj_sections_locate (uint32_t mask, { base_offset = rtems_rtl_obj_align (base_offset, sect->alignment); sect->base = base + base_offset; + base_offset += sect->size; } if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) @@ -1055,9 +1041,6 @@ rtems_rtl_obj_sections_locate (uint32_t mask, order, sect->name, sect->base, sect->size, sect->flags, sect->alignment, sect->link); - if (sect->base) - base_offset += sect->size; - ++order; node = rtems_chain_first (sections); @@ -1069,34 +1052,95 @@ rtems_rtl_obj_sections_locate (uint32_t mask, } } -bool -rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, - int fd, - rtems_rtl_obj_sect_handler handler, - void* data) +static void +rtems_rtl_obj_set_sizes (rtems_rtl_obj* obj) { size_t text_size; + size_t tramp_size; size_t const_size; size_t eh_size; size_t data_size; size_t bss_size; - text_size = rtems_rtl_obj_text_size (obj) + rtems_rtl_obj_const_alignment (obj); - const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_eh_alignment (obj); - eh_size = rtems_rtl_obj_eh_size (obj) + rtems_rtl_obj_data_alignment (obj); - data_size = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_bss_alignment (obj); - bss_size = rtems_rtl_obj_bss_size (obj); + /* + * The allocator may not align memory to the required boundary. Add + * the alignment size to the size allocated. + */ + text_size = rtems_rtl_obj_text_size (obj) + rtems_rtl_obj_text_alignment (obj); + tramp_size = rtems_rtl_obj_tramp_size (obj); + if (tramp_size != 0) + tramp_size += rtems_rtl_obj_tramp_alignment (obj); + const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_const_alignment (obj); + eh_size = rtems_rtl_obj_eh_size (obj) + rtems_rtl_obj_eh_alignment (obj); + data_size = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_data_alignment (obj); + bss_size = rtems_rtl_obj_bss_size (obj) + rtems_rtl_obj_bss_alignment (obj); /* * Set the sizes held in the object data. We need this for a fast reference. */ - obj->text_size = text_size; + obj->text_size = text_size + tramp_size; + obj->tramp_size = tramp_size; obj->const_size = const_size; obj->data_size = data_size; obj->eh_size = eh_size; obj->bss_size = bss_size; + obj->exec_size = text_size + const_size + eh_size + data_size + bss_size; +} + +static void +rtems_rtl_obj_print_sizes (rtems_rtl_obj* obj, const char* label) +{ + if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) + { + printf ("rtl: %s sect: text - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->text_base, obj->text_size, rtems_rtl_obj_text_alignment (obj)); + printf ("rtl: %s sect: tramp - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->tramp_base, obj->tramp_size, rtems_rtl_obj_tramp_alignment (obj)); + printf ("rtl: %s sect: const - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->const_base, obj->const_size, rtems_rtl_obj_const_alignment (obj)); + printf ("rtl: %s sect: eh - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->eh_base, obj->eh_size, rtems_rtl_obj_eh_alignment (obj)); + printf ("rtl: %s sect: data - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->data_base, obj->data_size, rtems_rtl_obj_data_alignment (obj)); + printf ("rtl: %s sect: bss - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->bss_base, obj->bss_size, rtems_rtl_obj_bss_alignment (obj)); + } +} + +static void +rtems_rtl_obj_locate (rtems_rtl_obj* obj) +{ /* + * Locate all text, data and bss sections in seperate operations so each type of + * section is grouped together. + */ + rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_TEXT, + rtems_rtl_alloc_text_tag (), + obj, obj->text_base); + rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_CONST, + rtems_rtl_alloc_const_tag (), + obj, obj->const_base); + rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_EH, + rtems_rtl_alloc_eh_tag (), + obj, obj->eh_base); + rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_DATA, + rtems_rtl_alloc_data_tag (), + obj, obj->data_base); + rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_BSS, + rtems_rtl_alloc_bss_tag (), + obj, obj->bss_base); +} + +bool +rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, + int fd, + rtems_rtl_obj_sect_handler handler, + void* data) +{ + rtems_rtl_obj_set_sizes (obj); + + /* * Perform any specific allocations for sections. */ if (handler != NULL) @@ -1116,33 +1160,28 @@ rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, * Let the allocator manage the actual allocation. The user can use the * standard heap or provide a specific allocator with memory protection. */ - if (!rtems_rtl_alloc_module_new (&obj->text_base, text_size, - &obj->const_base, const_size, - &obj->eh_base, eh_size, - &obj->data_base, data_size, - &obj->bss_base, bss_size)) + if (!rtems_rtl_alloc_module_new (&obj->text_base, obj->text_size, + &obj->const_base, obj->const_size, + &obj->eh_base, obj->eh_size, + &obj->data_base, obj->data_size, + &obj->bss_base, obj->bss_size)) { obj->exec_size = 0; rtems_rtl_set_error (ENOMEM, "no memory to load obj"); return false; } - obj->exec_size = text_size + const_size + eh_size + data_size + bss_size; - - if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) + /* + * Set the trampoline base if there are trampolines + */ + if (obj->tramp_size != 0) { - printf ("rtl: load sect: text - b:%p s:%zi a:%" PRIu32 "\n", - obj->text_base, text_size, rtems_rtl_obj_text_alignment (obj)); - printf ("rtl: load sect: const - b:%p s:%zi a:%" PRIu32 "\n", - obj->const_base, const_size, rtems_rtl_obj_const_alignment (obj)); - printf ("rtl: load sect: eh - b:%p s:%zi a:%" PRIu32 "\n", - obj->eh_base, eh_size, rtems_rtl_obj_eh_alignment (obj)); - printf ("rtl: load sect: data - b:%p s:%zi a:%" PRIu32 "\n", - obj->data_base, data_size, rtems_rtl_obj_data_alignment (obj)); - printf ("rtl: load sect: bss - b:%p s:%zi a:%" PRIu32 "\n", - obj->bss_base, bss_size, rtems_rtl_obj_bss_alignment (obj)); + obj->tramp_base = obj->tramp_brk = + obj->text_base + obj->text_size - obj->tramp_size; } + rtems_rtl_obj_print_sizes (obj, "alloc"); + /* * Determine the load order. */ @@ -1153,24 +1192,48 @@ rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_BSS, obj); /* - * Locate all text, data and bss sections in seperate operations so each type of - * section is grouped together. + * Locate the sections to the allocated section bases */ - rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_TEXT, - rtems_rtl_alloc_text_tag (), - obj, obj->text_base); - rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_CONST, - rtems_rtl_alloc_const_tag (), - obj, obj->const_base); - rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_EH, - rtems_rtl_alloc_eh_tag (), - obj, obj->eh_base); - rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_DATA, - rtems_rtl_alloc_data_tag (), - obj, obj->data_base); - rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_BSS, - rtems_rtl_alloc_bss_tag (), - obj, obj->bss_base); + rtems_rtl_obj_locate (obj); + + return true; +} + +bool +rtems_rtl_obj_resize_sections (rtems_rtl_obj* obj) +{ + rtems_rtl_obj_set_sizes (obj); + + /* + * Let the allocator manage the resizing. + */ + if (!rtems_rtl_alloc_module_resize (&obj->text_base, obj->text_size, + &obj->const_base, obj->const_size, + &obj->eh_base, obj->eh_size, + &obj->data_base, obj->data_size, + &obj->bss_base, obj->bss_size)) + { + rtems_rtl_obj_free (obj); + obj->exec_size = 0; + rtems_rtl_set_error (ENOMEM, "no memory resize obj"); + return false; + } + + /* + * Set the trampoline base if there are trampolines + */ + if (obj->tramp_size != 0) + { + obj->tramp_base = obj->tramp_brk = + obj->text_base + obj->text_size - obj->tramp_size; + } + + rtems_rtl_obj_print_sizes (obj, "resize"); + + /* + * Locate the sections to the allocated section bases + */ + rtems_rtl_obj_locate (obj); return true; } diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c index 69de6bad83..18f1e08901 100644 --- a/cpukit/libdl/rtl-shell.c +++ b/cpukit/libdl/rtl-shell.c @@ -572,7 +572,7 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj) rtems_printf (print->printer, "%-*cslots : %zu\n", indent + 4, ' ', slots); rtems_printf (print->printer, "%-*csize : %zu\n", indent + 4, ' ', - obj->tramps_size); + obj->tramp_size); rtems_printf (print->printer, "%-*cslot size : %zu\n", indent + 4, ' ', obj->tramp_size); rtems_printf (print->printer, "%-*cused : %zu\n", indent + 4, ' ', diff --git a/cpukit/libdl/rtl-sym.c b/cpukit/libdl/rtl-sym.c index 5c9c3981df..bd203fd158 100644 --- a/cpukit/libdl/rtl-sym.c +++ b/cpukit/libdl/rtl-sym.c @@ -77,6 +77,22 @@ rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols, &symbol->node); } +static rtems_rtl_tls_offset* +rtems_rtl_symbol_find_tls_offset (size_t index, + rtems_rtl_tls_offset* tls_offsets, + size_t tls_size) +{ + size_t entry; + for (entry = 0; entry < tls_size; ++entry) + { + if (tls_offsets[entry].index == index) + { + return &tls_offsets[entry]; + } + } + return NULL; +} + bool rtems_rtl_symbol_table_open (rtems_rtl_symbols* symbols, size_t buckets) @@ -103,9 +119,11 @@ rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols) } bool -rtems_rtl_symbol_global_add (rtems_rtl_obj* obj, - const unsigned char* esyms, - unsigned int size) +rtems_rtl_symbol_global_add (rtems_rtl_obj* obj, + const unsigned char* esyms, + unsigned int size, + rtems_rtl_tls_offset* tls_offsets, + unsigned int tls_size) { rtems_rtl_symbols* symbols; rtems_rtl_obj_sym* sym; @@ -159,6 +177,9 @@ rtems_rtl_symbol_global_add (rtems_rtl_obj* obj, symbols = rtems_rtl_global_symbols (); + obj->global_syms = count; + + count = 0; s = 0; sym = obj->global_table; @@ -171,24 +192,29 @@ rtems_rtl_symbol_global_add (rtems_rtl_obj* obj, */ union { uint8_t data[sizeof (void*)]; - void* value; + void* voidp; } copy_voidp; + rtems_rtl_tls_offset* tls_off; int b; sym->name = (const char*) &esyms[s]; s += strlen (sym->name) + 1; for (b = 0; b < sizeof (void*); ++b, ++s) copy_voidp.data[b] = esyms[s]; - sym->value = copy_voidp.value; + tls_off = rtems_rtl_symbol_find_tls_offset (count, tls_offsets, tls_size); + if (tls_off == NULL) { + sym->value = copy_voidp.voidp; + } else { + sym->value = (void*) tls_off->offset(); + } if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM)) printf ("rtl: esyms: %s -> %8p\n", sym->name, sym->value); if (rtems_rtl_symbol_global_find (sym->name) == NULL) rtems_rtl_symbol_global_insert (symbols, sym); + ++count; ++sym; } - obj->global_syms = count; - return true; } diff --git a/cpukit/score/src/pheapiterate.c b/cpukit/libdl/rtl-tls.c index 61ecb8fabb..7eb12831eb 100644 --- a/cpukit/score/src/pheapiterate.c +++ b/cpukit/libdl/rtl-tls.c @@ -3,14 +3,17 @@ /** * @file * - * @ingroup RTEMSScoreProtHeap + * @ingroup rtems_rtld * - * @brief This source file contains the implementation of - * _Protected_heap_Iterate(). + * @brief RTEMS Run-Time Link Editor Thread Local Storage + * + * TLS support the RTL. */ /* - * Copyright (c) 2011 embedded brains GmbH & Co. KG + * COPYRIGHT (c) 2023 Chris Johns <chrisj@rtems.org> + * + * Copyright (C) 2023 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,15 +41,13 @@ #include "config.h" #endif -#include <rtems/score/protectedheap.h> +#include "rtl-tls.h" + +#include <rtems/score/cpuimpl.h> +#include <rtems/score/percpu.h> +#include <rtems/score/thread.h> -void _Protected_heap_Iterate( - Heap_Control *heap, - Heap_Block_visitor visitor, - void *visitor_arg -) +void* rtems_rtl_tls_get_base (void) { - _RTEMS_Lock_allocator(); - _Heap_Iterate( heap, visitor, visitor_arg ); - _RTEMS_Unlock_allocator(); + return _CPU_Get_TLS_thread_pointer (&_Thread_Get_executing()->Registers); } diff --git a/cpukit/score/cpu/microblaze/include/rtems/score/cpuatomic.h b/cpukit/libdl/rtl-tls.h index 6dc769b95a..78dc738dd4 100644 --- a/cpukit/score/cpu/microblaze/include/rtems/score/cpuatomic.h +++ b/cpukit/libdl/rtl-tls.h @@ -3,13 +3,15 @@ /** * @file * - * @ingroup RTEMSScoreCPU + * @ingroup rtems_rtld * - * @brief MicroBlaze atomic support + * @brief RTEMS Run-Time Link Editor Thread Local Storage + * + * TLS support the RTL. */ /* - * Copyright (C) 2021 On-Line Applications Research Corporation (OAR) + * COPYRIGHT (c) 2023 Chris Johns <chrisj@rtems.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,9 +35,17 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H +#if !defined (_RTEMS_RTL_TLS_H_) +#define _RTEMS_RTL_TLS_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void* rtems_rtl_tls_get_base (void); -#include <rtems/score/cpustdatomic.h> +#ifdef __cplusplus +} +#endif /* __cplusplus */ -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ +#endif diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c index 21ddb00aac..8250af24c9 100644 --- a/cpukit/libdl/rtl.c +++ b/cpukit/libdl/rtl.c @@ -857,8 +857,10 @@ rtems_rtl_path_prepend (const char* path) } void -rtems_rtl_base_sym_global_add (const unsigned char* esyms, - unsigned int size) +rtems_rtl_base_sym_global_add (const unsigned char* esyms, + unsigned int size, + rtems_rtl_tls_offset* tls_offsets, + unsigned int tls_size) { if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM)) printf ("rtl: adding global symbols, table size %u\n", size); @@ -869,7 +871,7 @@ rtems_rtl_base_sym_global_add (const unsigned char* esyms, return; } - rtems_rtl_symbol_global_add (rtl->base, esyms, size); + rtems_rtl_symbol_global_add (rtl->base, esyms, size, tls_offsets, tls_size); rtems_rtl_unlock (); } diff --git a/cpukit/libfs/src/dosfs/fat.c b/cpukit/libfs/src/dosfs/fat.c index 9229406dec..88b4a2859b 100644 --- a/cpukit/libfs/src/dosfs/fat.c +++ b/cpukit/libfs/src/dosfs/fat.c @@ -93,7 +93,6 @@ fat_buf_release(fat_fs_info_t *fs_info) uint32_t sec_num = fs_info->c.blk_num; bool sec_of_fat = ((sec_num >= fs_info->vol.fat_loc) && (sec_num < fs_info->vol.rdir_loc)); - uint32_t blk = fat_sector_num_to_block_num(fs_info, sec_num); uint32_t blk_ofs = fat_sector_offset_to_block_offset(fs_info, sec_num, 0); @@ -115,6 +114,7 @@ fat_buf_release(fat_fs_info_t *fs_info) for (i = 1; i < fs_info->vol.fats; i++) { rtems_bdbuf_buffer *bd; + uint32_t blk; sec_num = fs_info->c.blk_num + fs_info->vol.fat_length * i, blk = fat_sector_num_to_block_num(fs_info, sec_num); diff --git a/cpukit/libfs/src/dosfs/fat_fat_operations.c b/cpukit/libfs/src/dosfs/fat_fat_operations.c index 24a408f9c7..fe6bbf03ce 100644 --- a/cpukit/libfs/src/dosfs/fat_fat_operations.c +++ b/cpukit/libfs/src/dosfs/fat_fat_operations.c @@ -203,9 +203,9 @@ fat_free_fat_clusters_chain( cur_cln = next_cln; } - fs_info->vol.next_cl = chain; - if (fs_info->vol.free_cls != FAT_UNDEFINED_VALUE) - fs_info->vol.free_cls += freed_cls_cnt; + fs_info->vol.next_cl = chain; + if (fs_info->vol.free_cls != FAT_UNDEFINED_VALUE) + fs_info->vol.free_cls += freed_cls_cnt; fat_buf_release(fs_info); if (rc1 != RC_OK) @@ -356,7 +356,7 @@ fat_set_fat_cluster( if (rc != RC_OK) return rc; - *sec_buf &= 0x00; + *sec_buf = 0x00; *sec_buf |= (uint8_t)((fat16_clv & 0xFF00)>>8); @@ -364,7 +364,7 @@ fat_set_fat_cluster( } else { - *(sec_buf + ofs + 1) &= 0x00; + *(sec_buf + ofs + 1) = 0x00; *(sec_buf + ofs + 1) |= (uint8_t )((fat16_clv & 0xFF00)>>8); } @@ -372,7 +372,7 @@ fat_set_fat_cluster( else { fat16_clv = ((uint16_t )in_val) & FAT_FAT12_MASK; - *(sec_buf + ofs) &= 0x00; + *(sec_buf + ofs) = 0x00; *(sec_buf + ofs) |= (uint8_t)(fat16_clv & 0x00FF); diff --git a/cpukit/libfs/src/dosfs/msdos_create.c b/cpukit/libfs/src/dosfs/msdos_create.c index 26df0451c9..f71969f787 100644 --- a/cpukit/libfs/src/dosfs/msdos_create.c +++ b/cpukit/libfs/src/dosfs/msdos_create.c @@ -202,7 +202,7 @@ msdos_creat_node(const rtems_filesystem_location_info_t *parent_loc, fs_info->fat.vol.bpc, &unused); if (rc != RC_OK) - goto err; + goto error; /* * dot and dotdot entries are identical to new node except the diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c index 4ae2c32415..d9585635d9 100644 --- a/cpukit/libfs/src/dosfs/msdos_dir.c +++ b/cpukit/libfs/src/dosfs/msdos_dir.c @@ -339,14 +339,14 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count) iop->offset = iop->offset + sizeof(struct dirent); cmpltd += (sizeof(struct dirent)); count -= (sizeof(struct dirent)); + } - /* inode number extracted, close fat-file */ - rc = fat_file_close(&fs_info->fat, tmp_fat_fd); - if (rc != RC_OK) - { - msdos_fs_unlock(fs_info); - return rc; - } + /* inode number extracted, close fat-file */ + rc = fat_file_close(&fs_info->fat, tmp_fat_fd); + if (rc != RC_OK) + { + msdos_fs_unlock(fs_info); + return rc; } } diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c index d142968337..e25f292484 100644 --- a/cpukit/libfs/src/dosfs/msdos_file.c +++ b/cpukit/libfs/src/dosfs/msdos_file.c @@ -179,7 +179,7 @@ msdos_file_ftruncate(rtems_libio_t *iop, off_t length) length, &new_length); if (rc == RC_OK && length != new_length) { - fat_file_truncate(&fs_info->fat, fat_fd, old_length); + (void) fat_file_truncate(&fs_info->fat, fat_fd, old_length); errno = ENOSPC; rc = -1; } @@ -223,6 +223,11 @@ msdos_file_sync(rtems_libio_t *iop) } rc = fat_sync(&fs_info->fat); + if (rc != RC_OK) + { + msdos_fs_unlock(fs_info); + return rc; + } msdos_fs_unlock(fs_info); diff --git a/cpukit/libfs/src/dosfs/msdos_misc.c b/cpukit/libfs/src/dosfs/msdos_misc.c index 8bde792ae5..cd59c494ea 100644 --- a/cpukit/libfs/src/dosfs/msdos_misc.c +++ b/cpukit/libfs/src/dosfs/msdos_misc.c @@ -288,7 +288,6 @@ msdos_long_to_short(rtems_dosfs_convert_control *converter, &codepage_name_len); if (eno == EINVAL) { - eno = 0; type = MSDOS_NAME_LONG; } else @@ -1304,7 +1303,6 @@ static int msdos_find_file_in_directory ( const uint8_t *filename_converted, const size_t name_len_for_compare, - const size_t name_len_for_save, const msdos_name_type_t name_type, msdos_fs_info_t *fs_info, fat_file_fd_t *fat_fd, @@ -1747,6 +1745,8 @@ msdos_add_file ( /* Get position of short file name entry */ ret = msdos_get_pos(fs_info, fat_fd, bts2rd, short_file_offset, &dir_pos->sname); + if (ret != RC_OK) + return ret; /* * Handle the entry writes. @@ -1918,7 +1918,6 @@ msdos_find_name_in_fat_file ( retval = msdos_find_file_in_directory ( buffer, name_len_for_compare, - name_len_for_save, name_type, fs_info, fat_fd, diff --git a/cpukit/libfs/src/dosfs/msdos_mknod.c b/cpukit/libfs/src/dosfs/msdos_mknod.c index 934805c5f1..8fe01e4985 100644 --- a/cpukit/libfs/src/dosfs/msdos_mknod.c +++ b/cpukit/libfs/src/dosfs/msdos_mknod.c @@ -44,7 +44,7 @@ int msdos_mknod( ) { int rc = RC_OK; - fat_file_type_t type = 0; + fat_file_type_t type = FAT_DIRECTORY; /* * Figure out what type of msdos node this is. diff --git a/cpukit/libfs/src/imfs/imfs_load_tar.c b/cpukit/libfs/src/imfs/imfs_load_tar.c index ec651d820a..18c5366b56 100644 --- a/cpukit/libfs/src/imfs/imfs_load_tar.c +++ b/cpukit/libfs/src/imfs/imfs_load_tar.c @@ -45,7 +45,7 @@ int rtems_tarfs_load( const char *mountpoint, - uint8_t *tar_image, + const void *tar_image, size_t tar_size ) { @@ -57,6 +57,7 @@ int rtems_tarfs_load( size_t len; Untar_HeaderContext ctx; unsigned long ptr; + const uint8_t *image; len = strlen( mountpoint ); if ( len >= sizeof( buf ) - UNTAR_FILE_NAME_SIZE - 2 ) { @@ -82,11 +83,12 @@ int rtems_tarfs_load( } ptr = 0; + image = tar_image; while ( ptr + 512 <= tar_size ) { int retval; - retval = Untar_ProcessHeader( &ctx, (const char *) &tar_image[ ptr ] ); + retval = Untar_ProcessHeader( &ctx, (const char *) &image[ ptr ] ); if ( retval != UNTAR_SUCCESSFUL ) { return -1; } @@ -97,7 +99,7 @@ int rtems_tarfs_load( retval = IMFS_make_linearfile( ctx.file_path, ctx.mode, - &tar_image[ ptr ], + &image[ ptr ], ctx.file_size ); if ( retval != 0 ) { diff --git a/cpukit/libfs/src/imfs/imfs_memfile.c b/cpukit/libfs/src/imfs/imfs_memfile.c index 66c67c6ba0..3930fd6ae5 100644 --- a/cpukit/libfs/src/imfs/imfs_memfile.c +++ b/cpukit/libfs/src/imfs/imfs_memfile.c @@ -638,7 +638,6 @@ ssize_t IMFS_memfile_write( fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src ); #endif memcpy( &(*block_ptr)[ 0 ], src, my_length ); - my_length = 0; copied += to_copy; } diff --git a/cpukit/libfs/src/jffs2/include/linux/mutex.h b/cpukit/libfs/src/jffs2/include/linux/mutex.h index be8709f125..cc82a3f17a 100644 --- a/cpukit/libfs/src/jffs2/include/linux/mutex.h +++ b/cpukit/libfs/src/jffs2/include/linux/mutex.h @@ -1,19 +1,30 @@ #ifndef __LINUX_MUTEX_H #define __LINUX_MUTEX_H -#include <rtems/thread.h> - -struct mutex { rtems_mutex r_m; }; +struct mutex { }; #define DEFINE_MUTEX(m) struct mutex m -#define mutex_init(m) rtems_mutex_init(&(m)->r_m, "JFFS2 Mutex"); - -#define mutex_lock(m) rtems_mutex_lock(&(m)->r_m); - -#define mutex_lock_interruptible(m) ({ mutex_lock(m); 0; }) - -#define mutex_unlock(m) rtems_mutex_unlock(&(m)->r_m); +static inline void mutex_init(struct mutex *m) +{ + (void) m; +} + +static inline void mutex_lock(struct mutex *m) +{ + (void) m; +} + +static inline int mutex_lock_interruptible(struct mutex *m) +{ + (void) m; + return 0; +} + +static inline void mutex_unlock(struct mutex *m) +{ + (void) m; +} #define mutex_is_locked(m) 1 diff --git a/cpukit/libfs/src/jffs2/include/linux/rwsem.h b/cpukit/libfs/src/jffs2/include/linux/rwsem.h index 9db6d45ad2..e59e1cede3 100644 --- a/cpukit/libfs/src/jffs2/include/linux/rwsem.h +++ b/cpukit/libfs/src/jffs2/include/linux/rwsem.h @@ -1,20 +1,16 @@ #ifndef __LINUX_RWSEM_H__ #define __LINUX_RWSEM_H__ -#include <pthread.h> +struct rw_semaphore {}; -struct rw_semaphore { - pthread_rwlock_t lock; -}; +#define init_rwsem(rwsem) -#define init_rwsem(rwsem) pthread_rwlock_init(&(rwsem)->lock, NULL) +#define down_read(rwsem) -#define down_read(rwsem) pthread_rwlock_rdlock(&(rwsem)->lock) +#define down_write(rwsem) -#define down_write(rwsem) pthread_rwlock_wrlock(&(rwsem)->lock) +#define up_read(rwsem) -#define up_read(rwsem) pthread_rwlock_unlock(&(rwsem)->lock) - -#define up_write(rwsem) pthread_rwlock_unlock(&(rwsem)->lock) +#define up_write(rwsem) #endif /* __LINUX_RWSEM_H__ */ diff --git a/cpukit/libfs/src/jffs2/include/linux/workqueue.h b/cpukit/libfs/src/jffs2/include/linux/workqueue.h index 45a2942bfc..9811c7cd3e 100644 --- a/cpukit/libfs/src/jffs2/include/linux/workqueue.h +++ b/cpukit/libfs/src/jffs2/include/linux/workqueue.h @@ -2,6 +2,7 @@ #define __LINUX_WORKQUEUE_H__ #include <rtems/chain.h> +#include <linux/mutex.h> struct work_struct { rtems_chain_node node; }; @@ -11,7 +12,6 @@ struct work_struct { rtems_chain_node node; }; }) #define INIT_DELAYED_WORK(delayed_work, delayed_workqueue_callback) ({ \ - _Chain_Initialize_node(&(delayed_work)->work.node); \ (delayed_work)->callback = delayed_workqueue_callback; \ }) @@ -20,8 +20,12 @@ struct work_struct { rtems_chain_node node; }; typedef void (*work_callback_t)(struct work_struct *work); struct delayed_work { struct work_struct work; - uint64_t execution_time; + struct mutex dw_mutex; + volatile bool pending; + volatile uint64_t execution_time; work_callback_t callback; + /* Superblock provided for locking */ + struct super_block *sb; }; #define to_delayed_work(work) RTEMS_CONTAINER_OF(work, struct delayed_work, work) diff --git a/cpukit/libfs/src/jffs2/src/fs-rtems.c b/cpukit/libfs/src/jffs2/src/fs-rtems.c index 59d03effe6..029cba6618 100644 --- a/cpukit/libfs/src/jffs2/src/fs-rtems.c +++ b/cpukit/libfs/src/jffs2/src/fs-rtems.c @@ -579,6 +579,9 @@ static int rtems_jffs2_ioctl( break; case RTEMS_JFFS2_FORCE_GARBAGE_COLLECTION: eno = -jffs2_garbage_collect_pass(&inode->i_sb->jffs2_sb); + if (!eno) { + eno = -jffs2_flush_wbuf_pad(&inode->i_sb->jffs2_sb); + } break; default: eno = EINVAL; @@ -1066,6 +1069,7 @@ static void rtems_jffs2_fsunmount(rtems_filesystem_mount_table_entry_t *mt_entry /* Flush any pending writes */ if (!sb_rdonly(&fs_info->sb)) { jffs2_flush_wbuf_gc(c, 0); + jffs2_flush_wbuf_pad(c); } #endif @@ -1241,39 +1245,41 @@ rtems_chain_control delayed_work_chain; /* Lock for protecting the delayed work chain */ struct mutex delayed_work_mutex; -void jffs2_queue_delayed_work(struct delayed_work *work, int delay_ms) +/* + * All delayed work structs are initialized and added to the chain during FS + * init. Must be called with no locks held + */ +static void add_delayed_work_to_chain(struct delayed_work *work) { + /* Initialize delayed work */ + mutex_init(&work->dw_mutex); + work->pending = false; + _Chain_Initialize_node(&work->work.node); \ + work->callback = NULL; + mutex_lock(&delayed_work_mutex); - if (rtems_chain_is_node_off_chain(&work->work.node)) { - work->execution_time = rtems_clock_get_uptime_nanoseconds() + delay_ms*1000000; - rtems_chain_append(&delayed_work_chain, &work->work.node); - } + rtems_chain_append_unprotected(&delayed_work_chain, &work->work.node); mutex_unlock(&delayed_work_mutex); } -static void jffs2_remove_delayed_work(struct delayed_work *dwork) +void jffs2_queue_delayed_work(struct delayed_work *work, int delay_ms) { - struct delayed_work* work; - rtems_chain_node* node; - - mutex_lock(&delayed_work_mutex); - if (rtems_chain_is_node_off_chain(&dwork->work.node)) { - mutex_unlock(&delayed_work_mutex); - return; + mutex_lock(&work->dw_mutex); + if (!work->pending) { + work->execution_time = rtems_clock_get_uptime_nanoseconds(); + work->execution_time += delay_ms*1000000; + work->pending = true; } + mutex_unlock(&work->dw_mutex); +} - node = rtems_chain_first(&delayed_work_chain); - while (!rtems_chain_is_tail(&delayed_work_chain, node)) { - work = (struct delayed_work*) node; - rtems_chain_node* next_node = rtems_chain_next(node); - if (work == dwork) { - rtems_chain_extract(node); - mutex_unlock(&delayed_work_mutex); - return; - } - node = next_node; - } +/* Clean up during FS unmount */ +static void jffs2_remove_delayed_work(struct delayed_work *dwork) +{ + mutex_lock(&delayed_work_mutex); + rtems_chain_extract_unprotected(&dwork->work.node); mutex_unlock(&delayed_work_mutex); + /* Don't run pending delayed work, this will happen during unmount */ } static void process_delayed_work(void) @@ -1291,15 +1297,27 @@ static void process_delayed_work(void) node = rtems_chain_first(&delayed_work_chain); while (!rtems_chain_is_tail(&delayed_work_chain, node)) { work = (struct delayed_work*) node; - rtems_chain_node* next_node = rtems_chain_next(node); - if (rtems_clock_get_uptime_nanoseconds() >= work->execution_time) { - rtems_chain_extract(node); - work->callback(&work->work); + node = rtems_chain_next(node); + + if (!work->pending) { + continue; + } + + if (rtems_clock_get_uptime_nanoseconds() < work->execution_time) { + continue; } - node = next_node; + + mutex_lock(&work->dw_mutex); + work->pending = false; + mutex_unlock(&work->dw_mutex); + + rtems_jffs2_do_lock(work->sb); + work->callback(&work->work); + rtems_jffs2_do_unlock(work->sb); } mutex_unlock(&delayed_work_mutex); } + /* Task for processing delayed work */ static rtems_task delayed_work_task( rtems_task_argument unused @@ -1308,7 +1326,7 @@ static rtems_task delayed_work_task( (void)unused; while (1) { process_delayed_work(); - sleep(1); + usleep(1); } } @@ -1369,6 +1387,12 @@ int rtems_jffs2_initialize( if (err == 0) { sb = &fs_info->sb; c = JFFS2_SB_INFO(sb); +#ifdef CONFIG_JFFS2_FS_WRITEBUFFER + c->wbuf_dwork.sb = sb; + add_delayed_work_to_chain(&c->wbuf_dwork); +#endif + spin_lock_init(&c->erase_completion_lock); + spin_lock_init(&c->inocache_lock); c->mtd = NULL; rtems_recursive_mutex_init(&sb->s_mutex, RTEMS_FILESYSTEM_TYPE_JFFS2); } @@ -1455,6 +1479,9 @@ int rtems_jffs2_initialize( return 0; } else { if (fs_info != NULL) { +#ifdef CONFIG_JFFS2_FS_WRITEBUFFER + jffs2_remove_delayed_work(&c->wbuf_dwork); +#endif free(c->mtd); c->mtd = NULL; rtems_jffs2_free_fs_info(fs_info, do_mount_fs_was_successful); @@ -1503,6 +1530,8 @@ static struct _inode *new_inode(struct super_block *sb) inode->i_cache_next = NULL; // Newest inode, about to be cached + mutex_init(&JFFS2_INODE_INFO(inode)->sem); + // Add to the icache for (cached_inode = sb->s_root; cached_inode != NULL; cached_inode = cached_inode->i_cache_next) { @@ -1619,8 +1648,14 @@ void jffs2_iput(struct _inode *i) static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) { - memset(f, 0, sizeof(*f)); - mutex_init(&f->sem); + /* These must be set manually to preserve other members */ + f->highest_version = 0; + f->fragtree = RB_ROOT; + f->metadata = NULL; + f->dents = NULL; + f->target = NULL; + f->flags = 0; + f->usercompr = 0; } static void jffs2_clear_inode (struct _inode *inode) diff --git a/cpukit/libfs/src/jffs2/src/jffs2_fs_sb.h b/cpukit/libfs/src/jffs2/src/jffs2_fs_sb.h index 4ee43a6f30..7960f92f85 100644 --- a/cpukit/libfs/src/jffs2/src/jffs2_fs_sb.h +++ b/cpukit/libfs/src/jffs2/src/jffs2_fs_sb.h @@ -75,6 +75,9 @@ struct jffs2_sb_info { uint32_t bad_size; uint32_t sector_size; uint32_t unchecked_size; +#ifdef __rtems__ + uint32_t obsolete_size; +#endif uint32_t nr_free_blocks; uint32_t nr_erasing_blocks; diff --git a/cpukit/libfs/src/jffs2/src/os-rtems.h b/cpukit/libfs/src/jffs2/src/os-rtems.h index 63841a5e50..4bc6f5df13 100644 --- a/cpukit/libfs/src/jffs2/src/os-rtems.h +++ b/cpukit/libfs/src/jffs2/src/os-rtems.h @@ -100,6 +100,10 @@ struct _inode { struct super_block { struct jffs2_sb_info jffs2_sb; + /* + * If granular locking is ever enabled for JFFS2, the inode cache + * (s_root) needs to be protected due to NAND delayed writes. + */ struct _inode * s_root; rtems_jffs2_flash_control *s_flash_control; rtems_jffs2_compressor_control *s_compressor_control; diff --git a/cpukit/libfs/src/jffs2/src/scan.c b/cpukit/libfs/src/jffs2/src/scan.c index 10663feb1f..8ac4a40414 100644 --- a/cpukit/libfs/src/jffs2/src/scan.c +++ b/cpukit/libfs/src/jffs2/src/scan.c @@ -264,14 +264,32 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } #endif if (c->nr_erasing_blocks) { +#ifdef __rtems__ + if (c->obsolete_size != c->dirty_size) { +#endif if (!c->used_size && !c->unchecked_size && ((c->nr_free_blocks+empty_blocks+bad_blocks) != c->nr_blocks || bad_blocks == c->nr_blocks)) { pr_notice("Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); pr_notice("empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n", empty_blocks, bad_blocks, c->nr_blocks); +#ifdef __rtems__ + pr_notice("nr_erasing_blocks %d, used 0x%x, dirty 0x%x, wasted 0x%x, free 0x%x, erasing 0x%x, bad 0x%x, obsolete 0x%x, unchecked 0x%x\n", + c->nr_erasing_blocks, + c->used_size, + c->dirty_size, + c->wasted_size, + c->free_size, + c->erasing_size, + c->bad_size, + c->obsolete_size, + c->unchecked_size); +#endif ret = -EIO; goto out; } +#ifdef __rtems__ + } +#endif spin_lock(&c->erase_completion_lock); jffs2_garbage_collect_trigger(c); spin_unlock(&c->erase_completion_lock); @@ -646,6 +664,9 @@ scan_more: sizeof(struct jffs2_unknown_node), jeb->offset, c->sector_size, ofs, sizeof(*node)); +#ifdef __rtems__ + c->obsolete_size += (jeb->offset + c->sector_size - ofs); +#endif if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs))) return err; break; @@ -796,6 +817,9 @@ scan_more: if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen))))) return err; ofs += PAD(je32_to_cpu(node->totlen)); +#ifdef __rtems__ + c->obsolete_size += PAD(je32_to_cpu(node->totlen)); +#endif continue; } diff --git a/cpukit/libmisc/regulator/regulator.c b/cpukit/libmisc/regulator/regulator.c new file mode 100644 index 0000000000..97a48be4f5 --- /dev/null +++ b/cpukit/libmisc/regulator/regulator.c @@ -0,0 +1,680 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @brief Regulator Library Implementation + */ + +/* + * Copyright (C) 2022 On-Line Applications Research Corporation (OAR) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdlib.h> + +#include <rtems.h> +#include <rtems/regulator.h> +#include <string.h> + +#include <rtems/regulatorimpl.h> + +/** + * @ingroup RegulatorInternalAPI + * + * This method is the body for the task which delivers the output for + * this regulator instance at the configured rate. + * + * @param[in] arg points to the regulator instance this thread + * is associated with + * + * @note The argument passed in cannot be NULL if the + * rtems_regulator_create worked. + */ +static rtems_task _Regulator_Output_task_body( + rtems_task_argument arg +) +{ + _Regulator_Control *the_regulator = (_Regulator_Control *)arg; + rtems_status_code sc; + size_t to_dequeue; + _Regulator_Message_t regulator_message; + size_t regulator_message_size; + bool release_it; + + the_regulator->delivery_thread_is_running = true; + + /** + * This thread uses a rate monotonic period object instance. A rate + * monotonic period object must be created by the thread using it. + * It can be deleted by any thread which simplifies clean up. + * + * The rate_monotonic_create() call can fail if the application + * is incorrectly configured. This thread has no way to report the + * failure. If it continues with an invalid id, then the thread will + * not block on the period and spin continuously consuming CPU. The only + * alternatives are to invoke rtems_fatal_error_occurred() or silently + * exit the thread. + */ + sc = rtems_rate_monotonic_create( + rtems_build_name('P', 'E', 'R', 'D'), + &the_regulator->delivery_thread_period_id + ); + if (sc != RTEMS_SUCCESSFUL) { + goto exit_delivery_thread; + } + + /** + * Loop on the rate_monotonic_period() based on the specified period. + */ + while (1) { + sc = rtems_rate_monotonic_period( + the_regulator->delivery_thread_period_id, + the_regulator->Attributes.delivery_thread_period + ); + _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL); + + /** + * If the delivery thread has been requested to exit, then + * quit processing messages, break out of this loop, and exit + * this thread. + */ + if (the_regulator->delivery_thread_request_exit) { + break; + } + + /** + * Loop for the configured number of messages to deliver per period. + * If we reach the point, there are no more messages, block for the + * rest of this period. If there are messages, deliver them. + */ + for (to_dequeue = 0; + to_dequeue < the_regulator->Attributes.maximum_to_dequeue_per_period; + to_dequeue++) { + regulator_message_size = sizeof(_Regulator_Message_t); + sc = rtems_message_queue_receive( + the_regulator->queue_id, + ®ulator_message, + ®ulator_message_size, + RTEMS_NO_WAIT, + 0 + ); + _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL); + if (sc != RTEMS_SUCCESSFUL) { + break; + } + + release_it = the_regulator->Attributes.deliverer( + the_regulator->Attributes.deliverer_context, + regulator_message.buffer, + regulator_message.length + ); + + the_regulator->Statistics.delivered++; + + /** + * The message was successfully delivered. If the delivery function + * wants the buffer returned, do it now. The delivery to the Destination + * may involve handing the buffer off to something like DMA + * and need to wait for it to complete before releasing the buffer. + * + * Note that this is the underlying RTEMS service + * used by @a rtems_regulator_obtain_buffer() and @a + * rtems_regulator_release_buffer(). + */ + if (release_it == true) { + the_regulator->Statistics.released++; + sc = rtems_partition_return_buffer( + the_regulator->messages_partition_id, + regulator_message.buffer + ); + _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL); + } + } + } + + /** + * This thread was requested to exit. Do so. + */ +exit_delivery_thread: + the_regulator->delivery_thread_is_running = false; + the_regulator->delivery_thread_has_exited = true; + + (void) rtems_rate_monotonic_delete(the_regulator->delivery_thread_period_id); + + rtems_task_exit(); +} + +/** + * @ingroup RegulatorInternalAPI + * + * This method frees the resources associated with a regulator instance. + * The resources are freed in the opposite of the order in which they are + * allocated. This is used on error cases in @a rtems_regulator_create() and in + * @a rtems_regulator_delete(). + * + * @param[in] the_regulator is the instance to operate upon + * @param[in] ticks is the length of time to wait for the delivery thread + * to exit + * + * @return This method returns true is successful and false on timeout. + */ +static bool _Regulator_Free_helper( + _Regulator_Control *the_regulator, + rtems_interval ticks +) +{ + rtems_status_code sc; + + + /* + * If the output thread has not started running, then we can just delete it. + */ + + if (ticks == 0 || the_regulator->delivery_thread_is_running == false) { + sc = rtems_task_delete(the_regulator->delivery_thread_id); + _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL); + } else { + rtems_interval remaining = ticks; + + the_regulator->delivery_thread_request_exit = true; + + while (1) { + if (the_regulator->delivery_thread_has_exited) { + break; + } + + if (remaining == 0) { + return false; + } + + (void) rtems_task_wake_after(1); + remaining--; + } + } + + /* + * The output thread deletes the rate monotonic period that it created. + */ + + /* + * The regulator's message_queue_storage is implicitly freed by this call. + */ + sc = rtems_message_queue_delete(the_regulator->queue_id); + _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL); + + sc = rtems_partition_delete(the_regulator->messages_partition_id); + _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL); + + if (the_regulator->message_memory) { + free(the_regulator->message_memory); + } + + the_regulator->initialized = 0; + free(the_regulator); + return true; +} + +/** + * @ingroup RegulatorInternalAPI + */ +rtems_status_code rtems_regulator_create( + rtems_regulator_attributes *attributes, + rtems_regulator_instance **regulator +) +{ + _Regulator_Control *the_regulator; + rtems_status_code sc; + size_t alloc_size; + + /** + * Perform basic validation of parameters + */ + if (attributes == NULL) { + return RTEMS_INVALID_ADDRESS; + } + + if (regulator == NULL) { + return RTEMS_INVALID_ADDRESS; + } + + /** + * Verify attributes are OK. Some are checked by calls to object create + * methods. Specifically the following are not checked: + * + * - delivery_thread_priority by rtems_task_create() + * - delivery_thread_stack_size can be any value + */ + if (attributes->deliverer == NULL) { + return RTEMS_INVALID_ADDRESS; + } + + if (attributes->maximum_messages == 0) { + return RTEMS_INVALID_NUMBER; + } + + if (attributes->maximum_message_size == 0) { + return RTEMS_INVALID_SIZE; + } + + if (attributes->maximum_to_dequeue_per_period == 0) { + return RTEMS_INVALID_NUMBER; + } + + if (attributes->delivery_thread_period == 0) { + return RTEMS_INVALID_NUMBER; + } + + /** + * Allocate memory for regulator instance + */ + the_regulator = (_Regulator_Control *) calloc(sizeof(_Regulator_Control), 1); + if (the_regulator == NULL) { + return RTEMS_NO_MEMORY; + } + + /** + * We do NOT want the delivery_thread_id field to be initialized to 0. If the + * @a rtems_task_create() fails, then the field will not be overwritten. + * This results in an attempt to rtems_task_delete(0) during clean + * up. The thread ID of 0 is self which results in the calling thread + * accidentally deleting itself. + */ + the_regulator->delivery_thread_id = (rtems_id) -1; + + /** + * Copy the attributes to an internal area for later use + */ + the_regulator->Attributes = *attributes; + + /** + * Allocate memory for the messages. There is no need to zero out the + * message memory because the user should fill that in. + */ + alloc_size = attributes->maximum_message_size * attributes->maximum_messages; + the_regulator->message_memory = calloc(alloc_size, 1); + if (the_regulator->message_memory == NULL) { + _Regulator_Free_helper(the_regulator, 0); + return RTEMS_NO_MEMORY; + } + + /** + * Associate message memory with a partition so allocations are atomic + */ + sc = rtems_partition_create( + rtems_build_name('P', 'O', 'O', 'L'), + the_regulator->message_memory, + alloc_size, + attributes->maximum_message_size, + RTEMS_DEFAULT_ATTRIBUTES, + &the_regulator->messages_partition_id + ); + if (sc != RTEMS_SUCCESSFUL) { + _Regulator_Free_helper(the_regulator, 0); + return sc; + } + + /** + * Create the message queue between the sender and output thread + */ + RTEMS_MESSAGE_QUEUE_BUFFER(sizeof(_Regulator_Message_t)) regulator_message_t; + + size_t storage_size = sizeof(regulator_message_t) * attributes->maximum_messages; + + the_regulator->message_queue_storage = malloc(storage_size); + if (the_regulator->message_queue_storage == NULL) { + _Regulator_Free_helper(the_regulator, 0); + return RTEMS_NO_MEMORY; + } + + rtems_message_queue_config mq_config = { + .name = rtems_build_name('S', 'N', 'D', 'Q'), + .maximum_pending_messages = attributes->maximum_messages, + .maximum_message_size = sizeof(_Regulator_Message_t), + .storage_area = the_regulator->message_queue_storage, + .storage_size = storage_size, + .storage_free = free, + .attributes = RTEMS_DEFAULT_ATTRIBUTES + }; + sc = rtems_message_queue_construct( + &mq_config, + &the_regulator->queue_id + ); + if (sc != RTEMS_SUCCESSFUL) { + _Regulator_Free_helper(the_regulator, 0); + return sc; + } + + /** + * @note A rate monotonic period object must be created by the thread + * using it. Thus that specific create operation is not included + * in this method. All other resources are allocated here. + */ + + /** + * Create the output thread Using the priority and stack size attributes + * specified by the user. + */ + sc = rtems_task_create( + rtems_build_name('R', 'E', 'G', 'U'), + attributes->delivery_thread_priority, + attributes->delivery_thread_stack_size, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &the_regulator->delivery_thread_id + ); + if (sc != RTEMS_SUCCESSFUL) { + _Regulator_Free_helper(the_regulator, 0); + return sc; + } + + /** + * Start the output thread. + * + * @note There should be no way this call can fail. The task id is valid, + * the regulator output thread entry point is valid, and the argument + * is valid. + */ + the_regulator->delivery_thread_is_running = true; + the_regulator->delivery_thread_request_exit = false; + the_regulator->delivery_thread_has_exited = false; + + sc = rtems_task_start( + the_regulator->delivery_thread_id, + _Regulator_Output_task_body, + (rtems_task_argument) the_regulator + ); + _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL); + + /** + * The regulator is successfully initialized. Set the initialized field + * to reflect this and return the instance pointer. + */ + the_regulator->initialized = REGULATOR_INITIALIZED; + + *regulator = (void *)the_regulator; + + return RTEMS_SUCCESSFUL; +} + +/** + * @brief Validate the regulator instance provided by the user + * + * Validate the regulator instance provided by the user + * + * @param[in] regulator is the instance provided by the user + * @param[inout] status will contain the RTEMS status for this check + * + * @return This method returns a @a _Regulator_Control instance pointer + * which is NULL if invalid or points to the internal regulator + * control structure if valid. + */ +static inline _Regulator_Control *_Regulator_Get( + rtems_regulator_instance *regulator, + rtems_status_code *status +) +{ + _Regulator_Control *the_regulator = (_Regulator_Control *) regulator; + + if (the_regulator == NULL) { + *status = RTEMS_INVALID_ADDRESS; + return NULL; + } + + if (the_regulator->initialized != REGULATOR_INITIALIZED) { + *status = RTEMS_INCORRECT_STATE; + return NULL; + } + + status = RTEMS_SUCCESSFUL; + return the_regulator; +} + +/** + * @ingroup RegulatorInternalAPI + */ +rtems_status_code rtems_regulator_delete( + rtems_regulator_instance *regulator, + rtems_interval ticks +) +{ + _Regulator_Control *the_regulator; + rtems_status_code status; + + /** + * Convert external handle to internal instance pointer + */ + the_regulator = _Regulator_Get(regulator, &status); + if (the_regulator == NULL) { + return status; + } + + /** + * There can be no buffers outstanding + */ + _Regulator_Statistics *stats = &the_regulator->Statistics; + + if (stats->obtained != stats->released ) { + return RTEMS_RESOURCE_IN_USE; + } + + /** + * Free the resources associated with this regulator instance. + */ + bool bc; + bc = _Regulator_Free_helper(the_regulator, ticks); + if (bc == false) { + return RTEMS_TIMEOUT; + } + + return RTEMS_SUCCESSFUL; +} + +/** + * @ingroup RegulatorInternalAPI + * + * Allocate a buffer for the caller using the internal partition. + */ +rtems_status_code rtems_regulator_obtain_buffer( + rtems_regulator_instance *regulator, + void **buffer +) +{ + _Regulator_Control *the_regulator; + rtems_status_code status; + + /** + * Convert external handle to internal instance pointer + */ + the_regulator = _Regulator_Get(regulator, &status); + if (the_regulator == NULL) { + return status; + } + + /** + * Allocate a buffer for the user application from the buffer pool managed + * by an Classic API partition. + */ + status = rtems_partition_get_buffer( + the_regulator->messages_partition_id, + buffer + ); + + if (status == RTEMS_SUCCESSFUL) { + the_regulator->Statistics.obtained++; + } + + return status; +} + +/** + * @ingroup RegulatorInternalAPI + * + * Allocate a buffer for the caller using the internal partition. + */ +rtems_status_code rtems_regulator_release_buffer( + rtems_regulator_instance *regulator, + void *buffer +) +{ + _Regulator_Control *the_regulator; + rtems_status_code status; + + /** + * Convert external handle to internal instance pointer + */ + the_regulator = _Regulator_Get(regulator, &status); + if (the_regulator == NULL) { + return status; + } + + /** + * Deallocate the buffer to the buffer pool managed by a Classic + * API partition. + */ + status = rtems_partition_return_buffer( + the_regulator->messages_partition_id, + buffer + ); + + if (status == RTEMS_SUCCESSFUL) { + the_regulator->Statistics.released++; + } + + return status; +} + +/** + * @ingroup RegulatorInternalAPI + */ +rtems_status_code rtems_regulator_send( + rtems_regulator_instance *regulator, + void *message, + size_t length +) +{ + _Regulator_Control *the_regulator; + rtems_status_code status; + _Regulator_Message_t regulator_message; + + the_regulator = (_Regulator_Control *) regulator; + + /** + * Validate the arguments and ensure the regulator was successfully + * initialized. + */ + if (message == NULL) { + return RTEMS_INVALID_ADDRESS; + } + + if (length == 0) { + return RTEMS_INVALID_NUMBER; + } + + /** + * Convert external handle to internal instance pointer + */ + the_regulator = _Regulator_Get(regulator, &status); + if (the_regulator == NULL) { + return status; + } + + /** + * Place the message pointer and length into a temporary structure. This + * lets the implementation internally send the message by reference and + * have a zero-copy implementation. + */ + regulator_message.buffer = message; + regulator_message.length = length; + + /** + * Send the application message to the output thread for delivery using + * a Classic API message queue. + */ + status = rtems_message_queue_send( + the_regulator->queue_id, + ®ulator_message, + sizeof(_Regulator_Message_t) + ); + if (status != RTEMS_SUCCESSFUL) { + return status; + } + + return status; +} + +/** + * @ingroup RegulatorInternalAPI + */ +rtems_status_code rtems_regulator_get_statistics( + rtems_regulator_instance *regulator, + rtems_regulator_statistics *statistics +) +{ + _Regulator_Control *the_regulator; + rtems_status_code status; + + /** + * Validate the arguments and ensure the regulator was successfully + * initialized. + */ + if (statistics == NULL) { + return RTEMS_INVALID_ADDRESS; + } + + /** + * Convert external handle to internal instance pointer + */ + the_regulator = _Regulator_Get(regulator, &status); + if (the_regulator == NULL) { + return status; + } + + /** + * Zero out the statistics structure in case the get period statistics + * fails below. + */ + memset(statistics, 0, sizeof(rtems_regulator_statistics)); + + /** + * Fill in the caller's statistics structure from information + * maintained by the regulator instance about buffers processed. + */ + statistics->obtained = the_regulator->Statistics.obtained; + statistics->released = the_regulator->Statistics.released; + statistics->delivered = the_regulator->Statistics.delivered; + + /** + * Attempt to retrieve the delivery thread's period's statistics. + * + * NOTE; If the Delivery Thread has not run yet, the period will not + * exist yet. We should not fail for this reason but it is why + * we zeroed out the entire structure above. + */ + (void) rtems_rate_monotonic_get_statistics( + the_regulator->delivery_thread_period_id, + &statistics->period_statistics + ); + + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/libmisc/rtems-fdt/rtems-fdt.c b/cpukit/libmisc/rtems-fdt/rtems-fdt.c index ec8f270eef..9f8d7bfb24 100644 --- a/cpukit/libmisc/rtems-fdt/rtems-fdt.c +++ b/cpukit/libmisc/rtems-fdt/rtems-fdt.c @@ -1165,7 +1165,7 @@ rtems_fdt_get_value (const char* path, } if (length == sizeof (uintptr_t)) - *value = rtems_fdt_get_uint32 (prop); + *value = rtems_fdt_get_uintptr (prop); else *value = 0; diff --git a/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c index cd83aa56d1..9cefc80255 100644 --- a/cpukit/libmisc/shell/shell.c +++ b/cpukit/libmisc/shell/shell.c @@ -806,6 +806,109 @@ void rtems_shell_print_env( #endif /* + * Wait for the string to return or timeout. + */ +static bool rtems_shell_term_wait_for(const int fd, const char* str, const int timeout) +{ + int msec = timeout; + int i = 0; + while (msec-- > 0 && str[i] != '\0') { + char ch[2]; + if (read(fd, &ch[0], 1) == 1) { + fflush(stdout); + if (ch[0] != str[i++]) { + return false; + } + msec = timeout; + } else { + usleep(1000); + } + } + if (msec == 0) { + return false; + } + return true; +} + +/* + * Buffer a string up to the end string + */ +static int rtems_shell_term_buffer_until(const int fd, + char* buf, + const int size, + const char* end, + const int timeout) +{ + int msec = timeout; + int i = 0; + int e = 0; + memset(&buf[0], 0, size); + while (msec-- > 0 && i < size && end[e] != '\0') { + char ch[2]; + if (read(fd, &ch[0], 1) == 1) { + fflush(stdout); + buf[i++] = ch[0]; + if (ch[0] == end[e]) { + e++; + } else { + e = 0; + } + msec = timeout; + } else { + usleep(1000); + } + } + if (msec == 0 || end[e] != '\0') { + return -1; + } + i -= e; + if (i < size) { + buf[i] = '\0'; + } + return i; +} + +/* + * Determine if the terminal has the row and column values + * swapped + * + * https://github.com/tmux/tmux/issues/3457 + * + * Tmux has a bug where the lines and cols are swapped. There is a lag + * in the time it takes to get the fix into code so see if tmux is + * running and which version and work around the bug. + * + * The terminal device needs to have VMIN=0, and VTIME=0 + */ +static bool rtems_shell_term_row_column_swapped(const int fd, const int timeout) { + char buf[64]; + memset(&buf[0], 0, sizeof(buf)); + /* + * CSI > Ps q + * Ps = 0 => DCS > | text ST + */ + fputs("\033[>0q", stdout); + fflush(stdout); + if (rtems_shell_term_wait_for(fd, "\033P>|", timeout)) { + int len = rtems_shell_term_buffer_until(fd, buf, sizeof(buf), "\033\\", timeout); + if (len > 0) { + if (memcmp(buf, "tmux ", 5) == 0) { + static const char* bad_versions[] = { + "3.2", "3.2a", "3.3", "3.3a" + }; + size_t i; + for (i = 0; i < RTEMS_ARRAY_SIZE(bad_versions); ++i) { + if (strcmp(bad_versions[i], buf + 5) == 0) { + return true; + } + } + } + } + } + return false; +} + +/* * Direct method to get the size of an XTERM window. * * If you do not use an XTERM the env variables are not define. @@ -814,6 +917,7 @@ static void rtems_shell_winsize( void ) { const int fd = fileno(stdin); struct winsize ws; + const int timeout = 150; char buf[64]; bool ok = false; int lines = 0; @@ -831,9 +935,6 @@ static void rtems_shell_winsize( void ) term.c_cc[VMIN] = 0; term.c_cc[VTIME] = 0; if (tcsetattr (fd, TCSADRAIN, &term) >= 0) { - int msec = 50; - int len = 0; - int i = 0; memset(&buf[0], 0, sizeof(buf)); /* * https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Miscellaneous @@ -842,35 +943,34 @@ static void rtems_shell_winsize( void ) */ fputs("\033[18t", stdout); fflush(stdout); - while (msec-- > 0 && len < sizeof(buf)) { - char ch[2]; - if (read(fd, &ch[0], 1) == 1) { - buf[len++] = ch[0]; - msec = 50; - } else { - usleep(1000); - } - } - while (i < len) { - static const char resp[] = "\033[8;"; - if (memcmp(resp, &buf[i], sizeof(resp) - 1) == 0) { - i += sizeof(resp) - 1; - while (i < len && buf[i] != ';') { + if (rtems_shell_term_wait_for(fd, "\033[8;", timeout)) { + int len = rtems_shell_term_buffer_until(fd, buf, sizeof(buf), ";", timeout); + if (len > 0) { + int i; + lines = 0; + i = 0; + while (i < len) { lines *= 10; lines += buf[i++] - '0'; } - cols = 0; - ++i; - while (i < len && buf[i] != 't') { - cols *= 10; - cols += buf[i++] - '0'; + len = rtems_shell_term_buffer_until(fd, buf, sizeof(buf), "t", timeout); + if (len > 0) { + cols = 0; + i = 0; + while (i < len) { + cols *= 10; + cols += buf[i++] - '0'; + } + ok = true; } - } else { - i++; } - ok = true; } } + if (rtems_shell_term_row_column_swapped(fd, timeout)) { + int tmp = lines; + lines = cols; + cols = tmp; + } tcsetattr (fd, TCSADRAIN, &cterm); } } diff --git a/cpukit/libmisc/uuid/gen_uuid.c b/cpukit/libmisc/uuid/gen_uuid.c index 71b8a569bb..5601c887c9 100644 --- a/cpukit/libmisc/uuid/gen_uuid.c +++ b/cpukit/libmisc/uuid/gen_uuid.c @@ -171,7 +171,12 @@ static int get_random_fd(void) fcntl(fd, F_SETFD, i | FD_CLOEXEC); } #endif +#ifdef __rtems__ + srand((((time_t)getpid()) << ((sizeof(pid_t)*CHAR_BIT)>>1)) ^ getuid() + ^ tv.tv_sec ^ tv.tv_usec); +#else srand((getpid() << ((sizeof(pid_t)*CHAR_BIT)>>1)) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); +#endif #ifdef DO_JRAND_MIX jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF); jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF); @@ -343,11 +348,17 @@ static int get_clock(uint32_t *clock_high, uint32_t *clock_low, state_fd = open("/var/lib/libuuid/clock.txt", O_RDWR|O_CREAT, 0660); (void) umask(save_umask); +#ifdef __rtems__ + if (state_fd >= 0) { +#endif state_f = fdopen(state_fd, "r+"); if (!state_f) { close(state_fd); state_fd = -1; } +#ifdef __rtems__ + } +#endif } fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; diff --git a/cpukit/score/src/gcovdumpinfo.c b/cpukit/libtest/gcovdumpinfo.c index be00df2db8..87021ad613 100644 --- a/cpukit/score/src/gcovdumpinfo.c +++ b/cpukit/libtest/gcovdumpinfo.c @@ -3,7 +3,7 @@ /** * @file * - * @ingroup RTEMSScoreIO + * @ingroup RTEMSImplGcov * * @brief This source file contains the implementation of _Gcov_Ddump_info(). */ @@ -37,7 +37,7 @@ #include "config.h" #endif -#include <rtems/score/gcov.h> +#include <rtems/test-gcov.h> typedef struct { IO_Put_char put_char; diff --git a/cpukit/score/src/gcovdumpinfobase64.c b/cpukit/libtest/gcovdumpinfobase64.c index b7a9849084..62cd89ac7e 100644 --- a/cpukit/score/src/gcovdumpinfobase64.c +++ b/cpukit/libtest/gcovdumpinfobase64.c @@ -3,7 +3,7 @@ /** * @file * - * @ingroup RTEMSScoreIO + * @ingroup RTEMSImplGcov * * @brief This source file contains the implementation of * _Gcov_Dump_info_base64(). @@ -38,11 +38,13 @@ #include "config.h" #endif -#include <rtems/score/gcov.h> +#include <rtems/test-gcov.h> #include <limits.h> #include <string.h> +#include <rtems/base64.h> + typedef struct { IO_Put_char put_char; void *arg; @@ -77,7 +79,7 @@ static void _Gcov_Base64_encode( int c, void *arg ) if ( index == RTEMS_ARRAY_SIZE( ctx->buf ) - 1 ) { index = 0; - _IO_Base64( + _Base64_Encode( _Gcov_Base64_put_char, ctx, ctx->buf, @@ -100,5 +102,9 @@ void _Gcov_Dump_info_base64( IO_Put_char put_char, void *arg ) ctx.put_char = put_char; ctx.arg = arg; _Gcov_Dump_info( _Gcov_Base64_encode, &ctx ); - _IO_Base64( _Gcov_Base64_put_char, &ctx, ctx.buf, ctx.index, NULL, INT_MAX ); + + if ( ctx.index > 0 ) { + _Base64_Encode( put_char, arg, ctx.buf, ctx.index, NULL, INT_MAX ); + ( *put_char )( '\n', arg ); + } } diff --git a/cpukit/score/src/gcovinfoset.c b/cpukit/libtest/gcovinfoset.c index cb22e8252b..284c993d32 100644 --- a/cpukit/score/src/gcovinfoset.c +++ b/cpukit/libtest/gcovinfoset.c @@ -3,7 +3,7 @@ /** * @file * - * @ingroup RTEMSScoreIO + * @ingroup RTEMSImplGcov * * @brief This source file contains the definition of the gcov information * linker set. @@ -38,6 +38,6 @@ #include "config.h" #endif -#include <rtems/score/gcov.h> +#include <rtems/test-gcov.h> RTEMS_LINKER_ROSET( gcov_info, const struct gcov_info * ); diff --git a/cpukit/libtest/t-test-busy-tick.c b/cpukit/libtest/t-test-busy-tick.c index b7fed247fa..5e45757f24 100644 --- a/cpukit/libtest/t-test-busy-tick.c +++ b/cpukit/libtest/t-test-busy-tick.c @@ -5,7 +5,8 @@ * * @ingroup RTEMSTestFrameworkImpl * - * @brief Implementation of T_get_one_clock_tick_busy(). + * @brief This source file contains the implementation of + * T_get_one_clock_tick_busy(). */ /* diff --git a/cpukit/libtest/t-test-busy.c b/cpukit/libtest/t-test-busy.c index 8583284087..e28fa3e5e4 100644 --- a/cpukit/libtest/t-test-busy.c +++ b/cpukit/libtest/t-test-busy.c @@ -5,7 +5,8 @@ * * @ingroup RTEMSTestFrameworkImpl * - * @brief Implementation of T_busy(). + * @brief This source file contains the implementation of + * T_busy(). */ /* diff --git a/cpukit/libtest/t-test-checks-eno.c b/cpukit/libtest/t-test-checks-eno.c index 5b450ccf99..48736915b4 100644 --- a/cpukit/libtest/t-test-checks-eno.c +++ b/cpukit/libtest/t-test-checks-eno.c @@ -1,6 +1,15 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl * + * @brief This source file contains the implementation of + * T_strerror(), T_check_eno(), and T_check_eno_success(). + */ + +/* * Copyright (C) 2018 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without diff --git a/cpukit/libtest/t-test-checks-psx.c b/cpukit/libtest/t-test-checks-psx.c index 5394ea537a..5d6ec25bda 100644 --- a/cpukit/libtest/t-test-checks-psx.c +++ b/cpukit/libtest/t-test-checks-psx.c @@ -3,7 +3,10 @@ /** * @file * - * @brief + * @ingroup RTEMSTestFrameworkImpl + * + * @brief This source file contains the implementation of + * T_check_psx_error() and T_check_psx_success(). */ /* diff --git a/cpukit/libtest/t-test-checks.c b/cpukit/libtest/t-test-checks.c index 40479a8277..b83e83f1f3 100644 --- a/cpukit/libtest/t-test-checks.c +++ b/cpukit/libtest/t-test-checks.c @@ -1,6 +1,15 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl * + * @brief This source file contains the implementation of various RTEMS Test + * Framework check functions. + */ + +/* * Copyright (C) 2018 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without diff --git a/cpukit/libtest/t-test-hash-sha256.c b/cpukit/libtest/t-test-hash-sha256.c index a9aa4df023..79da4b5dfb 100644 --- a/cpukit/libtest/t-test-hash-sha256.c +++ b/cpukit/libtest/t-test-hash-sha256.c @@ -1,6 +1,15 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file * + * @ingroup RTEMSTestFrameworkImpl + * + * @brief This source file contains the implementation of + * T_report_hash_sha256_update() and T_report_hash_sha256(). + */ + +/* * Copyright (C) 2019, 2021 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without @@ -26,7 +35,6 @@ */ #include <rtems/test.h> -#include <rtems/score/io.h> #include <limits.h> @@ -36,6 +44,8 @@ #include <openssl/sha.h> #endif +#include <rtems/base64.h> + typedef struct { SHA256_CTX sha256; T_putchar putchar; @@ -85,7 +95,7 @@ T_report_hash_sha256_finalize(void) ctx = &T_report_hash_sha256_instance; SHA256_Final(hash, &ctx->sha256); T_printf("Y:ReportHash:SHA256:"); - (void)_IO_Base64url(ctx->putchar, ctx->putchar_arg, hash, + (void)_Base64url_Encode(ctx->putchar, ctx->putchar_arg, hash, sizeof(hash), NULL, INT_MAX); T_printf("\n"); } diff --git a/cpukit/libtest/t-test-interrupt.c b/cpukit/libtest/t-test-interrupt.c index 800724dd93..8796dc0b5a 100644 --- a/cpukit/libtest/t-test-interrupt.c +++ b/cpukit/libtest/t-test-interrupt.c @@ -5,7 +5,8 @@ * * @ingroup RTEMSTestFrameworkImpl * - * @brief Implementation of T_interrupt_test(). + * @brief This source file contains the implementation of + * T_interrupt_test(). */ /* diff --git a/cpukit/libtest/t-test-rtems-context.c b/cpukit/libtest/t-test-rtems-context.c index 351a29a1ca..1405db0c7d 100644 --- a/cpukit/libtest/t-test-rtems-context.c +++ b/cpukit/libtest/t-test-rtems-context.c @@ -1,6 +1,15 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl * + * @brief This source file contains the implementation of + * T_check_task_context(). + */ + +/* * Copyright (C) 2019 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without diff --git a/cpukit/libtest/t-test-rtems-fds.c b/cpukit/libtest/t-test-rtems-fds.c index df5279f585..2b520972d2 100644 --- a/cpukit/libtest/t-test-rtems-fds.c +++ b/cpukit/libtest/t-test-rtems-fds.c @@ -1,6 +1,15 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl * + * @brief This source file contains the implementation of + * T_check_file_descriptors(). + */ + +/* * Copyright (C) 2018 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without diff --git a/cpukit/libtest/t-test-rtems-heap.c b/cpukit/libtest/t-test-rtems-heap.c index ac54e96fc7..2fb069a50e 100644 --- a/cpukit/libtest/t-test-rtems-heap.c +++ b/cpukit/libtest/t-test-rtems-heap.c @@ -1,6 +1,15 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl * + * @brief This source file contains the implementation of + * T_check_heap(). + */ + +/* * Copyright (C) 2018 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without diff --git a/cpukit/libtest/t-test-rtems-measure.c b/cpukit/libtest/t-test-rtems-measure.c index c165fc8f2a..2a2376cd27 100644 --- a/cpukit/libtest/t-test-rtems-measure.c +++ b/cpukit/libtest/t-test-rtems-measure.c @@ -1,6 +1,15 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl * + * @brief This source file contains the implementation of + * T_measure_runtime(). + */ + +/* * Copyright (C) 2018, 2021 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without diff --git a/cpukit/libtest/t-test-rtems-memory.c b/cpukit/libtest/t-test-rtems-memory.c index 1d41192f56..ed0908ae10 100644 --- a/cpukit/libtest/t-test-rtems-memory.c +++ b/cpukit/libtest/t-test-rtems-memory.c @@ -1,5 +1,14 @@ /* SPDX-License-Identifier: BSD-2-Clause */ +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl + * + * @brief This source file contains the implementation of + * T_memory_allocate(), T_memory_deallocate(), and T_memory_action(). + */ + /* * Copyright (C) 2020 embedded brains GmbH & Co. KG * diff --git a/cpukit/libtest/t-test-rtems-objs.c b/cpukit/libtest/t-test-rtems-objs.c index 2eb3db6f7f..ce752424b5 100644 --- a/cpukit/libtest/t-test-rtems-objs.c +++ b/cpukit/libtest/t-test-rtems-objs.c @@ -3,9 +3,10 @@ /** * @file * - * @ingroup RTEMSTestFramework + * @ingroup RTEMSTestFrameworkImpl * - * @brief RTEMS Objects Support for Test Framework + * @brief This source file contains the implementation of the RTEMS objects + * test support. */ /* diff --git a/cpukit/libtest/t-test-rtems-posix-keys.c b/cpukit/libtest/t-test-rtems-posix-keys.c index a26988e27a..65153d3d33 100644 --- a/cpukit/libtest/t-test-rtems-posix-keys.c +++ b/cpukit/libtest/t-test-rtems-posix-keys.c @@ -3,9 +3,10 @@ /** * @file * - * @ingroup RTEMSTestFramework + * @ingroup RTEMSTestFrameworkImpl * - * @brief RTEMS POSIX Keys Support for Test Framework + * @brief This source file contains the implementation of + * T_check_posix_keys(). */ /* diff --git a/cpukit/libtest/t-test-rtems.c b/cpukit/libtest/t-test-rtems.c index 97864c1c76..d4fc6827af 100644 --- a/cpukit/libtest/t-test-rtems.c +++ b/cpukit/libtest/t-test-rtems.c @@ -1,6 +1,15 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl * + * @brief This source file contains the implementation of + * T_putchar_default(), T_check_rsc(), and T_check_rsc_success(). + */ + +/* * Copyright (C) 2018 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without diff --git a/cpukit/libtest/t-test-rtems.h b/cpukit/libtest/t-test-rtems.h index 9d40f1aa9b..d429c4f5bd 100644 --- a/cpukit/libtest/t-test-rtems.h +++ b/cpukit/libtest/t-test-rtems.h @@ -3,9 +3,10 @@ /** * @file * - * @ingroup RTEMSTestFrameworkImpl + * @ingroup RTEMSTestFramework * - * @brief RTEMS Support for Test Framework + * @brief This header file provides the RTEMS-specific API of the RTEMS Test + * Framework. */ /* diff --git a/cpukit/libtest/t-test-thread-switch.c b/cpukit/libtest/t-test-thread-switch.c index 44cd819dd1..99d2d7ee29 100644 --- a/cpukit/libtest/t-test-thread-switch.c +++ b/cpukit/libtest/t-test-thread-switch.c @@ -5,7 +5,8 @@ * * @ingroup RTEMSTestFrameworkImpl * - * @brief Implementation of T_thread_switch_record(). + * @brief This source file contains the implementation of the thread switch + * recorder. */ /* diff --git a/cpukit/libtest/t-test-time.c b/cpukit/libtest/t-test-time.c index 3f953626a5..2acb75f799 100644 --- a/cpukit/libtest/t-test-time.c +++ b/cpukit/libtest/t-test-time.c @@ -1,6 +1,15 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl * + * @brief This source file contains the implementation of the time and ticks + * test support. + */ + +/* * Copyright (C) 2018 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without diff --git a/cpukit/libtest/t-test.c b/cpukit/libtest/t-test.c index 4f3bf56142..1230505edf 100644 --- a/cpukit/libtest/t-test.c +++ b/cpukit/libtest/t-test.c @@ -1,7 +1,16 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl * - * Copyright (C) 2018, 2020 embedded brains GmbH & Co. KG + * @brief This source file contains the core implementation of RTEMS Test + * Framework. + */ + +/* + * Copyright (C) 2018, 2023 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,7 +46,7 @@ #include <stdatomic.h> #ifdef __rtems__ -#include <rtems/score/io.h> +#include <rtems/dev/io.h> #include <rtems/score/percpu.h> #include <rtems/score/smp.h> #include <rtems/score/threadimpl.h> @@ -63,6 +72,7 @@ typedef struct { T_fixture_node *fixtures; T_fixture_node case_fixture; LIST_HEAD(, T_destructor) destructors; + T_remark remarks; T_time case_begin_time; atomic_uint planned_steps; atomic_uint steps; @@ -922,6 +932,23 @@ T_call_destructors(const T_context *ctx) #endif } +static void +T_make_remarks(T_context *ctx) +{ + T_remark *remark; + + remark = ctx->remarks.next; + + while (remark != &ctx->remarks) { + T_remark *current; + + current = remark; + remark = current->next; + current->next = NULL; + T_do_log(ctx, T_QUIET, "R:%s\n", current->remark); + } +} + static T_context * T_do_run_initialize(const T_config *config) { @@ -973,6 +1000,7 @@ T_do_case_begin(T_context *ctx, const T_case_context *tc) ctx->current_case = tc; ctx->fixtures = &ctx->case_fixture; LIST_INIT(&ctx->destructors); + ctx->remarks.next = &ctx->remarks; atomic_store_explicit(&ctx->planned_steps, UINT_MAX, memory_order_relaxed); atomic_store_explicit(&ctx->steps, 0, memory_order_relaxed); @@ -1024,6 +1052,7 @@ T_do_case_end(T_context *ctx, const T_case_context *tc) T_call_destructors(ctx); config = ctx->config; T_actions_backward(config, T_EVENT_CASE_END, tc->name); + T_make_remarks(ctx); planned_steps = atomic_fetch_add_explicit(&ctx->planned_steps, 0, memory_order_relaxed); @@ -1284,6 +1313,18 @@ T_pop_fixture(void) T_do_pop_fixture(&T_instance); } +void +T_add_remark(T_remark *remark) +{ + if (remark->next == NULL) { + T_context *ctx; + + ctx = &T_instance; + remark->next = ctx->remarks.next; + ctx->remarks.next = remark; + } +} + size_t T_get_scope(const char * const * const *desc, char *buf, size_t n, const size_t *second_indices) diff --git a/cpukit/libtest/testbeginend.c b/cpukit/libtest/testbeginend.c index 067155fef3..eca8712b35 100644 --- a/cpukit/libtest/testbeginend.c +++ b/cpukit/libtest/testbeginend.c @@ -1,5 +1,14 @@ /* SPDX-License-Identifier: BSD-2-Clause */ +/** + * @file + * + * @ingroup RTEMSTestFrameworkImpl + * + * @brief This source file contains the implementation of + * rtems_test_begin() and rtems_test_end(). + */ + /* * Copyright (C) 2014, 2018 embedded brains GmbH & Co. KG * @@ -32,6 +41,7 @@ #endif #include <rtems/test-info.h> +#include <rtems/test-printer.h> #include <rtems/bspIo.h> #include <rtems/version.h> diff --git a/cpukit/libtest/testextension.c b/cpukit/libtest/testextension.c index bba6a53a75..483c13ca85 100644 --- a/cpukit/libtest/testextension.c +++ b/cpukit/libtest/testextension.c @@ -30,6 +30,7 @@ #endif #include <rtems/test-info.h> +#include <rtems/test-printer.h> #include <rtems/profiling.h> #include <rtems/bspIo.h> diff --git a/cpukit/libtest/testgcovbspreset.c b/cpukit/libtest/testgcovbspreset.c index 2b1e399bc4..f40102c944 100644 --- a/cpukit/libtest/testgcovbspreset.c +++ b/cpukit/libtest/testgcovbspreset.c @@ -3,7 +3,7 @@ /** * @file * - * @ingroup RTEMSTest + * @ingroup RTEMSTestFrameworkImpl * * @brief This source file contains the implementation of a wrapper for * bsp_reset() which dumps the gcov information using diff --git a/cpukit/libtest/testgcovcpufatalhalt.c b/cpukit/libtest/testgcovcpufatalhalt.c index 55a4c3ee40..9ac242885b 100644 --- a/cpukit/libtest/testgcovcpufatalhalt.c +++ b/cpukit/libtest/testgcovcpufatalhalt.c @@ -3,7 +3,7 @@ /** * @file * - * @ingroup RTEMSTest + * @ingroup RTEMSTestFrameworkImpl * * @brief This source file contains the implementation of a wrapper for * _CPU_Fatal_halt() which dumps the gcov information using diff --git a/cpukit/libtest/testgcovdumpinfo.c b/cpukit/libtest/testgcovdumpinfo.c index 68ce0439fa..9687280e21 100644 --- a/cpukit/libtest/testgcovdumpinfo.c +++ b/cpukit/libtest/testgcovdumpinfo.c @@ -3,14 +3,14 @@ /** * @file * - * @ingroup RTEMSTest + * @ingroup RTEMSTestFrameworkImpl * * @brief This source file contains the implementation of * rtems_test_gcov_dump_info(). */ /* - * Copyright (C) 2021, 2022 embedded brains GmbH & Co. KG + * Copyright (C) 2021, 2023 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,14 +40,26 @@ #include <rtems/test-info.h> -#include <rtems/score/gcov.h> +#include <rtems/test-gcov.h> #include <rtems/score/isrlock.h> +#include <rtems/score/hash.h> #include <rtems/bspIo.h> ISR_LOCK_DEFINE( static, gcov_dump_lock, "gcov dump" ); static bool gcov_dump_done; +static Hash_Context gcov_hash; + +static void gcov_put_char( int c, void *arg ) +{ + uint8_t byte; + + rtems_put_char( c, arg ); + byte = (uint8_t) c; + _Hash_Add_data( &gcov_hash, &byte, sizeof( byte ) ); +} + void rtems_test_gcov_dump_info( void ) { ISR_lock_Context lock_context; @@ -55,11 +67,21 @@ void rtems_test_gcov_dump_info( void ) _ISR_lock_ISR_disable_and_acquire( &gcov_dump_lock, &lock_context ); if ( !gcov_dump_done ) { + Hash_Control result; + gcov_dump_done = true; _IO_Printf( rtems_put_char, NULL, "\n*** BEGIN OF GCOV INFO BASE64 ***\n" ); - _Gcov_Dump_info_base64( rtems_put_char, NULL ); - _IO_Printf( rtems_put_char, NULL, "\n*** END OF GCOV INFO BASE64 ***\n" ); + _Hash_Initialize( &gcov_hash ); + _Gcov_Dump_info_base64( gcov_put_char, NULL ); + _Hash_Finalize( &gcov_hash, &result ); + _IO_Printf( rtems_put_char, NULL, "*** END OF GCOV INFO BASE64 ***\n" ); + _IO_Printf( + rtems_put_char, + NULL, + "*** GCOV INFO SHA256 %s ***\n", + _Hash_Get_string( &result ) + ); } _ISR_lock_Release_and_ISR_enable( &gcov_dump_lock, &lock_context ); diff --git a/cpukit/libtest/testrun.c b/cpukit/libtest/testrun.c index 0d392e4581..e7be6e91a7 100644 --- a/cpukit/libtest/testrun.c +++ b/cpukit/libtest/testrun.c @@ -3,13 +3,13 @@ /** * @file * - * @ingroup RTEMSAPI + * @ingroup RTEMSTest * - * @brief Implementation of rtems_test_run_default(). + * @brief This source file provides the implementation of rtems_test_run(). */ /* - * Copyright (C) 2020 embedded brains GmbH & Co. KG + * Copyright (C) 2020, 2023 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,6 +38,7 @@ #endif #include <rtems/test-info.h> +#include <rtems/test-printer.h> #include <rtems/test.h> #include <stdlib.h> @@ -65,7 +66,7 @@ static const T_config config = { .buf = buffer, .buf_size = sizeof( buffer ), .putchar = T_putchar_default, - .verbosity = T_VERBOSE, + .verbosity = T_NORMAL, .now = T_now_clock, .allocate = malloc, .deallocate = free, @@ -73,17 +74,33 @@ static const T_config config = { .actions = actions }; +static int printer(void *context, const char *fmt, va_list ap) +{ + (void) context; + return T_vprintf(fmt, ap); +} + void rtems_test_run( rtems_task_argument arg, const RTEMS_TEST_STATE state ) { + rtems_print_printer previous_printer; + int exit_code; + (void) arg; rtems_test_begin( rtems_test_name, state ); T_register(); - if ( T_main( &config ) == 0 ) { + previous_printer = rtems_test_printer.printer; + rtems_test_printer.printer = printer; + + exit_code = T_main( &config ); + + rtems_test_printer.printer = previous_printer; + + if ( exit_code == 0 ) { rtems_test_end( rtems_test_name ); } diff --git a/cpukit/libtest/testwrappers.c b/cpukit/libtest/testwrappers.c index 3c6e8fccc3..2316208f7c 100644 --- a/cpukit/libtest/testwrappers.c +++ b/cpukit/libtest/testwrappers.c @@ -29,7 +29,7 @@ #include "config.h" #endif -#include <rtems/test-info.h> +#include <rtems/test-printer.h> int __wrap_printf(const char* format, ...); int __wrap_puts(const char *str); diff --git a/cpukit/libtrace/record/record-dump-base64.c b/cpukit/libtrace/record/record-dump-base64.c index a021c7016c..9438041664 100644 --- a/cpukit/libtrace/record/record-dump-base64.c +++ b/cpukit/libtrace/record/record-dump-base64.c @@ -30,11 +30,12 @@ #endif #include <rtems/recorddump.h> -#include <rtems/score/io.h> #include <limits.h> #include <string.h> +#include <rtems/base64.h> + typedef struct { IO_Put_char put_char; void *arg; @@ -76,7 +77,7 @@ static void chunk( void *arg, const void *data, size_t length ) if ( index == RTEMS_ARRAY_SIZE( ctx->buf ) - 1 ) { index = 0; - _IO_Base64( + _Base64_Encode( put_char, ctx, ctx->buf, @@ -94,7 +95,7 @@ static void chunk( void *arg, const void *data, size_t length ) static void flush( dump_context *ctx ) { - _IO_Base64( put_char, ctx, ctx->buf, ctx->index, NULL, INT_MAX ); + _Base64_Encode( put_char, ctx, ctx->buf, ctx->index, NULL, INT_MAX ); } void rtems_record_dump_base64( IO_Put_char put_char, void *arg ) diff --git a/cpukit/libtrace/record/record-dump-zbase64.c b/cpukit/libtrace/record/record-dump-zbase64.c index 9359429d0b..43bd0ecff8 100644 --- a/cpukit/libtrace/record/record-dump-zbase64.c +++ b/cpukit/libtrace/record/record-dump-zbase64.c @@ -30,11 +30,12 @@ #endif #include <rtems/recorddump.h> -#include <rtems/score/io.h> #include <limits.h> #include <string.h> +#include <rtems/base64.h> + static void *dump_zalloc( void *opaque, unsigned items, unsigned size ) { rtems_record_dump_base64_zlib_context *ctx; @@ -96,7 +97,7 @@ static void chunk( void *arg, const void *data, size_t length ) ctx->stream.next_out = &ctx->buf[ 0 ]; ctx->stream.avail_out = sizeof( ctx->buf ); - _IO_Base64( put_char, ctx, ctx->buf, sizeof( ctx->buf ), NULL, INT_MAX ); + _Base64_Encode( put_char, ctx, ctx->buf, sizeof( ctx->buf ), NULL, INT_MAX ); } } } @@ -115,11 +116,11 @@ static void flush( rtems_record_dump_base64_zlib_context *ctx ) ctx->stream.next_out = &ctx->buf[ 0 ]; ctx->stream.avail_out = sizeof( ctx->buf ); - _IO_Base64( put_char, ctx, ctx->buf, sizeof( ctx->buf ), NULL, INT_MAX ); + _Base64_Encode( put_char, ctx, ctx->buf, sizeof( ctx->buf ), NULL, INT_MAX ); } } - _IO_Base64( + _Base64_Encode( put_char, ctx, ctx->buf, diff --git a/cpukit/posix/src/condtimedwait.c b/cpukit/posix/src/condtimedwait.c index b063aac9b1..258e38a357 100644 --- a/cpukit/posix/src/condtimedwait.c +++ b/cpukit/posix/src/condtimedwait.c @@ -39,7 +39,6 @@ #endif #include <rtems/posix/condimpl.h> -#include <rtems/score/todimpl.h> /* * 11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105 diff --git a/cpukit/posix/src/killinfo.c b/cpukit/posix/src/killinfo.c index 2765ab30ca..bde511504a 100644 --- a/cpukit/posix/src/killinfo.c +++ b/cpukit/posix/src/killinfo.c @@ -47,7 +47,6 @@ #include <rtems/posix/pthreadimpl.h> #include <rtems/posix/psignalimpl.h> #include <rtems/score/isr.h> -#include <rtems/score/schedulerimpl.h> #include <rtems/score/statesimpl.h> #include <rtems/seterr.h> @@ -324,7 +323,6 @@ int _POSIX_signals_Send( * + sigprocmask() unblocks the signal, OR * + sigaction() which changes the handler to SIG_IGN. */ - the_thread = NULL; goto post_process_signal; /* diff --git a/cpukit/posix/src/mutexattrsetprotocol.c b/cpukit/posix/src/mutexattrsetprotocol.c index 5a6c44cf52..c3205c9a75 100644 --- a/cpukit/posix/src/mutexattrsetprotocol.c +++ b/cpukit/posix/src/mutexattrsetprotocol.c @@ -44,7 +44,6 @@ #include <rtems/score/coremuteximpl.h> #include <rtems/score/watchdog.h> #include <rtems/posix/muteximpl.h> -#include <rtems/posix/priorityimpl.h> /* * 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128 diff --git a/cpukit/posix/src/mutexunlock.c b/cpukit/posix/src/mutexunlock.c index 681aa8fd1b..0644cec188 100644 --- a/cpukit/posix/src/mutexunlock.c +++ b/cpukit/posix/src/mutexunlock.c @@ -41,8 +41,6 @@ #include <rtems/posix/muteximpl.h> #include <rtems/posix/posixapi.h> -#include <string.h> - bool _POSIX_Mutex_Auto_initialization( POSIX_Mutex_Control *the_mutex ) { unsigned long zero; diff --git a/cpukit/posix/src/psignal.c b/cpukit/posix/src/psignal.c index a829c60ee1..3bfd779630 100644 --- a/cpukit/posix/src/psignal.c +++ b/cpukit/posix/src/psignal.c @@ -50,7 +50,6 @@ #include <rtems/posix/psignalimpl.h> #include <rtems/posix/pthreadimpl.h> #include <rtems/config.h> -#include <rtems/seterr.h> #include <rtems/sysinit.h> /* diff --git a/cpukit/posix/src/psignalclearsignals.c b/cpukit/posix/src/psignalclearsignals.c index f31cbf0d27..0c8ae8e1a6 100644 --- a/cpukit/posix/src/psignalclearsignals.c +++ b/cpukit/posix/src/psignalclearsignals.c @@ -44,7 +44,6 @@ #include <rtems/score/isr.h> #include <rtems/score/thread.h> -#include <rtems/seterr.h> #include <rtems/posix/threadsup.h> #include <rtems/posix/psignalimpl.h> #include <rtems/posix/pthreadimpl.h> diff --git a/cpukit/posix/src/psignalsetprocesssignals.c b/cpukit/posix/src/psignalsetprocesssignals.c index 213de57406..9af03943f4 100644 --- a/cpukit/posix/src/psignalsetprocesssignals.c +++ b/cpukit/posix/src/psignalsetprocesssignals.c @@ -43,7 +43,6 @@ #include <rtems/score/isr.h> #include <rtems/score/thread.h> -#include <rtems/seterr.h> #include <rtems/posix/threadsup.h> #include <rtems/posix/psignalimpl.h> #include <rtems/posix/pthreadimpl.h> diff --git a/cpukit/posix/src/psignalunblockthread.c b/cpukit/posix/src/psignalunblockthread.c index 5b0168c22d..61c2602b96 100644 --- a/cpukit/posix/src/psignalunblockthread.c +++ b/cpukit/posix/src/psignalunblockthread.c @@ -46,7 +46,6 @@ #include <rtems/score/threadimpl.h> #include <rtems/score/threadqimpl.h> #include <rtems/score/watchdogimpl.h> -#include <rtems/seterr.h> #include <rtems/posix/threadsup.h> #include <rtems/posix/psignalimpl.h> #include <rtems/posix/pthreadimpl.h> diff --git a/cpukit/posix/src/pthreadgetschedparam.c b/cpukit/posix/src/pthreadgetschedparam.c index 09c2611ce9..88ea525d1b 100644 --- a/cpukit/posix/src/pthreadgetschedparam.c +++ b/cpukit/posix/src/pthreadgetschedparam.c @@ -47,7 +47,6 @@ #include <rtems/posix/pthreadimpl.h> #include <rtems/posix/pthreadattrimpl.h> #include <rtems/posix/priorityimpl.h> -#include <rtems/score/schedulerimpl.h> #include <rtems/score/threadimpl.h> int pthread_getschedparam( diff --git a/cpukit/posix/src/pthreadsetschedparam.c b/cpukit/posix/src/pthreadsetschedparam.c index 18168a5501..06508ef451 100644 --- a/cpukit/posix/src/pthreadsetschedparam.c +++ b/cpukit/posix/src/pthreadsetschedparam.c @@ -49,7 +49,6 @@ #include <rtems/posix/pthreadimpl.h> #include <rtems/posix/priorityimpl.h> #include <rtems/score/threadimpl.h> -#include <rtems/score/schedulerimpl.h> static int _POSIX_Set_sched_param( Thread_Control *the_thread, diff --git a/cpukit/sapi/src/cpucounterconverter.c b/cpukit/sapi/src/cpucounterconverter.c index 4cabdc5e4a..587fe460df 100644 --- a/cpukit/sapi/src/cpucounterconverter.c +++ b/cpukit/sapi/src/cpucounterconverter.c @@ -1,5 +1,14 @@ /* SPDX-License-Identifier: BSD-2-Clause */ +/** + * @file + * + * @ingroup RTEMSImpl + * + * @brief This source file contains a implementation of the counter value + * conversion functions. + */ + /* * Copyright (C) 2014, 2018 embedded brains GmbH & Co. KG * diff --git a/cpukit/sapi/src/sapirbtreeinsert.c b/cpukit/sapi/src/sapirbtreeinsert.c index 0d0871891c..41fc47ef33 100644 --- a/cpukit/sapi/src/sapirbtreeinsert.c +++ b/cpukit/sapi/src/sapirbtreeinsert.c @@ -39,7 +39,6 @@ #endif #include <rtems/rbtree.h> -#include <rtems/score/rbtreeimpl.h> RTEMS_STATIC_ASSERT( sizeof( rtems_rbtree_compare_result ) >= sizeof( intptr_t ), diff --git a/cpukit/sapi/src/version.c b/cpukit/sapi/src/version.c index 385cf83f2a..7197ddd153 100644 --- a/cpukit/sapi/src/version.c +++ b/cpukit/sapi/src/version.c @@ -3,7 +3,7 @@ /** * @file * - * @ingroup RTEMSAPIClassicVersion + * @ingroup RTEMSImplClassic * * @brief This source file contains the implementation of rtems_version(), * rtems_version_control_key(), rtems_version_major(), rtems_version_minor(), @@ -54,8 +54,8 @@ const char *rtems_version( void ) { -#ifdef RTEMS_VERSION_VC_KEY - return RTEMS_VERSION "." RTEMS_VERSION_VC_KEY; +#ifdef RTEMS_VERSION_CONTROL_KEY + return RTEMS_VERSION "." RTEMS_VERSION_CONTROL_KEY; #else return RTEMS_VERSION; #endif @@ -78,8 +78,8 @@ int rtems_version_revision( void ) const char *rtems_version_control_key( void ) { -#ifdef RTEMS_VERSION_VC_KEY - return RTEMS_VERSION_VC_KEY; +#ifdef RTEMS_VERSION_CONTROL_KEY + return RTEMS_VERSION_CONTROL_KEY; #else return ""; #endif diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c b/cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c index c5b477c72f..04a3dfdc0d 100644 --- a/cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c +++ b/cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c @@ -45,7 +45,7 @@ #include <inttypes.h> #include <rtems/score/cpu.h> -#include <rtems/score/io.h> +#include <rtems/dev/io.h> #include <rtems/bspIo.h> typedef struct { diff --git a/cpukit/score/cpu/aarch64/include/libcpu/mmu-vmsav8-64.h b/cpukit/score/cpu/aarch64/include/libcpu/mmu-vmsav8-64.h index 0d65004f88..ca9b60e6d1 100644 --- a/cpukit/score/cpu/aarch64/include/libcpu/mmu-vmsav8-64.h +++ b/cpukit/score/cpu/aarch64/include/libcpu/mmu-vmsav8-64.h @@ -70,7 +70,7 @@ extern "C" { #define AARCH64_MMU_CODE_RW_CACHED AARCH64_MMU_DATA_RW_CACHED #define AARCH64_MMU_DATA_RO \ - ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 1 ) | MMU_DESC_WRITE_DISABLE ) + ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 2 ) | MMU_DESC_WRITE_DISABLE ) #define AARCH64_MMU_CODE AARCH64_MMU_DATA_RO #define AARCH64_MMU_CODE_RW AARCH64_MMU_DATA_RW @@ -78,7 +78,7 @@ extern "C" { #define AARCH64_MMU_DATA_RW_CACHED \ ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 3 ) ) #define AARCH64_MMU_DATA_RW \ - ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 1 ) ) + ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 2 ) ) #define AARCH64_MMU_DEVICE ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 0 ) ) rtems_status_code aarch64_mmu_map( diff --git a/cpukit/score/cpu/aarch64/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/aarch64/include/rtems/score/cpuatomic.h deleted file mode 100644 index ed8091d73c..0000000000 --- a/cpukit/score/cpu/aarch64/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup RTEMSScoreCPU - * - * @brief AArch64 Atomics support - */ - -/* - * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) - * Written by Kinsey Moore <kinsey.moore@oarcorp.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h index b520e8bffb..8a0e476899 100644 --- a/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h @@ -174,6 +174,13 @@ static inline void _CPU_Use_thread_local_storage( ); } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + return (void *)(uintptr_t) context->thread_id; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/arm/__tls_get_addr.c b/cpukit/score/cpu/arm/__tls_get_addr.c index 7ef42fdcb4..407bf3d639 100644 --- a/cpukit/score/cpu/arm/__tls_get_addr.c +++ b/cpukit/score/cpu/arm/__tls_get_addr.c @@ -48,7 +48,7 @@ void *__tls_get_addr(const TLS_Index *ti) { const Thread_Control *executing = _Thread_Get_executing(); void *tls_data = (char *) executing->Registers.thread_id - + _TLS_Get_thread_control_block_area_size(); + + _TLS_Get_thread_control_block_area_size( &_TLS_Configuration ); assert(ti->module == 1); diff --git a/cpukit/score/cpu/arm/arm-exception-frame-print.c b/cpukit/score/cpu/arm/arm-exception-frame-print.c index 7bc6795ea5..b089648184 100644 --- a/cpukit/score/cpu/arm/arm-exception-frame-print.c +++ b/cpukit/score/cpu/arm/arm-exception-frame-print.c @@ -41,11 +41,14 @@ #include <inttypes.h> #include <rtems/score/cpu.h> +#if defined(ARM_MULTILIB_ARCH_V7M) +#include <rtems/score/armv7m.h> +#endif #include <rtems/bspIo.h> static void _ARM_VFP_context_print( const ARM_VFP_context *vfp_context ) { -#ifdef ARM_MULTILIB_VFP_D32 +#ifdef ARM_MULTILIB_VFP if ( vfp_context != NULL ) { const uint64_t *dx = &vfp_context->register_d0; int i; @@ -56,7 +59,14 @@ static void _ARM_VFP_context_print( const ARM_VFP_context *vfp_context ) vfp_context->register_fpscr ); - for ( i = 0; i < 32; ++i ) { +#if defined(ARM_MULTILIB_VFP_D32) + int regcount = 32; +#elif defined(ARM_MULTILIB_VFP_D16) + int regcount = 16; +#else + int regcount = 0; +#endif + for ( i = 0; i < regcount; ++i ) { uint32_t low = (uint32_t) dx[i]; uint32_t high = (uint32_t) (dx[i] >> 32); @@ -66,6 +76,136 @@ static void _ARM_VFP_context_print( const ARM_VFP_context *vfp_context ) #endif } +static void _ARM_Cortex_M_fault_info_print( void ) +{ +#if defined(ARM_MULTILIB_ARCH_V7M) + /* + * prints content of additional debugging registers + * available on Cortex-Mx where x > 0 cores. + */ + uint32_t cfsr = _ARMV7M_SCB->cfsr; + uint8_t mmfsr = ARMV7M_SCB_CFSR_MMFSR_GET( cfsr ); + uint8_t bfsr = ( ARMV7M_SCB_CFSR_BFSR_GET( cfsr ) >> 8 ); + uint16_t ufsr = ( ARMV7M_SCB_CFSR_UFSR_GET( cfsr ) >> 16 ); + uint32_t hfsr = _ARMV7M_SCB->hfsr; + if ( mmfsr > 0 ) { + printk( "MMFSR= 0x%08" PRIx32 " (memory fault)\n", mmfsr ); + if ( ( mmfsr & 0x1 ) != 0 ) { + printk( " IACCVIOL : 1 (instruction access violation)\n" ); + } + if ( ( mmfsr & 0x2 ) != 0 ) { + printk( " DACCVIOL : 1 (data access violation)\n" ); + } + if ( (mmfsr & 0x8 ) != 0 ) { + printk( + " MUNSTKERR : 1 (fault on unstacking on exception return)\n" + ); + } + if ( ( mmfsr & 0x10 ) != 0 ) { + printk( " MSTKERR : 1 (fault on stacking on exception entry)\n" ); + } + if ( (mmfsr & 0x20 ) != 0 ) { + printk( " MLSPERR : 1 (fault during lazy FP stack preservation)\n" ); + } + if ( (mmfsr & 0x80 ) != 0 ) { + printk( + " MMFARVALID : 1 -> 0x%08" PRIx32 " (error address)\n", + _ARMV7M_SCB->mmfar + ); + } + else { + printk( " MMFARVALID : 0 (undetermined error address)\n" ); + } + } + if ( bfsr > 0 ) { + printk( "BFSR = 0x%08" PRIx32 " (bus fault)\n", bfsr ); + if ( ( bfsr & 0x1 ) != 0 ) { + printk( " IBUSERR : 1 (instruction fetch error)\n" ); + } + if ( (bfsr & 0x2 ) != 0 ) { + printk( + " PRECISERR : 1 (data bus error with known exact location)\n" + ); + } + if ( ( bfsr & 0x4) != 0 ) { + printk( + " IMPRECISERR: 1 (data bus error without known exact location)\n" + ); + } + if ( (bfsr & 0x8 ) != 0 ) { + printk( + " UNSTKERR : 1 (fault on unstacking on exception return)\n" + ); + } + if ( ( bfsr & 0x10 ) != 0 ) { + printk( " STKERR : 1 (fault on stacking on exception entry)\n" ); + } + if ( ( bfsr & 0x20 ) != 0 ) { + printk( " LSPERR : 1 (fault during lazy FP stack preservation)\n" ); + } + if ( (bfsr & 0x80 ) != 0 ) { + printk( + " BFARVALID : 1 -> 0x%08" PRIx32 " (error address)\n", + _ARMV7M_SCB->bfar + ); + } + else { + printk( " BFARVALID : 0 (undetermined error address)\n" ); + } + } + if ( ufsr > 0 ) { + printk( "UFSR = 0x%08" PRIx32 " (usage fault)\n", ufsr); + if ( (ufsr & 0x1 ) != 0 ) { + printk( " UNDEFINSTR : 1 (undefined instruction issued)\n"); + } + if ( (ufsr & 0x2 ) != 0 ) { + printk( + " INVSTATE : 1" + " (invalid instruction state" + " (Thumb not set in EPSR or invalid IT state in EPSR))\n" + ); + } + if ( (ufsr & 0x4 ) != 0 ) { + printk( " INVPC : 1 (integrity check failure on EXC_RETURN)\n" ); + } + if ( (ufsr & 0x8 ) != 0 ) { + printk( + " NOCP : 1" + " (coprocessor instruction issued" + " but coprocessor disabled or non existent)\n" + ); + } + if ( ( ufsr & 0x100) != 0 ) { + printk( " UNALIGNED : 1 (unaligned access operation occurred)\n" ); + } + if ( ( ufsr & 0x200) != 0 ) { + printk( " DIVBYZERO : 1 (division by zero)" ); + } + } + if ( (hfsr & ( + ARMV7M_SCB_HFSR_VECTTBL_MASK + | ARMV7M_SCB_HFSR_DEBUGEVT_MASK + | ARMV7M_SCB_HFSR_FORCED_MASK + ) ) != 0 ) { + printk( "HFSR = 0x%08" PRIx32 " (hard fault)\n", hfsr ); + if ( (hfsr & ARMV7M_SCB_HFSR_VECTTBL_MASK ) != 0 ) { + printk( + " VECTTBL : 1 (error in address located in vector table)\n" + ); + } + if ( (hfsr & ARMV7M_SCB_HFSR_FORCED_MASK ) != 0 ) { + printk( + " FORCED : 1 (configurable fault escalated to hard fault)\n" + ); + } + if ( (hfsr & ARMV7M_SCB_HFSR_DEBUGEVT_MASK ) != 0 ) { + printk( + " DEBUGEVT : 1 (debug event occurred with debug system disabled)\n" + ); + } + } +#endif +} void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) { printk( @@ -109,4 +249,5 @@ void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) ); _ARM_VFP_context_print( frame->vfp_context ); + _ARM_Cortex_M_fault_info_print(); } diff --git a/cpukit/score/cpu/arm/armv4-isr-install-vector.c b/cpukit/score/cpu/arm/armv4-isr-install-vector.c new file mode 100644 index 0000000000..739b02f8bf --- /dev/null +++ b/cpukit/score/cpu/arm/armv4-isr-install-vector.c @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSScoreCPUARM + * + * @brief This source file contains the ARM-specific _CPU_ISR_install_vector(). + */ + +/* + * COPYRIGHT (c) 2000 Canon Research Centre France SA. + * Emmanuel Raguet, mailto:raguet@crf.canon.fr + * + * Copyright (c) 2002 Advent Networks, Inc + * Jay Monkman <jmonkman@adventnetworks.com> + * + * Copyright (C) 2009, 2017 embedded brains GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/score/cpu.h> + +#ifdef ARM_MULTILIB_ARCH_V4 + +void _CPU_ISR_install_vector( + uint32_t vector, + CPU_ISR_handler new_handler, + CPU_ISR_handler *old_handler +) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + /* Redirection table starts at the end of the vector table */ + CPU_ISR_handler volatile *table = (CPU_ISR_handler *) (MAX_EXCEPTIONS * 4); + + CPU_ISR_handler current_handler = table [vector]; + + /* The current handler is now the old one */ + if (old_handler != NULL) { + *old_handler = current_handler; + } + + /* Write only if necessary to avoid writes to a maybe read-only memory */ + if (current_handler != new_handler) { + table [vector] = new_handler; + } +#pragma GCC diagnostic pop +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/cpukit/score/cpu/arm/cpu.c b/cpukit/score/cpu/arm/cpu.c index 65f1ad2014..c27f4de9f9 100644 --- a/cpukit/score/cpu/arm/cpu.c +++ b/cpukit/score/cpu/arm/cpu.c @@ -8,8 +8,7 @@ * @brief This source file contains static assertions to ensure the consistency * of interfaces used in C and assembler and it contains the ARM-specific * implementation of _CPU_Initialize(), _CPU_ISR_Get_level(), - * _CPU_ISR_Set_level(), _CPU_ISR_install_vector(), - * _CPU_Context_Initialize(), and _CPU_Fatal_halt(). + * _CPU_ISR_Set_level(), _CPU_Context_Initialize(), and _CPU_Fatal_halt(). */ /* @@ -160,31 +159,6 @@ uint32_t _CPU_ISR_Get_level( void ) return ( level & ARM_PSR_I ) != 0; } -void _CPU_ISR_install_vector( - uint32_t vector, - CPU_ISR_handler new_handler, - CPU_ISR_handler *old_handler -) -{ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warray-bounds" - /* Redirection table starts at the end of the vector table */ - CPU_ISR_handler volatile *table = (CPU_ISR_handler *) (MAX_EXCEPTIONS * 4); - - CPU_ISR_handler current_handler = table [vector]; - - /* The current handler is now the old one */ - if (old_handler != NULL) { - *old_handler = current_handler; - } - - /* Write only if necessary to avoid writes to a maybe read-only memory */ - if (current_handler != new_handler) { - table [vector] = new_handler; - } -#pragma GCC diagnostic pop -} - void _CPU_Initialize( void ) { /* Do nothing */ diff --git a/cpukit/score/cpu/arm/include/libcpu/arm-cp15.h b/cpukit/score/cpu/arm/include/libcpu/arm-cp15.h index 333cd7c8a0..c239eaccc8 100644 --- a/cpukit/score/cpu/arm/include/libcpu/arm-cp15.h +++ b/cpukit/score/cpu/arm/include/libcpu/arm-cp15.h @@ -1309,15 +1309,17 @@ arm_cp15_data_cache_test_and_clean(void) ); } -/* In DDI0301H_arm1176jzfs_r0p7_trm - * 'MCR p15, 0, <Rd>, c7, c14, 0' means - * Clean and Invalidate Entire Data Cache - */ ARM_CP15_TEXT_SECTION static inline void arm_cp15_data_cache_clean_and_invalidate(void) { ARM_SWITCH_REGISTERS; +#if __ARM_ARCH >= 6 + /* + * In DDI0301H_arm1176jzfs_r0p7_trm + * 'MCR p15, 0, <Rd>, c7, c14, 0' means + * Clean and Invalidate Entire Data Cache + */ uint32_t sbz = 0; __asm__ volatile ( @@ -1328,6 +1330,22 @@ arm_cp15_data_cache_clean_and_invalidate(void) : [sbz] "r" (sbz) : "memory" ); +#else + /* + * Assume this is an ARM926EJ-S. Use the test, clean, and invalidate DCache + * operation. + */ + __asm__ volatile ( + ARM_SWITCH_TO_ARM + "1:\n" + "mrc p15, 0, r15, c7, c14, 3\n" + "bne 1b\n" + ARM_SWITCH_BACK + : ARM_SWITCH_OUTPUT + : + : "memory" + ); +#endif } ARM_CP15_TEXT_SECTION static inline void diff --git a/cpukit/score/cpu/arm/include/rtems/score/armv7m.h b/cpukit/score/cpu/arm/include/rtems/score/armv7m.h index 0f129f1d2e..7fa48b3aa5 100644 --- a/cpukit/score/cpu/arm/include/rtems/score/armv7m.h +++ b/cpukit/score/cpu/arm/include/rtems/score/armv7m.h @@ -159,8 +159,19 @@ typedef struct { #define ARMV7M_SCB_SHCSR_MEMFAULTENA (1U << 16) uint32_t shcsr; +#define ARMV7M_SCB_CFSR_MMFSR_MASK 0xff +#define ARMV7M_SCB_CFSR_MMFSR_GET(n) (n & ARMV7M_SCB_CFSR_MMFSR_MASK) +#define ARMV7M_SCB_CFSR_BFSR_MASK 0xff00 +#define ARMV7M_SCB_CFSR_BFSR_GET(n) (n & ARMV7M_SCB_CFSR_BFSR_MASK) +#define ARMV7M_SCB_CFSR_UFSR_MASK 0xffff0000 +#define ARMV7M_SCB_CFSR_UFSR_GET(n) (n & ARMV7M_SCB_CFSR_UFSR_MASK) uint32_t cfsr; + +#define ARMV7M_SCB_HFSR_VECTTBL_MASK 0x2 +#define ARMV7M_SCB_HFSR_FORCED_MASK (1U << 30) +#define ARMV7M_SCB_HFSR_DEBUGEVT_MASK (1U << 31) uint32_t hfsr; + uint32_t dfsr; uint32_t mmfar; uint32_t bfar; diff --git a/cpukit/score/cpu/arm/include/rtems/score/cpu.h b/cpukit/score/cpu/arm/include/rtems/score/cpu.h index 3cd43970b1..a462b48cf1 100644 --- a/cpukit/score/cpu/arm/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/arm/include/rtems/score/cpu.h @@ -585,7 +585,7 @@ typedef enum { ARM_EXCEPTION_IRQ = 6, ARM_EXCEPTION_FIQ = 7, MAX_EXCEPTIONS = 8, - ARM_EXCEPTION_MAKE_ENUM_32_BIT = 0xffffffff + ARM_EXCEPTION_MAKE_ENUM_32_BIT = 0x7fffffff } Arm_symbolic_exception_name; #endif /* defined(ARM_MULTILIB_ARCH_V4) */ diff --git a/cpukit/score/cpu/arm/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/arm/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/arm/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h index f9b40889f5..04d23f0ea7 100644 --- a/cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h @@ -178,6 +178,13 @@ static inline void _CPU_Use_thread_local_storage( #endif } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + return (void *) context->thread_id; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/bfin/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/bfin/include/rtems/score/cpuatomic.h deleted file mode 100644 index 598ee76b20..0000000000 --- a/cpukit/score/cpu/bfin/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h index 05628a2c0b..5a445d9420 100644 --- a/cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h @@ -41,11 +41,15 @@ RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); static inline void _CPU_Context_volatile_clobber( uintptr_t pattern ) { + (void) pattern; + /* TODO */ } static inline void _CPU_Context_validate( uintptr_t pattern ) { + (void) pattern; + while (1) { /* TODO */ } @@ -68,6 +72,14 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + (void) context; + return NULL; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/i386/cpu_asm.S b/cpukit/score/cpu/i386/cpu_asm.S index 6b114e94e1..bb5c096e72 100644 --- a/cpukit/score/cpu/i386/cpu_asm.S +++ b/cpukit/score/cpu/i386/cpu_asm.S @@ -67,11 +67,13 @@ .p2align 1 PUBLIC (_CPU_Context_switch) + PUBLIC (_CPU_Context_switch_no_return) .set RUNCONTEXT_ARG, 4 /* save context argument */ .set HEIRCONTEXT_ARG, 8 /* restore context argument */ SYM (_CPU_Context_switch): +SYM (_CPU_Context_switch_no_return): movl RUNCONTEXT_ARG(esp),eax /* eax = running threads context */ GET_SELF_CPU_CONTROL edx /* edx has address for per_CPU information */ movl PER_CPU_ISR_DISPATCH_DISABLE(edx),ecx diff --git a/cpukit/score/cpu/i386/include/rtems/score/cpu.h b/cpukit/score/cpu/i386/include/rtems/score/cpu.h index 6aa97d309e..a12b0f2b92 100644 --- a/cpukit/score/cpu/i386/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/i386/include/rtems/score/cpu.h @@ -2,9 +2,9 @@ /** * @file - * + * * @brief Intel I386 CPU Dependent Source - * + * * This include file contains information pertaining to the Intel * i386 processor. */ @@ -51,7 +51,7 @@ extern "C" { #include <rtems/score/paravirt.h> #endif #include <rtems/score/i386.h> - + /** * @defgroup RTEMSScoreCPUi386 i386 Specific Support * @@ -163,7 +163,7 @@ typedef struct { } Context_Control; #define _CPU_Context_Get_SP( _context ) \ - (_context)->esp + (uintptr_t) (_context)->esp #ifdef RTEMS_SMP static inline bool _CPU_Context_Get_is_executing( @@ -572,6 +572,11 @@ void _CPU_Context_switch( Context_Control *heir ); +RTEMS_NO_RETURN void _CPU_Context_switch_no_return( + Context_Control *executing, + Context_Control *heir +); + /* * _CPU_Context_restore * diff --git a/cpukit/score/cpu/i386/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/i386/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/i386/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h index f0e4088218..da38ecacf7 100644 --- a/cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h @@ -62,11 +62,15 @@ RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); static inline void _CPU_Context_volatile_clobber( uintptr_t pattern ) { + (void) pattern; + /* TODO */ } static inline void _CPU_Context_validate( uintptr_t pattern ) { + (void) pattern; + while (1) { /* TODO */ } @@ -108,6 +112,13 @@ static inline void _CPU_Use_thread_local_storage( ); } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + return (void *) &context->gs; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/lm32/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/lm32/include/rtems/score/cpuatomic.h deleted file mode 100644 index 598ee76b20..0000000000 --- a/cpukit/score/cpu/lm32/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h index 679ef452f4..70a1db1d4d 100644 --- a/cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h @@ -40,11 +40,15 @@ RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); static inline void _CPU_Context_volatile_clobber( uintptr_t pattern ) { + (void) pattern; + /* TODO */ } static inline void _CPU_Context_validate( uintptr_t pattern ) { + (void) pattern; + while (1) { /* TODO */ } @@ -67,6 +71,14 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + (void) context; + return NULL; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/m68k/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/m68k/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/m68k/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h index ec90a41ae2..521e9fc4c2 100644 --- a/cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h @@ -60,11 +60,15 @@ RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); static inline void _CPU_Context_volatile_clobber( uintptr_t pattern ) { + (void) pattern; + /* TODO */ } static inline void _CPU_Context_validate( uintptr_t pattern ) { + (void) pattern; + while (1) { /* TODO */ } @@ -91,6 +95,13 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + return (void *) context->thread_pointer; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/microblaze/include/machine/elf_machdep.h b/cpukit/score/cpu/microblaze/include/machine/elf_machdep.h new file mode 100644 index 0000000000..e6d661c596 --- /dev/null +++ b/cpukit/score/cpu/microblaze/include/machine/elf_machdep.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (C) 2023 On-Line Applications Research Corporation (OAR) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MICROBLAZE_ELF_MACHDEP_H_ +#define _MICROBLAZE_ELF_MACHDEP_H_ + +#define ELF64_MACHDEP_ID EM_MICROBLAZE +#define ELF32_MACHDEP_ID EM_MICROBLAZE + +#define ELF64_MACHDEP_ENDIANNESS ELFDATA2LSB +#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB + +#define ELF32_MACHDEP_ID_CASES \ + case EM_MICROBLAZE: \ + break; + +#define ELF64_MACHDEP_ID_CASES \ + case EM_MICROBLAZE: \ + break; + +#define KERN_ELFSIZE 32 +#define ARCH_ELFSIZE 32 /* MD native binary size */ + +/* Processor specific relocation types */ + +#define R_MICROBLAZE_NONE 0 +#define R_MICROBLAZE_32 1 +#define R_MICROBLAZE_32_PCREL 2 +#define R_MICROBLAZE_64_PCREL 3 +#define R_MICROBLAZE_32_PCREL_LO 4 +#define R_MICROBLAZE_64 5 +#define R_MICROBLAZE_32_LO 6 +#define R_MICROBLAZE_SRO32 7 +#define R_MICROBLAZE_SRW32 8 +#define R_MICROBLAZE_64_NONE 9 +#define R_MICROBLAZE_32_SYM_OP_SYM 10 +#define R_MICROBLAZE_GNU_VTINHERIT 11 +#define R_MICROBLAZE_GNU_VTENTRY 12 +#define R_MICROBLAZE_GOTPC_64 13 +#define R_MICROBLAZE_GOT_64 14 +#define R_MICROBLAZE_PLT_64 15 +#define R_MICROBLAZE_REL 16 +#define R_MICROBLAZE_JUMP_SLOT 17 +#define R_MICROBLAZE_GLOB_DAT 18 +#define R_MICROBLAZE_GOTOFF_64 19 +#define R_MICROBLAZE_GOTOFF_32 20 +#define R_MICROBLAZE_COPY 21 +#define R_MICROBLAZE_TLS 22 +#define R_MICROBLAZE_TLSGD 23 +#define R_MICROBLAZE_TLSLD 24 +#define R_MICROBLAZE_TLSDTPMOD32 25 +#define R_MICROBLAZE_TLSDTPREL32 26 +#define R_MICROBLAZE_TLSDTPREL64 27 +#define R_MICROBLAZE_TLSGOTTPREL32 28 +#define R_MICROBLAZE_TLSTPREL32 29 + +#define R_TYPE( name ) R_MICROBLAZE_##name + +#endif /* _MICROBLAZE_ELF_MACHDEP_H_ */ diff --git a/cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h index 4e315e856d..760ebbfbbb 100644 --- a/cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h @@ -100,6 +100,13 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + return (void *) context->thread_pointer; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/mips/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/mips/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/mips/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h index ad6b7ae615..98ed1c492f 100644 --- a/cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h @@ -60,11 +60,15 @@ RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); static inline void _CPU_Context_volatile_clobber( uintptr_t pattern ) { + (void) pattern; + /* TODO */ } static inline void _CPU_Context_validate( uintptr_t pattern ) { + (void) pattern; + while (1) { /* TODO */ } @@ -87,6 +91,14 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + (void) context; + return NULL; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/moxie/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/moxie/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/moxie/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h index 8ded8c34e9..44c70cc56d 100644 --- a/cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h @@ -60,11 +60,15 @@ RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); static inline void _CPU_Context_volatile_clobber( uintptr_t pattern ) { + (void) pattern; + /* TODO */ } static inline void _CPU_Context_validate( uintptr_t pattern ) { + (void) pattern; + while (1) { /* TODO */ } @@ -87,6 +91,14 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + (void) context; + return NULL; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/nios2/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/nios2/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/nios2/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h index e1beaca74c..3c9c6734ec 100644 --- a/cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h @@ -84,6 +84,13 @@ static inline void _CPU_Use_thread_local_storage( __asm__ volatile ( "" : : "r" ( r23 ) ); } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + return (void *) context->r23; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/no_cpu/cpuidle.c b/cpukit/score/cpu/no_cpu/cpuidle.c index bff1309d39..dbaf109905 100644 --- a/cpukit/score/cpu/no_cpu/cpuidle.c +++ b/cpukit/score/cpu/no_cpu/cpuidle.c @@ -1,5 +1,14 @@ /* SPDX-License-Identifier: BSD-2-Clause */ +/** + * @file + * + * @ingroup RTEMSScoreCPU + * + * @brief This source file contains the implementation of the + * _CPU_Thread_Idle_body(). + */ + /* * Copyright (C) 2013, 2014 embedded brains GmbH & Co. KG * @@ -33,6 +42,13 @@ void *_CPU_Thread_Idle_body( uintptr_t ignored ) { + /* + * This is a workaround for: + * + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108658 + */ + __asm__ volatile (""); + while ( true ) { /* Do nothing */ } diff --git a/cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h index 61afcdd014..61f1ab7ba5 100644 --- a/cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h @@ -201,6 +201,22 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +/** + * @brief Gets the thread pointer of the context. + * + * The thread pointer is used to get the address of thread-local storage + * objects associated with a thread. + * + * @param context is the processor context containing the thread pointer. + */ +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + (void) context; + return NULL; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/or1k/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/or1k/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/or1k/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h index 5e6865eb1f..9b58b1b77a 100644 --- a/cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h @@ -79,6 +79,14 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + (void) context; + return NULL; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/powerpc/include/rtems/asm.h b/cpukit/score/cpu/powerpc/include/rtems/asm.h index 27af64e724..94f54245b4 100644 --- a/cpukit/score/cpu/powerpc/include/rtems/asm.h +++ b/cpukit/score/cpu/powerpc/include/rtems/asm.h @@ -75,23 +75,21 @@ #define __PROC_LABEL_PREFIX__ __USER_LABEL_PREFIX__ #endif -#include <rtems/concat.h> - /* Use the right prefix for global labels. */ -#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) +#define SYM(x) RTEMS_XCONCAT (__USER_LABEL_PREFIX__, x) /* Use the right prefix for procedure labels. */ -#define PROC(x) CONCAT1 (__PROC_LABEL_PREFIX__, x) +#define PROC(x) RTEMS_XCONCAT (__PROC_LABEL_PREFIX__, x) /* Use the right prefix for registers. */ -#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) +#define REG(x) RTEMS_XCONCAT (__REGISTER_PREFIX__, x) /* Use the right prefix for floating point registers. */ -#define FREG(x) CONCAT1 (__FLOAT_REGISTER_PREFIX__, x) +#define FREG(x) RTEMS_XCONCAT (__FLOAT_REGISTER_PREFIX__, x) /* * define macros for all of the registers on this CPU diff --git a/cpukit/score/cpu/powerpc/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/powerpc/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/powerpc/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h index 6d984b92e4..68b7165546 100644 --- a/cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h @@ -301,6 +301,13 @@ static inline void _CPU_Use_thread_local_storage( __asm__ volatile ( "" : : "r" ( tp ) ); } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + return (void *) ppc_get_context( context )->tp; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/riscv/include/rtems/score/cpuatomic.h deleted file mode 100644 index 8ee9606b44..0000000000 --- a/cpukit/score/cpu/riscv/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h index 47cf2e338c..13fd60ed8c 100644 --- a/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h @@ -454,6 +454,13 @@ static inline void _CPU_Use_thread_local_storage( __asm__ volatile ( "" : : "r" ( tp ) ); } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + return (void *) context->tp; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/sh/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/sh/include/rtems/score/cpuatomic.h deleted file mode 100644 index 598ee76b20..0000000000 --- a/cpukit/score/cpu/sh/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h index 3e37c8f57d..e5f45eb363 100644 --- a/cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h @@ -41,11 +41,15 @@ RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); static inline void _CPU_Context_volatile_clobber( uintptr_t pattern ) { + (void) pattern; + /* TODO */ } static inline void _CPU_Context_validate( uintptr_t pattern ) { + (void) pattern; + while (1) { /* TODO */ } @@ -68,6 +72,14 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + (void) context; + return NULL; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/sparc/cpu_asm.S b/cpukit/score/cpu/sparc/cpu_asm.S index 8947064ff8..fd7186b499 100644 --- a/cpukit/score/cpu/sparc/cpu_asm.S +++ b/cpukit/score/cpu/sparc/cpu_asm.S @@ -246,6 +246,14 @@ done_flushing: mov %g1, %psr ! restore status register and ! **** ENABLE TRAPS **** + /* + * WARNING: This code does not run with the restored stack pointer. In + * SMP configurations, it uses a processor-specific stack. In + * uniprocessor configurations, it uses the stack of the caller. In + * this case, the caller shall ensure that it is not the interrupt + * stack (which is also the system initialization stack). + */ + ld [%o1 + G5_OFFSET], %g5 ! restore the global registers ld [%o1 + G7_OFFSET], %g7 @@ -266,7 +274,9 @@ done_flushing: ldd [%o1 + I4_OFFSET], %i4 ldd [%o1 + I6_FP_OFFSET], %i6 - ldd [%o1 + O6_SP_OFFSET], %o6 ! restore the output registers + ldd [%o1 + O6_SP_OFFSET], %o6 ! restore the non-volatile output + ! registers (stack pointer, + ! link register) jmp %o7 + 8 ! return nop ! delay slot @@ -325,6 +335,23 @@ SYM(_CPU_Context_restore): ba SYM(_CPU_Context_restore_heir) mov %i0, %o1 ! in the delay slot +#if !defined(RTEMS_SMP) + .align 4 + PUBLIC(_SPARC_Start_multitasking) +SYM(_SPARC_Start_multitasking): + /* + * Restore the stack pointer right now, so that the window flushing and + * interrupts during _CPU_Context_restore_heir() use the stack of the + * heir thread. This is crucial for the interrupt handling to prevent + * a concurrent use of the interrupt stack (which is also the system + * initialization stack). + */ + ld [%o0 + O6_SP_OFFSET], %o6 + + ba SYM(_CPU_Context_restore) + nop +#endif + /* * void _SPARC_Interrupt_trap() * @@ -496,9 +523,7 @@ dont_do_the_window: bnz dont_switch_stacks ! No, then do not switch stacks #if defined(RTEMS_PROFILING) - sethi %hi(_SPARC_Counter), %o5 - ld [%o5 + %lo(_SPARC_Counter)], %l4 - call %l4 + call SYM(_SPARC_Counter_read_ISR_disabled) nop mov %o0, %o5 #else @@ -577,7 +602,7 @@ dont_switch_stacks: cmp %l7, 0 bne profiling_not_outer_most_exit nop - call %l4 ! Call _SPARC_Counter.counter_read + call SYM(_SPARC_Counter_read_ISR_disabled) mov %g1, %l4 ! Save previous interrupt status mov %o0, %o2 ! o2 = 3rd arg = interrupt exit instant mov %l3, %o1 ! o1 = 2nd arg = interrupt entry instant diff --git a/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h b/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h index bb43234128..10f34c6123 100644 --- a/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h +++ b/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h @@ -1,5 +1,14 @@ /* SPDX-License-Identifier: BSD-2-Clause */ +/** + * @file + * + * @ingroup RTEMSScoreCPUSPARC + * + * @brief This header file provides interfaces of the GRLIB-TN-0018 LEON3FT + * RETT Restart Errata fixes. + */ + /* * Copyright (C) 2020 Cobham Gaisler AB * diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h index 43b9b75bec..a21cef371f 100644 --- a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h @@ -993,6 +993,25 @@ RTEMS_NO_RETURN void _CPU_Context_switch_no_return( */ RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context ); +#if !defined(RTEMS_SMP) +/** + * @brief Starts multitasking in uniprocessor configurations. + * + * This function just sets the stack of the heir thread and then calls + * _CPU_Context_restore(). + * + * This is causes that the window flushing and interrupts during + * _CPU_Context_restore() use the stack of the heir thread. This is crucial + * for the interrupt handling to prevent a concurrent use of the interrupt + * stack (which is also the system initialization stack). + * + * @param[in] heir is the context of the heir thread. + */ +RTEMS_NO_RETURN void _SPARC_Start_multitasking( Context_Control *heir ); + +#define _CPU_Start_multitasking( _heir ) _SPARC_Start_multitasking( _heir ) +#endif + #if defined(RTEMS_SMP) uint32_t _CPU_SMP_Initialize( void ); @@ -1132,31 +1151,7 @@ typedef uint32_t CPU_Counter_ticks; uint32_t _CPU_Counter_frequency( void ); -typedef CPU_Counter_ticks ( *SPARC_Counter_read )( void ); - -/* - * The SPARC processors supported by RTEMS have no built-in CPU counter - * support. We have to use some hardware counter module for this purpose, for - * example the GPTIMER instance used by the clock driver. The BSP must provide - * an implementation of the CPU counter read function. This allows the use of - * dynamic hardware enumeration. - */ -typedef struct { - SPARC_Counter_read read_isr_disabled; - SPARC_Counter_read read; - volatile const CPU_Counter_ticks *counter_register; - volatile const uint32_t *pending_register; - uint32_t pending_mask; - CPU_Counter_ticks accumulated; - CPU_Counter_ticks interval; -} SPARC_Counter; - -extern const SPARC_Counter _SPARC_Counter; - -static inline CPU_Counter_ticks _CPU_Counter_read( void ) -{ - return ( *_SPARC_Counter.read )(); -} +CPU_Counter_ticks _CPU_Counter_read( void ); /** Type that can store a 32-bit integer or a pointer. */ typedef uintptr_t CPU_Uint32ptr; diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/sparc/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/sparc/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h index e15be48e9e..9697209a97 100644 --- a/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h @@ -251,6 +251,20 @@ static inline void _CPU_Use_thread_local_storage( __asm__ volatile ( "" : : "r" ( g7 ) ); } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + return (void *) context->g7; +} + +#if defined(RTEMS_PROFILING) +/** + * @brief Reads the CPU counter while interrupts are disabled. + */ +CPU_Counter_ticks _SPARC_Counter_read_ISR_disabled( void ); +#endif + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h b/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h deleted file mode 100644 index d9be984179..0000000000 --- a/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup RTEMSScoreCPUSPARC - * - * @brief This header file provides interfaces used by the SPARC port of RTEMS. - */ - -/* - * Copyright (C) 2016, 2018 embedded brains GmbH & Co. KG - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_SPARCIMPL_H -#define _RTEMS_SCORE_SPARCIMPL_H - -#include <rtems/score/cpu.h> - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -struct timecounter; - -/* - * Provides a mutable alias to _SPARC_Counter for use in - * _SPARC_Counter_initialize(). The _SPARC_Counter and _SPARC_Counter_mutable - * are defined via the SPARC_COUNTER_DEFINITION define. - */ -extern SPARC_Counter _SPARC_Counter_mutable; - -void _SPARC_Counter_at_tick_clock( void ); - -CPU_Counter_ticks _SPARC_Counter_read_default( void ); - -CPU_Counter_ticks _SPARC_Counter_read_up( void ); - -CPU_Counter_ticks _SPARC_Counter_read_down( void ); - -CPU_Counter_ticks _SPARC_Counter_read_clock_isr_disabled( void ); - -CPU_Counter_ticks _SPARC_Counter_read_clock( void ); - -CPU_Counter_ticks _SPARC_Counter_read_asr23( void ); - -uint32_t _SPARC_Get_timecount_up( struct timecounter * ); - -uint32_t _SPARC_Get_timecount_down( struct timecounter * ); - -uint32_t _SPARC_Get_timecount_clock( struct timecounter * ); - -uint32_t _SPARC_Get_timecount_asr23( struct timecounter * ); - -/* - * Defines the _SPARC_Counter and _SPARC_Counter_mutable global variables. - * Place this define in the global file scope of the CPU counter support file - * of the BSP. - */ -#define SPARC_COUNTER_DEFINITION \ - __asm__ ( \ - "\t.global\t_SPARC_Counter\n" \ - "\t.global\t_SPARC_Counter_mutable\n" \ - "\t.section\t.data._SPARC_Counter,\"aw\",@progbits\n" \ - "\t.align\t4\n" \ - "\t.type\t_SPARC_Counter, #object\n" \ - "\t.size\t_SPARC_Counter, 28\n" \ - "_SPARC_Counter:\n" \ - "_SPARC_Counter_mutable:\n" \ - "\t.long\t_SPARC_Counter_read_default\n" \ - "\t.long\t_SPARC_Counter_read_default\n" \ - "\t.long\t0\n" \ - "\t.long\t0\n" \ - "\t.long\t0\n" \ - "\t.long\t0\n" \ - "\t.long\t0\n" \ - "\t.previous\n" \ - ) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _RTEMS_SCORE_SPARCIMPL_H */ diff --git a/cpukit/score/cpu/sparc/sparc-counter-asm.S b/cpukit/score/cpu/sparc/sparc-counter-asm.S deleted file mode 100644 index 890876eff1..0000000000 --- a/cpukit/score/cpu/sparc/sparc-counter-asm.S +++ /dev/null @@ -1,151 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * Copyright (C) 2016, 2018 embedded brains GmbH & Co. KG - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <rtems/asm.h> - - /* - * All functions except _SPARC_Counter_read_clock() in this module are - * sometimes called with traps disabled. - */ - - .section ".text" - .align 4 - - PUBLIC(_SPARC_Counter_read_default) -SYM(_SPARC_Counter_read_default): - sethi %hi(_SPARC_Counter + 12), %o1 - ld [%o1 + %lo(_SPARC_Counter + 12)], %o0 - add %o0, 1, %o0 - st %o0, [%o1 + %lo(_SPARC_Counter + 12)] - jmp %o7 + 8 - nop - - PUBLIC(_SPARC_Counter_read_up) - PUBLIC(_SPARC_Get_timecount_up) -SYM(_SPARC_Counter_read_up): -SYM(_SPARC_Get_timecount_up): - sethi %hi(_SPARC_Counter + 8), %o0 - ld [%o0 + %lo(_SPARC_Counter + 8)], %o0 - jmp %o7 + 8 - ld [%o0], %o0 - - PUBLIC(_SPARC_Counter_read_down) - PUBLIC(_SPARC_Get_timecount_down) -SYM(_SPARC_Counter_read_down): -SYM(_SPARC_Get_timecount_down): - sethi %hi(_SPARC_Counter + 8), %o0 - ld [%o0 + %lo(_SPARC_Counter + 8)], %o0 - ld [%o0], %o0 - jmp %o7 + 8 - xnor %g0, %o0, %o0 - - /* - * For the corresponding C code is something like this: - * - * CPU_Counter_ticks _SPARC_Counter_read_clock_isr_disabled( void ) - * { - * const SPARC_Counter *ctr; - * CPU_Counter_ticks ticks; - * CPU_Counter_ticks accumulated; - * - * ctr = &_SPARC_Counter; - * ticks = *ctr->counter_register; - * accumulated = ctr->accumulated; - * - * if ( ( *ctr->pending_register & ctr->pending_mask ) != 0 ) { - * ticks = *ctr->counter_register; - * accumulated += ctr->interval; - * } - * - * return accumulated - ticks; - * } - */ - PUBLIC(_SPARC_Counter_read_clock_isr_disabled) -SYM(_SPARC_Counter_read_clock_isr_disabled): - sethi %hi(_SPARC_Counter), %o5 - or %o5, %lo(_SPARC_Counter), %o5 - ld [%o5 + 8], %o3 - ld [%o5 + 12], %o4 - ld [%o5 + 16], %o2 - ld [%o3], %o0 - ld [%o4], %o1 - btst %o1, %o2 - bne .Lpending_isr_disabled - ld [%o5 + 20], %o4 - jmp %o7 + 8 - sub %o4, %o0, %o0 -.Lpending_isr_disabled: - ld [%o5 + 24], %o5 - ld [%o3], %o0 - add %o4, %o5, %o4 - jmp %o7 + 8 - sub %o4, %o0, %o0 - - /* - * For the corresponding C code see - * _SPARC_Counter_read_clock_isr_disabled() above. - */ - PUBLIC(_SPARC_Counter_read_clock) - PUBLIC(_SPARC_Get_timecount_clock) -SYM(_SPARC_Counter_read_clock): -SYM(_SPARC_Get_timecount_clock): - sethi %hi(_SPARC_Counter), %o5 - or %o5, %lo(_SPARC_Counter), %o5 - ta SPARC_SWTRAP_IRQDIS - ld [%o5 + 8], %o3 - ld [%o5 + 12], %o4 - ld [%o5 + 16], %o2 - ld [%o3], %o0 - ld [%o4], %o1 - btst %o1, %o2 - bne .Lpending - ld [%o5 + 20], %o4 - ta SPARC_SWTRAP_IRQEN -#ifdef __FIX_LEON3FT_TN0018 - /* A nop is added to work around the GRLIB-TN-0018 errata */ - nop -#endif - jmp %o7 + 8 - sub %o4, %o0, %o0 -.Lpending: - ld [%o5 + 24], %o5 - ld [%o3], %o0 - ta SPARC_SWTRAP_IRQEN - add %o4, %o5, %o4 - jmp %o7 + 8 - sub %o4, %o0, %o0 - - PUBLIC(_SPARC_Counter_read_asr23) - PUBLIC(_SPARC_Get_timecount_asr23) -SYM(_SPARC_Counter_read_asr23): -SYM(_SPARC_Get_timecount_asr23): - jmp %o7 + 8 - mov %asr23, %o0 diff --git a/cpukit/score/cpu/sparc/sparc-isr-handler.S b/cpukit/score/cpu/sparc/sparc-isr-handler.S index cb4fb345a3..9ecb44e870 100644 --- a/cpukit/score/cpu/sparc/sparc-isr-handler.S +++ b/cpukit/score/cpu/sparc/sparc-isr-handler.S @@ -231,9 +231,7 @@ dont_do_the_window: bnz dont_switch_stacks ! No, then do not switch stacks #if defined(RTEMS_PROFILING) - sethi %hi(_SPARC_Counter), %o5 - ld [%o5 + %lo(_SPARC_Counter)], %l4 - call %l4 + call SYM(_SPARC_Counter_read_ISR_disabled) nop mov %o0, %o5 #else @@ -335,7 +333,7 @@ pil_fixed: cmp %l7, 0 bne profiling_not_outer_most_exit nop - call %l4 ! Call _SPARC_Counter.counter_read + call SYM(_SPARC_Counter_read_ISR_disabled) mov %g1, %l4 ! Save previous interrupt status mov %o0, %o2 ! o2 = 3rd arg = interrupt exit instant mov %l3, %o1 ! o1 = 2nd arg = interrupt entry instant diff --git a/cpukit/score/cpu/sparc/syscall.S b/cpukit/score/cpu/sparc/syscall.S index 0beffd4162..ee21c1b005 100644 --- a/cpukit/score/cpu/sparc/syscall.S +++ b/cpukit/score/cpu/sparc/syscall.S @@ -44,8 +44,10 @@ SYM(syscall): ta 0 ! syscall 1, halt with %g1,%g2,%g3 info PUBLIC(sparc_syscall_exit) + PUBLIC(_CPU_Fatal_halt) SYM(sparc_syscall_exit): +SYM(_CPU_Fatal_halt): mov SYS_exit, %g1 mov %o0, %g2 ! Additional exit code 1 diff --git a/cpukit/score/cpu/sparc/syscall.h b/cpukit/score/cpu/sparc/syscall.h index 2f20886840..6fc8fa3a6f 100644 --- a/cpukit/score/cpu/sparc/syscall.h +++ b/cpukit/score/cpu/sparc/syscall.h @@ -1 +1,9 @@ +/** + * @file + * + * @ingroup RTEMSScoreCPUSPARC + * + * @brief This header file provides system call interfaces. + */ + #define SYS_exit 1 diff --git a/cpukit/score/cpu/sparc64/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/sparc64/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/sparc64/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h index c49c637805..25a362c350 100644 --- a/cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h @@ -60,11 +60,15 @@ RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); static inline void _CPU_Context_volatile_clobber( uintptr_t pattern ) { + (void) pattern; + /* TODO */ } static inline void _CPU_Context_validate( uintptr_t pattern ) { + (void) pattern; + while (1) { /* TODO */ } @@ -87,6 +91,14 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + (void) context; + return NULL; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/v850/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/v850/include/rtems/score/cpuatomic.h deleted file mode 100644 index 01bb99cda3..0000000000 --- a/cpukit/score/cpu/v850/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h index 5ec528961c..5bc1c42459 100644 --- a/cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h @@ -60,11 +60,15 @@ RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); static inline void _CPU_Context_volatile_clobber( uintptr_t pattern ) { + (void) pattern; + /* TODO */ } static inline void _CPU_Context_validate( uintptr_t pattern ) { + (void) pattern; + while (1) { /* TODO */ } @@ -87,6 +91,14 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + (void) context; + return NULL; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/x86_64/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/x86_64/include/rtems/score/cpuatomic.h deleted file mode 100644 index 598ee76b20..0000000000 --- a/cpukit/score/cpu/x86_64/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_ATOMIC_CPU_H -#define _RTEMS_SCORE_ATOMIC_CPU_H - -#include <rtems/score/cpustdatomic.h> - -#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h index e0e301b6bc..d4b7a71009 100644 --- a/cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h @@ -44,21 +44,25 @@ RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); static inline void _CPU_Context_volatile_clobber( uintptr_t pattern ) { - /* TODO */ -} + (void) pattern; -static inline void _CPU_Instruction_illegal( void ) -{ - __asm__ volatile ( ".word 0" ); + /* TODO */ } static inline void _CPU_Context_validate( uintptr_t pattern ) { + (void) pattern; + while (1) { /* TODO */ } } +static inline void _CPU_Instruction_illegal( void ) +{ + __asm__ volatile ( ".word 0" ); +} + static inline void _CPU_Instruction_no_operation( void ) { __asm__ volatile ( "nop" ); @@ -71,6 +75,14 @@ static inline void _CPU_Use_thread_local_storage( (void) context; } +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + (void) context; + return NULL; +} + #ifdef __cplusplus } #endif diff --git a/cpukit/score/src/hash.c b/cpukit/score/src/hash.c index dc9143f4c0..0b9f127e54 100644 --- a/cpukit/score/src/hash.c +++ b/cpukit/score/src/hash.c @@ -39,7 +39,7 @@ #include <rtems/score/hash.h> #include <rtems/score/assert.h> -#include <rtems/score/io.h> +#include <rtems/base64.h> #include <limits.h> @@ -64,7 +64,7 @@ void _Hash_Finalize( Hash_Context *context, Hash_Control *hash ) context->hash = hash; context->index = 0; hash->chars[ sizeof( *hash ) - 1 ] = '\0'; - n = _IO_Base64url( + n = _Base64url_Encode( _Hash_Put_char, context, digest, diff --git a/cpukit/score/src/iobase64.c b/cpukit/score/src/iobase64.c deleted file mode 100644 index 27b977c8a0..0000000000 --- a/cpukit/score/src/iobase64.c +++ /dev/null @@ -1,111 +0,0 @@ -/* SPDX-License-Identifier: ISC */ - -/** - * @file - * - * @ingroup RTEMSScoreIO - * - * @brief This source file contains the implementation of - * _IO_Base64() and _IO_Base64url(). - */ - -/* - * Copyright (C) 2020, 2021 embedded brains GmbH & Co. KG - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1998-2001, 2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include <rtems/score/io.h> - -static void -_IO_Put(int c, void *arg, IO_Put_char put_char) -{ - (*put_char)(c, arg); -} - -static int -_IO_Base64_with_encoding(IO_Put_char put_char, void *arg, const void *src, - size_t srclen, const char *wordbreak, int wordlen, const char *encoding) -{ - unsigned int loops = 0; - const unsigned char *in = src; - int out = 0; - - if (wordlen < 4) { - wordlen = 4; - } - - while (srclen > 2) { - _IO_Put(encoding[(in[0]>>2)&0x3f], arg, put_char); - _IO_Put(encoding[((in[0]<<4)&0x30)| - ((in[1]>>4)&0x0f)], arg, put_char); - _IO_Put(encoding[((in[1]<<2)&0x3c)| - ((in[2]>>6)&0x03)], arg, put_char); - _IO_Put(encoding[in[2]&0x3f], arg, put_char); - in += 3; - srclen -= 3; - out += 4; - - loops++; - if (srclen != 0 && - (int)((loops + 1) * 4) >= wordlen) - { - const char *w = wordbreak; - loops = 0; - while (*w != '\0') { - _IO_Put(*w, arg, put_char); - ++w; - ++out; - } - } - } - if (srclen == 2) { - _IO_Put(encoding[(in[0]>>2)&0x3f], arg, put_char); - _IO_Put(encoding[((in[0]<<4)&0x30)| - ((in[1]>>4)&0x0f)], arg, put_char); - _IO_Put(encoding[((in[1]<<2)&0x3c)], arg, put_char); - _IO_Put('=', arg, put_char); - out += 4; - } else if (srclen == 1) { - _IO_Put(encoding[(in[0]>>2)&0x3f], arg, put_char); - _IO_Put(encoding[((in[0]<<4)&0x30)], arg, put_char); - _IO_Put('=', arg, put_char); - _IO_Put('=', arg, put_char); - out += 4; - } - return out; -} - -static const char base64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - -int -_IO_Base64(IO_Put_char put_char, void *arg, const void *src, size_t srclen, - const char *wordbreak, int wordlen) -{ - return _IO_Base64_with_encoding(put_char, arg, src, srclen, wordbreak, - wordlen, base64); -} - -static const char base64url[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_="; - -int -_IO_Base64url(IO_Put_char put_char, void *arg, const void *src, size_t srclen, - const char *wordbreak, int wordlen) -{ - return _IO_Base64_with_encoding(put_char, arg, src, srclen, wordbreak, - wordlen, base64url); -} diff --git a/cpukit/score/src/isr.c b/cpukit/score/src/isr.c index 75df00e228..7337028b0f 100644 --- a/cpukit/score/src/isr.c +++ b/cpukit/score/src/isr.c @@ -44,6 +44,8 @@ #include <rtems/score/percpu.h> #include <rtems/config.h> +const char * const volatile _ISR_Stack_size_object = _ISR_Stack_size; + void _ISR_Handler_initialization( void ) { uint32_t cpu_max; diff --git a/cpukit/score/src/objectextendinformation.c b/cpukit/score/src/objectextendinformation.c index 414766f219..9a627b1a7c 100644 --- a/cpukit/score/src/objectextendinformation.c +++ b/cpukit/score/src/objectextendinformation.c @@ -59,7 +59,7 @@ Objects_Maximum _Objects_Extend_information( uint32_t index_base; uint32_t index_end; uint32_t index; - Objects_Maximum extend_count; + uint32_t extend_count; Objects_Maximum old_maximum; uint32_t new_maximum; size_t object_block_size; diff --git a/cpukit/score/src/objectinitializeinformation.c b/cpukit/score/src/objectinitializeinformation.c index 3482f2871e..7c1bfd877f 100644 --- a/cpukit/score/src/objectinitializeinformation.c +++ b/cpukit/score/src/objectinitializeinformation.c @@ -42,7 +42,6 @@ #include <rtems/score/objectimpl.h> #include <rtems/score/address.h> #include <rtems/score/chainimpl.h> -#include <rtems/score/interr.h> #include <rtems/score/sysstate.h> void _Objects_Initialize_information( diff --git a/cpukit/score/src/processormaskcopy.c b/cpukit/score/src/processormaskcopy.c index 863bd1574e..3f1c2cf250 100644 --- a/cpukit/score/src/processormaskcopy.c +++ b/cpukit/score/src/processormaskcopy.c @@ -39,7 +39,7 @@ #include "config.h" #endif -#include <rtems/score/processormask.h> +#include <rtems/score/processormaskimpl.h> const Processor_mask _Processor_mask_The_one_and_only = { .__bits[ 0 ] = 1 }; diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c index ca49f6f417..78291b7798 100644 --- a/cpukit/score/src/threadchangepriority.c +++ b/cpukit/score/src/threadchangepriority.c @@ -111,6 +111,7 @@ static void _Thread_Priority_action_change( void *arg ) { + (void) arg; _Thread_Set_scheduler_node_priority( priority_aggregation, priority_group_order diff --git a/cpukit/score/src/threadq.c b/cpukit/score/src/threadq.c index e694029a46..3c6d72bd14 100644 --- a/cpukit/score/src/threadq.c +++ b/cpukit/score/src/threadq.c @@ -179,5 +179,7 @@ void _Thread_queue_MP_callout_do_nothing( ) { /* Do nothing */ + (void) the_proxy; + (void) mp_id; } #endif diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c index e43efd925b..038c483f65 100644 --- a/cpukit/score/src/threadqenqueue.c +++ b/cpukit/score/src/threadqenqueue.c @@ -400,6 +400,7 @@ void _Thread_queue_Deadlock_status( Thread_Control *the_thread ) void _Thread_queue_Deadlock_fatal( Thread_Control *the_thread ) { + (void) the_thread; _Internal_error( INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK ); } diff --git a/cpukit/score/src/threadqops.c b/cpukit/score/src/threadqops.c index 83e00ca3ae..9a09b4c442 100644 --- a/cpukit/score/src/threadqops.c +++ b/cpukit/score/src/threadqops.c @@ -156,6 +156,8 @@ static void _Thread_queue_FIFO_do_initialize( { Scheduler_Node *scheduler_node; + (void) queue; + (void) queue_context; scheduler_node = _Thread_Scheduler_get_home_node( the_thread ); _Chain_Initialize_node( &scheduler_node->Wait.Priority.Node.Node.Chain ); @@ -291,6 +293,7 @@ static Thread_queue_Priority_queue *_Thread_queue_Priority_queue_by_index( ) { #if defined(RTEMS_SMP) + _Assert( scheduler_index < _Scheduler_Count ); return &heads->Priority[ scheduler_index ]; #else (void) scheduler_index; diff --git a/cpukit/score/src/threadqtimeout.c b/cpukit/score/src/threadqtimeout.c index acb3c1d048..e30a2ffded 100644 --- a/cpukit/score/src/threadqtimeout.c +++ b/cpukit/score/src/threadqtimeout.c @@ -53,6 +53,7 @@ void _Thread_queue_Add_timeout_ticks( { Watchdog_Interval ticks; + (void) queue; ticks = queue_context->Timeout.ticks; if ( ticks != WATCHDOG_NO_TIMEOUT ) { diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c index 16b09a96eb..72326682ca 100644 --- a/cpukit/score/src/threadrestart.c +++ b/cpukit/score/src/threadrestart.c @@ -46,10 +46,8 @@ #include <rtems/score/apimutex.h> #include <rtems/score/assert.h> #include <rtems/score/chainimpl.h> -#include <rtems/score/freechainimpl.h> #include <rtems/score/isrlock.h> #include <rtems/score/schedulerimpl.h> -#include <rtems/score/stackimpl.h> #include <rtems/score/sysstate.h> #include <rtems/score/threadqimpl.h> #include <rtems/score/userextimpl.h> @@ -85,6 +83,7 @@ static Thread_Control *_Thread_Join_flush_filter( { Thread_Join_context *join_context; + (void) queue; join_context = (Thread_Join_context *) queue_context; the_thread->Wait.return_argument = join_context->exit_value; diff --git a/cpukit/score/src/tlsallocsize.c b/cpukit/score/src/tlsallocsize.c index f78239192c..fa28391b83 100644 --- a/cpukit/score/src/tlsallocsize.c +++ b/cpukit/score/src/tlsallocsize.c @@ -10,7 +10,7 @@ */ /* - * Copyright (C) 2014, 2022 embedded brains GmbH & Co. KG + * Copyright (C) 2014, 2023 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,14 +42,47 @@ #include <rtems/score/interr.h> #include <rtems/score/thread.h> +extern char _TLS_Data_begin[]; + +extern char _TLS_Data_size[]; + +extern char _TLS_BSS_begin[]; + +extern char _TLS_BSS_size[]; + +extern char _TLS_Size[]; + +/** + * @brief The TLS section alignment. + * + * This symbol is provided by the linker command file as the maximum alignment + * of the .tdata and .tbss sections. The linker ensures that the first TLS + * output section is aligned to the maximum alignment of all TLS output + * sections, see function _bfd_elf_tls_setup() in bfd/elflink.c of the GNU + * Binutils sources. The linker command file must take into account the case + * that the .tdata section is empty and the .tbss section is non-empty. + */ +extern char _TLS_Alignment[]; + +const volatile TLS_Configuration _TLS_Configuration = { + .data_begin = _TLS_Data_begin, + .data_size = _TLS_Data_size, + .bss_begin = _TLS_BSS_begin, + .bss_size = _TLS_BSS_size, + .size = _TLS_Size, + .alignment = _TLS_Alignment +}; + static uintptr_t _TLS_Allocation_size; uintptr_t _TLS_Get_allocation_size( void ) { - uintptr_t size; - uintptr_t allocation_size; + const volatile TLS_Configuration *config; + uintptr_t size; + uintptr_t allocation_size; - size = _TLS_Get_size(); + config = &_TLS_Configuration; + size = (uintptr_t) config->size; if ( size == 0 ) { return 0; @@ -66,7 +99,7 @@ uintptr_t _TLS_Get_allocation_size( void ) * shall meet the stack alignment requirement. */ stack_align = CPU_STACK_ALIGNMENT; - tls_align = RTEMS_ALIGN_UP( (uintptr_t) _TLS_Alignment, stack_align ); + tls_align = RTEMS_ALIGN_UP( (uintptr_t) config->alignment, stack_align ); #ifndef __i386__ /* Reserve space for the dynamic thread vector */ diff --git a/cpukit/score/src/userextiterate.c b/cpukit/score/src/userextiterate.c index 25f0f9658b..cae76d173c 100644 --- a/cpukit/score/src/userextiterate.c +++ b/cpukit/score/src/userextiterate.c @@ -47,8 +47,6 @@ #include <rtems/score/userextimpl.h> -#include <pthread.h> - User_extensions_List _User_extensions_List = { CHAIN_INITIALIZER_EMPTY( _User_extensions_List.Active ), CHAIN_ITERATOR_REGISTRY_INITIALIZER( _User_extensions_List.Iterators ) @@ -120,6 +118,8 @@ void _User_extensions_Thread_begin_visitor( { User_extensions_thread_begin_extension callout = callouts->thread_begin; + (void) arg; + if ( callout != NULL ) { (*callout)( executing ); } |