mem.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Copyright 2021 The Libc Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:build !libc.membrk && !libc.memgrind && !(linux && (amd64 || arm64 || loong64 || ppc64le || s390x || riscv64 || 386 || arm))
  5. package libc // import "modernc.org/libc"
  6. import (
  7. "modernc.org/libc/errno"
  8. "modernc.org/libc/sys/types"
  9. "modernc.org/memory"
  10. )
  11. const memgrind = false
  12. var (
  13. allocator memory.Allocator
  14. )
  15. // void *malloc(size_t size);
  16. func Xmalloc(t *TLS, n types.Size_t) uintptr {
  17. if __ccgo_strace {
  18. trc("t=%v n=%v, (%v:)", t, n, origin(2))
  19. }
  20. if n == 0 {
  21. // malloc(0) should return unique pointers
  22. // (often expected and gnulib replaces malloc if malloc(0) returns 0)
  23. n = 1
  24. }
  25. allocMu.Lock()
  26. defer allocMu.Unlock()
  27. p, err := allocator.UintptrMalloc(int(n))
  28. if err != nil {
  29. t.setErrno(errno.ENOMEM)
  30. return 0
  31. }
  32. return p
  33. }
  34. // void *calloc(size_t nmemb, size_t size);
  35. func Xcalloc(t *TLS, n, size types.Size_t) uintptr {
  36. if __ccgo_strace {
  37. trc("t=%v n=%v size=%v, (%v:)", t, n, size, origin(2))
  38. }
  39. rq := int(n * size)
  40. if rq == 0 {
  41. rq = 1
  42. }
  43. allocMu.Lock()
  44. defer allocMu.Unlock()
  45. p, err := allocator.UintptrCalloc(rq)
  46. if err != nil {
  47. t.setErrno(errno.ENOMEM)
  48. return 0
  49. }
  50. return p
  51. }
  52. // void *realloc(void *ptr, size_t size);
  53. func Xrealloc(t *TLS, ptr uintptr, size types.Size_t) uintptr {
  54. if __ccgo_strace {
  55. trc("t=%v ptr=%v size=%v, (%v:)", t, ptr, size, origin(2))
  56. }
  57. allocMu.Lock()
  58. defer allocMu.Unlock()
  59. p, err := allocator.UintptrRealloc(ptr, int(size))
  60. if err != nil {
  61. t.setErrno(errno.ENOMEM)
  62. return 0
  63. }
  64. return p
  65. }
  66. // void free(void *ptr);
  67. func Xfree(t *TLS, p uintptr) {
  68. if __ccgo_strace {
  69. trc("t=%v p=%v, (%v:)", t, p, origin(2))
  70. }
  71. if p == 0 {
  72. return
  73. }
  74. allocMu.Lock()
  75. defer allocMu.Unlock()
  76. allocator.UintptrFree(p)
  77. }
  78. func Xmalloc_usable_size(tls *TLS, p uintptr) (r types.Size_t) {
  79. if __ccgo_strace {
  80. trc("tls=%v p=%v, (%v:)", tls, p, origin(2))
  81. defer func() { trc("-> %v", r) }()
  82. }
  83. if p == 0 {
  84. return 0
  85. }
  86. allocMu.Lock()
  87. defer allocMu.Unlock()
  88. return types.Size_t(memory.UintptrUsableSize(p))
  89. }
  90. func UsableSize(p uintptr) types.Size_t {
  91. allocMu.Lock()
  92. defer allocMu.Unlock()
  93. return types.Size_t(memory.UintptrUsableSize(p))
  94. }
  95. type MemAllocatorStat struct {
  96. Allocs int
  97. Bytes int
  98. Mmaps int
  99. }
  100. // MemStat returns the global memory allocator statistics.
  101. // should be compiled with the memory.counters build tag for the data to be available.
  102. func MemStat() MemAllocatorStat {
  103. allocMu.Lock()
  104. defer allocMu.Unlock()
  105. return MemAllocatorStat{
  106. Allocs: allocator.Allocs,
  107. Bytes: allocator.Bytes,
  108. Mmaps: allocator.Mmaps,
  109. }
  110. }
  111. // MemAuditStart locks the memory allocator, initializes and enables memory
  112. // auditing. Finaly it unlocks the memory allocator.
  113. //
  114. // Some memory handling errors, like double free or freeing of unallocated
  115. // memory, will panic when memory auditing is enabled.
  116. //
  117. // This memory auditing functionality has to be enabled using the libc.memgrind
  118. // build tag.
  119. //
  120. // It is intended only for debug/test builds. It slows down memory allocation
  121. // routines and it has additional memory costs.
  122. func MemAuditStart() {}
  123. // MemAuditReport locks the memory allocator, reports memory leaks, if any.
  124. // Finally it disables memory auditing and unlocks the memory allocator.
  125. //
  126. // This memory auditing functionality has to be enabled using the libc.memgrind
  127. // build tag.
  128. //
  129. // It is intended only for debug/test builds. It slows down memory allocation
  130. // routines and it has additional memory costs.
  131. func MemAuditReport() error { return nil }