[llvm-commits] [poolalloc] r102718 - in /poolalloc/branches/release_26: include/poolalloc/PoolAllocate.h lib/DSA/DataStructure.cpp lib/DSA/EquivClassGraphs.cpp lib/PoolAllocate/PoolAllocate.cpp lib/PoolAllocate/TransformFunctionBody.cpp lib/rDSA/ lib/rDSA/CMakeLists.txt runtime/FL2Allocator/CMakeLists.txt runtime/FL2Allocator/PoolAllocator.cpp runtime/FL2Allocator/PoolAllocator.h

Patrick Simmons simmon12 at illinois.edu
Fri Apr 30 09:28:28 PDT 2010


Author: psimmons
Date: Fri Apr 30 11:28:28 2010
New Revision: 102718

URL: http://llvm.org/viewvc/llvm-project?rev=102718&view=rev
Log:
Make pool allocation runtime thread-safe.
Add support for pthreads (USE_DYNCALL macro must be set).
Minor fixups & corrections to comments.

Added:
    poolalloc/branches/release_26/lib/rDSA/
      - copied from r96246, poolalloc/trunk/lib/rDSA/
Modified:
    poolalloc/branches/release_26/include/poolalloc/PoolAllocate.h
    poolalloc/branches/release_26/lib/DSA/DataStructure.cpp
    poolalloc/branches/release_26/lib/DSA/EquivClassGraphs.cpp
    poolalloc/branches/release_26/lib/PoolAllocate/PoolAllocate.cpp
    poolalloc/branches/release_26/lib/PoolAllocate/TransformFunctionBody.cpp
    poolalloc/branches/release_26/lib/rDSA/CMakeLists.txt
    poolalloc/branches/release_26/runtime/FL2Allocator/CMakeLists.txt
    poolalloc/branches/release_26/runtime/FL2Allocator/PoolAllocator.cpp
    poolalloc/branches/release_26/runtime/FL2Allocator/PoolAllocator.h

Modified: poolalloc/branches/release_26/include/poolalloc/PoolAllocate.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/release_26/include/poolalloc/PoolAllocate.h?rev=102718&r1=102717&r2=102718&view=diff
==============================================================================
--- poolalloc/branches/release_26/include/poolalloc/PoolAllocate.h (original)
+++ poolalloc/branches/release_26/include/poolalloc/PoolAllocate.h Fri Apr 30 11:28:28 2010
@@ -55,7 +55,7 @@
   /// maps to the original function...
   ///
   struct FuncInfo {
-    FuncInfo(Function &f) : F(f), Clone(0) {}
+    FuncInfo(Function &f) : F(f), Clone(0), rev_pool_desc_map_computed(false) {}
 
     /// MarkedNodes - The set of nodes which are not locally pool allocatable in
     /// the current function.
@@ -84,6 +84,23 @@
     /// function.
     std::map<const DSNode*, Value*> PoolDescriptors;
 
+    //Reverse mapping for PoolDescriptors, needed by TPPA
+    std::map<Value*, const DSNode*> ReversePoolDescriptors;
+
+    //This is a hack -- a function should be added which maintains these in parallel
+    //and all of PoolAlloc and SafeCode should be updated to use it instead of adding
+    //to either map directly.
+    bool rev_pool_desc_map_computed;
+    void calculate_reverse_pool_descriptors()
+    {
+    	if(rev_pool_desc_map_computed)
+    		return;
+    	rev_pool_desc_map_computed = true;
+
+    	for(std::map<const DSNode*, Value*>::iterator i = PoolDescriptors.begin(); i!=PoolDescriptors.end(); i++)
+    		ReversePoolDescriptors[i->second] = i->first;
+    }
+
     /// This is a map from Old to New Values (the reverse of NewToOldValueMap).
     /// SAFECode uses this for check insertion.
     std::map<const Value*, Value*> ValueMap;
@@ -145,6 +162,7 @@
     return Graphs->getGlobalsGraph ();
   }
 
+  /* Return value is of type PoolDescPtrTy */
   virtual Value * getPool (const DSNode * N, Function & F) {return 0;}
 
   virtual Value * getGlobalPool (const DSNode * Node) {return 0;}
