@k13engineering/linux-dmabuf-allocator 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/allocation-size.d.ts +8 -0
- package/dist/lib/allocation-size.js +15 -0
- package/dist/lib/dmabuf-allocator-interface.d.ts +18 -0
- package/dist/lib/dmabuf-allocator-interface.js +23 -0
- package/dist/lib/dmabuf-heap/dmabuf-heap-ioctl.d.ts +19 -0
- package/dist/lib/dmabuf-heap/dmabuf-heap-ioctl.js +97 -0
- package/dist/lib/dmabuf-heap/dmabuf-heap-manager.d.ts +42 -0
- package/dist/lib/dmabuf-heap/dmabuf-heap-manager.js +215 -0
- package/dist/lib/dmabuf-heap/dmabuf-heap.d.ts +15 -0
- package/dist/lib/dmabuf-heap/dmabuf-heap.js +84 -0
- package/dist/lib/dmabuf-heap/index.d.ts +3 -0
- package/dist/lib/dmabuf-heap/index.js +19 -0
- package/dist/lib/endian-buffer.d.ts +54 -0
- package/dist/lib/endian-buffer.js +59 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.js +5 -0
- package/dist/lib/kernel-interface-impl-linux.d.ts +3 -0
- package/dist/lib/kernel-interface-impl-linux.js +75 -0
- package/dist/lib/kernel-interface.d.ts +39 -0
- package/dist/lib/kernel-interface.js +32 -0
- package/package.json +1 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const createDefaultAllocationSizeDeterminer = ({ pageSize }/*: { pageSize: number }*/) => {
|
|
2
|
+
|
|
3
|
+
const determineOptimalAllocationSize = ({ minimumSize }/*: { minimumSize: number }*/)/*: number*/ => {
|
|
4
|
+
const pagesNeeded = Math.ceil(minimumSize / pageSize);
|
|
5
|
+
return pagesNeeded * pageSize;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
determineOptimalAllocationSize
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
createDefaultAllocationSizeDeterminer
|
|
15
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type TDmabufAllocateArgs = {
|
|
2
|
+
size: number;
|
|
3
|
+
};
|
|
4
|
+
type TDmabufAllocateResult = {
|
|
5
|
+
error: Error;
|
|
6
|
+
dmabufFd: undefined;
|
|
7
|
+
} | {
|
|
8
|
+
error: undefined;
|
|
9
|
+
dmabufFd: number;
|
|
10
|
+
};
|
|
11
|
+
type TDmabufAllocator = {
|
|
12
|
+
allocate: (args: TDmabufAllocateArgs) => TDmabufAllocateResult;
|
|
13
|
+
pageSize: number;
|
|
14
|
+
determineOptimalAllocationSize: (args: {
|
|
15
|
+
minimumSize: number;
|
|
16
|
+
}) => number;
|
|
17
|
+
};
|
|
18
|
+
export type { TDmabufAllocator };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* c8 ignore start */
|
|
2
|
+
/*type TDmabufAllocateArgs = {
|
|
3
|
+
size: number;
|
|
4
|
+
};*/
|
|
5
|
+
|
|
6
|
+
/*type TDmabufAllocateResult = {
|
|
7
|
+
error: Error;
|
|
8
|
+
dmabufFd: undefined;
|
|
9
|
+
} | {
|
|
10
|
+
error: undefined;
|
|
11
|
+
dmabufFd: number;
|
|
12
|
+
};*/
|
|
13
|
+
|
|
14
|
+
/*type TDmabufAllocator = {
|
|
15
|
+
allocate: (args: TDmabufAllocateArgs) => TDmabufAllocateResult;
|
|
16
|
+
pageSize: number;
|
|
17
|
+
determineOptimalAllocationSize: (args: { minimumSize: number }) => number;
|
|
18
|
+
};*/
|
|
19
|
+
|
|
20
|
+
/*export type {
|
|
21
|
+
TDmabufAllocator
|
|
22
|
+
};*/
|
|
23
|
+
/* c8 ignore end */
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TDmabufHeapIoctlKernelInterface } from "../kernel-interface.js";
|
|
2
|
+
type TDmabufHeapIoctlAllocateResult = {
|
|
3
|
+
errno: undefined;
|
|
4
|
+
dmabufFd: number;
|
|
5
|
+
} | {
|
|
6
|
+
errno: number;
|
|
7
|
+
dmabufFd: undefined;
|
|
8
|
+
};
|
|
9
|
+
declare const createDmabufHeapIoctls: ({ kernelIoctlInterface }: {
|
|
10
|
+
kernelIoctlInterface: TDmabufHeapIoctlKernelInterface;
|
|
11
|
+
}) => {
|
|
12
|
+
dmabufHeapIoctlAllocate: ({ dmabufHeapFd, size, fdFlags, heapFlags }: {
|
|
13
|
+
dmabufHeapFd: number;
|
|
14
|
+
size: number;
|
|
15
|
+
fdFlags: bigint;
|
|
16
|
+
heapFlags: bigint;
|
|
17
|
+
}) => TDmabufHeapIoctlAllocateResult;
|
|
18
|
+
};
|
|
19
|
+
export { createDmabufHeapIoctls };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { endianBufferViewFor } from "../endian-buffer.js";
|
|
2
|
+
/*import type { TDmabufHeapIoctlKernelInterface } from "../kernel-interface.ts";*/
|
|
3
|
+
|
|
4
|
+
/*type TDmabufHeapIoctlAllocateResult = {
|
|
5
|
+
errno: undefined;
|
|
6
|
+
dmabufFd: number;
|
|
7
|
+
} | {
|
|
8
|
+
errno: number;
|
|
9
|
+
dmabufFd: undefined;
|
|
10
|
+
};*/
|
|
11
|
+
|
|
12
|
+
const formatAllocationData = ({
|
|
13
|
+
endianness,
|
|
14
|
+
len,
|
|
15
|
+
fdFlags,
|
|
16
|
+
heapFlags
|
|
17
|
+
}/*: {
|
|
18
|
+
endianness: TDmabufHeapIoctlKernelInterface["endianness"];
|
|
19
|
+
len: number;
|
|
20
|
+
fdFlags: bigint;
|
|
21
|
+
heapFlags: bigint;
|
|
22
|
+
}*/) => {
|
|
23
|
+
|
|
24
|
+
const allocationData = new Uint8Array(24);
|
|
25
|
+
|
|
26
|
+
const view = endianBufferViewFor({ buffer: allocationData, endianness });
|
|
27
|
+
|
|
28
|
+
// struct dma_heap_allocation_data {
|
|
29
|
+
// __u64 len
|
|
30
|
+
view.writeU64({ offset: 0, value: BigInt(len) });
|
|
31
|
+
// __u32 fd
|
|
32
|
+
view.writeU32({ offset: 8, value: 0 });
|
|
33
|
+
// __u32 fd_flags
|
|
34
|
+
view.writeU32({ offset: 12, value: Number(fdFlags) });
|
|
35
|
+
// __u64 heap_flags
|
|
36
|
+
view.writeU64({ offset: 16, value: heapFlags });
|
|
37
|
+
// }
|
|
38
|
+
|
|
39
|
+
return allocationData;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const DMA_HEAP_IOCTL_ALLOC = BigInt(0xc0184800);
|
|
43
|
+
|
|
44
|
+
const createDmabufHeapIoctls = ({
|
|
45
|
+
kernelIoctlInterface
|
|
46
|
+
}/*: {
|
|
47
|
+
kernelIoctlInterface: TDmabufHeapIoctlKernelInterface
|
|
48
|
+
}*/) => {
|
|
49
|
+
const dmabufHeapIoctlAllocate = ({
|
|
50
|
+
dmabufHeapFd,
|
|
51
|
+
size,
|
|
52
|
+
fdFlags,
|
|
53
|
+
heapFlags
|
|
54
|
+
}/*: {
|
|
55
|
+
dmabufHeapFd: number;
|
|
56
|
+
size: number;
|
|
57
|
+
fdFlags: bigint;
|
|
58
|
+
heapFlags: bigint;
|
|
59
|
+
}*/)/*: TDmabufHeapIoctlAllocateResult*/ => {
|
|
60
|
+
|
|
61
|
+
const allocationData = formatAllocationData({
|
|
62
|
+
endianness: kernelIoctlInterface.endianness,
|
|
63
|
+
len: size,
|
|
64
|
+
fdFlags,
|
|
65
|
+
heapFlags
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const { errno } = kernelIoctlInterface.ioctl({
|
|
69
|
+
fd: dmabufHeapFd,
|
|
70
|
+
request: DMA_HEAP_IOCTL_ALLOC,
|
|
71
|
+
arg: allocationData
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (errno !== undefined) {
|
|
75
|
+
return {
|
|
76
|
+
errno,
|
|
77
|
+
dmabufFd: undefined
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const view = endianBufferViewFor({ buffer: allocationData, endianness: kernelIoctlInterface.endianness });
|
|
82
|
+
const dmabufFd = view.readU32({ offset: 8 });
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
errno: undefined,
|
|
86
|
+
dmabufFd
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
dmabufHeapIoctlAllocate
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export {
|
|
96
|
+
createDmabufHeapIoctls
|
|
97
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type TDmabufHeap } from "./dmabuf-heap.js";
|
|
2
|
+
import type { TDmabufHeapKernelInterface } from "../kernel-interface.js";
|
|
3
|
+
declare const findDefaultDmabufHeapDevFolder: () => string;
|
|
4
|
+
type TDmabufHeapInfo = {
|
|
5
|
+
name: string;
|
|
6
|
+
properties: {
|
|
7
|
+
physicalMemory: {
|
|
8
|
+
contiguous: boolean | undefined;
|
|
9
|
+
};
|
|
10
|
+
cachable: boolean | undefined;
|
|
11
|
+
protected: boolean | undefined;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
type TDmabufHeapPropertySpecification = "required" | "preferred" | "optional" | "forbidden";
|
|
15
|
+
type TDmabufHeapSpecification = {
|
|
16
|
+
physicalMemory: {
|
|
17
|
+
contiguous: TDmabufHeapPropertySpecification;
|
|
18
|
+
};
|
|
19
|
+
cachable: TDmabufHeapPropertySpecification;
|
|
20
|
+
protected: TDmabufHeapPropertySpecification;
|
|
21
|
+
};
|
|
22
|
+
declare const createDmabufHeapManager: ({ dmabufHeapDevFolder, kernelInterface }: {
|
|
23
|
+
dmabufHeapDevFolder: string;
|
|
24
|
+
kernelInterface: TDmabufHeapKernelInterface;
|
|
25
|
+
}) => {
|
|
26
|
+
findAvailableDmabufHeapInfos: () => TDmabufHeapInfo[];
|
|
27
|
+
findDmabufHeapInfosBySpecification: ({ specification }: {
|
|
28
|
+
specification: TDmabufHeapSpecification;
|
|
29
|
+
}) => any;
|
|
30
|
+
openDmabufHeapByName: ({ name }: {
|
|
31
|
+
name: string;
|
|
32
|
+
}) => {
|
|
33
|
+
error: Error;
|
|
34
|
+
dmabufHeap: undefined;
|
|
35
|
+
} | {
|
|
36
|
+
error: undefined;
|
|
37
|
+
dmabufHeap: TDmabufHeap;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
type TDmabufHeapManager = ReturnType<typeof createDmabufHeapManager>;
|
|
41
|
+
export { findDefaultDmabufHeapDevFolder, createDmabufHeapManager };
|
|
42
|
+
export type { TDmabufHeapManager, };
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { createDmabufHeapFactory, /*type TDmabufHeap */} from "./dmabuf-heap.js";
|
|
2
|
+
/*import type { TDmabufHeapKernelInterface } from "../kernel-interface.ts";*/
|
|
3
|
+
|
|
4
|
+
const findDefaultDmabufHeapDevFolder = ()/*: string*/ => {
|
|
5
|
+
return "/dev/dma_heap";
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/*type TDmabufHeapInfo = {
|
|
9
|
+
name: string;
|
|
10
|
+
properties: {
|
|
11
|
+
physicalMemory: {
|
|
12
|
+
contiguous: boolean | undefined;
|
|
13
|
+
},
|
|
14
|
+
cachable: boolean | undefined;
|
|
15
|
+
protected: boolean | undefined;
|
|
16
|
+
}
|
|
17
|
+
};*/
|
|
18
|
+
|
|
19
|
+
/*type TDmabufHeapPropertySpecification = "required" | "preferred" | "optional" | "forbidden";*/
|
|
20
|
+
/*type TDmabufHeapSpecification = {
|
|
21
|
+
physicalMemory: {
|
|
22
|
+
contiguous: TDmabufHeapPropertySpecification;
|
|
23
|
+
},
|
|
24
|
+
cachable: TDmabufHeapPropertySpecification;
|
|
25
|
+
protected: TDmabufHeapPropertySpecification;
|
|
26
|
+
};*/
|
|
27
|
+
|
|
28
|
+
const wellKnownHeapPropertiesByName/*: { [key: string]: TDmabufHeapInfo["properties"] }*/ = {
|
|
29
|
+
// eslint-disable-next-line quote-props
|
|
30
|
+
"system": {
|
|
31
|
+
physicalMemory: {
|
|
32
|
+
contiguous: false
|
|
33
|
+
},
|
|
34
|
+
cachable: true,
|
|
35
|
+
protected: false
|
|
36
|
+
},
|
|
37
|
+
// eslint-disable-next-line quote-props
|
|
38
|
+
"default_cma_region": {
|
|
39
|
+
physicalMemory: {
|
|
40
|
+
contiguous: true
|
|
41
|
+
},
|
|
42
|
+
cachable: true,
|
|
43
|
+
protected: false
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const heapInfoByName = ({ name }/*: { name: string }*/)/*: TDmabufHeapInfo*/ => {
|
|
48
|
+
const wellKnownProperties = wellKnownHeapPropertiesByName[name];
|
|
49
|
+
if (wellKnownProperties === undefined) {
|
|
50
|
+
return {
|
|
51
|
+
name,
|
|
52
|
+
properties: {
|
|
53
|
+
physicalMemory: {
|
|
54
|
+
contiguous: undefined
|
|
55
|
+
},
|
|
56
|
+
cachable: undefined,
|
|
57
|
+
protected: undefined
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
name,
|
|
64
|
+
properties: wellKnownProperties
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const createDmabufHeapManager = ({
|
|
69
|
+
dmabufHeapDevFolder,
|
|
70
|
+
kernelInterface
|
|
71
|
+
}/*: {
|
|
72
|
+
dmabufHeapDevFolder: string,
|
|
73
|
+
kernelInterface: TDmabufHeapKernelInterface
|
|
74
|
+
}*/) => {
|
|
75
|
+
|
|
76
|
+
const heapFactory = createDmabufHeapFactory({ kernelInterface });
|
|
77
|
+
|
|
78
|
+
const findAvailableDmabufHeapInfos = ()/*: TDmabufHeapInfo[]*/ => {
|
|
79
|
+
const { errno, entries } = kernelInterface.readdir({ path: dmabufHeapDevFolder });
|
|
80
|
+
if (errno !== undefined) {
|
|
81
|
+
throw Error(`failed to read dmabuf heap dev folder ${dmabufHeapDevFolder}, errno ${errno}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const infos = entries.map((entryName) => {
|
|
85
|
+
return heapInfoByName({ name: entryName });
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return infos;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
findAvailableDmabufHeapInfos();
|
|
93
|
+
} catch (ex) {
|
|
94
|
+
throw Error("valid dmabuf heap dev folder required to create dmabuf heap manager, look before you leap", { cause: ex });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const findDmabufHeapInfosBySpecification = ({
|
|
98
|
+
specification
|
|
99
|
+
}/*: {
|
|
100
|
+
specification: TDmabufHeapSpecification
|
|
101
|
+
}*/) => {
|
|
102
|
+
const availableHeaps = findAvailableDmabufHeapInfos();
|
|
103
|
+
|
|
104
|
+
// eslint-disable-next-line complexity, max-statements
|
|
105
|
+
const matchingHeaps = availableHeaps.filter((heapInfo) => {
|
|
106
|
+
const props = heapInfo.properties;
|
|
107
|
+
|
|
108
|
+
// physicalMemory.contiguous
|
|
109
|
+
const contiguousSpec = specification.physicalMemory.contiguous;
|
|
110
|
+
if (contiguousSpec === "required" && props.physicalMemory.contiguous !== true) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (contiguousSpec === "forbidden" && props.physicalMemory.contiguous === true) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// cachable
|
|
118
|
+
const cachableSpec = specification.cachable;
|
|
119
|
+
if (cachableSpec === "required" && props.cachable !== true) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
if (cachableSpec === "forbidden" && props.cachable === true) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// protected
|
|
127
|
+
const protectedSpec = specification.protected;
|
|
128
|
+
if (protectedSpec === "required" && props.protected !== true) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
if (protectedSpec === "forbidden" && props.protected === true) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return true;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return matchingHeaps;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/*type TOpenByNameResult = {
|
|
142
|
+
error: Error,
|
|
143
|
+
dmabufHeap: undefined
|
|
144
|
+
} | {
|
|
145
|
+
error: undefined,
|
|
146
|
+
dmabufHeap: TDmabufHeap
|
|
147
|
+
};*/
|
|
148
|
+
|
|
149
|
+
const O_RDWR = 0x02;
|
|
150
|
+
const O_CLOEXEC = 0x80000;
|
|
151
|
+
|
|
152
|
+
const ENOENT = 2;
|
|
153
|
+
const EACCES = 13;
|
|
154
|
+
|
|
155
|
+
const createOpenErrorByErrno = ({ errno, dmabufHeapPath }/*: { errno: number, dmabufHeapPath: string }*/)/*: Error*/ => {
|
|
156
|
+
|
|
157
|
+
if (errno === ENOENT) {
|
|
158
|
+
return Error(`dmabuf heap at "${dmabufHeapPath}" does not exist`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (errno === EACCES) {
|
|
162
|
+
return Error(`permission denied opening dmabuf heap at "${dmabufHeapPath}", your process may lack required privileges`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return Error(`open dmabuf heap at "${dmabufHeapPath}" failed, errno ${errno}`);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const openDmabufHeapByName = ({ name }/*: { name: string }*/)/*: TOpenByNameResult*/ => {
|
|
169
|
+
|
|
170
|
+
const dmabufHeapPath = `${dmabufHeapDevFolder}/${name}`;
|
|
171
|
+
|
|
172
|
+
const { errno: openErrno, fd: dmabufHeapFd } = kernelInterface.open({
|
|
173
|
+
path: dmabufHeapPath,
|
|
174
|
+
flags: O_RDWR | O_CLOEXEC
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (openErrno !== undefined) {
|
|
178
|
+
return {
|
|
179
|
+
error: createOpenErrorByErrno({ errno: openErrno, dmabufHeapPath }),
|
|
180
|
+
dmabufHeap: undefined
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
const dmabufHeap = heapFactory.openDmabufHeapAllocatorByDuppingFd({
|
|
186
|
+
dmabufHeapFd
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
error: undefined,
|
|
191
|
+
dmabufHeap
|
|
192
|
+
};
|
|
193
|
+
} finally {
|
|
194
|
+
kernelInterface.close({ fd: dmabufHeapFd });
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
findAvailableDmabufHeapInfos,
|
|
201
|
+
findDmabufHeapInfosBySpecification,
|
|
202
|
+
openDmabufHeapByName
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/*type TDmabufHeapManager = ReturnType<typeof createDmabufHeapManager>;*/
|
|
207
|
+
|
|
208
|
+
export {
|
|
209
|
+
findDefaultDmabufHeapDevFolder,
|
|
210
|
+
createDmabufHeapManager
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/*export type {
|
|
214
|
+
TDmabufHeapManager,
|
|
215
|
+
};*/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TDmabufAllocator } from "../dmabuf-allocator-interface.js";
|
|
2
|
+
import type { TDmabufHeapAllocatorKernelInterface } from "../kernel-interface.js";
|
|
3
|
+
type TDmabufHeap = TDmabufAllocator & {
|
|
4
|
+
dupHeapFd: () => number;
|
|
5
|
+
close: () => void;
|
|
6
|
+
};
|
|
7
|
+
declare const createDmabufHeapFactory: ({ kernelInterface }: {
|
|
8
|
+
kernelInterface: TDmabufHeapAllocatorKernelInterface;
|
|
9
|
+
}) => {
|
|
10
|
+
openDmabufHeapAllocatorByDuppingFd: ({ dmabufHeapFd: providedDmabufHeapFd }: {
|
|
11
|
+
dmabufHeapFd: number;
|
|
12
|
+
}) => TDmabufHeap;
|
|
13
|
+
};
|
|
14
|
+
export { createDmabufHeapFactory };
|
|
15
|
+
export type { TDmabufHeap };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/*import type { TDmabufAllocator } from "../dmabuf-allocator-interface.ts";*/
|
|
2
|
+
import { createDefaultAllocationSizeDeterminer } from "../allocation-size.js";
|
|
3
|
+
import { createDmabufHeapIoctls } from "./dmabuf-heap-ioctl.js";
|
|
4
|
+
/*import type { TDmabufHeapAllocatorKernelInterface } from "../kernel-interface.ts";*/
|
|
5
|
+
// import nodeFs from "node:fs";
|
|
6
|
+
|
|
7
|
+
/*type TDmabufHeap = TDmabufAllocator & {
|
|
8
|
+
dupHeapFd: () => number;
|
|
9
|
+
close: () => void;
|
|
10
|
+
};*/
|
|
11
|
+
|
|
12
|
+
const O_RDWR = BigInt(0x02);
|
|
13
|
+
const O_CLOEXEC = BigInt(0x80000);
|
|
14
|
+
|
|
15
|
+
const createDmabufHeapFactory = ({ kernelInterface }/*: { kernelInterface: TDmabufHeapAllocatorKernelInterface }*/) => {
|
|
16
|
+
const openDmabufHeapAllocatorByDuppingFd = ({
|
|
17
|
+
dmabufHeapFd: providedDmabufHeapFd
|
|
18
|
+
}/*: {
|
|
19
|
+
dmabufHeapFd: number
|
|
20
|
+
}*/)/*: TDmabufHeap*/ => {
|
|
21
|
+
|
|
22
|
+
const dmabufHeapFd = kernelInterface.dup({ fd: providedDmabufHeapFd });
|
|
23
|
+
const pageSize = kernelInterface.determinePageSize();
|
|
24
|
+
|
|
25
|
+
const allocationSizeDeterminer = createDefaultAllocationSizeDeterminer({ pageSize });
|
|
26
|
+
|
|
27
|
+
const { dmabufHeapIoctlAllocate } = createDmabufHeapIoctls({ kernelIoctlInterface: kernelInterface });
|
|
28
|
+
|
|
29
|
+
const determineOptimalAllocationSize/*: TDmabufHeap["determineOptimalAllocationSize"]*/ = ({ minimumSize }) => {
|
|
30
|
+
return allocationSizeDeterminer.determineOptimalAllocationSize({ minimumSize });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const allocate/*: TDmabufHeap["allocate"]*/ = ({ size }) => {
|
|
34
|
+
|
|
35
|
+
const { errno: allocateErrno, dmabufFd } = dmabufHeapIoctlAllocate({
|
|
36
|
+
dmabufHeapFd,
|
|
37
|
+
fdFlags: O_RDWR | O_CLOEXEC,
|
|
38
|
+
heapFlags: BigInt(0),
|
|
39
|
+
size
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (allocateErrno !== undefined) {
|
|
43
|
+
return {
|
|
44
|
+
// TODO: better
|
|
45
|
+
error: Error(`dmabuf heap allocation failed with errno ${allocateErrno}`),
|
|
46
|
+
handle: undefined
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
error: undefined,
|
|
52
|
+
dmabufFd
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const dupHeapFd/*: TDmabufHeap["dupHeapFd"]*/ = () => {
|
|
57
|
+
return kernelInterface.dup({ fd: dmabufHeapFd });
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const close = () => {
|
|
61
|
+
kernelInterface.close({ fd: dmabufHeapFd });
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
allocate,
|
|
66
|
+
pageSize,
|
|
67
|
+
determineOptimalAllocationSize,
|
|
68
|
+
dupHeapFd,
|
|
69
|
+
close
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
openDmabufHeapAllocatorByDuppingFd
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export {
|
|
79
|
+
createDmabufHeapFactory
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/*export type {
|
|
83
|
+
TDmabufHeap
|
|
84
|
+
};*/
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createDmabufHeapManager, findDefaultDmabufHeapDevFolder, /*type TDmabufHeapManager */} from "./dmabuf-heap-manager.js";
|
|
2
|
+
import { createDefaultDmabufHeapAllocatorLinuxInterface } from "../kernel-interface-impl-linux.js";
|
|
3
|
+
|
|
4
|
+
const createDefaultDmabufHeapManager = ()/*: TDmabufHeapManager*/ => {
|
|
5
|
+
const dmabufHeapDevFolder = findDefaultDmabufHeapDevFolder();
|
|
6
|
+
const kernelInterface = createDefaultDmabufHeapAllocatorLinuxInterface();
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const dmabufHeapManager = createDmabufHeapManager({
|
|
10
|
+
dmabufHeapDevFolder,
|
|
11
|
+
kernelInterface
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
return dmabufHeapManager;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
createDefaultDmabufHeapManager,
|
|
19
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
type TEndianness = "LE" | "BE";
|
|
2
|
+
declare const endianBufferViewFor: ({ buffer, endianness }: {
|
|
3
|
+
buffer: Uint8Array;
|
|
4
|
+
endianness: TEndianness;
|
|
5
|
+
}) => {
|
|
6
|
+
readU16: ({ offset }: {
|
|
7
|
+
offset: number;
|
|
8
|
+
}) => any;
|
|
9
|
+
readU32: ({ offset }: {
|
|
10
|
+
offset: number;
|
|
11
|
+
}) => any;
|
|
12
|
+
readU64: ({ offset }: {
|
|
13
|
+
offset: number;
|
|
14
|
+
}) => any;
|
|
15
|
+
writeU16: ({ offset, value }: {
|
|
16
|
+
offset: number;
|
|
17
|
+
value: number;
|
|
18
|
+
}) => void;
|
|
19
|
+
writeU32: ({ offset, value }: {
|
|
20
|
+
offset: number;
|
|
21
|
+
value: number;
|
|
22
|
+
}) => void;
|
|
23
|
+
writeU64: ({ offset, value }: {
|
|
24
|
+
offset: number;
|
|
25
|
+
value: bigint;
|
|
26
|
+
}) => void;
|
|
27
|
+
};
|
|
28
|
+
declare const hostEndianBufferViewFor: ({ buffer }: {
|
|
29
|
+
buffer: Uint8Array;
|
|
30
|
+
}) => {
|
|
31
|
+
readU16: ({ offset }: {
|
|
32
|
+
offset: number;
|
|
33
|
+
}) => any;
|
|
34
|
+
readU32: ({ offset }: {
|
|
35
|
+
offset: number;
|
|
36
|
+
}) => any;
|
|
37
|
+
readU64: ({ offset }: {
|
|
38
|
+
offset: number;
|
|
39
|
+
}) => any;
|
|
40
|
+
writeU16: ({ offset, value }: {
|
|
41
|
+
offset: number;
|
|
42
|
+
value: number;
|
|
43
|
+
}) => void;
|
|
44
|
+
writeU32: ({ offset, value }: {
|
|
45
|
+
offset: number;
|
|
46
|
+
value: number;
|
|
47
|
+
}) => void;
|
|
48
|
+
writeU64: ({ offset, value }: {
|
|
49
|
+
offset: number;
|
|
50
|
+
value: bigint;
|
|
51
|
+
}) => void;
|
|
52
|
+
};
|
|
53
|
+
export { endianBufferViewFor, hostEndianBufferViewFor };
|
|
54
|
+
export type { TEndianness };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import nodeOs from "node:os";
|
|
2
|
+
|
|
3
|
+
/*type TEndianness = "LE" | "BE";*/
|
|
4
|
+
|
|
5
|
+
const endianBufferViewFor = ({ buffer, endianness }/*: { buffer: Uint8Array, endianness: TEndianness }*/) => {
|
|
6
|
+
const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
7
|
+
|
|
8
|
+
const isLittleEndian = endianness === "LE";
|
|
9
|
+
|
|
10
|
+
const readU16 = ({ offset }/*: { offset: number }*/) => {
|
|
11
|
+
return dataView.getUint16(offset, isLittleEndian);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const readU32 = ({ offset }/*: { offset: number }*/) => {
|
|
15
|
+
return dataView.getUint32(offset, isLittleEndian);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const readU64 = ({ offset }/*: { offset: number }*/) => {
|
|
19
|
+
return dataView.getBigUint64(offset, isLittleEndian);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const writeU16 = ({ offset, value }/*: { offset: number, value: number }*/) => {
|
|
23
|
+
dataView.setUint16(offset, value, isLittleEndian);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const writeU32 = ({ offset, value }/*: { offset: number, value: number }*/) => {
|
|
27
|
+
dataView.setUint32(offset, value, isLittleEndian);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const writeU64 = ({ offset, value }/*: { offset: number, value: bigint }*/) => {
|
|
31
|
+
dataView.setBigUint64(offset, value, isLittleEndian);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
readU16,
|
|
36
|
+
readU32,
|
|
37
|
+
readU64,
|
|
38
|
+
writeU16,
|
|
39
|
+
writeU32,
|
|
40
|
+
writeU64
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const determineSystemEndianness = ()/*: TEndianness*/ => {
|
|
45
|
+
return nodeOs.endianness();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const hostEndianBufferViewFor = ({ buffer }/*: { buffer: Uint8Array }*/) => {
|
|
49
|
+
return endianBufferViewFor({ buffer, endianness: determineSystemEndianness() });
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
endianBufferViewFor,
|
|
54
|
+
hostEndianBufferViewFor
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/*export type {
|
|
58
|
+
TEndianness
|
|
59
|
+
};*/
|
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.js
CHANGED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*import type { TDmabufHeapKernelInterface } from "./kernel-interface.ts";*/
|
|
2
|
+
import { ioctl as nativeIoctl } from "@k13engineering/po6-ioctl";
|
|
3
|
+
import nodeFs from "node:fs";
|
|
4
|
+
import nodeOs from "node:os";
|
|
5
|
+
import { syscall, syscallNumbers } from "syscall-napi";
|
|
6
|
+
|
|
7
|
+
const createDefaultDmabufHeapAllocatorLinuxInterface = ()/*: TDmabufHeapKernelInterface*/ => {
|
|
8
|
+
|
|
9
|
+
/*type C = TDmabufHeapKernelInterface;*/
|
|
10
|
+
|
|
11
|
+
const endianness = nodeOs.endianness();
|
|
12
|
+
|
|
13
|
+
const determinePageSize/*: C["determinePageSize"]*/ = () => {
|
|
14
|
+
// TODO: get from system
|
|
15
|
+
return 4096;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const ioctl/*: C["ioctl"]*/ = ({ fd, request, arg }) => {
|
|
19
|
+
const { errno } = nativeIoctl({ fd, request, arg });
|
|
20
|
+
return { errno };
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const dup = ({ fd }/*: { fd: number }*/)/*: number*/ => {
|
|
24
|
+
const { errno, ret: newFd } = syscall({
|
|
25
|
+
syscallNumber: syscallNumbers.dup,
|
|
26
|
+
args: [
|
|
27
|
+
BigInt(fd)
|
|
28
|
+
]
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (errno !== undefined) {
|
|
32
|
+
throw Error(`dup failed with errno ${errno}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return Number(newFd);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const readdir/*: C["readdir"]*/ = ({ path }) => {
|
|
39
|
+
try {
|
|
40
|
+
const entries = nodeFs.readdirSync(path);
|
|
41
|
+
return { errno: undefined, entries };
|
|
42
|
+
} catch (ex) {
|
|
43
|
+
const err = ex /*as NodeJS.ErrnoException*/;
|
|
44
|
+
return { errno: -err.errno/*!*/, entries: undefined };
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const open/*: C["open"]*/ = ({ path, flags }) => {
|
|
49
|
+
try {
|
|
50
|
+
const fd = nodeFs.openSync(path, flags);
|
|
51
|
+
return { errno: undefined, fd };
|
|
52
|
+
} catch (ex) {
|
|
53
|
+
const err = ex /*as NodeJS.ErrnoException*/;
|
|
54
|
+
return { errno: -err.errno/*!*/, fd: undefined };
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const close/*: C["close"]*/ = ({ fd }) => {
|
|
59
|
+
nodeFs.closeSync(fd);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
endianness,
|
|
64
|
+
determinePageSize,
|
|
65
|
+
ioctl,
|
|
66
|
+
dup,
|
|
67
|
+
readdir,
|
|
68
|
+
open,
|
|
69
|
+
close
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
createDefaultDmabufHeapAllocatorLinuxInterface
|
|
75
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
type TDmabufHeapKernelInterface = {
|
|
2
|
+
endianness: "LE" | "BE";
|
|
3
|
+
determinePageSize: () => number;
|
|
4
|
+
ioctl: (args: {
|
|
5
|
+
fd: number;
|
|
6
|
+
request: bigint;
|
|
7
|
+
arg: Uint8Array;
|
|
8
|
+
}) => {
|
|
9
|
+
errno: undefined | number;
|
|
10
|
+
};
|
|
11
|
+
dup: (args: {
|
|
12
|
+
fd: number;
|
|
13
|
+
}) => number;
|
|
14
|
+
close: (args: {
|
|
15
|
+
fd: number;
|
|
16
|
+
}) => void;
|
|
17
|
+
readdir: ({ path }: {
|
|
18
|
+
path: string;
|
|
19
|
+
}) => {
|
|
20
|
+
errno: undefined;
|
|
21
|
+
entries: string[];
|
|
22
|
+
} | {
|
|
23
|
+
errno: number;
|
|
24
|
+
entries: undefined;
|
|
25
|
+
};
|
|
26
|
+
open: (args: {
|
|
27
|
+
path: string;
|
|
28
|
+
flags: number;
|
|
29
|
+
}) => {
|
|
30
|
+
errno: undefined;
|
|
31
|
+
fd: number;
|
|
32
|
+
} | {
|
|
33
|
+
errno: number;
|
|
34
|
+
fd: undefined;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
type TDmabufHeapAllocatorKernelInterface = Pick<TDmabufHeapKernelInterface, "endianness" | "determinePageSize" | "ioctl" | "dup" | "close">;
|
|
38
|
+
type TDmabufHeapIoctlKernelInterface = Pick<TDmabufHeapKernelInterface, "endianness" | "ioctl">;
|
|
39
|
+
export type { TDmabufHeapKernelInterface, TDmabufHeapAllocatorKernelInterface, TDmabufHeapIoctlKernelInterface };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/* c8 ignore start */
|
|
2
|
+
/*type TDmabufHeapKernelInterface = {
|
|
3
|
+
endianness: "LE" | "BE";
|
|
4
|
+
determinePageSize: () => number;
|
|
5
|
+
ioctl: (args: { fd: number; request: bigint, arg: Uint8Array }) => { errno: undefined | number };
|
|
6
|
+
dup: (args: { fd: number }) => number;
|
|
7
|
+
close: (args: { fd: number }) => void;
|
|
8
|
+
|
|
9
|
+
// dmabuf heap listing
|
|
10
|
+
readdir: ({ path }: { path: string }) => { errno: undefined, entries: string[] } | { errno: number, entries: undefined };
|
|
11
|
+
open: (args: { path: string, flags: number }) => { errno: undefined, fd: number } | { errno: number, fd: undefined };
|
|
12
|
+
};*/
|
|
13
|
+
|
|
14
|
+
/*type TDmabufHeapAllocatorKernelInterface = Pick<TDmabufHeapKernelInterface,
|
|
15
|
+
"endianness" |
|
|
16
|
+
"determinePageSize" |
|
|
17
|
+
"ioctl" |
|
|
18
|
+
"dup" |
|
|
19
|
+
"close"
|
|
20
|
+
>;*/
|
|
21
|
+
|
|
22
|
+
/*type TDmabufHeapIoctlKernelInterface = Pick<TDmabufHeapKernelInterface,
|
|
23
|
+
"endianness" |
|
|
24
|
+
"ioctl"
|
|
25
|
+
>;*/
|
|
26
|
+
|
|
27
|
+
/*export type {
|
|
28
|
+
TDmabufHeapKernelInterface,
|
|
29
|
+
TDmabufHeapAllocatorKernelInterface,
|
|
30
|
+
TDmabufHeapIoctlKernelInterface
|
|
31
|
+
};*/
|
|
32
|
+
/* c8 ignore stop */
|
package/package.json
CHANGED