| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | // Copyright 2021 The Libc Authors. All rights reserved. | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style | 
					
						
							|  |  |  | // license that can be found in the LICENSE file. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  | //go:build !libc.membrk && !libc.memgrind && !(linux && (amd64 || arm64 || loong64 || ppc64le || s390x || riscv64 || 386 || arm)) | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | package libc // import "modernc.org/libc" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"modernc.org/libc/errno" | 
					
						
							|  |  |  | 	"modernc.org/libc/sys/types" | 
					
						
							|  |  |  | 	"modernc.org/memory" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const memgrind = false | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	allocator memory.Allocator | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // void *malloc(size_t size); | 
					
						
							|  |  |  | func Xmalloc(t *TLS, n types.Size_t) uintptr { | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  | 		trc("t=%v n=%v, (%v:)", t, n, origin(2)) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	if n == 0 { | 
					
						
							| 
									
										
										
										
											2025-05-22 16:27:55 +02:00
										 |  |  | 		// malloc(0) should return unique pointers | 
					
						
							|  |  |  | 		// (often expected and gnulib replaces malloc if malloc(0) returns 0) | 
					
						
							|  |  |  | 		n = 1 | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	allocMu.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer allocMu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p, err := allocator.UintptrMalloc(int(n)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.setErrno(errno.ENOMEM) | 
					
						
							|  |  |  | 		return 0 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return p | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // void *calloc(size_t nmemb, size_t size); | 
					
						
							|  |  |  | func Xcalloc(t *TLS, n, size types.Size_t) uintptr { | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  | 	if __ccgo_strace { | 
					
						
							| 
									
										
										
										
											2025-05-22 16:27:55 +02:00
										 |  |  | 		trc("t=%v n=%v size=%v, (%v:)", t, n, size, origin(2)) | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	rq := int(n * size) | 
					
						
							|  |  |  | 	if rq == 0 { | 
					
						
							| 
									
										
										
										
											2025-05-22 16:27:55 +02:00
										 |  |  | 		rq = 1 | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	allocMu.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer allocMu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-22 16:27:55 +02:00
										 |  |  | 	p, err := allocator.UintptrCalloc(rq) | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.setErrno(errno.ENOMEM) | 
					
						
							|  |  |  | 		return 0 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return p | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // void *realloc(void *ptr, size_t size); | 
					
						
							|  |  |  | func Xrealloc(t *TLS, ptr uintptr, size types.Size_t) uintptr { | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  | 		trc("t=%v ptr=%v size=%v, (%v:)", t, ptr, size, origin(2)) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	allocMu.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer allocMu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p, err := allocator.UintptrRealloc(ptr, int(size)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.setErrno(errno.ENOMEM) | 
					
						
							|  |  |  | 		return 0 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return p | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // void free(void *ptr); | 
					
						
							|  |  |  | func Xfree(t *TLS, p uintptr) { | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  | 		trc("t=%v p=%v, (%v:)", t, p, origin(2)) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	if p == 0 { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	allocMu.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer allocMu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	allocator.UintptrFree(p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-06 14:40:53 +00:00
										 |  |  | func Xmalloc_usable_size(tls *TLS, p uintptr) (r types.Size_t) { | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  | 		trc("tls=%v p=%v, (%v:)", tls, p, origin(2)) | 
					
						
							|  |  |  | 		defer func() { trc("-> %v", r) }() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-06 14:40:53 +00:00
										 |  |  | 	if p == 0 { | 
					
						
							|  |  |  | 		return 0 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	allocMu.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer allocMu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return types.Size_t(memory.UintptrUsableSize(p)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | func UsableSize(p uintptr) types.Size_t { | 
					
						
							|  |  |  | 	allocMu.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer allocMu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return types.Size_t(memory.UintptrUsableSize(p)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-01 15:24:11 +00:00
										 |  |  | type MemAllocatorStat struct { | 
					
						
							|  |  |  | 	Allocs int | 
					
						
							|  |  |  | 	Bytes  int | 
					
						
							|  |  |  | 	Mmaps  int | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MemStat returns the global memory allocator statistics. | 
					
						
							|  |  |  | // should be compiled with the memory.counters build tag for the data to be available. | 
					
						
							|  |  |  | func MemStat() MemAllocatorStat { | 
					
						
							|  |  |  | 	allocMu.Lock() | 
					
						
							|  |  |  | 	defer allocMu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return MemAllocatorStat{ | 
					
						
							|  |  |  | 		Allocs: allocator.Allocs, | 
					
						
							|  |  |  | 		Bytes:  allocator.Bytes, | 
					
						
							|  |  |  | 		Mmaps:  allocator.Mmaps, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | // MemAuditStart locks the memory allocator, initializes and enables memory | 
					
						
							|  |  |  | // auditing. Finaly it unlocks the memory allocator. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Some memory handling errors, like double free or freeing of unallocated | 
					
						
							|  |  |  | // memory, will panic when memory auditing is enabled. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This memory auditing functionality has to be enabled using the libc.memgrind | 
					
						
							|  |  |  | // build tag. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // It is intended only for debug/test builds. It slows down memory allocation | 
					
						
							|  |  |  | // routines and it has additional memory costs. | 
					
						
							|  |  |  | func MemAuditStart() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MemAuditReport locks the memory allocator, reports memory leaks, if any. | 
					
						
							|  |  |  | // Finally it disables memory auditing and unlocks the memory allocator. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This memory auditing functionality has to be enabled using the libc.memgrind | 
					
						
							|  |  |  | // build tag. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // It is intended only for debug/test builds. It slows down memory allocation | 
					
						
							|  |  |  | // routines and it has additional memory costs. | 
					
						
							|  |  |  | func MemAuditReport() error { return nil } |