@@ -168,7 +186,7 @@
   std::map<const Function*, Function*> CloneToOrigMap;
 public:
 
-  Constant *PoolInit, *PoolDestroy, *PoolAlloc, *PoolRealloc, *PoolMemAlign;
+  Constant *PoolInit, *PoolDestroy, *PoolAlloc, *PoolRealloc, *PoolMemAlign, *PoolThreadWrapper;
   Constant *PoolFree;
   Constant *PoolCalloc;
   Constant *PoolStrdup;

Modified: poolalloc/branches/release_26/lib/DSA/DataStructure.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/release_26/lib/DSA/DataStructure.cpp?rev=102718&r1=102717&r2=102718&view=diff
==============================================================================
--- poolalloc/branches/release_26/lib/DSA/DataStructure.cpp (original)
+++ poolalloc/branches/release_26/lib/DSA/DataStructure.cpp Fri Apr 30 11:28:28 2010
@@ -2609,8 +2609,8 @@
 }
 
 
-/// computeGToGGMapping - Compute the mapping of nodes in the global graph to
-/// nodes in this graph.
+/// computeGToGGMapping - Compute the mapping of global nodes in this graph to
+/// nodes in the globals graph.
 void DSGraph::computeGToGGMapping(NodeMapTy &NodeMap) {
   DSGraph &GG = *getGlobalsGraph();
 

Modified: poolalloc/branches/release_26/lib/DSA/EquivClassGraphs.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/release_26/lib/DSA/EquivClassGraphs.cpp?rev=102718&r1=102717&r2=102718&view=diff
==============================================================================
--- poolalloc/branches/release_26/lib/DSA/EquivClassGraphs.cpp (original)
+++ poolalloc/branches/release_26/lib/DSA/EquivClassGraphs.cpp Fri Apr 30 11:28:28 2010
@@ -64,6 +64,8 @@
     for (EquivalenceClasses<const GlobalValue*>::member_iterator MI = GlobalECs.member_begin(EQSI);
          MI != GlobalECs.member_end(); ++MI) {
       if (const Function* F = dyn_cast<Function>(*MI)) {
+        if(F->isDeclaration()) //ignore functions with no body
+    	  continue;
         if (!BaseGraph) {
           BaseGraph = getOrCreateGraph(F);
           BaseGraph->getFunctionArgumentsForCall(F, Args);

Modified: poolalloc/branches/release_26/lib/PoolAllocate/PoolAllocate.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/release_26/lib/PoolAllocate/PoolAllocate.cpp?rev=102718&r1=102717&r2=102718&view=diff
==============================================================================
--- poolalloc/branches/release_26/lib/PoolAllocate/PoolAllocate.cpp (original)
+++ poolalloc/branches/release_26/lib/PoolAllocate/PoolAllocate.cpp Fri Apr 30 11:28:28 2010
@@ -269,6 +269,15 @@
   //Get the poolregister function
   PoolRegister = M->getOrInsertFunction("poolregister", VoidType,
                                  PoolDescPtrTy, VoidPtrTy, Int32Type, NULL);
+
+  Function* pthread_create_func = M->getFunction("pthread_create");
+  Function::arg_iterator i = pthread_create_func->arg_begin();
+  vector<const Type*> non_vararg_params;
+  non_vararg_params.push_back(i++->getType());
+  non_vararg_params.push_back(i++->getType());
+  non_vararg_params.push_back(i++->getType());
+  non_vararg_params.push_back(Int32Type);
+  PoolThreadWrapper = M->getOrInsertFunction("poolalloc_pthread_create",FunctionType::get(Int32Type,non_vararg_params,true));
 }
 
 static void getCallsOf(Constant *C, std::vector<CallInst*> &Calls) {

Modified: poolalloc/branches/release_26/lib/PoolAllocate/TransformFunctionBody.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/release_26/lib/PoolAllocate/TransformFunctionBody.cpp?rev=102718&r1=102717&r2=102718&view=diff
==============================================================================
--- poolalloc/branches/release_26/lib/PoolAllocate/TransformFunctionBody.cpp (original)
+++ poolalloc/branches/release_26/lib/PoolAllocate/TransformFunctionBody.cpp Fri Apr 30 11:28:28 2010
@@ -545,6 +545,7 @@
 void FuncTransform::visitCallSite(CallSite& CS) {
   const Function *CF = CS.getCalledFunction();
   Instruction *TheCall = CS.getInstruction();
+  bool thread_creation_point = false;
 
   // If the called function is casted from one function type to another, peer
   // into the cast instruction and pull out the actual function being called.
@@ -583,6 +584,21 @@
     } else if (CF->getName() == "valloc") {
       std::cerr << "VALLOC USED BUT NOT HANDLED!\n";
       abort();
+    } else if (CF->getName() == "pthread_create") {
+      thread_creation_point = true;
+      //Get DSNode representing the void* passed to the callee
+	  DSNodeHandle passed_dsnode_handle = G->getNodeForValue(CS.getArgument(3));
+
+      //Get DSNode representing the DSNode of the function pointer Value of the pthread_create call
+      DSNode* thread_callee_node = G->getNodeForValue(CS.getArgument(2)).getNode();
+      if(!thread_callee_node)
+      {
+    	  FuncInfo *CFI = PAInfo.getFuncInfo(*CF);
+    	  thread_callee_node = G->getNodeForValue(CFI->MapValueToOriginal(CS.getArgument(2))).getNode();
+      }
+
+      //Fill in CF with the name of one of the functions in thread_callee_node
+      CF = const_cast<Function*>(dyn_cast<Function>(*thread_callee_node->globals_begin()));
     }
   }
 
@@ -754,8 +770,9 @@
     Args.push_back(ArgVal);
   }
 
-  // Add the rest of the arguments...
-  Args.insert(Args.end(), CS.arg_begin(), CS.arg_end());
+  // Add the rest of the arguments unless we're a thread creation point, in which case we only need the pools
+  if(!thread_creation_point)
+	  Args.insert(Args.end(), CS.arg_begin(), CS.arg_end());
     
   //
   // There are circumstances where a function is casted to another type and
@@ -776,7 +793,27 @@
 
   std::string Name = TheCall->getName();    TheCall->setName("");
 
-  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
+  if(thread_creation_point) {
+	Module *M = CS.getInstruction()->getParent()->getParent()->getParent();
+	Value* pthread_replacement = M->getFunction("poolalloc_pthread_create");
+	vector<Value*> thread_args;
+
+	//Push back original thread arguments through the callee
+	thread_args.push_back(CS.getArgument(0));
+	thread_args.push_back(CS.getArgument(1));
+	thread_args.push_back(CS.getArgument(2));
+
+	//Push back the integer argument saying how many uses there are
+	thread_args.push_back(Constant::getIntegerValue(llvm::Type::getInt32Ty(M->getContext()),APInt(32,Args.size())));
+	thread_args.insert(thread_args.end(),Args.begin(),Args.end());
+	thread_args.push_back(CS.getArgument(3));
+
+	//Make the thread creation call
+	NewCall = CallInst::Create(pthread_replacement,
+							   thread_args.begin(),thread_args.end(),
+							   Name,TheCall);
+  }
+  else if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
     NewCall = InvokeInst::Create (NewCallee, II->getNormalDest(),
                                   II->getUnwindDest(),
                                   Args.begin(), Args.end(), Name, TheCall);

Modified: poolalloc/branches/release_26/lib/rDSA/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/release_26/lib/rDSA/CMakeLists.txt?rev=102718&r1=96246&r2=102718&view=diff
==============================================================================
--- poolalloc/branches/release_26/lib/rDSA/CMakeLists.txt (original)
+++ poolalloc/branches/release_26/lib/rDSA/CMakeLists.txt Fri Apr 30 11:28:28 2010
@@ -1,2 +1,2 @@
 file(GLOB sources *.cpp)
-add_llvm_library( LLVMDataStructure ${sources} )
+add_llvm_library( rDSA ${sources} )

Modified: poolalloc/branches/release_26/runtime/FL2Allocator/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/release_26/runtime/FL2Allocator/CMakeLists.txt?rev=102718&r1=102717&r2=102718&view=diff
==============================================================================
--- poolalloc/branches/release_26/runtime/FL2Allocator/CMakeLists.txt (original)
+++ poolalloc/branches/release_26/runtime/FL2Allocator/CMakeLists.txt Fri Apr 30 11:28:28 2010
@@ -1,2 +1,9 @@
+include_directories(/localhome/simmon12/progs/dyncall-0.5/dyncall)
+link_directories(/localhome/simmon12/progs/dyncall-0.5/dyncall/build_out/linux_x86_gcc_release)
 file(GLOB sources *.cpp)
-add_llvm_library( poolalloc_rt ${sources} )
\ No newline at end of file
+add_llvm_library( poolalloc_rt ${sources} )
+set_property(
+   TARGET poolalloc_rt 
+   PROPERTY COMPILE_DEFINITIONS USE_DYNCALL
+   )
+target_link_libraries( poolalloc_rt dyncall_s )

Modified: poolalloc/branches/release_26/runtime/FL2Allocator/PoolAllocator.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/release_26/runtime/FL2Allocator/PoolAllocator.cpp?rev=102718&r1=102717&r2=102718&view=diff
==============================================================================
--- poolalloc/branches/release_26/runtime/FL2Allocator/PoolAllocator.cpp (original)
+++ poolalloc/branches/release_26/runtime/FL2Allocator/PoolAllocator.cpp Fri Apr 30 11:28:28 2010
@@ -366,6 +366,7 @@
 
 void poolinit_bp(PoolTy<NormalPoolTraits> *Pool, unsigned ObjAlignment) {
   DO_IF_PNP(memset(Pool, 0, sizeof(PoolTy<NormalPoolTraits>)));
+  pthread_mutex_init(&Pool->pool_lock,NULL);
   Pool->Slabs = 0;
   if (ObjAlignment < 4) ObjAlignment = __alignof(double);
   Pool->AllocSize = INITIAL_SLAB_SIZE;
@@ -392,6 +393,8 @@
                       getPoolNumber(Pool), NumBytes));
   DO_IF_PNP(if (Pool->NumObjects == 0) ++PoolCounter);  // Track # pools.
 
+  pthread_mutex_lock(&Pool->pool_lock);
+
   if (NumBytes >= LARGE_SLAB_SIZE)
     goto LargeObject;
 
@@ -415,6 +418,7 @@
     // Update bump ptr.
     Pool->ObjFreeList = (FreedNodeHeader<NormalPoolTraits>*)(BumpPtr+NumBytes);
     DO_IF_TRACE(fprintf(stderr, "%p\n", Result));
+    pthread_mutex_unlock(&Pool->pool_lock);
     return Result;
   }
   
