From 5afa41551b3d8e0a84cf21cebfc89a194d326e76 Mon Sep 17 00:00:00 2001 From: Stephen Cprek Date: Thu, 6 Apr 2017 17:08:15 -0500 Subject: Add map list initialization and at() methods Also add ErrnoToString() as a test which is a functionality ported from p8 Change-Id: Ia6dd9b37638af2634267e224d9b97133bf984fb4 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/38956 Tested-by: Jenkins Server Reviewed-by: Nicholas E. Bofferding Reviewed-by: Martin Gloff Tested-by: Jenkins OP Build CI Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell --- src/include/errno.h | 38 ++++++----------- src/include/map | 94 +++++++++++++++++++++++++++++++----------- src/include/util/impl/stlmap.H | 32 +++++++++++++- src/kernel/msghandler.C | 8 ++-- src/lib/errno.C | 60 +++++++++++++++++++++++++++ src/lib/makefile | 1 + src/makefile | 1 + src/usr/testcore/lib/stltest.H | 20 ++++++++- 8 files changed, 199 insertions(+), 55 deletions(-) create mode 100644 src/lib/errno.C diff --git a/src/include/errno.h b/src/include/errno.h index 9e75d50fe..3817fd4bc 100644 --- a/src/include/errno.h +++ b/src/include/errno.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2016 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -27,9 +27,6 @@ #include -// Map to to store strings of errorno codes -typedef std::map ErrorNoNames; - #define ENOENT 2 // No such file or directory #define EIO 5 // I/O error #define ENXIO 6 // No such device or address @@ -46,27 +43,16 @@ typedef std::map ErrorNoNames; #define EWOULDBLOCK EAGAIN // operation would block -// @Brief Initialize an ErrorNoNames map -// Note: All keys and values are preceded with a '-', this is because the -// the errno's will be set to 2's complement when there's an error. -inline ErrorNoNames init_map() -{ - ErrorNoNames l_map; - l_map[-ENOENT] = "-ENOENT"; - l_map[-EIO] = "-EIO"; - l_map[-ENXIO] = "-ENXIO"; - l_map[-ENOEXEC] = "-ENOEXEC"; - l_map[-EBADF] = "-EBADF"; - l_map[-EAGAIN] = "-EAGAIN"; - l_map[-EACCES] = "-EACCES"; - l_map[-EFAULT] = "-EFAULT"; - l_map[-EINVAL] = "-EINVAL"; - l_map[-ENFILE] = "-ENFILE"; - l_map[-EDEADLK] = "-EDEADLK"; - l_map[-ETIME] = "-ETIME"; - l_map[-EALREADY] = "-EALREADY"; - l_map[-EWOULDBLOCK] = "-EWOULDBLOCK"; - return l_map; -}; +/** + * @brief Returns string representation of an errno. + * + * @param[in] i_errno errno to get string for. + * + * @return const char* - If found, String associated with errno + * else, "UNKNOWN" string + * +*/ +const char * ErrnoToString( int i_errno ); + #endif diff --git a/src/include/map b/src/include/map index 19989f594..ddfa17ea7 100644 --- a/src/include/map +++ b/src/include/map @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -35,6 +37,7 @@ #include #include +#include #ifndef __UTIL_STLMAP_NS #define __UTIL_STLMAP_NS ::Util::__Util_StlMap_Impl @@ -45,11 +48,11 @@ namespace std /** * STL map template class. - * + * * @note value_comp not supported. * * This class inherits from Util::__Util_StlMap_Impl::Map, which hides all - * of the implementation details of the map. Most of the functions here + * of the implementation details of the map. Most of the functions here * are simply a redirection to the Util::...::Map version. */ template > @@ -92,20 +95,35 @@ namespace std * Copies all of the elements from [first, last) into the map. */ template __attribute__ ((always_inline)) - map( InputIterator first, InputIterator last, + map( InputIterator first, InputIterator last, const key_compare& c = Compare()) : submap(c) - { + { this->insert(first, last); } /** * Copy Constructor * @param i_x Source map - */ + */ __attribute__ ((always_inline)) map (const map& i_x) : submap(i_x) {} + /** + * Initializer list constructor" + * @param[in] init_list Initializer list + * @param[in] key_compare A comparison functor. + * @returns None. + * @post map is created with init_list items + */ + __attribute__ ((always_inline)) + map ( std::initializer_list init_list, + const key_compare& c = Compare()) + : submap(c) + { + insert(init_list); + } + /** * Destructor */ @@ -129,7 +147,7 @@ namespace std * @return iterator */ __attribute__ ((always_inline)) - iterator begin() + iterator begin() { return submap::begin(); } /** @@ -193,7 +211,7 @@ namespace std * @return true if container is empty otherwise false */ __attribute__ ((always_inline)) - bool empty() const + bool empty() const { return submap::empty(); } /** @@ -201,7 +219,7 @@ namespace std * @return number of elements in the container */ __attribute__ ((always_inline)) - size_type size() const + size_type size() const { return submap::size(); } /** @@ -209,7 +227,7 @@ namespace std * @return theoretical maximum size based on cpu word size */ __attribute__ ((always_inline)) - size_type max_size() const + size_type max_size() const { return UINT64_MAX/sizeof(T); } /** @@ -218,28 +236,58 @@ namespace std * @return a reference to the element whos key is x */ __attribute__ ((always_inline)) - T& operator[] (const key_type& k) + T& operator[] (const key_type& k) { return submap::operator[](k); } + /** + * Access a mutable reference to an element in the container + * @param[in] k - key to map. Asserts if key does not exist + * @return a reference to the element whose key is k + */ + __attribute__ ((always_inline)) + T& at( const key_type& k) + { + return submap::at(k); + } + + /** + * Get an immutable reference to an element in the container + * @param[in] k key, if it does not exist the it will assert + * @return a const reference to the element whose key is k + */ + __attribute__ ((always_inline)) + const T& at( const key_type& k) const + { + return submap::at(k); + } + /** * Insert element * @param[in] x map key/value pair - * @return std::pair.first is iterator pointing to new or existing - * element, std::pair.second is true if new element + * @return std::pair.first is iterator pointing to new or existing + * element, std::pair.second is true if new element * inserted, false if already existing. * * @note won't add element if it's key already exists in the map */ - pair insert (const value_type& x ) + pair insert (const value_type& x ) { return submap::insert(x); } + /** + * Insert element + * @param list A std::initializer_list of pairs to be + * inserted. + */ + void insert(std::initializer_list list) + { return submap::insert(list); } + /** * Insert element * @param[in] hint bidi iterator that is a hint to where to insert * the element * @param[in] x map key/value to insert (copy in) * - * @return an iterator pointing to either the new or existing + * @return an iterator pointing to either the new or existing * element * @note A good hint makes this very efficient. A bad hint slows * it down. An element will never be inserted out of order. @@ -249,7 +297,7 @@ namespace std { return submap::insert(hint, x); } /** - * Insert a range of new elements + * Insert a range of new elements * * (optimized function for iterator) * @@ -261,7 +309,7 @@ namespace std { return submap::insert(first, last); } /** - * Insert a range of new elements + * Insert a range of new elements * * (optimized function for const_iterator) * @@ -309,7 +357,7 @@ namespace std * @param last iterator of element to remove + 1 */ __attribute__ ((always_inline)) - void erase (iterator first, iterator last) + void erase (iterator first, iterator last) { submap::erase(first,last); } /** @@ -318,7 +366,7 @@ namespace std */ __attribute__ ((always_inline)) void swap(map& mp) - { submap::swap(mp); } + { submap::swap(mp); } /** * clear the map @@ -326,10 +374,10 @@ namespace std __attribute__ ((always_inline)) void clear() { submap::clear();; } - + //Observers /** - * Returns the key comparison object from which the map was + * Returns the key comparison object from which the map was * constructed * @return Compare */ @@ -357,7 +405,7 @@ namespace std * @return const_iterator to element or end() if not found */ __attribute__ ((always_inline)) - const_iterator find( const key_type& k) const + const_iterator find( const key_type& k) const { return submap::find(k); } /** @@ -421,7 +469,7 @@ namespace std /** * Const verstion of equal_range - see equal_range above */ - pair + pair equal_range( const key_type& k) const { return submap::equal_range(k); } }; diff --git a/src/include/util/impl/stlmap.H b/src/include/util/impl/stlmap.H index cdf5824e4..c451a0fa2 100644 --- a/src/include/util/impl/stlmap.H +++ b/src/include/util/impl/stlmap.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2016 */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -39,6 +39,8 @@ #include #include #include +#include +#include #ifndef __UTIL_SPLAYTREE_NS @@ -65,6 +67,7 @@ namespace Util typedef ptrdiff_t difference_type; typedef T* pointer; typedef T& reference; + typedef const T& const_reference; // Allow Map and other GenericIterators to be friends. template @@ -111,13 +114,19 @@ namespace Util return t; } - /** Dereference Operator */ + /** Dereference Operators */ reference operator*() { return reinterpret_cast<__UTIL_SPLAYTREE_NS::Node*>( const_cast<__UTIL_SPLAYTREE_NS::Node*>( (Itr::getNode())))->data_T(); } + const_reference operator*() const + { + return reinterpret_cast<__UTIL_SPLAYTREE_NS::Node*>( + const_cast<__UTIL_SPLAYTREE_NS::Node*>( + (Itr::getNode())))->data_T(); + } /** Pointer Operator */ pointer operator->() { @@ -332,6 +341,20 @@ namespace Util return (result.first)->second; } + T& at(const key_type& k) + { + auto result = lower_bound(k); + crit_assert(result != end()); + return (*result).second; + } + + const T& at(const key_type& k) const + { + const auto result = lower_bound(k); + crit_assert(result != end()); + return (*result).second; + } + template std::pair emplace ( Args&&... args ) { @@ -364,6 +387,11 @@ namespace Util } + void insert(std::initializer_list list) + { + insert(list.begin(), list.end()); + } + iterator insert(iterator hint, const value_type& x) { // I don't anticipate much performance improvement with diff --git a/src/kernel/msghandler.C b/src/kernel/msghandler.C index 46bad32fb..1f22a7a70 100644 --- a/src/kernel/msghandler.C +++ b/src/kernel/msghandler.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2016 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -177,8 +177,10 @@ int MessageHandler::recvMessage(msg_t* i_msg) else if (UNHANDLED_RC == rc) { // Unsuccessful, unhandled response. Kill task. - printk("Unhandled msg rc %d for key %p on task %d @ %p\n", - msg_rc, key, deferred_task->tid, deferred_task->context.nip); + // Print the errorno string if we have mapped it in errno.h + printk("Unhandled msg rc %d (%s) for key %p on task %d @ %p\n", + msg_rc, ErrnoToString(msg_rc), key, deferred_task->tid, + deferred_task->context.nip); endTaskList.insert(deferred_task); } else if (CONTINUE_DEFER == rc) diff --git a/src/lib/errno.C b/src/lib/errno.C new file mode 100644 index 000000000..d4597d23a --- /dev/null +++ b/src/lib/errno.C @@ -0,0 +1,60 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/lib/errno.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include + +const char * ErrnoToString( int i_errno ) +{ + // Map of errnos to string. + // Kept within function for deferred malloc and more error handling + // Otherwise the map is malloc'd before memory is initialized + // Note: All keys and values are preceded with a '-', this is because the + // the errno's will be set to 2's complement when there's an error. + static const std::map ErrnoToStringMap = + { + { -ENOENT , "-ENOENT"}, + { -EIO , "-EIO"}, + { -ENXIO , "-ENXIO"}, + { -ENOEXEC , "-ENOEXEC"}, + { -EBADF , "-EBADF"}, + { -EAGAIN , "-EAGAIN"}, + { -EACCES , "-EACCES"}, + { -EFAULT , "-EFAULT"}, + { -EINVAL , "-EINVAL"}, + { -ENFILE , "-ENFILE"}, + { -EDEADLK , "-EDEADLK"}, + { -ETIME , "-ETIME"}, + { -EALREADY , "-EALREADY"}, + { -EWOULDBLOCK, "-EWOULDBLOCK"}, + }; + + if (ErrnoToStringMap.count(i_errno) > 0) + { + return ErrnoToStringMap.at(i_errno); + } + else + { + return "UNKNOWN"; + } +} \ No newline at end of file diff --git a/src/lib/makefile b/src/lib/makefile index 5fdf78ac8..5e64025d1 100644 --- a/src/lib/makefile +++ b/src/lib/makefile @@ -49,6 +49,7 @@ OBJS += crc32.o OBJS += utilmisc.o OBJS += tls.o +OBJS += errno.o ifdef HOSTBOOT_MEMORY_LEAKS COMMONFLAGS += -DHOSTBOOT_MEMORY_LEAKS=1 diff --git a/src/makefile b/src/makefile index f1d6fa071..30811069b 100644 --- a/src/makefile +++ b/src/makefile @@ -134,6 +134,7 @@ DIRECT_BOOT_OBJECTS += stdlib.o DIRECT_BOOT_OBJECTS += assert.o DIRECT_BOOT_OBJECTS += workitem.o DIRECT_BOOT_OBJECTS += bltohbdatamgr.o +DIRECT_BOOT_OBJECTS += errno.o BASE_MODULES += trace BASE_MODULES += errl diff --git a/src/usr/testcore/lib/stltest.H b/src/usr/testcore/lib/stltest.H index 227a3f5c7..c16354ff3 100644 --- a/src/usr/testcore/lib/stltest.H +++ b/src/usr/testcore/lib/stltest.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2016 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -95,6 +95,12 @@ class STLTest : public CxxTest::TestSuite mymap[v5].value()); } + if (v5.value() != mymap.at(v5).value()) // map::at value + { + TS_FAIL("map::at() returned wrong value %d", + mymap.at(v5).value()); + } + // test map::insert(v), map::insert(h,v), lower_bound() mymap.insert(std::map::value_type(v2,v2)); //map::insert(v); @@ -483,6 +489,18 @@ class STLTest : public CxxTest::TestSuite std::list< std::list > l = { {},{1},{1,2,3} }; std::array a1 { {1,2,3,4,5} }; std::array a2 = {1,2,3,4,5}; + std::map m = { + {1, 100}, + {2, 100}, + {3, 100}, + {4, 100}, + }; + + if (m.size() != 4) + { + TS_FAIL("testInitListCompile(): std::map has an incorrect size after list initialization"); + } + // Compiler warns that std::arrays are unused, so compare their // sizes if (a1.size() != a2.size()) -- cgit v1.2.1