remove unused functions from CoupledSFR

parent 7c2a91ca
# Coupled-SFR
## Build instructions
Refer to build instructions in ./runtime/
## Persistent Region APIs
A preview is provided here. See `runtime/include/atlas_alloc.h` for the
actual interfaces.
A programmer needs to create one or more named persistent regions,
entities that hold everything persistent. The interface
**_NVM_FindOrCreateRegion_** or a variant can be used for this purpose. If a
region with the provided name exists, a handle to the region is
returned. Otherwise a region is created and its handle is
returned. Interfaces to close or delete a region are available.
To populate a persistent region, memory must be dynamically allocated
from that persistent region using **_nvm_alloc_** (or a variant) that has a
malloc-style interface. The region identifier must be provided so as
to identify the persistent region intended. An **_nvm_free_** is provided
for deallocation purposes.
Management of persistent regions and the contained data together
identify the persistent objects used by a program. Care must be taken
to ensure that all valid data within a persistent region is reachable
from the persistent root of the region. Use the interface
**_NVM_SetRegionRoot_** for this purpose.
## Consistency APIs
See `runtime/include/atlas_api.h` for the actual interfaces.
Persistent data must be kept consistent regardless of failures. The
programmer needs to call **_NVM_Initialize_** and **_NVM_Finalize_**
to start and stop Atlas support. Additionally, Atlas needs to know
code sections where program invariants are modified. If the program is
multithreaded and written using locks for synchronization, Atlas
automatically infers boundaries of regions where it must preserve
failure-atomicity (all-or-nothing) of updates to persistent
memory. Optionally, the programmer can demarcate sections of code with
calls to **_nvm_begin_durable_** and **_nvm_end_durable_** to identify
a durable or failure-atomic section of code. Note that no isolation
among threads is provided by a durable section. In contrast, if
persistent data is modified within a critical section, the critical
section provides both isolation among threads and durability to
persistent memory.
## Restart Code
A program might want to reuse data within a persistent region. For
this purpose, after finding a region handle, use the interface
**_NVM_GetRegionRoot_** to access the reachable data. Instead of
starting from scratch, this data can be reused to essentially restart
from where the region was left off the last time around.
That's all, as far as Atlas APIs are concerned. Compared to a
transient program, the idea is to write persistent memory programs
with as few changes as possible.
## Organization
- The APIs for this model are in `runtime/include`. [API doc here](http://hewlettpackard.github.io/Atlas/runtime/doc/atlas__api_8h.html).
- Instructions on how to build the compiler-plugin are in
`compiler-plugin/README.md`.
- Instructions on how to build the runtime are in `runtime/README.md`.
- For example programs using Atlas, see `runtime/tests`.
- The Atlas library sources are in `runtime/src`.
## Dependencies
* Currently, we support only x86-64 CPUs
* We assume Linux OS. Linux tmpfs must be supported. Testing has been
done on RedHat and Ubuntu.
* We assume modern C/C++ compilers in the build environment that must
support C/C++11.
* The default compiler used in the build is clang. Testing has been
done with version 3.6.0 or later. The instrumentation support is
currently available only with clang/LLVM. The runtime should build
with any compiler supporting C/C++11 though clang is preferred for
uniformity purposes.
* cmake version 3.1 or later
* boost library
* bash 4.0
For Ubuntu 16.04, these dependencies can be installed with:
sudo apt-get install llvm clang cmake libboost-graph-dev
* ruby (for certain test scripts), see **Installing Ruby** at [gorails](https://gorails.com/setup/ubuntu/16.04) for instructions.
cmake .. -DFLC=true -DNO_NEST=true
......@@ -264,13 +264,13 @@ include_directories (${CMAKE_SOURCE_DIR}/${ATLAS_INTERNAL_INCLUDES} ${CMAKE_SOUR
set (LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
#variable to build only data structures in tests
if (NOT DATA_STRUCTS_ONLY)
message ("Defaulting to build all tests")
add_subdirectory (tests)
else ()
#if (NOT DATA_STRUCTS_ONLY)
# message ("Defaulting to build all tests")
# add_subdirectory (tests)
#else ()
message ("Building only data structures")
add_subdirectory (tests/data_structures)
endif ()
#endif ()
add_subdirectory (src)
add_library (atlas $<TARGET_OBJECTS:Cache_flush> $<TARGET_OBJECTS:Consistency> $<TARGET_OBJECTS:Logger> $<TARGET_OBJECTS:Util> $<TARGET_OBJECTS:Pregion_mgr> $<TARGET_OBJECTS:Pmalloc>) #defaults to static build
......
......@@ -45,31 +45,31 @@ extern "C" {
///
uint32_t NVM_CreateRegion(const char *name, int flags);
///
/// @brief Create a persistent region with the provided name.
/// @param name Name of the persistent region
/// @param flags access flag (one of O_RDONLY, O_WRONLY, O_RDWR)
/// @param is_created Indicator whether the region got created as a
/// result of the call
/// @return Id of the region found or created
///
/// If the region already exists, the existing id of the region is returned.
/// Otherwise a region is created and its newly assigned id returned.
///
uint32_t NVM_FindOrCreateRegion(const char *name, int flags, int *is_created);
///
/// @brief Find the id of a region when it is known to exist already
/// @param name Name of the persistent region
/// @param flags access flag (one of O_RDONLY, O_WRONLY, O_RDWR)
/// @return Id of the region found
///
/// This interface should be used over NVM_FindOrCreateRegion for
/// efficiency reasons if the region is known to exist. If a region
/// with the provided name does not exist, an assertion failure will
/// occur.
///
uint32_t NVM_FindRegion(const char *name, int flags);
/////
///// @brief Create a persistent region with the provided name.
///// @param name Name of the persistent region
///// @param flags access flag (one of O_RDONLY, O_WRONLY, O_RDWR)
///// @param is_created Indicator whether the region got created as a
///// result of the call
///// @return Id of the region found or created
/////
///// If the region already exists, the existing id of the region is returned.
///// Otherwise a region is created and its newly assigned id returned.
/////
//uint32_t NVM_FindOrCreateRegion(const char *name, int flags, int *is_created);
//
/////
///// @brief Find the id of a region when it is known to exist already
///// @param name Name of the persistent region
///// @param flags access flag (one of O_RDONLY, O_WRONLY, O_RDWR)
///// @return Id of the region found
/////
///// This interface should be used over NVM_FindOrCreateRegion for
///// efficiency reasons if the region is known to exist. If a region
///// with the provided name does not exist, an assertion failure will
///// occur.
/////
//uint32_t NVM_FindRegion(const char *name, int flags);
///
/// @brief Delete the region with the provided name.
......@@ -80,31 +80,31 @@ uint32_t NVM_FindRegion(const char *name, int flags);
///
void NVM_DeleteRegion(const char *name);
///
/// @brief Close a persistent region
/// @param rid Region id
///
/// After closing, it won't be available to the calling process
/// without calling NVM_FindOrCreateRegion. The region will stay in
/// NVM even after calling this interface. This interface allows
/// closing a region with normal bookkeeping.
///
void NVM_CloseRegion(uint32_t rid);
///
/// @brief Get the root pointer of the persistent region
/// @param rid Region id
/// @return Root pointer of the region
///
/// The region must have been created already. Currently, only one
/// root is implemented for a given region. The idea is that anything
/// within a region that is not reachable from the root after program
/// termination is assumed to be garbage and can be recycled. During
/// execution, anything within a region that is not reachable from the
/// root or from other _roots_ (in the GC sense) is assumed to be
/// garbage as well.
///
void *NVM_GetRegionRoot(uint32_t rid);
/////
///// @brief Close a persistent region
///// @param rid Region id
/////
///// After closing, it won't be available to the calling process
///// without calling NVM_FindOrCreateRegion. The region will stay in
///// NVM even after calling this interface. This interface allows
///// closing a region with normal bookkeeping.
/////
//void NVM_CloseRegion(uint32_t rid);
//
/////
///// @brief Get the root pointer of the persistent region
///// @param rid Region id
///// @return Root pointer of the region
/////
///// The region must have been created already. Currently, only one
///// root is implemented for a given region. The idea is that anything
///// within a region that is not reachable from the root after program
///// termination is assumed to be garbage and can be recycled. During
///// execution, anything within a region that is not reachable from the
///// root or from other _roots_ (in the GC sense) is assumed to be
///// garbage as well.
/////
//void *NVM_GetRegionRoot(uint32_t rid);
///
/// @brief Set the root pointer of an existing persistent region
......@@ -113,14 +113,14 @@ void *NVM_GetRegionRoot(uint32_t rid);
///
void NVM_SetRegionRoot(uint32_t rid, void *root);
///
/// @brief Determines if a memory location is within a region
/// @param ptr Queried address
/// @param sz Size of the location in bytes
/// @return 1 if within the region, otherwise 0
///
int NVM_IsInRegion(void *ptr, size_t sz);
/////
///// @brief Determines if a memory location is within a region
///// @param ptr Queried address
///// @param sz Size of the location in bytes
///// @return 1 if within the region, otherwise 0
/////
//int NVM_IsInRegion(void *ptr, size_t sz);
///
/// @brief Determines if the addresses are on different cache lines
///
......@@ -143,50 +143,50 @@ int isOnDifferentCacheLine(void *p1, void *p2);
///
int isCacheLineAligned(void *p);
///
/// @brief Malloc style interface for allocation from a persistent
/// region
///
/// @param sz Size of location to be allocated
/// @param rid Id of persistent region for allocation
/// @return Address of memory location allocated
///
void *nvm_alloc(size_t sz, uint32_t rid);
///
/// @brief Calloc style interface for allocation from a persistent
/// region
///
/// @param nmemb Number of elements in the array to be allocated
/// @param sz Size of each element
/// @param rid Id of persistent region for allocation
/// @return Pointer to allocated memory
///
void *nvm_calloc(size_t nmemb, size_t sz, uint32_t rid);
///
/// @brief Realloc style interface for allocation from a persistent
/// region
///
/// @param ptr Address of memory block provided
/// @param sz New size of allocation
/// @param rid Id of persistent region for allocation
/// @return Pointer to re-allocated memory
///
void *nvm_realloc(void *ptr, size_t sz, uint32_t rid);
///
/// @brief Deallocation interface for persistent data
///
/// @param ptr Address of memory location to be freed.
///
/// Though the usual use case would be for the location to be in
/// persistent memory, this interface will also work for transient
/// data. The implementation is required to transparently handle
/// this case as well.
///
void nvm_free(void *ptr);
/////
///// @brief Malloc style interface for allocation from a persistent
///// region
/////
///// @param sz Size of location to be allocated
///// @param rid Id of persistent region for allocation
///// @return Address of memory location allocated
/////
//void *nvm_alloc(size_t sz, uint32_t rid);
//
/////
///// @brief Calloc style interface for allocation from a persistent
///// region
/////
///// @param nmemb Number of elements in the array to be allocated
///// @param sz Size of each element
///// @param rid Id of persistent region for allocation
///// @return Pointer to allocated memory
/////
//void *nvm_calloc(size_t nmemb, size_t sz, uint32_t rid);
//
/////
///// @brief Realloc style interface for allocation from a persistent
///// region
/////
///// @param ptr Address of memory block provided
///// @param sz New size of allocation
///// @param rid Id of persistent region for allocation
///// @return Pointer to re-allocated memory
/////
//void *nvm_realloc(void *ptr, size_t sz, uint32_t rid);
//
/////
///// @brief Deallocation interface for persistent data
/////
///// @param ptr Address of memory location to be freed.
/////
///// Though the usual use case would be for the location to be in
///// persistent memory, this interface will also work for transient
///// data. The implementation is required to transparently handle
///// this case as well.
/////
//void nvm_free(void *ptr);
//
#ifdef __cplusplus
}
#endif
......
......@@ -18,20 +18,20 @@
#define ATLAS_ALLOC_CPP_H
// Forward declarations
namespace Atlas
namespace Atlas
{
class PRegion;
}
///
/// @brief Get a handle to a persistent region
/// @param rid Region identifier
/// @return Pointer to the corresponding persistent region
///
/// Currently, this interface is to be used by a client only for the
/// placement new operations
///
Atlas::PRegion *NVM_GetRegion(uint32_t rid);
/////
///// @brief Get a handle to a persistent region
///// @param rid Region identifier
///// @return Pointer to the corresponding persistent region
/////
///// Currently, this interface is to be used by a client only for the
///// placement new operations
/////
//Atlas::PRegion *NVM_GetRegion(uint32_t rid);
///
/// @brief Object allocation for C++
......@@ -46,7 +46,7 @@ void* operator new(size_t sz, Atlas::PRegion *rgn) noexcept;
///
/// @brief Array form allocation for C++, type must have explicit
/// destructor
/// destructor
/// @param sz Allocation size
/// @param rgn Pointer to the region to serve the allocation from
/// @return Pointer to memory allocated
......@@ -58,63 +58,63 @@ void* operator new(size_t sz, Atlas::PRegion *rgn) noexcept;
///
void* operator new[](size_t sz, Atlas::PRegion *rgn) noexcept;
///
/// @brief Object destruction for C++
/// @param ptr Pointer to memory to be deallocated
///
/// This interface should be called for destroying an object that was
/// created from a persistent region using the single-object new
/// operator. The implementation calls the destructor followed by
/// actual deallocation. This interface can also be called for
/// destroying an object that was created using the default
/// single-object new operator. If the latter is the case, the
/// implementation detects this situation and turns around to call the
/// default single-object delete operator. This interface must not be
/// called for deallocating an object created in any other way, e.g. a
/// placement new operator where the placement address is not within a
/// persistent region.
///
template <class T> static inline void NVM_Destroy(T *ptr)
{
if (!ptr) return;
if (!NVM_IsInRegion(ptr, 1 /* dummy, since size unknown */)) {
delete ptr;
return;
}
ptr->~T();
void nvm_delete(void*);
nvm_delete(ptr);
}
///
/// @brief Array form destruction for C++, type must have explicit
/// destructor
/// @param ptr Pointer to memory to be deallocated
///
/// This interface should be called for destroying an array of objects
/// that was created from a persistent region using the array-form new
/// operator. The implementation calls the destructors for all objects
/// of the array followed by actual deallocation. Note that the type
/// of the array elements must have an explicit destructor for this
/// interface to work correctly. This interface can also be called for
/// destroying an array of objects that was created using the default
/// array-form new operator. If the latter is the case, the
/// implementation detects this situation and turns around to call the
/// default array-form delete operator. This interface must not be
/// called for deallocating an object created in any other way.
///
template <class T> static inline void NVM_Destroy_Array(T *ptr)
{
if (!ptr) return;
if (!NVM_IsInRegion(ptr, 1 /* dummy, since size unknown */)) {
delete [] ptr;
return;
}
char *delete_ptr = reinterpret_cast<char*>(ptr) - sizeof(size_t);
size_t count = *reinterpret_cast<size_t*>(delete_ptr);
for (int i=count-1; i>=0; --i) (ptr+i)->~T();
void nvm_delete(void*);
nvm_delete(delete_ptr);
}
/////
///// @brief Object destruction for C++
///// @param ptr Pointer to memory to be deallocated
/////
///// This interface should be called for destroying an object that was
///// created from a persistent region using the single-object new
///// operator. The implementation calls the destructor followed by
///// actual deallocation. This interface can also be called for
///// destroying an object that was created using the default
///// single-object new operator. If the latter is the case, the
///// implementation detects this situation and turns around to call the
///// default single-object delete operator. This interface must not be
///// called for deallocating an object created in any other way, e.g. a
///// placement new operator where the placement address is not within a
///// persistent region.
/////
//template <class T> static inline void NVM_Destroy(T *ptr)
//{
// if (!ptr) return;
// if (!NVM_IsInRegion(ptr, 1 /* dummy, since size unknown */)) {
// delete ptr;
// return;
// }
// ptr->~T();
// void nvm_delete(void*);
// nvm_delete(ptr);
//}
//
/////
///// @brief Array form destruction for C++, type must have explicit
///// destructor
///// @param ptr Pointer to memory to be deallocated
/////
///// This interface should be called for destroying an array of objects
///// that was created from a persistent region using the array-form new
///// operator. The implementation calls the destructors for all objects
///// of the array followed by actual deallocation. Note that the type
///// of the array elements must have an explicit destructor for this
///// interface to work correctly. This interface can also be called for
///// destroying an array of objects that was created using the default
///// array-form new operator. If the latter is the case, the
///// implementation detects this situation and turns around to call the
///// default array-form delete operator. This interface must not be
///// called for deallocating an object created in any other way.
/////
//template <class T> static inline void NVM_Destroy_Array(T *ptr)
//{
// if (!ptr) return;
// if (!NVM_IsInRegion(ptr, 1 /* dummy, since size unknown */)) {
// delete [] ptr;
// return;
// }
// char *delete_ptr = reinterpret_cast<char*>(ptr) - sizeof(size_t);
// size_t count = *reinterpret_cast<size_t*>(delete_ptr);
// for (int i=count-1; i>=0; --i) (ptr+i)->~T();
// void nvm_delete(void*);
// nvm_delete(delete_ptr);
//}
//
#endif
......@@ -35,32 +35,32 @@ extern "C" {
void NVM_Initialize();
///
/// Finalize Atlas internal data structures. This should be called
/// before normal program exit. If not called, the implementation
/// will assume that program exit was abnormal and will require
/// invocation of recovery before restart.
///
///// Finalize Atlas internal data structures. This should be called
///// before normal program exit. If not called, the implementation
///// will assume that program exit was abnormal and will require
///// invocation of recovery before restart.
/////
void NVM_Finalize();
void NVM_UsrDone();
//void NVM_UsrDone();
//
// No special interfaces are required for lock-based critical
// sections if compiler support is available. Use the
// compiler-plugin to take advantage of automatic instrumentation
// of critical sections.
//
///
/// The following 2 interfaces demarcate a failure-atomic section
/// of code, i.e. code where persistent locations are updated and
/// all-or-nothing behavior of those updates is required. Note that
/// no isolation among threads is provided by these 2 interfaces.
///
void nvm_begin_durable();
void nvm_end_durable();
////
//// No special interfaces are required for lock-based critical
//// sections if compiler support is available. Use the
//// compiler-plugin to take advantage of automatic instrumentation
//// of critical sections.
////
//
/////
///// The following 2 interfaces demarcate a failure-atomic section
///// of code, i.e. code where persistent locations are updated and
///// all-or-nothing behavior of those updates is required. Note that
///// no isolation among threads is provided by these 2 interfaces.
/////
//void nvm_begin_durable();
//void nvm_end_durable();
//
// The following interfaces are for low-level programming of
......@@ -75,35 +75,35 @@ void nvm_end_durable();
///
int NVM_IsInOpenPR(void *addr, size_t sz /* in bytes */);
///
/// Persistent sync of a range of addresses
///
void nvm_psync(void *addr, size_t sz /* in bytes */);
///
/// Persistent sync of a range of addresses without a trailing barrier
///
void nvm_psync_acq(void *addr, size_t sz /* in bytes */);
// This may be invoked by a user program to print out Atlas statistics
#ifdef NVM_STATS
void NVM_PrintStats();
#endif
/////
///// Persistent sync of a range of addresses
/////
//void nvm_psync(void *addr, size_t sz /* in bytes */);
//
/////
///// Persistent sync of a range of addresses without a trailing barrier
/////
//void nvm_psync_acq(void *addr, size_t sz /* in bytes */);
//
//// This may be invoked by a user program to print out Atlas statistics
//#ifdef NVM_STATS
// void NVM_PrintStats();
//#endif
//
#ifdef __cplusplus
}
#endif
// End of Atlas APIs
#ifdef NVM_STATS
extern __thread uint64_t num_flushes;
#endif
// Useful macros
#define NVM_BEGIN_DURABLE() nvm_begin_durable()
#define NVM_END_DURABLE() nvm_end_durable()
//
//// End of Atlas APIs
//
//#ifdef NVM_STATS
//extern __thread uint64_t num_flushes;
//#endif
//
//// Useful macros
//#define NVM_BEGIN_DURABLE() nvm_begin_durable()
//#define NVM_END_DURABLE() nvm_end_durable()
//
#define NVM_CLFLUSH(p) nvm_clflush((char*)(void*)(p))
#ifndef DISABLE_FLUSHES
......@@ -113,19 +113,19 @@ extern __thread uint64_t num_flushes;
full_fence(); \
}
#define NVM_FLUSH_COND(p) \
{ if (NVM_IsInOpenPR(p, 1)) { \
full_fence(); \
NVM_CLFLUSH((p)); \
full_fence(); \
} \
}
#define NVM_FLUSH_ACQ(p) \
{ full_fence(); \
NVM_CLFLUSH(p); \
}
//#define NVM_FLUSH_COND(p) \
// { if (NVM_IsInOpenPR(p, 1)) { \
// full_fence(); \
// NVM_CLFLUSH((p)); \
// full_fence(); \
// } \
// }
//
//#define NVM_FLUSH_ACQ(p) \
// { full_fence(); \
// NVM_CLFLUSH(p); \
// }
//
#define NVM_FLUSH_ACQ_COND(p) \
{ if (NVM_IsInOpenPR(p, 1)) { \
full_fence(); \
......@@ -133,30 +133,30 @@ extern __thread uint64_t num_flushes;
} \
}
#define NVM_PSYNC(p1,s) nvm_psync(p1,s)
#define NVM_PSYNC_COND(p1,s) \
{ if (NVM_IsInOpenPR(p1, s)) nvm_psync(p1,s); }
#define NVM_PSYNC_ACQ(p1,s) \
{ \
nvm_psync_acq(p1,s); \
} \
#define NVM_PSYNC_ACQ_COND(p1,s) \
{ \
if (NVM_IsInOpenPR(p1, s)) nvm_psync_acq(p1, s); \
} \
//#define NVM_PSYNC(p1,s) nvm_psync(p1,s)
//
//#define NVM_PSYNC_COND(p1,s) \
// { if (NVM_IsInOpenPR(p1, s)) nvm_psync(p1,s); }
//
//#define NVM_PSYNC_ACQ(p1,s) \
// { \
// nvm_psync_acq(p1,s); \
// } \
//
//#define NVM_PSYNC_ACQ_COND(p1,s) \
// { \
// if (NVM_IsInOpenPR(p1, s)) nvm_psync_acq(p1, s); \
// } \
//
#else
#define NVM_FLUSH(p)
#define NVM_FLUSH_COND(p)
#define NVM_FLUSH_ACQ(p)
#define NVM_FLUSH_ACQ_COND(p)
#define NVM_PSYNC(p1,s)
#define NVM_PSYNC_COND(p1,s)
#define NVM_PSYNC_ACQ(p1,s)
#define NVM_PSYNC_ACQ_COND(p1,s)
//#define NVM_FLUSH_COND(p)
//#define NVM_FLUSH_ACQ(p)
//#define NVM_FLUSH_ACQ_COND(p)
//#define NVM_PSYNC(p1,s)
//#define NVM_PSYNC_COND(p1,s)
//#define NVM_PSYNC_ACQ(p1,s)
//#define NVM_PSYNC_ACQ_COND(p1,s)
#endif
static __inline void nvm_clflush(const void *p)
......
......@@ -20,4 +20,4 @@ add_subdirectory (logger)
add_subdirectory (util)
add_subdirectory (pmalloc)
add_subdirectory (pregion_mgr)
add_subdirectory (recover)
#add_subdirectory (recover)