| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | // Copyright 2011 Evan Shaw. All rights reserved. | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style | 
					
						
							|  |  |  | // license that can be found in the LICENSE-MMAP-GO file. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-01 15:24:11 +00:00
										 |  |  | //go:build unix | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Modifications (c) 2017 The Memory Authors. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package memory // import "modernc.org/memory" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2025-04-01 15:24:11 +00:00
										 |  |  | 	"golang.org/x/sys/unix" | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2025-04-01 15:24:11 +00:00
										 |  |  | 	"unsafe" | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-22 16:27:55 +02:00
										 |  |  | const pageSizeLog = 16 | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	osPageMask = osPageSize - 1 | 
					
						
							|  |  |  | 	osPageSize = os.Getpagesize() | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func unmap(addr uintptr, size int) error { | 
					
						
							| 
									
										
										
										
											2025-04-01 15:24:11 +00:00
										 |  |  | 	return unix.MunmapPtr(unsafe.Pointer(addr), uintptr(size)) | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // pageSize aligned. | 
					
						
							|  |  |  | func mmap(size int) (uintptr, int, error) { | 
					
						
							|  |  |  | 	size = roundup(size, osPageSize) | 
					
						
							| 
									
										
										
										
											2025-05-22 16:27:55 +02:00
										 |  |  | 	// Ask for more so we can align the result at a pageSize boundary | 
					
						
							|  |  |  | 	n := size + pageSize | 
					
						
							|  |  |  | 	up, err := unix.MmapPtr(-1, 0, nil, uintptr(n), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_PRIVATE|unix.MAP_ANON) | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return 0, 0, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-01 15:24:11 +00:00
										 |  |  | 	p := uintptr(up) | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	if p&uintptr(osPageMask) != 0 { | 
					
						
							|  |  |  | 		panic("internal error") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mod := int(p) & pageMask | 
					
						
							| 
									
										
										
										
											2025-05-22 16:27:55 +02:00
										 |  |  | 	if mod != 0 { // Return the extra part before pageSize aligned block | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 		m := pageSize - mod | 
					
						
							|  |  |  | 		if err := unmap(p, m); err != nil { | 
					
						
							| 
									
										
										
										
											2025-05-22 16:27:55 +02:00
										 |  |  | 			unmap(p, n) // Do not leak the first mmap | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 			return 0, 0, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		n -= m | 
					
						
							|  |  |  | 		p += uintptr(m) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if p&uintptr(pageMask) != 0 { | 
					
						
							|  |  |  | 		panic("internal error") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-22 16:27:55 +02:00
										 |  |  | 	if n > size { // Return the extra part after pageSize aligned block | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 		if err := unmap(p+uintptr(size), n-size); err != nil { | 
					
						
							| 
									
										
										
										
											2025-05-22 16:27:55 +02:00
										 |  |  | 			// Do not error when the kernel rejects the extra part after, just return the | 
					
						
							|  |  |  | 			// unexpectedly enlarged size. | 
					
						
							|  |  |  | 			// | 
					
						
							|  |  |  | 			// Fixes the bigsort.test failures on linux/s390x, see: https://gitlab.com/cznic/sqlite/-/issues/207 | 
					
						
							|  |  |  | 			size = n | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return p, size, nil | 
					
						
							|  |  |  | } |