From 212fc47768dd1788ece10b345472105f43f82c1f Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Wed, 4 Dec 2013 20:44:18 +0100 Subject: [PATCH] base: provide template for unmanaged singletons An unmanaged singleton is a singleton object that isn't constructed or destructed implicitly through the C++ runtime enviroment. The new header provides a helper to create such objects and is located in src/base/include. ref #989 --- base/src/base/include/unmanaged_singleton.h | 74 +++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 base/src/base/include/unmanaged_singleton.h diff --git a/base/src/base/include/unmanaged_singleton.h b/base/src/base/include/unmanaged_singleton.h new file mode 100644 index 000000000..24836d226 --- /dev/null +++ b/base/src/base/include/unmanaged_singleton.h @@ -0,0 +1,74 @@ +/* + * \brief Singleton objects that aren't implicitly constructed or destructed + * \author Norman Feske + * \author Martin Stein + * \date 2013-12-04 + * + * Before enabling the MMU on ARM, the 'cmpxchg' implementation is not always + * guaranteed to work. For example, on the Raspberry Pi, the 'ldrex' as used by + * 'cmpxchg' causes the machine to reboot. After enabling the MMU, everything + * is fine. Hence, we need to avoid executing 'cmpxchg' prior this point. + * Unfortunately, 'cmpxchg' is implicitly called each time when creating a + * singleton object via a local-static object pattern. In this case, the + * compiler generates code that calls the '__cxa_guard_acquire' function of the + * C++ runtime, which, in turn, relies 'cmpxchg' for synchronization. + * + * The utility provided herein is an alternative way to create single object + * instances without implicitly calling 'cmpxchg'. Furthermore, the created + * objects are not destructed automatically at program exit which is useful + * because it prevents the main thread of a program from destructing the + * enviroment it needs to finish program close-down. Because object creation + * is not synchronized via a spin lock, it must not be used in scenarios where + * multiple threads may contend. + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _UNMANAGED_SINGLETON_H_ +#define _UNMANAGED_SINGLETON_H_ + +/* Genode includes */ +#include + +/** + * Placement new operator + * + * \param p destination address + */ +inline void * operator new(Genode::size_t, void * p) { return p; } + +/** + * Create a singleton object that isn't implicitly constructed or destructed + * + * \param T object type + * \param ALIGNMENT object alignment + * \param ARGS arguments to the object constructor + * + * \return object pointer + */ +template +static inline T * unmanaged_singleton(ARGS... args) +{ + /* + * Each instantiation of the function template with a different type 'T' + * yields a dedicated instance of the local static variables, thereby + * creating the living space for the singleton objects. + */ + enum { OBJECT_SIZE = sizeof(T) / sizeof(char) + 1 }; + static bool object_constructed = false; + static char object_space[OBJECT_SIZE] __attribute__((aligned(ALIGNMENT))); + + /* execute constructor on first call */ + if (!object_constructed) { + object_constructed = true; + new (&object_space) T(args...); + } + return reinterpret_cast(object_space); +} + +#endif /* _UNMANAGED_SINGLETON_H_ */