genode/repos/base/src/base/include/unmanaged_singleton.h
Norman Feske ca971bbfd8 Move repositories to 'repos/' subdirectory
This patch changes the top-level directory layout as a preparatory
step for improving the tools for managing 3rd-party source codes.
The rationale is described in the issue referenced below.

Issue #1082
2014-05-14 16:08:00 +02:00

75 lines
2.6 KiB
C++

/*
* \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 <base/stdint.h>
/**
* 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 <typename T, int ALIGNMENT = sizeof(Genode::addr_t), typename... ARGS>
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<T *>(object_space);
}
#endif /* _UNMANAGED_SINGLETON_H_ */