1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
# Copyright (c) 2018, Mellanox Technologies. All rights reserved. See COPYING file
#cython: language_level=3
from posix.stdlib cimport posix_memalign as c_posix_memalign
from libc.stdlib cimport malloc as c_malloc, free as c_free
from posix.mman cimport mmap as c_mmap, munmap as c_munmap, madvise as c_madvise
from libc.stdint cimport uintptr_t, uint32_t, uint64_t
from pyverbs.base import PyverbsRDMAErrno
from libc.string cimport memcpy
from libc.string cimport memset
cimport posix.mman as mm
cdef extern from 'sys/mman.h':
cdef void* MAP_FAILED
cdef int MADV_DONTNEED
cdef extern from 'endian.h':
unsigned long htobe32(unsigned long host_32bits)
unsigned long htobe64(unsigned long host_64bits)
def mmap(addr=0, length=100, prot=mm.PROT_READ | mm.PROT_WRITE,
flags=mm.MAP_PRIVATE | mm.MAP_ANONYMOUS, fd=0, offset=0):
"""
Python wrapper for sys mmap function
:param addr: Address to mmap the memory
:param length: The length of the requested memory in bytes
:param prot: Indicate the protection of this memory
:param flags: Specify speicific flags to this memory
:param fd: File descriptor to mmap specific file
:param offset: Offset to use when mmap
:return: The address to the mapped memory
"""
# uintptr_t is guaranteed to be large enough to hold any pointer.
# In order to safely cast addr to void*, it is firstly cast to uintptr_t.
ptr = c_mmap(<void*><uintptr_t>addr, length, prot, flags, fd, offset)
if <void *>ptr == MAP_FAILED:
raise MemoryError('Failed to mmap memory')
return <uintptr_t> ptr
def madvise(addr, length, flags=MADV_DONTNEED):
"""
Python wrapper for sys madvise function
:param addr: Address of the memory to be advised about
:param length: The length of the requested memory in bytes
:param flags: Specify speicific flags to this memory
"""
rc = c_madvise(<void*><uintptr_t>addr, length, flags)
if rc:
raise PyverbsRDMAErrno('Failed to madvise memory')
def munmap(addr, length):
"""
Python wrapper for sys munmap function
:param addr: The address of the mapped memory to unmap
:param length: The length of this mapped memory
"""
ret = c_munmap(<void*><uintptr_t>addr, length)
if ret:
raise MemoryError('Failed to munmap requested memory')
def malloc(size):
"""
Python wrapper for stdlib malloc function
:param size: The size of the memory block in bytes
:return: The address of the allocated memory, or 0 if the request fails
"""
ptr = c_malloc(size)
if not ptr:
raise MemoryError('Failed to allocate memory')
return <uintptr_t>ptr
def posix_memalign(size, alignment=8):
"""
Python wrapper for the stdlib posix_memalign function.
The function calls posix_memalign and memsets the memory to 0.
:param size: The size of the memory block in bytes
:param alignment: Alignment of the allocated memory, must be a power of two
:return: The address of the allocated memory, which is a multiple of
alignment.
"""
cdef void* ptr
ret = c_posix_memalign(&ptr, alignment, size)
if ret:
raise MemoryError('Failed to allocate memory ({err}'.format(ret))
memset(ptr, 0, size)
return <uintptr_t>ptr
def free(ptr):
"""
Python wrapper for stdlib free function
:param ptr: The address of a previously allocated memory block
"""
c_free(<void*><uintptr_t>ptr)
def writebe32(addr, val, offset=0):
"""
Write 32-bit value <val> as Big Endian to address <addr> and offset <offset>
:param addr: The start of the address to write the value to
:param val: Value to write
:param offset: Offset of the address to write the value to (in 4-bytes)
"""
(<uint32_t*><void*><uintptr_t>addr)[offset] = htobe32(val)
def writebe64(addr, val, offset=0):
"""
Write 64-bit value <val> as Big Endian to address <addr> and offset <offset>
:param addr: The start of the address to write the value to
:param val: Value to write
:param offset: Offset of the address to write the value to (in 8-bytes)
"""
(<uint64_t*><void*><uintptr_t>addr)[offset] = htobe64(val)
def write(addr, data, length, offset=0):
"""
Write user data to a given address
:param addr: The start of the address to write to
:param data: User data to write (string or bytes)
:param length: Length of the data to write (in bytes)
:param offset: Writing offset (in bytes)
"""
cdef int off = offset
cdef void* buf = <void*><uintptr_t>addr
# If data is a string, cast it to bytes as Python3 doesn't
# automatically convert it.
if isinstance(data, str):
data = data.encode()
memcpy(<char*>(buf + off), <char *>data, length)
def read32(addr, offset=0):
"""
Read 32-bit value from address <addr> and offset <offset>
:param addr: The start of the address to read from
:param offset: Offset of the address to read from (in 4-bytes)
:return: The read value
"""
return (<uint32_t*><uintptr_t>addr)[offset]
def read64(addr, offset=0):
"""
Read 64-bit value from address <addr> and offset <offset>
:param addr: The start of the address to read from
:param offset: Offset of the address to read from (in 8-bytes)
:return: The read value
"""
return (<uint64_t*><uintptr_t>addr)[offset]
def read(addr, length, offset=0):
"""
Reads data from a given address
:param addr: The start of the address to read from
:param length: Length of data to read (in bytes)
:param offset: Reading offset (in bytes)
:return: The data on the buffer in the requested offset (bytes)
"""
cdef char *data
data = <char*><uintptr_t>(addr + offset)
return data[:length]
# protection bits for mmap/mprotect
PROT_EXEC_ = mm.PROT_EXEC
PROT_READ_ = mm.PROT_READ
PROT_WRITE_ = mm.PROT_WRITE
PROT_NONE_ = mm.PROT_NONE
# flag bits for mmap
MAP_PRIVATE_ = mm.MAP_PRIVATE
MAP_SHARED_ = mm.MAP_SHARED
MAP_FIXED_ = mm.MAP_FIXED
MAP_ANONYMOUS_ = mm.MAP_ANONYMOUS
MAP_STACK_ = mm.MAP_STACK
MAP_LOCKED_ = mm.MAP_LOCKED
MAP_HUGETLB_ = mm.MAP_HUGETLB
MAP_POPULATE_ = mm.MAP_POPULATE
MAP_NORESERVE_ = mm.MAP_NORESERVE
MAP_GROWSDOWN_ = mm.MAP_GROWSDOWN
|