1    	/****************************************************************************
2    	 *   Copyright (C) 2006-2008 by Jason Ansel                                 *
3    	 *   jansel@csail.mit.edu                                                   *
4    	 *                                                                          *
5    	 *   This file is part of the JALIB module of DMTCP (DMTCP:dmtcp/jalib).    *
6    	 *                                                                          *
7    	 *  DMTCP:dmtcp/jalib is free software: you can redistribute it and/or      *
8    	 *  modify it under the terms of the GNU Lesser General Public License as   *
9    	 *  published by the Free Software Foundation, either version 3 of the      *
10   	 *  License, or (at your option) any later version.                         *
11   	 *                                                                          *
12   	 *  DMTCP:dmtcp/src is distributed in the hope that it will be useful,      *
13   	 *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
14   	 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
15   	 *  GNU Lesser General Public License for more details.                     *
16   	 *                                                                          *
17   	 *  You should have received a copy of the GNU Lesser General Public        *
18   	 *  License along with DMTCP:dmtcp/src.  If not, see                        *
19   	 *  <http://www.gnu.org/licenses/>.                                         *
20   	 ****************************************************************************/
21   	
22   	#include "jalloc.h"
23   	#include <pthread.h>
24   	#include <stdio.h>
25   	
26   	#ifdef HAVE_CONFIG_H
27   	# include "config.h"
28   	#endif
29   	
30   	static pthread_mutex_t allocateLock = PTHREAD_MUTEX_INITIALIZER;
31   	
32   	void jalib::JAllocDispatcher::reset_on_fork()
33   	{
34   	  pthread_mutex_t tmpLock = PTHREAD_MUTEX_INITIALIZER;
35   	  allocateLock = tmpLock;
36   	}
37   	
38   	void jalib::JAllocDispatcher::lock()
39   	{
40   	  if(pthread_mutex_lock(&allocateLock) != 0)
41   	    perror("JGlobalAlloc::ckptThreadAcquireLock");
42   	}
43   	
44   	void jalib::JAllocDispatcher::unlock()
45   	{
46   	  if(pthread_mutex_unlock(&allocateLock) != 0)
47   	    perror("JGlobalAlloc::ckptThreadReleaseLock");
48   	}
49   	
50   	
51   	#ifdef JALIB_ALLOCATOR
52   	
53   	#include <sys/mman.h>
54   	#include <unistd.h>
55   	#include <stdlib.h>
56   	#include <sys/user.h>
57   	
58   	
59   	namespace jalib
60   	{
61   	
62   	inline void* _alloc_raw(size_t n) {
63   	#ifdef JALIB_USE_MALLOC
64   	  return malloc(n);
65   	#else
66   	
67   	//#define USE_DMTCP_ALLOC_ARENA
68   	# ifdef USE_DMTCP_ALLOC_ARENA
69   	#ifndef __x86_64__
70   	#error "USE_DMTCP_ALLOC_ARENA can't be used with 32-bit binaries"
71   	#endif
72   	  static void *mmapHintAddr = (void*) 0x1f000000000;
73   	  if (n % PAGE_SIZE != 0) {
74   	    n = (n + PAGE_SIZE) - (n % PAGE_SIZE);
75   	  }
76   	  void* p = mmap(mmapHintAddr, n, PROT_READ | PROT_WRITE, 
77   	                 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
78   	  if (p!= MAP_FAILED)
79   	    mmapHintAddr = p + n;
80   	# else
81   	  void* p = mmap(NULL, n, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
82   	# endif
83   	
84   	  if(p==MAP_FAILED)
85   	    perror("_alloc_raw: ");
86   	  return p;
87   	#endif
88   	}
89   	
90   	inline void _dealloc_raw(void* ptr, size_t n) {
91   	#ifdef JALIB_USE_MALLOC
92   	  free(ptr);
93   	#else
94   	  if(ptr==0 || n==0) return;
95   	  int rv = munmap(ptr, n);
96   	  if(rv!=0)
97   	    perror("_dealloc_raw: ");
98   	#endif
99   	}
100  	
101  	template < size_t _N, size_t BLOCKSIZE>
102  	class JFixedAllocStack {
103  	public:
104  	  enum { N=_N };
Event uninit_member: Non-static class member padding is not initialized in this constructor nor in any functions that it calls.
Also see events: [member_decl]
105  	  JFixedAllocStack() : _root(NULL) {}
106  	
107  	  //allocate a chunk of size N
108  	  void* allocate() {
109  	    if(_root == NULL) expand();
110  	    FreeItem* item = _root;
111  	    _root = item->next;
112  	    item->next = NULL;
113  	    return item;
114  	  }
115  	
116  	  //deallocate a chunk of size N
117  	  void deallocate(void* ptr) {
118  	    FreeItem* item = static_cast<FreeItem*>(ptr);
119  	    item->next = _root;
120  	    _root = item;
121  	  }
122  	protected:
123  	  //allocate more raw memory when stack is empty
124  	  void expand() {
125  	    FreeItem* bufs = static_cast<FreeItem*>(_alloc_raw(BLOCKSIZE));
126  	    int count=BLOCKSIZE / sizeof(FreeItem);
127  	    for(int i=0; i<count-1; ++i){
128  	      bufs[i].next=bufs+i+1;
129  	    }
130  	    bufs[count-1].next = _root;
131  	    _root=bufs; 
132  	  }
133  	protected:
134  	  struct FreeItem {
135  	    union {
136  	      FreeItem* next;
137  	      char buf[N];
138  	    };
139  	  };
140  	private:
141  	  FreeItem* _root;
Event member_decl: Class member declaration for padding.
Also see events: [uninit_member]
142  	  char padding[128];
143  	};
144  	
145  	// FIXME: Do we really need this class now?     --Kapil
146  	template < typename Alloc >
147  	class JGlobalAlloc {
148  	public:
149  	  enum { N = Alloc::N };
150  	
151  	  static void* allocate(){
152  	#if 0
153  	    if(pthread_mutex_lock(theMutex()) != 0)
154  	      perror("JGlobalAlloc::allocate");
155  	#endif
156  	   
157  	    void* ptr = theAlloc().allocate();
158  	
159  	#if 0
160  	    if(pthread_mutex_unlock(theMutex()) != 0)
161  	      perror("JGlobalAlloc::allocate");
162  	#endif
163  	
164  	    return ptr;
165  	  }
166  	
167  	  //deallocate a chunk of size N
168  	  static void deallocate(void* ptr){
169  	#if 0
170  	    if(pthread_mutex_lock(theMutex()) != 0)
171  	      perror("JGlobalAlloc::allocate");
172  	#endif
173  	   
174  	    theAlloc().deallocate(ptr);
175  	
176  	#if 0
177  	    if(pthread_mutex_unlock(theMutex()) != 0)
178  	      perror("JGlobalAlloc::allocate");
179  	#endif
180  	  }
181  	
182  	private:
183  	  static pthread_mutex_t* theMutex() {
184  	    static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
185  	    return &m;
186  	  }
187  	  static Alloc& theAlloc() {
188  	    static Alloc a;
189  	    return a;
190  	  }
191  	};
192  	
193  	typedef JGlobalAlloc< JFixedAllocStack<64 ,  1024*16 > > lvl1;
194  	typedef JGlobalAlloc< JFixedAllocStack<256,  1024*16 > > lvl2;
195  	typedef JGlobalAlloc< JFixedAllocStack<1024, 1024*16 > > lvl3;
196  	
197  	void* JAllocDispatcher::allocate(size_t n) {
198  	  lock();
199  	  void *retVal;
200  	  if(n <= lvl1::N) retVal = lvl1::allocate(); else
201  	  if(n <= lvl2::N) retVal = lvl2::allocate(); else
202  	  if(n <= lvl3::N) retVal = lvl3::allocate(); else
203  	  retVal = _alloc_raw(n);
204  	  unlock();
205  	  return retVal;
206  	}
207  	void JAllocDispatcher::deallocate(void* ptr, size_t n){
208  	  lock();
209  	  if(n <= lvl1::N) lvl1::deallocate(ptr); else
210  	  if(n <= lvl2::N) lvl2::deallocate(ptr); else
211  	  if(n <= lvl3::N) lvl3::deallocate(ptr); else
212  	  _dealloc_raw(ptr, n);
213  	  unlock();
214  	}
215  	
216  	} // namespace jalib
217  	
218  	#else
219  	
220  	#include <stdlib.h>
221  	
222  	void* jalib::JAllocDispatcher::allocate(size_t n) {
223  	  lock();
224  	  void* p = malloc(n);
225  	  unlock();
226  	  return p;
227  	}
228  	void jalib::JAllocDispatcher::deallocate(void* ptr, size_t){
229  	  lock();
230  	  free(ptr);
231  	  unlock();
232  	}
233  	
234  	#endif
235  	
236  	#ifdef OVERRIDE_GLOBAL_ALLOCATOR
237  	#  ifndef JALIB_ALLOCATOR
238  	#    error "JALIB_ALLOCATOR must be #defined in dmtcp/jalib/jalloc.h for --enable-allocator to work"
239  	#  endif
240  	void* operator new(size_t nbytes){
241  	  size_t* p = (size_t*) jalib::JAllocDispatcher::allocate(nbytes+sizeof(size_t));
242  	  *p = nbytes;
243  	  p+=1;
244  	  return p;
245  	}
246  	
247  	void operator delete(void* _p){
248  	  size_t* p = (size_t*) _p;
249  	  p-=1;
250  	  jalib::JAllocDispatcher::deallocate(p, *p+sizeof(size_t));
251  	}
252  	#endif