nlib
NMalloc.h
[詳解]
1 
2 /*--------------------------------------------------------------------------------*
3  Project: CrossRoad
4  Copyright (C)Nintendo All rights reserved.
5 
6  These coded instructions, statements, and computer programs contain proprietary
7  information of Nintendo and/or its licensed developers and are protected by
8  national and international copyright laws. They may not be disclosed to third
9  parties or copied or duplicated in any form, in whole or in part, without the
10  prior written consent of Nintendo.
11 
12  The content herein is highly confidential and should be handled accordingly.
13  *--------------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_HEAP_NMALLOC_H_
17 #define INCLUDE_NN_NLIB_HEAP_NMALLOC_H_
18 
19 #include <errno.h>
20 #include <stddef.h>
21 #include <stdlib.h> // for malloc/free
22 
23 #ifdef __cplusplus
24 #include <new>
25 #include "nn/nlib/Config.h"
26 #else
27 #include "nn/nlib/Platform.h"
28 #endif
29 
30 #if defined(_MSC_VER) && defined(nx_heap_EXPORTS)
31 #undef NLIB_VIS_PUBLIC
32 #define NLIB_VIS_PUBLIC NLIB_WINEXPORT
33 #endif
34 
35 #ifndef INCLUDE_NN_NLIB_PLATFORM_H_
36 // some compilers complain about double declaration
37 typedef int errno_t;
38 #endif
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 typedef struct NLIB_VIS_PUBLIC {
45  size_t alloc_count;
46  size_t alloc_size;
47  size_t hash;
48 } HeapHash;
49 
50 typedef struct NLIB_VIS_PUBLIC {
51  void* addr;
52  size_t size;
53  unsigned int heap_option;
55 
56 #define NMALLOC_HEAPOPTION_ENABLE_ENV (0x00000001)
57 #define NMALLOC_HEAPOPTION_CACHE_DISABLE (0x00000004)
58 
59 #ifdef _MSC_VER
60 void nmalloc_get_settings(NMallocSettings* settings); // weak function
61 NLIB_VIS_PUBLIC void nmalloc_get_settings_default(NMallocSettings* settings);
62 #ifndef _WIN64
63 #pragma comment(linker, "/alternatename:_nmalloc_get_settings=_nmalloc_get_settings_default")
64 #else
65 #pragma comment(linker, "/alternatename:nmalloc_get_settings=nmalloc_get_settings_default")
66 #endif
67 #else
68 NLIB_VIS_PUBLIC void nmalloc_get_settings(NMallocSettings* settings); // weak function
69 #endif
70 
71 typedef enum {
77  NMALLOC_DUMP_BASIC = kNmallocDumpBasic,
78  NMALLOC_DUMP_SPANS = kNmallocDumpSpans,
79  NMALLOC_DUMP_POINTERS = kNmallocDumpPointers,
80  NMALLOC_DUMP_PAGESUMMARY = kNmallocDumpPageSummary,
81  NMALLOC_DUMP_ALL = kNmallocDumpAll
83 
84 typedef enum {
85  kNmallocQueryDump = 0,
86  kNmallocQueryPageSize,
87  kNmallocQueryAllocatedSize,
88  kNmallocQueryFreeSize,
89  kNmallocQuerySystemSize,
90  kNmallocQueryMaxAllocatableSize,
91  kNmallocQueryIsClean,
92  kNmallocQueryHeapHash,
93  kNmallocQueryUnifyFreelist,
94  kNmallocQuerySetColor,
95  kNmallocQueryGetColor,
96  kNmallocQuerySetName,
97  kNmallocQueryGetName,
98  kNmallocQueryCacheMin_,
99  kNmallocQueryCheckCache,
100  kNmallocQueryClearCache,
101  kNmallocQueryFinalizeCache,
102  kNmallocQueryFreeSizeNx,
103  kNmallocQueryMaxAllocatableSizeNx,
104  NMALLOC_QUERY_DUMP = kNmallocQueryDump,
105  NMALLOC_QUERY_PAGE_SIZE = kNmallocQueryPageSize,
106  NMALLOC_QUERY_ALLOCATED_SIZE = kNmallocQueryAllocatedSize,
107  NMALLOC_QUERY_FREE_SIZE = kNmallocQueryFreeSize,
108  NMALLOC_QUERY_SYSTEM_SIZE = kNmallocQuerySystemSize,
109  NMALLOC_QUERY_MAX_ALLOCATABLE_SIZE = kNmallocQueryMaxAllocatableSize,
110  NMALLOC_QUERY_IS_CLEAN = kNmallocQueryIsClean,
111  NMALLOC_QUERY_HEAP_HASH = kNmallocQueryHeapHash,
112  NMALLOC_QUERY_UNIFY_FREELIST = kNmallocQueryUnifyFreelist,
113  NMALLOC_QUERY_SET_COLOR = kNmallocQuerySetColor,
114  NMALLOC_QUERY_GET_COLOR = kNmallocQueryGetColor,
115  NMALLOC_QUERY_SET_NAME = kNmallocQuerySetName,
116  NMALLOC_QUERY_GET_NAME = kNmallocQueryGetName,
117  NMALLOC_QUERY_CACHE_MIN_ = kNmallocQueryCacheMin_,
118  NMALLOC_QUERY_CHECK_CACHE = kNmallocQueryCheckCache,
119  NMALLOC_QUERY_CLEAR_CACHE = kNmallocQueryClearCache,
120  NMALLOC_QUERY_FINALIZE_CACHE = kNmallocQueryFinalizeCache,
121  NMALLOC_QUERY_FREE_SIZE_NX = kNmallocQueryFreeSizeNx,
122  NMALLOC_QUERY_MAX_ALLOCATABLE_SIZE_NX = kNmallocQueryMaxAllocatableSizeNx
123 } NMallocQuery;
124 
125 typedef int (*nmalloc_heapwalk_callback)(void* allocated_ptr, size_t size, void* user_ptr);
126 
127 NLIB_VIS_PUBLIC errno_t nmalloc_query(int query, ...);
128 NLIB_CHECK_RESULT NLIB_VIS_PUBLIC void* nrealloc(void* ptr, size_t size)
129 NLIB_ATTRIBUTE_MALLOC NLIB_ATTRIBUTE_ALLOC_SIZE1(2) NLIB_ATTRIBUTE_ASSUME_ALIGNED(8);
130 NLIB_CHECK_RESULT NLIB_VIS_PUBLIC void* nmalloc(size_t size)
131 NLIB_ATTRIBUTE_MALLOC NLIB_ATTRIBUTE_ALLOC_SIZE1(1) NLIB_ATTRIBUTE_ASSUME_ALIGNED(8);
132 NLIB_CHECK_RESULT NLIB_VIS_PUBLIC void* ncalloc(size_t nmemb, size_t size)
133 NLIB_ATTRIBUTE_MALLOC NLIB_ATTRIBUTE_ALLOC_SIZE2(1, 2) NLIB_ATTRIBUTE_ASSUME_ALIGNED(8);
134 NLIB_CHECK_RESULT NLIB_VIS_PUBLIC void* nmalloc_aligned(size_t size, size_t algn)
135 NLIB_ATTRIBUTE_MALLOC NLIB_ATTRIBUTE_ALLOC_SIZE1(1) NLIB_ATTRIBUTE_ALLOC_ALIGN(2)
136 NLIB_ATTRIBUTE_ASSUME_ALIGNED(8);
137 NLIB_VIS_PUBLIC size_t nmalloc_size(const void* ptr) NLIB_NONNULL;
138 NLIB_VIS_PUBLIC void nfree(void* p);
139 NLIB_VIS_PUBLIC void nfree_size(void* p, size_t size);
140 
142 
143 #ifdef __cplusplus
144 }
145 #endif
146 
147 #ifdef __cplusplus
148 
149 inline bool operator==(const HeapHash& rhs, const HeapHash& lhs) {
150  return rhs.alloc_count == lhs.alloc_count && rhs.alloc_size == lhs.alloc_size &&
151  rhs.hash == lhs.hash;
152 }
153 
154 inline bool operator!=(const HeapHash& rhs, const HeapHash& lhs) {
155  return rhs.alloc_count != lhs.alloc_count || rhs.alloc_size != lhs.alloc_size ||
156  rhs.hash != lhs.hash;
157 }
158 
159 NLIB_NAMESPACE_BEGIN
160 namespace heap {
161 
162 template <typename T>
163 struct NMallocStlAllocator {
164  typedef size_t size_type;
165  typedef T value_type;
166  typedef T* pointer;
167  typedef const T* const_pointer;
168  typedef T& reference;
169  typedef const T& const_reference;
170  typedef ptrdiff_t difference_type;
171  template <typename U>
172  struct rebind {
173  typedef NMallocStlAllocator<U> other;
174  };
175  NMallocStlAllocator() {}
176  explicit NMallocStlAllocator(const NMallocStlAllocator<T>&) {}
177  template <class _Other>
178  NMallocStlAllocator(const NMallocStlAllocator<_Other>&) {}
179  pointer allocate(size_type n, const void* p = 0);
180  void deallocate(pointer p, size_type n) {
181 #if 1
182  nfree_size(p, n * sizeof(T));
183 #else
184  (void)n;
185  nfree(p);
186 #endif
187  }
188  void construct(pointer p, const T& t) { new ((void*)p) T(t); } // NOLINT
189  void construct(pointer p) { new ((void*)p) T(); } // NOLINT
190 #if defined(__cpp_rvalue_references) && defined(__cpp_variadic_templates)
191  template<class X, class... ARGS>
192  void construct(X* p, ARGS&&... args) {
193  new ((void*)p) X(std::forward<ARGS>(args)...); // NOLINT
194  }
195 #endif
196  void destroy(pointer ptr) {
197  (void)ptr;
198  (*ptr).~T();
199  }
200  template<class X>
201  void destroy(X* p) {
202  NLIB_UNUSED(p); // workaround for VS2012
203  p->~X();
204  }
205  size_t max_size() const {
206  size_t cnt = (size_t)-1 / sizeof(T);
207  return 0 < cnt ? cnt : 1;
208  }
209  pointer address(reference value) const { return &value; }
210  const_pointer address(const_reference value) const { return &value; }
211 };
212 
213 template <typename T>
214 typename NMallocStlAllocator<T>::pointer NMallocStlAllocator<T>::allocate(size_type n,
215  const void* p) {
216  (void)p;
217  void* pp = nmalloc(n * sizeof(T));
218  return reinterpret_cast<T*>(pp);
219 }
220 
221 template <class T1, class T2>
222 inline bool operator==(const NMallocStlAllocator<T1>&, const NMallocStlAllocator<T2>&) {
223  return true;
224 }
225 
226 template <class T1, class T2>
227 inline bool operator!=(const NMallocStlAllocator<T1>&, const NMallocStlAllocator<T2>&) {
228  return false;
229 }
230 
231 } // namespace heap
232 NLIB_NAMESPACE_END
233 
234 #endif
235 
236 #ifdef __cplusplus
237 #define NLIB_REPLACE_MALLOC \
238 extern "C" { \
239 void* nlib_malloc(size_t n) { \
240  return nmalloc(n); \
241  } \
242 void nlib_free(void* p) { \
243  nfree(p); \
244  } \
245 void* nlib_calloc(size_t nmemb, size_t size) { \
246  return ncalloc(nmemb, size); \
247  } \
248 void* nlib_realloc(void* ptr, size_t size) { \
249  return nrealloc(ptr, size); \
250  } \
251 void* nlib_memalign(size_t alignment, size_t size) { \
252  return nmalloc_aligned(size, alignment); \
253  } \
254 void nlib_free_size(void* ptr, size_t size) { \
255  nfree_size(ptr, size); \
256  } \
257 }
258 
259 #ifndef NN_PLATFORM_CTR
260 #define NLIB_REPLACE_MALLOC_NEW \
261  NLIB_REPLACE_MALLOC \
262 void* operator new(size_t size) { \
263  return nlib_malloc(size); \
264  } \
265 void operator delete(void* ptr) NLIB_NOEXCEPT { \
266  nlib_free(ptr); \
267  } \
268 void* operator new(size_t size, const std::nothrow_t&) NLIB_NOEXCEPT { \
269  return nlib_malloc(size); \
270  } \
271 void operator delete(void* ptr, const std::nothrow_t&) NLIB_NOEXCEPT { \
272  nlib_free(ptr); \
273  } \
274 void* operator new[](size_t size) { return nlib_malloc(size); } \
275 void operator delete[](void* ptr) NLIB_NOEXCEPT { nlib_free(ptr); } \
276 void* operator new[](size_t size, const std::nothrow_t&) NLIB_NOEXCEPT \
277 { return nlib_malloc(size); } \
278 void operator delete [](void* ptr, const std::nothrow_t&) NLIB_NOEXCEPT { nlib_free(ptr); } \
279 void operator delete(void* ptr, size_t size) NLIB_NOEXCEPT { \
280  nlib_free_size(ptr, size); \
281  } \
282 void operator delete(void* ptr, size_t size, const std::nothrow_t&) NLIB_NOEXCEPT { \
283  nlib_free_size(ptr, size); \
284  } \
285 void operator delete[](void* ptr, size_t size)NLIB_NOEXCEPT { nlib_free_size(ptr, size); } \
286 void operator delete[](void* ptr, size_t size, const std::nothrow_t&) NLIB_NOEXCEPT { \
287  nlib_free_size(ptr, size); \
288 }
289 #else
290 #define NLIB_REPLACE_MALLOC_NEW \
291  NLIB_REPLACE_MALLOC \
292 void* operator new(size_t size) throw(std::bad_alloc) { \
293  return nlib_malloc(size); \
294  } \
295 void operator delete(void* ptr) throw() { \
296  nlib_free(ptr); \
297  } \
298 void* operator new(size_t size, const std::nothrow_t&) throw() { \
299  return nlib_malloc(size); \
300  } \
301 void* operator new[](size_t size) throw(std::bad_alloc) { \
302  return nlib_malloc(size); \
303  } \
304 void operator delete[](void* ptr) throw() { \
305  nlib_free(ptr); \
306  } \
307 void* operator new[](size_t size, const std::nothrow_t&) throw() { \
308  return nlib_malloc(size); \
309  }
310 #endif
311 #else
312 #define NLIB_REPLACE_MALLOC \
313 void* nlib_malloc(size_t n) { \
314  return nmalloc(n); \
315  } \
316 void nlib_free(void* p) { \
317  nfree(p); \
318  } \
319 void* nlib_calloc(size_t nmemb, size_t size) { \
320  return ncalloc(nmemb, size); \
321  } \
322 void* nlib_realloc(void* ptr, size_t size) { \
323  return nrealloc(ptr, size); \
324  } \
325 void* nlib_memalign(size_t alignment, size_t size) { \
326  return nmalloc_aligned(size, alignment); \
327  } \
328 void nlib_free_size(void* ptr, size_t size) { \
329  nfree_size(ptr, size); \
330  }
331 #define NLIB_REPLACE_MALLOC_NEW NLIB_REPLACE_MALLOC
332 #endif
333 
334 #if defined(_MSC_VER) && defined(nx_heap_EXPORTS)
335 #undef NLIB_VIS_PUBLIC
336 #define NLIB_VIS_PUBLIC NLIB_WINIMPORT
337 #endif
338 
339 #endif // INCLUDE_NN_NLIB_HEAP_NMALLOC_H_
void nfree_size(void *p, size_t size)
メモリ領域を解放します。メモリのサイズ情報を利用することで高速にメモリを解放できることがあります。 ...
#define NLIB_ATTRIBUTE_MALLOC
利用可能であれば__attribute__((malloc))が定義されます。
int(* nmalloc_heapwalk_callback)(void *allocated_ptr, size_t size, void *user_ptr)
nmalloc_walk_allocated_ptrs()から呼び出されるユーザー定義のコールバック関数です。 ...
Definition: NMalloc.h:125
基本的な情報のみを表示します。
Definition: NMalloc.h:72
void * nrealloc(void *ptr, size_t size)
メモリの割り当てを変更します。realloc()C標準関数に相当します。
情報を全て表示します。
Definition: NMalloc.h:76
#define NLIB_CHECK_RESULT
関数の呼び出し元が戻り値をチェックする必要があることを示します。
size_t nmalloc_size(const void *ptr)
ptrに実際に割り当てられたメモリ量を返します。
size_t alloc_size
ヒープ内でユーザーによってアロケートされた領域のサイズの合計です。
Definition: NMalloc.h:46
ユーザーによって確保されている全てのメモリのアドレスとサイズを表示します。
Definition: NMalloc.h:74
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価ならば、trueを返します。
Definition: NMalloc.h:149
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価でなければ、trueを返します。
Definition: NMalloc.h:154
errno_t nmalloc_query(int query,...)
ヒープに関する詳細なデータの取得や操作を行います。
基本的なAPIがCリンケージで宣言されています。
void * ncalloc(size_t nmemb, size_t size)
0に初期化される要素とメモリの配列を割り当てます。
void nfree(void *p)
メモリ領域を解放します。free()C標準関数に相当します。
#define NLIB_VIS_PUBLIC
関数やクラス等のシンボルをライブラリの外部に公開します。
Definition: Platform_unix.h:89
unsigned int heap_option
ヒープオプションを指定します。デフォルトは0です。
Definition: NMalloc.h:53
size_t alloc_count
ヒープ内でユーザーによってアロケートされた領域の数です。
Definition: NMalloc.h:45
size_t size
nmallocが利用する最大のメモリサイズを指定します。4096バイトの倍数を指定する必要があります。 ...
Definition: NMalloc.h:52
nmallocの初期設定を行うパラメータを記述します。nmalloc_get_settings()を定義して設定します。 ...
Definition: NMalloc.h:50
size_t hash
ヒープ内のユーザーによるメモリ確保の状況をハッシュ値にしたものです。
Definition: NMalloc.h:47
void * nmalloc(size_t size)
指定バイト分のメモリ領域を確保します。malloc()C標準関数に相当します。
ページ単位の利用状況を表示します。
Definition: NMalloc.h:73
開発環境別の設定が書かれるファイルです。
ヒープ全体のページの割当密度の概要を視覚的に表示します。1MBを1つのASCIIキャラクタで表現しています。 ...
Definition: NMalloc.h:75
void * addr
nmallocが利用する領域の先頭へのポインタを指定します。
Definition: NMalloc.h:51
void nmalloc_get_settings(NMallocSettings *settings)
ユーザーがこの関数を定義することでnmallocの初期化設定をコントロールすることができます。 ...
errno_t nmalloc_walk_allocated_ptrs(nmalloc_heapwalk_callback func, void *user_ptr)
ヒープにアロケートされた領域1つずつに対してコールバック関数func を呼び出します。
#define NLIB_NONNULL
全ての引数にNULLを指定することができないことを示します。
NMallocDumpMode
nmalloc_query()関数でkNmallocQueryDumpを指定した場合に第2引数に指定する値の型です。 ...
Definition: NMalloc.h:71
ユーザーが利用しているヒープ内のメモリの利用状況のサマリが記述される構造体です。
Definition: NMalloc.h:44
void * nmalloc_aligned(size_t size, size_t algn)
アライメントを指定してメモリ領域を確保します。
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:37