File: mem_alloc.pyx

package info (click to toggle)
rdma-core 56.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 17,196 kB
  • sloc: ansic: 171,361; python: 13,724; sh: 2,774; perl: 1,465; makefile: 73
file content (191 lines) | stat: -rw-r--r-- 6,340 bytes parent folder | download
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