def _alloc_C_libcall(self, size, ctype): if not self.available(): raise RuntimeError("Couldn't find `libc`'s `posix_memalign` to " "allocate memory") pagesize = self.lib.getpagesize() assert self.padding_bytes % pagesize == 0 npages_pad = self.padding_bytes // pagesize nbytes_user = size * ctypes.sizeof(ctype) npages_user = (nbytes_user + pagesize - 1) // pagesize npages_alloc = 2 * npages_pad + npages_user c_bytesize = ctypes.c_ulong(npages_alloc * pagesize) c_pointer = ctypes.cast(ctypes.c_void_p(), ctypes.c_void_p) alignment = self.lib.getpagesize() ret = self.lib.posix_memalign(ctypes.byref(c_pointer), alignment, c_bytesize) if ret != 0: return None, None # generate pointers to the left padding, the user data, and the right pad padleft_pointer = c_pointer c_pointer = ctypes.c_void_p(c_pointer.value + self.padding_bytes) padright_pointer = ctypes.c_void_p(c_pointer.value + npages_user * pagesize) # and set the permissions on the pad memory to 0 (no access) # if these fail, don't worry about failing the entire allocation c_padsize = ctypes.c_ulong(self.padding_bytes) if self.lib.mprotect(padleft_pointer, c_padsize, ctypes.c_int(0)): logger.warning("couldn't protect memory") if self.lib.mprotect(padright_pointer, c_padsize, ctypes.c_int(0)): logger.warning("couldn't protect memory") # if there is a multiple of 4 bytes left, use the code below to poison # the memory if nbytes_user % 4 == 0: poison_size = npages_user * pagesize - nbytes_user intp_type = ctypes.POINTER(ctypes.c_int) poison_ptr = ctypes.cast( ctypes.c_void_p(c_pointer.value + nbytes_user), intp_type) # for both float32 and float64, a sequence of -100 int32s represents NaNs, # at least on little-endian architectures. It shouldn't matter what we # put in there, anyway for i in range(poison_size // 4): poison_ptr[i] = -100 return c_pointer, (padleft_pointer, c_bytesize)
def _alloc_C_libcall(self, size, ctype): if not self.available(): raise RuntimeError("Couldn't find `libc`'s `posix_memalign` to " "allocate memory") pagesize = self.lib.getpagesize() assert self.padding_bytes % pagesize == 0 npages_pad = self.padding_bytes // pagesize nbytes_user = size * ctypes.sizeof(ctype) npages_user = (nbytes_user + pagesize - 1) // pagesize npages_alloc = 2*npages_pad + npages_user c_bytesize = ctypes.c_ulong(npages_alloc * pagesize) c_pointer = ctypes.cast(ctypes.c_void_p(), ctypes.c_void_p) alignment = self.lib.getpagesize() ret = self.lib.posix_memalign(ctypes.byref(c_pointer), alignment, c_bytesize) if ret != 0: return None, None # generate pointers to the left padding, the user data, and the right pad padleft_pointer = c_pointer c_pointer = ctypes.c_void_p(c_pointer.value + self.padding_bytes) padright_pointer = ctypes.c_void_p(c_pointer.value + npages_user * pagesize) # and set the permissions on the pad memory to 0 (no access) # if these fail, don't worry about failing the entire allocation c_padsize = ctypes.c_ulong(self.padding_bytes) if self.lib.mprotect(padleft_pointer, c_padsize, ctypes.c_int(0)): logger.warning("couldn't protect memory") if self.lib.mprotect(padright_pointer, c_padsize, ctypes.c_int(0)): logger.warning("couldn't protect memory") # if there is a multiple of 4 bytes left, use the code below to poison # the memory if nbytes_user % 4 == 0: poison_size = npages_user*pagesize - nbytes_user intp_type = ctypes.POINTER(ctypes.c_int) poison_ptr = ctypes.cast(ctypes.c_void_p(c_pointer.value + nbytes_user), intp_type) # for both float32 and float64, a sequence of -100 int32s represents NaNs, # at least on little-endian architectures. It shouldn't matter what we # put in there, anyway for i in range(poison_size // 4): poison_ptr[i] = -100 return c_pointer, (padleft_pointer, c_bytesize)