@@ -431,6 +435,7 @@
   LAH->Marker = ~0U;
   LAH->LinkIntoList(&Pool->LargeArrays);
   DO_IF_TRACE(fprintf(stderr, "%p  [large]\n", LAH+1));
+  pthread_mutex_unlock(&Pool->pool_lock);
   return LAH+1;
 }
 
@@ -444,6 +449,8 @@
 #endif
   DO_IF_POOLDESTROY_STATS(PrintPoolStats(Pool));
 
+  pthread_mutex_destroy(&Pool->pool_lock);
+
   // Free all allocated slabs.
   PoolSlab<NormalPoolTraits> *PS = Pool->Slabs;
   while (PS) {
@@ -476,6 +483,7 @@
                               unsigned DeclaredSize, unsigned ObjAlignment) {
   assert(Pool && "Null pool pointer passed into poolinit!\n");
   memset(Pool, 0, sizeof(PoolTy<PoolTraits>));
+  pthread_mutex_init(&Pool->pool_lock,NULL);
   Pool->AllocSize = INITIAL_SLAB_SIZE;
 
   if (ObjAlignment < 4) ObjAlignment = __alignof(double);
@@ -516,6 +524,7 @@
 //
 void pooldestroy(PoolTy<NormalPoolTraits> *Pool) {
   assert(Pool && "Null pool pointer passed in to pooldestroy!\n");
+  pthread_mutex_destroy(&Pool->pool_lock);
 
 #ifdef ENABLE_POOL_IDS
   unsigned PID;
@@ -858,29 +867,73 @@
 
 void *poolalloc(PoolTy<NormalPoolTraits> *Pool, unsigned NumBytes) {
   DO_IF_FORCE_MALLOCFREE(return malloc(NumBytes));
-  return poolalloc_internal(Pool, NumBytes);
+  pthread_mutex_lock(&Pool->pool_lock);
+  void* to_return = poolalloc_internal(Pool, NumBytes);
+  pthread_mutex_unlock(&Pool->pool_lock);
+  return to_return;
 }
 
 void *poolmemalign(PoolTy<NormalPoolTraits> *Pool,
                    unsigned Alignment, unsigned NumBytes) {
   //punt and use pool alloc.
   //I don't know if this is safe or breaks any assumptions in the runtime
+  pthread_mutex_lock(&Pool->pool_lock);
   intptr_t base = (intptr_t)poolalloc_internal(Pool, NumBytes + Alignment - 1);
+  pthread_mutex_unlock(&Pool->pool_lock);
   return (void*)((base + (Alignment - 1)) & ~((intptr_t)Alignment -1));
 }
 
 void poolfree(PoolTy<NormalPoolTraits> *Pool, void *Node) {
   DO_IF_FORCE_MALLOCFREE(free(Node); return);
+  pthread_mutex_lock(&Pool->pool_lock);
   poolfree_internal(Pool, Node);
+  pthread_mutex_unlock(&Pool->pool_lock);
 }
 
 void *poolrealloc(PoolTy<NormalPoolTraits> *Pool, void *Node,
                   unsigned NumBytes) {
   DO_IF_FORCE_MALLOCFREE(return realloc(Node, NumBytes));
-  return poolrealloc_internal(Pool, Node, NumBytes);
+  pthread_mutex_lock(&Pool->pool_lock);
+  void* to_return = poolrealloc_internal(Pool, Node, NumBytes);
+  pthread_mutex_unlock(&Pool->pool_lock);
 }
 
+#ifdef USE_DYNCALL
+#include <dyncall.h>
+#include <pthread.h>
+#include <stdarg.h>
+
+void* poolalloc_thread_start(void* arg_)
+{
+	void** arg = (void**)arg_;
+	DCCallVM* callVM = dcNewCallVM((size_t)arg[1]*sizeof(size_t)+108);
+	int i;
+	for(i=0; i<(size_t)arg[1]; i++)
+		dcArgPointer(callVM,arg[2+i]);
+	dcArgPointer(callVM,arg[2+i]);
+	void* to_return = dcCallPointer(callVM,arg[0]);
+	dcFree(callVM);
+	return to_return;
+}
 
+int poolalloc_pthread_create(pthread_t* thread,
+							 const pthread_attr_t* attr,
+							 void *(*start_routine)(void*), int num_pools, ...)
+{
+	void** arg_array = (void**)malloc(sizeof(void*)*(2+num_pools));
+	arg_array[0] = (void*)start_routine;
+	arg_array[1] = (void*)num_pools;
+	va_list argpools;
+	va_start(argpools,num_pools);
+	int i;
+	for(i=0; i<num_pools; i++)
+		arg_array[2+i]=va_arg(argpools,void*);
+	arg_array[2+i]=va_arg(argpools,void*);
+	va_end(argpools);
+	return pthread_create(thread,attr,poolalloc_thread_start,arg_array);
+}
+
+#endif
 
 //===----------------------------------------------------------------------===//
 // Pointer Compression runtime library.  Most of these are just wrappers
@@ -945,6 +998,7 @@
 
 void pooldestroy_pc(PoolTy<CompressedPoolTraits> *Pool) {
   assert(Pool && "Null pool pointer passed in to pooldestroy!\n");
+  pthread_mutex_destroy(&Pool->pool_lock);
   if (Pool->Slabs == 0)
     return;   // no memory allocated from this pool.
 
@@ -970,17 +1024,23 @@
 
 unsigned long long poolalloc_pc(PoolTy<CompressedPoolTraits> *Pool,
                                 unsigned NumBytes) {
+  pthread_mutex_lock(&Pool->pool_lock);
   void *Result = poolalloc_internal(Pool, NumBytes);
+  pthread_mutex_unlock(&Pool->pool_lock);
   return (char*)Result-(char*)Pool->Slabs;
 }
 
 void poolfree_pc(PoolTy<CompressedPoolTraits> *Pool, unsigned long long Node) {
+  pthread_mutex_lock(&Pool->pool_lock);
   poolfree_internal(Pool, (char*)Pool->Slabs+Node);
+  pthread_mutex_unlock(&Pool->pool_lock);
 }
 
 unsigned long long poolrealloc_pc(PoolTy<CompressedPoolTraits> *Pool,
                                   unsigned long long Node, unsigned NumBytes) {
+  pthread_mutex_lock(&Pool->pool_lock);
   void *Result = poolrealloc_internal(Pool, (char*)Pool->Slabs+Node, NumBytes);
+  pthread_mutex_unlock(&Pool->pool_lock);
   return (char*)Result-(char*)Pool->Slabs;
 }
 
@@ -998,18 +1058,26 @@
 
 void* poolalloc_pca(PoolTy<CompressedPoolTraits> *Pool, unsigned NumBytes)
 {
-  return poolalloc_internal(Pool, NumBytes);
+  pthread_mutex_lock(&Pool->pool_lock);
+  void* to_return = poolalloc_internal(Pool, NumBytes);
+  pthread_mutex_unlock(&Pool->pool_lock);
+  return to_return;
 }
 
 void poolfree_pca(PoolTy<CompressedPoolTraits> *Pool, void* Node)
 {
+  pthread_mutex_lock(&Pool->pool_lock);
   poolfree_internal(Pool, Node);
+  pthread_mutex_unlock(&Pool->pool_lock);
 }
 
 void* poolrealloc_pca(PoolTy<CompressedPoolTraits> *Pool, void* Node, 
 		      unsigned NumBytes)
 {
-  return poolrealloc_internal(Pool, Node, NumBytes);
+  pthread_mutex_lock(&Pool->pool_lock);
+  void* to_return = poolrealloc_internal(Pool, Node, NumBytes);
+  pthread_mutex_unlock(&Pool->pool_lock);
+  return to_return;
 }
 
 //===----------------------------------------------------------------------===//

Modified: poolalloc/branches/release_26/runtime/FL2Allocator/PoolAllocator.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/release_26/runtime/FL2Allocator/PoolAllocator.h?rev=102718&r1=102717&r2=102718&view=diff
==============================================================================
--- poolalloc/branches/release_26/runtime/FL2Allocator/PoolAllocator.h (original)
+++ poolalloc/branches/release_26/runtime/FL2Allocator/PoolAllocator.h Fri Apr 30 11:28:28 2010
@@ -23,6 +23,7 @@
 #define POOLALLOCATOR_RUNTIME_H
 
 #include <assert.h>
+#include <pthread.h>
 
 template<typename PoolTraits>
 struct PoolSlab;
@@ -174,6 +175,9 @@
   // BytesAllocated - The total number of bytes ever allocated from this pool.
   // Together with NumObjects, allows us to calculate average object size.
   unsigned BytesAllocated;
+
+  // Lock for the pool
+  pthread_mutex_t pool_lock;
 };
 
 extern "C" {
@@ -229,6 +233,13 @@
   // Access tracing runtime library support.
   void poolaccesstraceinit(void);
   void poolaccesstrace(void *Ptr, void *PD);
+
+  // Auxiliary functions for thread support
+#ifdef USE_DYNCALL
+  int poolalloc_pthread_create(pthread_t* thread,
+							   const pthread_attr_t* attr,
+							   void *(*start_routine)(void*), int num_pools, ...);
+#endif
 }
 
 #endif





More information about the llvm-commits mailing list