memory.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include <stdlib.h>
  2. #include <assert.h>
  3. #include "nvim/lib/ringbuf.h"
  4. enum { RB_SIZE = 1024 };
  5. typedef struct {
  6. void *ptr;
  7. size_t size;
  8. } AllocRecord;
  9. RINGBUF_TYPEDEF(AllocRecords, AllocRecord)
  10. RINGBUF_INIT(AllocRecords, arecs, AllocRecord, RINGBUF_DUMMY_FREE)
  11. RINGBUF_STATIC(static, AllocRecords, AllocRecord, arecs, RB_SIZE)
  12. size_t allocated_memory = 0;
  13. size_t ever_allocated_memory = 0;
  14. size_t allocated_memory_limit = SIZE_MAX;
  15. void *xmalloc(const size_t size)
  16. {
  17. void *ret = malloc(size);
  18. allocated_memory += size;
  19. ever_allocated_memory += size;
  20. assert(allocated_memory <= allocated_memory_limit);
  21. assert(arecs_rb_length(&arecs) < RB_SIZE);
  22. arecs_rb_push(&arecs, (AllocRecord) {
  23. .ptr = ret,
  24. .size = size,
  25. });
  26. return ret;
  27. }
  28. void xfree(void *const p)
  29. {
  30. if (p == NULL) {
  31. return;
  32. }
  33. RINGBUF_FORALL(&arecs, AllocRecord, arec) {
  34. if (arec->ptr == p) {
  35. allocated_memory -= arec->size;
  36. arecs_rb_remove(&arecs, arecs_rb_find_idx(&arecs, arec));
  37. return;
  38. }
  39. }
  40. abort();
  41. }
  42. void *xrealloc(void *const p, size_t new_size)
  43. {
  44. void *ret = realloc(p, new_size);
  45. RINGBUF_FORALL(&arecs, AllocRecord, arec) {
  46. if (arec->ptr == p) {
  47. allocated_memory -= arec->size;
  48. allocated_memory += new_size;
  49. if (new_size > arec->size) {
  50. ever_allocated_memory += (new_size - arec->size);
  51. }
  52. arec->ptr = ret;
  53. arec->size = new_size;
  54. return ret;
  55. }
  56. }
  57. abort();
  58. return (void *)(intptr_t)1;
  59. }
  60. char *xstrdup(const char *str)
  61. FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET
  62. FUNC_ATTR_NONNULL_ALL
  63. {
  64. return xmemdupz(str, strlen(str));
  65. }
  66. void *xmallocz(size_t size)
  67. FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
  68. {
  69. size_t total_size = size + 1;
  70. assert(total_size > size);
  71. void *ret = xmalloc(total_size);
  72. ((char *)ret)[size] = 0;
  73. return ret;
  74. }
  75. char *xstpcpy(char *restrict dst, const char *restrict src)
  76. FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
  77. {
  78. const size_t len = strlen(src);
  79. return (char *)memcpy(dst, src, len + 1) + len;
  80. }
  81. void *xmemdupz(const void *data, size_t len)
  82. FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
  83. FUNC_ATTR_NONNULL_ALL
  84. {
  85. return memcpy(xmallocz(len), data, len);
  86. }