On Mon, Mar 22, 2021 at 9:33 AM Christian MAUDERER <christian.maude...@embedded-brains.de> wrote: > > Am 22.03.21 um 15:55 schrieb Gedare Bloom: > > On Mon, Mar 22, 2021 at 2:27 AM Christian Mauderer > > <christian.maude...@embedded-brains.de> wrote: > >> > >> Adds a peek function that allows (for example) a file system to suggest > >> the next blocks that should be used for read ahead. This can increase > >> the read speed of fragmented files. > >> --- > >> cpukit/include/rtems/bdbuf.h | 21 ++++ > >> cpukit/include/rtems/diskdevs.h | 24 ++++- > >> cpukit/libblock/src/bdbuf.c | 84 +++++++++++---- > >> cpukit/libblock/src/blkdev-print-stats.c | 2 + > >> testsuites/fstests/fsdosfswrite01/init.c | 3 + > >> testsuites/libtests/block14/block14.scn | 19 +++- > >> testsuites/libtests/block14/init.c | 124 +++++++++++++++++------ > >> 7 files changed, 217 insertions(+), 60 deletions(-) > >> > >> diff --git a/cpukit/include/rtems/bdbuf.h b/cpukit/include/rtems/bdbuf.h > >> index fbb4fc05e9..0cde571816 100644 > >> --- a/cpukit/include/rtems/bdbuf.h > >> +++ b/cpukit/include/rtems/bdbuf.h > >> @@ -539,6 +539,27 @@ rtems_bdbuf_read ( > >> rtems_bdbuf_buffer** bd > >> ); > >> > >> +/** > > missing @brief? > > > > rest of this looks fine on a quick skim > > Didn't seem to be the style of the other comments in that header. So I > didn't add one here either. Would the following one be OK: > > @brief: Give a hint which blocks should be cached next. > Sure. I don't have the context for the other functions. I guess that the file doesn't quite adhere to the conventions :)
> > > >> + * Provide a hint to the read ahead mechanism which blocks should be > >> cached > >> + * next. This overwrites the default linear pattern. You should use it in > >> (for > >> + * example) a file system to tell bdbuf where the next part of a > >> fragmented file > >> + * is. If you know the length of the file, you can provide that too. > >> + * > >> + * Before you can use this function, the rtems_bdbuf_init() routine must > >> be > >> + * called at least once to initialize everything. Otherwise you might get > >> + * unexpected results. > >> + * > >> + * @param dd [in] The disk device. > >> + * @param block [in] Linear media block number. > >> + * @param nr_blocks [in] Number of consecutive blocks that can be > >> pre-fetched. > >> + */ > >> +void > >> +rtems_bdbuf_peek ( > >> + rtems_disk_device *dd, > >> + rtems_blkdev_bnum block, > >> + uint32_t nr_blocks > >> +); > >> + > >> /** > >> * Release the buffer obtained by a read call back to the cache. If the > >> buffer > >> * was obtained by a get call and was not already in the cache the > >> release > >> diff --git a/cpukit/include/rtems/diskdevs.h > >> b/cpukit/include/rtems/diskdevs.h > >> index 85d157dcd5..527a8cc955 100644 > >> --- a/cpukit/include/rtems/diskdevs.h > >> +++ b/cpukit/include/rtems/diskdevs.h > >> @@ -58,6 +58,11 @@ typedef int (*rtems_block_device_ioctl)( > >> */ > >> #define RTEMS_DISK_READ_AHEAD_NO_TRIGGER ((rtems_blkdev_bnum) -1) > >> > >> +/** > >> + * @brief Size value to set number of blocks based on config and disk > >> size. > >> + */ > >> +#define RTEMS_DISK_READ_AHEAD_SIZE_AUTO (0) > >> + > >> /** > >> * @brief Block device read-ahead control. > >> */ > >> @@ -71,7 +76,8 @@ typedef struct { > >> * @brief Block value to trigger the read-ahead request. > >> * > >> * A value of @ref RTEMS_DISK_READ_AHEAD_NO_TRIGGER will disable > >> further > >> - * read-ahead requests since no valid block can have this value. > >> + * read-ahead requests (except the ones triggered by @a > >> rtems_bdbuf_peek) > >> + * since no valid block can have this value. > >> */ > >> rtems_blkdev_bnum trigger; > >> > >> @@ -82,6 +88,14 @@ typedef struct { > >> * be arbitrary. > >> */ > >> rtems_blkdev_bnum next; > >> + > >> + /** > >> + * @brief Size of the next read-ahead request in blocks. > >> + * > >> + * A value of @ref RTEMS_DISK_READ_AHEAD_SIZE_AUTO will try to read the > >> rest > >> + * of the disk but at most the configured max_read_ahead_blocks. > >> + */ > >> + uint32_t nr_blocks; > >> } rtems_blkdev_read_ahead; > >> > >> /** > >> @@ -110,10 +124,16 @@ typedef struct { > >> /** > >> * @brief Read-ahead transfer count. > >> * > >> - * Each read-ahead transfer may read multiple blocks. > >> + * Each read-ahead transfer may read multiple blocks. This counts all > >> + * transfers (including peeks). > >> */ > >> uint32_t read_ahead_transfers; > >> > >> + /** > >> + * @brief Read-ahead transfers caused by a peek. > >> + */ > >> + uint32_t read_ahead_peeks; > >> + > >> /** > >> * @brief Count of blocks transfered from the device. > >> */ > >> diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c > >> index a7d471507c..8aadf9c8ae 100644 > >> --- a/cpukit/libblock/src/bdbuf.c > >> +++ b/cpukit/libblock/src/bdbuf.c > >> @@ -2018,6 +2018,23 @@ rtems_bdbuf_read_ahead_reset (rtems_disk_device *dd) > >> dd->read_ahead.trigger = RTEMS_DISK_READ_AHEAD_NO_TRIGGER; > >> } > >> > >> +static void > >> +rtems_bdbuf_read_ahead_add_to_chain (rtems_disk_device *dd) > >> +{ > >> + rtems_status_code sc; > >> + rtems_chain_control *chain = &bdbuf_cache.read_ahead_chain; > >> + > >> + if (rtems_chain_is_empty (chain)) > >> + { > >> + sc = rtems_event_send (bdbuf_cache.read_ahead_task, > >> + RTEMS_BDBUF_READ_AHEAD_WAKE_UP); > >> + if (sc != RTEMS_SUCCESSFUL) > >> + rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_RA_WAKE_UP); > >> + } > >> + > >> + rtems_chain_append_unprotected (chain, &dd->read_ahead.node); > >> +} > >> + > >> static void > >> rtems_bdbuf_check_read_ahead_trigger (rtems_disk_device *dd, > >> rtems_blkdev_bnum block) > >> @@ -2026,18 +2043,8 @@ rtems_bdbuf_check_read_ahead_trigger > >> (rtems_disk_device *dd, > >> && dd->read_ahead.trigger == block > >> && !rtems_bdbuf_is_read_ahead_active (dd)) > >> { > >> - rtems_status_code sc; > >> - rtems_chain_control *chain = &bdbuf_cache.read_ahead_chain; > >> - > >> - if (rtems_chain_is_empty (chain)) > >> - { > >> - sc = rtems_event_send (bdbuf_cache.read_ahead_task, > >> - RTEMS_BDBUF_READ_AHEAD_WAKE_UP); > >> - if (sc != RTEMS_SUCCESSFUL) > >> - rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_RA_WAKE_UP); > >> - } > >> - > >> - rtems_chain_append_unprotected (chain, &dd->read_ahead.node); > >> + dd->read_ahead.nr_blocks = RTEMS_DISK_READ_AHEAD_SIZE_AUTO; > >> + rtems_bdbuf_read_ahead_add_to_chain(dd); > >> } > >> } > >> > >> @@ -2112,6 +2119,24 @@ rtems_bdbuf_read (rtems_disk_device *dd, > >> return sc; > >> } > >> > >> +void > >> +rtems_bdbuf_peek (rtems_disk_device *dd, > >> + rtems_blkdev_bnum block, > >> + uint32_t nr_blocks) > >> +{ > >> + rtems_bdbuf_lock_cache (); > >> + > >> + if (bdbuf_cache.read_ahead_enabled && nr_blocks > 0) > >> + { > >> + rtems_bdbuf_read_ahead_reset(dd); > >> + dd->read_ahead.next = block; > >> + dd->read_ahead.nr_blocks = nr_blocks; > >> + rtems_bdbuf_read_ahead_add_to_chain(dd); > >> + } > >> + > >> + rtems_bdbuf_unlock_cache (); > >> +} > >> + > >> static rtems_status_code > >> rtems_bdbuf_check_bd_and_lock_cache (rtems_bdbuf_buffer *bd, const char > >> *kind) > >> { > >> @@ -2952,18 +2977,33 @@ rtems_bdbuf_read_ahead_task (rtems_task_argument > >> arg) > >> > >> if (bd != NULL) > >> { > >> - uint32_t transfer_count = dd->block_count - block; > >> + uint32_t transfer_count = dd->read_ahead.nr_blocks; > >> + uint32_t blocks_until_end_of_disk = dd->block_count - block; > >> uint32_t max_transfer_count = > >> bdbuf_config.max_read_ahead_blocks; > >> > >> - if (transfer_count >= max_transfer_count) > >> - { > >> - transfer_count = max_transfer_count; > >> - dd->read_ahead.trigger = block + transfer_count / 2; > >> - dd->read_ahead.next = block + transfer_count; > >> - } > >> - else > >> - { > >> - dd->read_ahead.trigger = RTEMS_DISK_READ_AHEAD_NO_TRIGGER; > >> + if (transfer_count == RTEMS_DISK_READ_AHEAD_SIZE_AUTO) { > >> + transfer_count = blocks_until_end_of_disk; > >> + > >> + if (transfer_count >= max_transfer_count) > >> + { > >> + transfer_count = max_transfer_count; > >> + dd->read_ahead.trigger = block + transfer_count / 2; > >> + dd->read_ahead.next = block + transfer_count; > >> + } > >> + else > >> + { > >> + dd->read_ahead.trigger = RTEMS_DISK_READ_AHEAD_NO_TRIGGER; > >> + } > >> + } else { > >> + if (transfer_count > blocks_until_end_of_disk) { > >> + transfer_count = blocks_until_end_of_disk; > >> + } > >> + > >> + if (transfer_count > max_transfer_count) { > >> + transfer_count = max_transfer_count; > >> + } > >> + > >> + ++dd->stats.read_ahead_peeks; > >> } > >> > >> ++dd->stats.read_ahead_transfers; > >> diff --git a/cpukit/libblock/src/blkdev-print-stats.c > >> b/cpukit/libblock/src/blkdev-print-stats.c > >> index 8edf24fd8c..539ff08157 100644 > >> --- a/cpukit/libblock/src/blkdev-print-stats.c > >> +++ b/cpukit/libblock/src/blkdev-print-stats.c > >> @@ -47,6 +47,7 @@ void rtems_blkdev_print_stats( > >> " READ HITS | %" PRIu32 "\n" > >> " READ MISSES | %" PRIu32 "\n" > >> " READ AHEAD TRANSFERS | %" PRIu32 "\n" > >> + " READ AHEAD PEEKS | %" PRIu32 "\n" > >> " READ BLOCKS | %" PRIu32 "\n" > >> " READ ERRORS | %" PRIu32 "\n" > >> " WRITE TRANSFERS | %" PRIu32 "\n" > >> @@ -59,6 +60,7 @@ void rtems_blkdev_print_stats( > >> stats->read_hits, > >> stats->read_misses, > >> stats->read_ahead_transfers, > >> + stats->read_ahead_peeks, > >> stats->read_blocks, > >> stats->read_errors, > >> stats->write_transfers, > >> diff --git a/testsuites/fstests/fsdosfswrite01/init.c > >> b/testsuites/fstests/fsdosfswrite01/init.c > >> index e5d8e5d6dd..64b43b7919 100644 > >> --- a/testsuites/fstests/fsdosfswrite01/init.c > >> +++ b/testsuites/fstests/fsdosfswrite01/init.c > >> @@ -129,6 +129,7 @@ static void test_normal_file_write( > >> .read_hits = 0, > >> .read_misses = 0, > >> .read_ahead_transfers = 0, > >> + .read_ahead_peeks = 0, > >> .read_blocks = 0, > >> .read_errors = 0, > >> .write_transfers = 1, > >> @@ -139,6 +140,7 @@ static void test_normal_file_write( > >> .read_hits = 3, > >> .read_misses = 2, > >> .read_ahead_transfers = 0, > >> + .read_ahead_peeks = 0, > >> .read_blocks = 2, > >> .read_errors = 0, > >> .write_transfers = 1, > >> @@ -149,6 +151,7 @@ static void test_normal_file_write( > >> .read_hits = 3, > >> .read_misses = 3, > >> .read_ahead_transfers = 0, > >> + .read_ahead_peeks = 0, > >> .read_blocks = 3, > >> .read_errors = 0, > >> .write_transfers = 1, > >> diff --git a/testsuites/libtests/block14/block14.scn > >> b/testsuites/libtests/block14/block14.scn > >> index 7170522579..cf5518adfd 100644 > >> --- a/testsuites/libtests/block14/block14.scn > >> +++ b/testsuites/libtests/block14/block14.scn > >> @@ -6,19 +6,30 @@ action 3 > >> action 4 > >> action 5 > >> action 6 > >> +action 7 > >> +action 8 > >> +action 9 > >> +action 10 > >> +action 11 > >> +action 12 > >> +action 13 > >> +action 14 > >> +action 15 > >> > >> ------------------------------------------------------------------------------- > >> DEVICE STATISTICS > >> > >> ----------------------+-------------------------------------------------------- > >> MEDIA BLOCK SIZE | 0 > >> MEDIA BLOCK COUNT | 1 > >> BLOCK SIZE | 2 > >> - READ HITS | 2 > >> - READ MISSES | 3 > >> - READ AHEAD TRANSFERS | 2 > >> - READ BLOCKS | 5 > >> + READ HITS | 4 > >> + READ MISSES | 7 > >> + READ AHEAD TRANSFERS | 6 > >> + READ AHEAD PEEKS | 3 > >> + READ BLOCKS | 13 > >> READ ERRORS | 1 > >> WRITE TRANSFERS | 2 > >> WRITE BLOCKS | 2 > >> WRITE ERRORS | 1 > >> > >> ----------------------+-------------------------------------------------------- > >> + > >> *** END OF TEST BLOCK 14 *** > >> diff --git a/testsuites/libtests/block14/init.c > >> b/testsuites/libtests/block14/init.c > >> index b4e73aadc9..13b7ab05ad 100644 > >> --- a/testsuites/libtests/block14/init.c > >> +++ b/testsuites/libtests/block14/init.c > >> @@ -29,9 +29,9 @@ > >> > >> const char rtems_test_name[] = "BLOCK 14"; > >> > >> -#define ACTION_COUNT 7 > >> +#define ACTION_COUNT 16 > >> > >> -#define BLOCK_COUNT 6 > >> +#define BLOCK_COUNT 14 > >> > >> #define DISK_PATH "/disk" > >> > >> @@ -42,50 +42,104 @@ typedef struct { > >> rtems_blkdev_bnum block, > >> rtems_bdbuf_buffer **bd_ptr > >> ); > >> + void (*peek)( > >> + rtems_disk_device *dd, > >> + rtems_blkdev_bnum block, > >> + uint32_t nr_blocks > >> + ); > >> rtems_status_code expected_get_status; > >> rtems_status_code (*release)(rtems_bdbuf_buffer *bd); > >> } test_action; > >> > >> static const test_action actions [ACTION_COUNT] = { > >> - { 0, rtems_bdbuf_read, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> - { 1, rtems_bdbuf_read, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> - { 2, rtems_bdbuf_read, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> - { 0, rtems_bdbuf_read, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> - { 4, rtems_bdbuf_get, RTEMS_SUCCESSFUL, rtems_bdbuf_sync }, > >> - { 5, rtems_bdbuf_read, RTEMS_IO_ERROR, rtems_bdbuf_release }, > >> - { 5, rtems_bdbuf_get, RTEMS_SUCCESSFUL, rtems_bdbuf_sync } > >> + /* normal read ahead */ > >> + { 0, rtems_bdbuf_read, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> + { 1, rtems_bdbuf_read, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> + { 2, rtems_bdbuf_read, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> + > >> + /* re-read a cached block */ > >> + { 0, rtems_bdbuf_read, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> + > >> + /* cause some writes */ > >> + { 4, rtems_bdbuf_get, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_sync }, > >> + { 5, rtems_bdbuf_read, NULL, RTEMS_IO_ERROR, rtems_bdbuf_release }, > >> + { 5, rtems_bdbuf_get, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_sync }, > >> + > >> + /* interrupt normal read ahead with a peek */ > >> + { 9, rtems_bdbuf_read, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> + { 13, NULL, rtems_bdbuf_peek, 0, NULL }, > >> + { 10, rtems_bdbuf_read, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> + { 11, rtems_bdbuf_read, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> + { 12, rtems_bdbuf_read, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> + > >> + /* peek with hit */ > >> + { 6, NULL, rtems_bdbuf_peek, 0, NULL }, > >> + { 6, rtems_bdbuf_read, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> + > >> + /* (wrong) peek with reading different block */ > >> + { 8, NULL, rtems_bdbuf_peek, 0, NULL }, > >> + { 7, rtems_bdbuf_read, NULL, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, > >> }; > >> > >> -#define STATS(a, b, c, d, e, f, g, h) \ > >> +#define STATS(a, b, c, d, e, f, g, h, i) \ > >> { \ > >> .read_hits = a, \ > >> .read_misses = b, \ > >> .read_ahead_transfers = c, \ > >> - .read_blocks = d, \ > >> - .read_errors = e, \ > >> - .write_transfers = f, \ > >> - .write_blocks = g, \ > >> - .write_errors = h \ > >> + .read_ahead_peeks = d, \ > >> + .read_blocks = e, \ > >> + .read_errors = f, \ > >> + .write_transfers = g, \ > >> + .write_blocks = h, \ > >> + .write_errors = i \ > >> } > >> > >> static const rtems_blkdev_stats expected_stats [ACTION_COUNT] = { > >> - STATS(0, 1, 0, 1, 0, 0, 0, 0), > >> - STATS(0, 2, 1, 3, 0, 0, 0, 0), > >> - STATS(1, 2, 2, 4, 0, 0, 0, 0), > >> - STATS(2, 2, 2, 4, 0, 0, 0, 0), > >> - STATS(2, 2, 2, 4, 0, 1, 1, 0), > >> - STATS(2, 3, 2, 5, 1, 1, 1, 0), > >> - STATS(2, 3, 2, 5, 1, 2, 2, 1) > >> + STATS(0, 1, 0, 0, 1, 0, 0, 0, 0), > >> + STATS(0, 2, 1, 0, 3, 0, 0, 0, 0), > >> + STATS(1, 2, 2, 0, 4, 0, 0, 0, 0), > >> + > >> + STATS(2, 2, 2, 0, 4, 0, 0, 0, 0), > >> + > >> + STATS(2, 2, 2, 0, 4, 0, 1, 1, 0), > >> + STATS(2, 3, 2, 0, 5, 1, 1, 1, 0), > >> + STATS(2, 3, 2, 0, 5, 1, 2, 2, 1), > >> + > >> + STATS(2, 4, 2, 0, 6, 1, 2, 2, 1), > >> + STATS(2, 4, 3, 1, 7, 1, 2, 2, 1), > >> + STATS(2, 5, 3, 1, 8, 1, 2, 2, 1), > >> + STATS(2, 6, 4, 1, 10, 1, 2, 2, 1), > >> + STATS(3, 6, 4, 1, 10, 1, 2, 2, 1), > >> + > >> + STATS(3, 6, 5, 2, 11, 1, 2, 2, 1), > >> + STATS(4, 6, 5, 2, 11, 1, 2, 2, 1), > >> + > >> + STATS(4, 6, 6, 3, 12, 1, 2, 2, 1), > >> + STATS(4, 7, 6, 3, 13, 1, 2, 2, 1), > >> }; > >> > >> static const int expected_block_access_counts [ACTION_COUNT] > >> [BLOCK_COUNT] = { > >> - { 1, 0, 0, 0, 0, 0 }, > >> - { 1, 1, 1, 0, 0, 0 }, > >> - { 1, 1, 1, 1, 0, 0 }, > >> - { 1, 1, 1, 1, 0, 0 }, > >> - { 1, 1, 1, 1, 1, 0 }, > >> - { 1, 1, 1, 1, 1, 1 }, > >> - { 1, 1, 1, 1, 1, 2 } > >> + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, > >> + { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, > >> + { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, > >> + > >> + { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, > >> + > >> + { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, > >> + { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, > >> + { 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, > >> + > >> + { 1, 1, 1, 1, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0 }, > >> + { 1, 1, 1, 1, 1, 2, 0, 0, 0, 1, 0, 0, 0, 1 }, > >> + { 1, 1, 1, 1, 1, 2, 0, 0, 0, 1, 1, 0, 0, 1 }, > >> + { 1, 1, 1, 1, 1, 2, 0, 0, 0, 1, 1, 1, 1, 1 }, > >> + { 1, 1, 1, 1, 1, 2, 0, 0, 0, 1, 1, 1, 1, 1 }, > >> + > >> + { 1, 1, 1, 1, 1, 2, 1, 0, 0, 1, 1, 1, 1, 1 }, > >> + { 1, 1, 1, 1, 1, 2, 1, 0, 0, 1, 1, 1, 1, 1 }, > >> + > >> + { 1, 1, 1, 1, 1, 2, 1, 0, 1, 1, 1, 1, 1, 1 }, > >> + { 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1 }, > >> }; > >> > >> static int block_access_counts [BLOCK_COUNT]; > >> @@ -132,10 +186,16 @@ static void test_actions(rtems_disk_device *dd) > >> > >> printf("action %i\n", i); > >> > >> - sc = (*action->get)(dd, action->block, &bd); > >> - rtems_test_assert(sc == action->expected_get_status); > >> + if (action->get != NULL) { > >> + sc = (*action->get)(dd, action->block, &bd); > >> + rtems_test_assert(sc == action->expected_get_status); > >> + } > >> + > >> + if (action->peek != NULL) { > >> + (*action->peek)(dd, action->block, 1); > >> + } > >> > >> - if (sc == RTEMS_SUCCESSFUL) { > >> + if (sc == RTEMS_SUCCESSFUL && action->release != NULL) { > >> sc = (*action->release)(bd); > >> rtems_test_assert(sc == RTEMS_SUCCESSFUL); > >> } > >> -- > >> 2.26.2 > >> > >> _______________________________________________ > >> devel mailing list > >> devel@rtems.org > >> http://lists.rtems.org/mailman/listinfo/devel > > -- > -------------------------------------------- > embedded brains GmbH > Herr Christian MAUDERER > Dornierstr. 4 > 82178 Puchheim > Germany > email: christian.maude...@embedded-brains.de > phone: +49-89-18 94 741 - 18 > fax: +49-89-18 94 741 - 08 > > Registergericht: Amtsgericht München > Registernummer: HRB 157899 > Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler > Unsere Datenschutzerklärung finden Sie hier: > https://embedded-brains.de/datenschutzerklaerung/ _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel