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 NLIB_VIS_PUBLIC void nmalloc_get_settings_default(NMallocSettings* settings);
61 #ifndef NLIB_WINDLL
62 void nmalloc_get_settings(NMallocSettings* settings); // weak function
63 #ifndef _WIN64
64 #pragma comment(linker, "/alternatename:_nmalloc_get_settings=_nmalloc_get_settings_default")
65 #else
66 #pragma comment(linker, "/alternatename:nmalloc_get_settings=nmalloc_get_settings_default")
67 #endif
68 #else
69 NLIB_VIS_PUBLIC extern void (*g_nmalloc_get_settings_func)(NMallocSettings*);
70 #endif
71 #else
72 NLIB_VIS_PUBLIC void nmalloc_get_settings(NMallocSettings* settings); // weak function
73 #endif
74 
75 typedef enum {
82 
83 typedef enum {
84  kNmallocQueryDump = 0,
85  kNmallocQueryPageSize,
86  kNmallocQueryAllocatedSize,
87  kNmallocQueryFreeSize,
88  kNmallocQuerySystemSize,
89  kNmallocQueryMaxAllocatableSize,
90  kNmallocQueryIsClean,
91  kNmallocQueryHeapHash,
92  kNmallocQueryUnifyFreelist,
93  kNmallocQuerySetColor,
94  kNmallocQueryGetColor,
95  kNmallocQuerySetName,
96  kNmallocQueryGetName,
97  kNmallocQueryCacheMin_,
98  kNmallocQueryCheckCache,
99  kNmallocQueryClearCache,
100  kNmallocQueryFinalizeCache,
101  kNmallocQueryFreeSizeNx,
102  kNmallocQueryMaxAllocatableSizeNx,
103  kNmallocQueryDumpJson
104 } NMallocQuery;
105 
106 typedef int (*nmalloc_heapwalk_callback)(void* allocated_ptr, size_t size, void* user_ptr);
107 
108 NLIB_VIS_PUBLIC errno_t nmalloc_query(int query, ...);
110  NLIB_ATTRIBUTE_ALLOC_SIZE1(2) NLIB_ATTRIBUTE_ASSUME_ALIGNED(8);
112  NLIB_ATTRIBUTE_ALLOC_SIZE1(1) NLIB_ATTRIBUTE_ASSUME_ALIGNED(8);
113 NLIB_CHECK_RESULT NLIB_VIS_PUBLIC void* ncalloc(size_t nmemb, size_t size) NLIB_ATTRIBUTE_MALLOC
114  NLIB_ATTRIBUTE_ALLOC_SIZE2(1, 2) NLIB_ATTRIBUTE_ASSUME_ALIGNED(8);
116 nmalloc_aligned(size_t size, size_t algn) NLIB_ATTRIBUTE_MALLOC NLIB_ATTRIBUTE_ALLOC_SIZE1(1)
117  NLIB_ATTRIBUTE_ALLOC_ALIGN(2) NLIB_ATTRIBUTE_ASSUME_ALIGNED(8);
118 NLIB_VIS_PUBLIC size_t nmalloc_size(const void* ptr) NLIB_NONNULL;
119 NLIB_VIS_PUBLIC void nfree(void* p);
120 NLIB_VIS_PUBLIC void nfree_size(void* p, size_t size);
121 
123 
124 #ifdef __cplusplus
125 }
126 #endif
127 
128 #ifdef __cplusplus
129 
130 inline bool operator==(const HeapHash& rhs, const HeapHash& lhs) {
131  return rhs.alloc_count == lhs.alloc_count && rhs.alloc_size == lhs.alloc_size &&
132  rhs.hash == lhs.hash;
133 }
134 
135 inline bool operator!=(const HeapHash& rhs, const HeapHash& lhs) {
136  return rhs.alloc_count != lhs.alloc_count || rhs.alloc_size != lhs.alloc_size ||
137  rhs.hash != lhs.hash;
138 }
139 
140 NLIB_NAMESPACE_BEGIN
141 namespace heap {
142 
143 template<typename T>
144 struct NMallocStlAllocator {
145  typedef size_t size_type;
146  typedef T value_type;
147  typedef T* pointer;
148  typedef const T* const_pointer;
149  typedef T& reference;
150  typedef const T& const_reference;
151  typedef ptrdiff_t difference_type;
152  template<typename U>
153  struct rebind {
154  typedef NMallocStlAllocator<U> other;
155  };
156  NMallocStlAllocator() {}
157  explicit NMallocStlAllocator(const NMallocStlAllocator<T>&) {}
158  template<class _Other>
159  NMallocStlAllocator(const NMallocStlAllocator<_Other>&) {}
160  pointer allocate(size_type n, const void* p = 0);
161  void deallocate(pointer p, size_type n) {
162 #if 1
163  nfree_size(p, n * sizeof(T));
164 #else
165  (void)n;
166  nfree(p);
167 #endif
168  }
169  void construct(pointer p, const T& t) { new ((void*)p) T(t); }
170  void construct(pointer p) { new ((void*)p) T(); }
171 #if defined(__cpp_rvalue_references) && defined(__cpp_variadic_templates)
172  template<class X, class... ARGS>
173  void construct(X* p, ARGS&&... args) {
174  new ((void*)p) X(std::forward<ARGS>(args)...);
175  }
176 #endif
177  void destroy(pointer ptr) {
178  (void)ptr;
179  (*ptr).~T();
180  }
181  template<class X>
182  void destroy(X* p) {
183  NLIB_UNUSED(p); // workaround for VS2012
184  p->~X();
185  }
186  size_t max_size() const {
187  size_t cnt = (size_t)-1 / sizeof(T);
188  return 0 < cnt ? cnt : 1;
189  }
190  pointer address(reference value) const { return &value; }
191  const_pointer address(const_reference value) const { return &value; }
192 };
193 
194 template<typename T>
195 typename NMallocStlAllocator<T>::pointer
196 NMallocStlAllocator<T>::allocate(size_type n, const void* p) {
197  (void)p;
198  void* pp = nmalloc(n * sizeof(T));
199  return reinterpret_cast<T*>(pp);
200 }
201 
202 template<class T1, class T2>
203 inline bool operator==(const NMallocStlAllocator<T1>&, const NMallocStlAllocator<T2>&) {
204  return true;
205 }
206 
207 template<class T1, class T2>
208 inline bool operator!=(const NMallocStlAllocator<T1>&, const NMallocStlAllocator<T2>&) {
209  return false;
210 }
211 
212 } // namespace heap
213 NLIB_NAMESPACE_END
214 
215 #endif
216 
217 #ifdef __cplusplus
218 #define NLIB_REPLACE_MALLOC \
219  extern "C" { \
220  void* nlib_malloc(size_t n) { return nmalloc(n); } \
221  void nlib_free(void* p) { nfree(p); } \
222  void* nlib_calloc(size_t nmemb, size_t size) { return ncalloc(nmemb, size); } \
223  void* nlib_realloc(void* ptr, size_t size) { return nrealloc(ptr, size); } \
224  void* nlib_memalign(size_t alignment, size_t size) { \
225  return nmalloc_aligned(size, alignment); \
226  } \
227  void nlib_free_size(void* ptr, size_t size) { nfree_size(ptr, size); } \
228  }
229 
230 #ifndef NN_PLATFORM_CTR
231 #define NLIB_REPLACE_MALLOC_NEW \
232  NLIB_REPLACE_MALLOC \
233  void* operator new(size_t size) { return nlib_malloc(size); } \
234  void operator delete(void* ptr)NLIB_NOEXCEPT { nlib_free(ptr); } \
235  void* operator new(size_t size, const std::nothrow_t&) NLIB_NOEXCEPT { \
236  return nlib_malloc(size); \
237  } \
238  void operator delete(void* ptr, const std::nothrow_t&)NLIB_NOEXCEPT { nlib_free(ptr); } \
239  void* operator new[](size_t size) { return nlib_malloc(size); } \
240  void operator delete[](void* ptr) NLIB_NOEXCEPT { nlib_free(ptr); } \
241  void* operator new[](size_t size, const std::nothrow_t&) NLIB_NOEXCEPT { \
242  return nlib_malloc(size); \
243  } \
244  void operator delete[](void* ptr, const std::nothrow_t&) NLIB_NOEXCEPT { nlib_free(ptr); } \
245  void operator delete(void* ptr, size_t size)NLIB_NOEXCEPT { nlib_free_size(ptr, size); } \
246  void operator delete(void* ptr, size_t size, const std::nothrow_t&)NLIB_NOEXCEPT { \
247  nlib_free_size(ptr, size); \
248  } \
249  void operator delete[](void* ptr, size_t size) NLIB_NOEXCEPT { nlib_free_size(ptr, size); } \
250  void operator delete[](void* ptr, size_t size, const std::nothrow_t&) NLIB_NOEXCEPT { \
251  nlib_free_size(ptr, size); \
252  }
253 #else
254 #define NLIB_REPLACE_MALLOC_NEW \
255  NLIB_REPLACE_MALLOC \
256  void* operator new(size_t size) throw(std::bad_alloc) { return nlib_malloc(size); } \
257  void operator delete(void* ptr) throw() { nlib_free(ptr); } \
258  void* operator new(size_t size, const std::nothrow_t&) throw() { return nlib_malloc(size); } \
259  void* operator new[](size_t size) throw(std::bad_alloc) { return nlib_malloc(size); } \
260  void operator delete[](void* ptr) throw() { nlib_free(ptr); } \
261  void* operator new[](size_t size, const std::nothrow_t&) throw() { return nlib_malloc(size); }
262 #endif
263 #else
264 #define NLIB_REPLACE_MALLOC \
265  void* nlib_malloc(size_t n) { return nmalloc(n); } \
266  void nlib_free(void* p) { nfree(p); } \
267  void* nlib_calloc(size_t nmemb, size_t size) { return ncalloc(nmemb, size); } \
268  void* nlib_realloc(void* ptr, size_t size) { return nrealloc(ptr, size); } \
269  void* nlib_memalign(size_t alignment, size_t size) { \
270  return nmalloc_aligned(size, alignment); \
271  } \
272  void nlib_free_size(void* ptr, size_t size) { nfree_size(ptr, size); }
273 #define NLIB_REPLACE_MALLOC_NEW NLIB_REPLACE_MALLOC
274 #endif
275 
276 #ifdef NLIB_WINDLL
277 #define NMALLOC_GET_SETTINGS \
278  void nmalloc_get_settings(NMallocSettings*); \
279  void __stdcall _nlib_tls_callback_heap(void* h, DWORD dwReason, void* r) { \
280  (void)h; \
281  (void)r; \
282  static __declspec(thread) int nlib_dummy_nmalloc; \
283  if (dwReason == DLL_PROCESS_ATTACH) { \
284  extern void (*g_nmalloc_get_settings_func)(NMallocSettings*); \
285  nlib_dummy_nmalloc = 1; \
286  g_nmalloc_get_settings_func = nmalloc_get_settings; \
287  } \
288  } \
289  __pragma(section(".CRT$XLB", long, read)) __declspec(allocate(".CRT$XLB")) \
290  PIMAGE_TLS_CALLBACK _xl_b = _nlib_tls_callback_heap; \
291  void nmalloc_get_settings(NMallocSettings* settings)
292 #else
293 #ifdef __cplusplus
294 #define NMALLOC_GET_SETTINGS extern "C" void nmalloc_get_settings(NMallocSettings* settings)
295 #else
296 #define NMALLOC_GET_SETTINGS void nmalloc_get_settings(NMallocSettings* settings)
297 #endif
298 #endif
299 
300 #if defined(_MSC_VER) && defined(nx_heap_EXPORTS)
301 #undef NLIB_VIS_PUBLIC
302 #define NLIB_VIS_PUBLIC NLIB_WINIMPORT
303 #endif
304 
305 #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:106
基本的な情報のみを表示します。
Definition: NMalloc.h:76
void * nrealloc(void *ptr, size_t size)
メモリの割り当てを変更します。realloc()C標準関数に相当します。
情報を全て表示します。
Definition: NMalloc.h:80
#define NLIB_CHECK_RESULT
関数の呼び出し元が戻り値をチェックする必要があることを示します。
size_t nmalloc_size(const void *ptr)
ptrに実際に割り当てられたメモリ量を返します。
size_t alloc_size
ヒープ内でユーザーによってアロケートされた領域のサイズの合計です。
Definition: NMalloc.h:46
ユーザーによって確保されている全てのメモリのアドレスとサイズを表示します。
Definition: NMalloc.h:78
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価ならば、trueを返します。
Definition: NMalloc.h:130
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価でなければ、trueを返します。
Definition: NMalloc.h:135
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:87
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:77
開発環境別の設定が書かれるファイルです。
ヒープ全体のページの割当密度の概要を視覚的に表示します。1MBを1つのASCIIキャラクタで表現しています。 ...
Definition: NMalloc.h:79
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:75
ユーザーが利用しているヒープ内のメモリの利用状況のサマリが記述される構造体です。
Definition: NMalloc.h:44
void * nmalloc_aligned(size_t size, size_t algn)
アライメントを指定してメモリ領域を確保します。
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:37