Advertisement
Guest User

Untitled

a guest
Dec 20th, 2014
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.64 KB | None | 0 0
  1. #include "thread_local_malloc.h"
  2.  
  3. #include <cassert>
  4. #include <malloc/malloc.h>
  5. #include <sys/mman.h>
  6. #include <unistd.h>
  7. #include <pthread/pthread.h>
  8. #include <thread>
  9.  
  10.  
  11. static pthread_key_t threadLocalZoneKey = 0;
  12.  
  13.  
  14. /**
  15. * This macro contains all the data that can be used to
  16. * generate the callbacks of a malloc_zone_t structure.
  17. *
  18. * This macro will call the macro functions A,B,C,D with the following parameters:
  19. *
  20. * A(x, y)
  21. * x := the return type
  22. * y := the malloc_zone_t callback name
  23. *
  24. * B(x, y)
  25. * x := an argument type
  26. * y := an argument name
  27. *
  28. * C(x, y)
  29. * x := a trailing argument type
  30. * y := a trailing argument name
  31. * The difference between B and C is that C signals that
  32. * this pair is the last one in the list of arguments.
  33. * Thus e.g. the trailing comma can be ommited.
  34. *
  35. * D(x)
  36. * x := the malloc_zone_t callback name (again)
  37. *
  38. * E(x)
  39. * x := an argument name
  40. *
  41. * F(x)
  42. * x := a trailing argument name
  43. *
  44. * B and C can be used to generate the arguments of a function.
  45. * E and F can be used to generate the matching parameters for a function.
  46. */
  47. #define MAP(A, B, C, D, E, F) \
  48. A(size_t, size) B(malloc_zone_t*, zone) C(const void*, ptr) D(size) E(zone) F(ptr) \
  49. A(void*, malloc) B(malloc_zone_t*, zone) C(size_t, size) D(malloc) E(zone) F(size) \
  50. A(void*, calloc) B(malloc_zone_t*, zone) B(size_t, num_items) C(size_t, size) D(calloc) E(zone) E(num_items) F(size) \
  51. A(void*, valloc) B(malloc_zone_t*, zone) C(size_t, size) D(valloc) E(zone) F(size) \
  52. A(void, free) B(malloc_zone_t*, zone) C(void*, ptr) D(free) E(zone) F(ptr) \
  53. A(void*, realloc) B(malloc_zone_t*, zone) B(void*, ptr) C(size_t, size) D(realloc) E(zone) E(ptr) F(size) \
  54. A(void, destroy) C(malloc_zone_t*, zone) D(destroy) F(zone) \
  55. A(unsigned, batch_malloc) B(malloc_zone_t*, zone) B(size_t, size) B(void**, results) C(unsigned, num_requested) D(batch_malloc) E(zone) E(size) E(results) F(num_requested) \
  56. A(void, batch_free) B(malloc_zone_t*, zone) B(void**, to_be_freed) C(unsigned, num_to_be_freed) D(batch_free) E(zone) E(to_be_freed) F(num_to_be_freed) \
  57. A(void*, memalign) B(malloc_zone_t*, zone) B(size_t, alignment) C(size_t, size) D(memalign) E(zone) E(alignment) F(size) \
  58. A(void, free_definite_size) B(malloc_zone_t*, zone) B(void*, ptr) C(size_t, size) D(free_definite_size) E(zone) E(ptr) F(size) \
  59. A(size_t, pressure_relief) B(malloc_zone_t*, zone) C(size_t, goal) D(pressure_relief) E(zone) F(goal) \
  60.  
  61. #define MAP_NIL(...)
  62. #define MAP_B(X, Y) X Y,
  63. #define MAP_C(X, Y) X Y
  64. #define MAP_E(X) X,
  65. #define MAP_F(X) X
  66.  
  67.  
  68. /*
  69. * This generates the necessary function pointers to store the original callback functions.
  70. * E.g.: void*(*orig_malloc)(malloc_zone_t* zone, size_t size);
  71. */
  72. #define A(X, Y) static X(*orig_##Y)(
  73. #define D(X) );
  74.  
  75. MAP(A, MAP_B, MAP_C, D, MAP_NIL, MAP_NIL)
  76.  
  77. #undef A
  78. #undef D
  79.  
  80.  
  81. /*
  82. * This generates the patched functions.
  83. * E.g.: void* tl_malloc(malloc_zone_t* zone, size_t size) { ... }
  84. */
  85. #define A(X, Y) static X tl_##Y(
  86. #define D(X) ) { \
  87. void* z = pthread_getspecific(threadLocalZoneKey); \
  88. if (z) zone = (malloc_zone_t*)z; \
  89. return orig_##X(
  90. #define F(X) X); }
  91.  
  92. MAP(A, MAP_B, MAP_C, D, MAP_E, F)
  93.  
  94. #undef A
  95. #undef D
  96. #undef F
  97.  
  98.  
  99. void tl_malloc_init() {
  100. pthread_key_create(&threadLocalZoneKey, [](void* data) {
  101. malloc_destroy_zone((malloc_zone_t*)data);
  102. });
  103.  
  104. malloc_zone_t* zone = malloc_default_zone();
  105.  
  106. vm_address_t pageStart = reinterpret_cast<vm_address_t>(zone) & static_cast<vm_size_t>(~(getpagesize() - 1));
  107. vm_size_t len = reinterpret_cast<vm_address_t>(zone) - pageStart + sizeof(malloc_zone_t);
  108. mprotect(reinterpret_cast<void*>(pageStart), len, PROT_READ | PROT_WRITE);
  109.  
  110. /*
  111. * Save the original callbacks in the function pointers.
  112. */
  113. #define A(X, Y) orig_##Y = zone->Y;
  114. MAP(A, MAP_NIL, MAP_NIL, MAP_NIL, MAP_NIL, MAP_NIL)
  115. #undef A
  116.  
  117. /*
  118. * Overwrite using the patched functions.
  119. */
  120. #define A(X, Y) zone->Y = tl_##Y;
  121. MAP(A, MAP_NIL, MAP_NIL, MAP_NIL, MAP_NIL, MAP_NIL)
  122. #undef A
  123.  
  124. mprotect(reinterpret_cast<void*>(pageStart), len, PROT_READ);
  125. }
  126.  
  127. void tl_malloc_register() {
  128. assert(threadLocalZoneKey != 0);
  129.  
  130. void* zone = pthread_getspecific(threadLocalZoneKey);
  131.  
  132. if (!zone) {
  133. zone = malloc_create_zone(0, 0);
  134. pthread_setspecific(threadLocalZoneKey, zone);
  135. }
  136. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement