@k13engineering/linux-dmabuf-allocator 0.0.4 → 0.0.5
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/index.d.ts +2 -1
- package/dist/lib/index.js +3 -1
- package/dist/lib/kernel-interface-impl-linux.js +58 -2
- package/dist/lib/kernel-interface.d.ts +34 -2
- package/dist/lib/kernel-interface.js +18 -2
- package/dist/lib/udmabuf/index.d.ts +3 -0
- package/dist/lib/udmabuf/index.js +26 -0
- package/dist/lib/udmabuf/udmabuf-allocator.d.ts +10 -0
- package/dist/lib/udmabuf/udmabuf-allocator.js +127 -0
- package/package.json +2 -2
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.js
CHANGED
|
@@ -16,8 +16,12 @@ const createDefaultDmabufHeapAllocatorLinuxInterface = ()/*: TDmabufHeapKernelIn
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
const ioctl/*: C["ioctl"]*/ = ({ fd, request, arg }) => {
|
|
19
|
-
const { errno } = nativeIoctl({ fd, request, arg });
|
|
20
|
-
|
|
19
|
+
const { errno, ret } = nativeIoctl({ fd, request, arg });
|
|
20
|
+
if (errno !== undefined) {
|
|
21
|
+
return { errno, ret: undefined };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return { errno, ret };
|
|
21
25
|
};
|
|
22
26
|
|
|
23
27
|
const dup = ({ fd }/*: { fd: number }*/)/*: number*/ => {
|
|
@@ -55,6 +59,55 @@ const createDefaultDmabufHeapAllocatorLinuxInterface = ()/*: TDmabufHeapKernelIn
|
|
|
55
59
|
}
|
|
56
60
|
};
|
|
57
61
|
|
|
62
|
+
const fcntl/*: C["fcntl"]*/ = ({ fd, cmd, arg }/*: { fd: number; cmd: number; arg: number }*/) => {
|
|
63
|
+
const { errno } = syscall({
|
|
64
|
+
syscallNumber: syscallNumbers.fcntl,
|
|
65
|
+
args: [BigInt(fd), BigInt(cmd), BigInt(arg)]
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (errno !== undefined) {
|
|
69
|
+
return { errno };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return { errno: undefined };
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const textEncoder = new TextEncoder();
|
|
76
|
+
|
|
77
|
+
const memfd_create/*: C["memfd_create"]*/ = ({ name, flags }/*: { name: string; flags: number }*/) => {
|
|
78
|
+
|
|
79
|
+
const nameAsBuffer = textEncoder.encode(`${name} \0`);
|
|
80
|
+
|
|
81
|
+
const { errno, ret } = syscall({
|
|
82
|
+
syscallNumber: syscallNumbers.memfd_create,
|
|
83
|
+
args: [
|
|
84
|
+
nameAsBuffer,
|
|
85
|
+
BigInt(flags)
|
|
86
|
+
]
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (errno !== undefined) {
|
|
90
|
+
return {
|
|
91
|
+
errno,
|
|
92
|
+
memfd: undefined
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return { errno: undefined, memfd: Number(ret) };
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const ftruncate/*: C["ftruncate"]*/ = ({ fd, length }/*: { fd: number; length: number }*/) => {
|
|
100
|
+
try {
|
|
101
|
+
nodeFs.ftruncateSync(fd, length);
|
|
102
|
+
} catch (e) {
|
|
103
|
+
return {
|
|
104
|
+
error: e /*as Error*/,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return { error: undefined };
|
|
109
|
+
};
|
|
110
|
+
|
|
58
111
|
const close/*: C["close"]*/ = ({ fd }) => {
|
|
59
112
|
nodeFs.closeSync(fd);
|
|
60
113
|
};
|
|
@@ -66,6 +119,9 @@ const createDefaultDmabufHeapAllocatorLinuxInterface = ()/*: TDmabufHeapKernelIn
|
|
|
66
119
|
dup,
|
|
67
120
|
readdir,
|
|
68
121
|
open,
|
|
122
|
+
fcntl,
|
|
123
|
+
memfd_create,
|
|
124
|
+
ftruncate,
|
|
69
125
|
close
|
|
70
126
|
};
|
|
71
127
|
};
|
|
@@ -6,7 +6,11 @@ type TDmabufHeapKernelInterface = {
|
|
|
6
6
|
request: bigint;
|
|
7
7
|
arg: Uint8Array;
|
|
8
8
|
}) => {
|
|
9
|
-
errno: undefined
|
|
9
|
+
errno: undefined;
|
|
10
|
+
ret: bigint;
|
|
11
|
+
} | {
|
|
12
|
+
errno: number;
|
|
13
|
+
ret: undefined;
|
|
10
14
|
};
|
|
11
15
|
dup: (args: {
|
|
12
16
|
fd: number;
|
|
@@ -33,7 +37,35 @@ type TDmabufHeapKernelInterface = {
|
|
|
33
37
|
errno: number;
|
|
34
38
|
fd: undefined;
|
|
35
39
|
};
|
|
40
|
+
fcntl: (args: {
|
|
41
|
+
fd: number;
|
|
42
|
+
cmd: number;
|
|
43
|
+
arg: number;
|
|
44
|
+
}) => {
|
|
45
|
+
errno: undefined;
|
|
46
|
+
} | {
|
|
47
|
+
errno: number;
|
|
48
|
+
};
|
|
49
|
+
memfd_create: (args: {
|
|
50
|
+
name: string;
|
|
51
|
+
flags: number;
|
|
52
|
+
}) => {
|
|
53
|
+
errno: undefined;
|
|
54
|
+
memfd: number;
|
|
55
|
+
} | {
|
|
56
|
+
errno: number;
|
|
57
|
+
memfd: undefined;
|
|
58
|
+
};
|
|
59
|
+
ftruncate: (args: {
|
|
60
|
+
fd: number;
|
|
61
|
+
length: number;
|
|
62
|
+
}) => {
|
|
63
|
+
error: undefined;
|
|
64
|
+
} | {
|
|
65
|
+
error: Error;
|
|
66
|
+
};
|
|
36
67
|
};
|
|
37
68
|
type TDmabufHeapAllocatorKernelInterface = Pick<TDmabufHeapKernelInterface, "endianness" | "determinePageSize" | "ioctl" | "dup" | "close">;
|
|
38
69
|
type TDmabufHeapIoctlKernelInterface = Pick<TDmabufHeapKernelInterface, "endianness" | "ioctl">;
|
|
39
|
-
|
|
70
|
+
type TDmabufUdmabufAllocatorKernelInterface = Pick<TDmabufHeapKernelInterface, "endianness" | "determinePageSize" | "fcntl" | "memfd_create" | "ftruncate" | "ioctl" | "close">;
|
|
71
|
+
export type { TDmabufHeapKernelInterface, TDmabufHeapAllocatorKernelInterface, TDmabufHeapIoctlKernelInterface, TDmabufUdmabufAllocatorKernelInterface };
|
|
@@ -2,13 +2,18 @@
|
|
|
2
2
|
/*type TDmabufHeapKernelInterface = {
|
|
3
3
|
endianness: "LE" | "BE";
|
|
4
4
|
determinePageSize: () => number;
|
|
5
|
-
ioctl: (args: { fd: number; request: bigint, arg: Uint8Array }) => { errno: undefined | number };
|
|
5
|
+
ioctl: (args: { fd: number; request: bigint, arg: Uint8Array }) => { errno: undefined, ret: bigint } | { errno: number, ret: undefined };
|
|
6
6
|
dup: (args: { fd: number }) => number;
|
|
7
7
|
close: (args: { fd: number }) => void;
|
|
8
8
|
|
|
9
9
|
// dmabuf heap listing
|
|
10
10
|
readdir: ({ path }: { path: string }) => { errno: undefined, entries: string[] } | { errno: number, entries: undefined };
|
|
11
11
|
open: (args: { path: string, flags: number }) => { errno: undefined, fd: number } | { errno: number, fd: undefined };
|
|
12
|
+
|
|
13
|
+
// udmabuf allocator
|
|
14
|
+
fcntl: (args: { fd: number; cmd: number; arg: number }) => { errno: undefined } | { errno: number };
|
|
15
|
+
memfd_create: (args: { name: string; flags: number }) => { errno: undefined, memfd: number } | { errno: number, memfd: undefined };
|
|
16
|
+
ftruncate: (args: { fd: number; length: number }) => { error: undefined } | { error: Error };
|
|
12
17
|
};*/
|
|
13
18
|
|
|
14
19
|
/*type TDmabufHeapAllocatorKernelInterface = Pick<TDmabufHeapKernelInterface,
|
|
@@ -24,9 +29,20 @@
|
|
|
24
29
|
"ioctl"
|
|
25
30
|
>;*/
|
|
26
31
|
|
|
32
|
+
/*type TDmabufUdmabufAllocatorKernelInterface = Pick<TDmabufHeapKernelInterface,
|
|
33
|
+
"endianness" |
|
|
34
|
+
"determinePageSize" |
|
|
35
|
+
"fcntl" |
|
|
36
|
+
"memfd_create" |
|
|
37
|
+
"ftruncate" |
|
|
38
|
+
"ioctl" |
|
|
39
|
+
"close"
|
|
40
|
+
>;*/
|
|
41
|
+
|
|
27
42
|
/*export type {
|
|
28
43
|
TDmabufHeapKernelInterface,
|
|
29
44
|
TDmabufHeapAllocatorKernelInterface,
|
|
30
|
-
TDmabufHeapIoctlKernelInterface
|
|
45
|
+
TDmabufHeapIoctlKernelInterface,
|
|
46
|
+
TDmabufUdmabufAllocatorKernelInterface
|
|
31
47
|
};*/
|
|
32
48
|
/* c8 ignore stop */
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { /*type TDmabufAllocator */} from "../dmabuf-allocator-interface.js";
|
|
2
|
+
import { createDefaultDmabufHeapAllocatorLinuxInterface } from "../kernel-interface-impl-linux.js";
|
|
3
|
+
import { createUdmabufAllocatorFactory } from "./udmabuf-allocator.js";
|
|
4
|
+
|
|
5
|
+
const O_RDWR = 0x02;
|
|
6
|
+
const O_CLOEXEC = 0x80000;
|
|
7
|
+
|
|
8
|
+
const createDefaultUdmabufAllocator = ()/*: TDmabufAllocator*/ => {
|
|
9
|
+
const kernelInterface = createDefaultDmabufHeapAllocatorLinuxInterface();
|
|
10
|
+
|
|
11
|
+
const { errno, fd } = kernelInterface.open({
|
|
12
|
+
path: "/dev/udmabuf",
|
|
13
|
+
flags: O_RDWR | O_CLOEXEC
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
if (errno !== undefined) {
|
|
17
|
+
throw Error(`failed to open /dev/udmabuf, errno ${errno}. Is the udmabuf kernel module loaded?`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const udmabufAllocatorFactory = createUdmabufAllocatorFactory({ kernelInterface });
|
|
21
|
+
return udmabufAllocatorFactory.createUdmabufAllocator({ udmabufFd: fd });
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
createDefaultUdmabufAllocator,
|
|
26
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type TDmabufAllocator } from "../dmabuf-allocator-interface.js";
|
|
2
|
+
import { type TDmabufUdmabufAllocatorKernelInterface } from "../kernel-interface.js";
|
|
3
|
+
declare const createUdmabufAllocatorFactory: ({ kernelInterface }: {
|
|
4
|
+
kernelInterface: TDmabufUdmabufAllocatorKernelInterface;
|
|
5
|
+
}) => {
|
|
6
|
+
createUdmabufAllocator: ({ udmabufFd }: {
|
|
7
|
+
udmabufFd: number;
|
|
8
|
+
}) => TDmabufAllocator;
|
|
9
|
+
};
|
|
10
|
+
export { createUdmabufAllocatorFactory };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { /*type TDmabufAllocator */} from "../dmabuf-allocator-interface.js";
|
|
2
|
+
import { createDefaultAllocationSizeDeterminer } from "../allocation-size.js";
|
|
3
|
+
import { /*type TDmabufHeap */} from "../dmabuf-heap/dmabuf-heap.js";
|
|
4
|
+
import { /*type TDmabufUdmabufAllocatorKernelInterface */} from "../kernel-interface.js";
|
|
5
|
+
|
|
6
|
+
/*type TUdmabufCreateResult = {
|
|
7
|
+
errno: number;
|
|
8
|
+
dmabufFd: undefined;
|
|
9
|
+
} | {
|
|
10
|
+
errno: undefined;
|
|
11
|
+
dmabufFd: number;
|
|
12
|
+
};*/
|
|
13
|
+
|
|
14
|
+
const UDMABUF_FLAGS_CLOEXEC = 1 << 0;
|
|
15
|
+
const UDMABUF_CREATE = 0x40187542n;
|
|
16
|
+
|
|
17
|
+
const F_ADD_SEALS = 1033;
|
|
18
|
+
const F_SEAL_SHRINK = 0x0002;
|
|
19
|
+
|
|
20
|
+
const MFD_ALLOW_SEALING = 0x0002;
|
|
21
|
+
|
|
22
|
+
const createUdmabufAllocatorFactory = ({ kernelInterface }/*: { kernelInterface: TDmabufUdmabufAllocatorKernelInterface }*/) => {
|
|
23
|
+
|
|
24
|
+
const udmabufCreate = ({ udmabufFd, memfd, size }/*: { udmabufFd: number, memfd: number; size: number }*/)/*: TUdmabufCreateResult*/ => {
|
|
25
|
+
|
|
26
|
+
const flags = UDMABUF_FLAGS_CLOEXEC;
|
|
27
|
+
const offset = 0n;
|
|
28
|
+
|
|
29
|
+
const udmabufCreateStruct = Buffer.alloc(24);
|
|
30
|
+
udmabufCreateStruct.writeUInt32LE(memfd, 0);
|
|
31
|
+
udmabufCreateStruct.writeUInt32LE(flags, 4);
|
|
32
|
+
udmabufCreateStruct.writeBigUInt64LE(offset, 8);
|
|
33
|
+
udmabufCreateStruct.writeBigUInt64LE(BigInt(size), 16);
|
|
34
|
+
|
|
35
|
+
const { errno: ioctlErrno, ret } = kernelInterface.ioctl({ fd: udmabufFd, request: UDMABUF_CREATE, arg: udmabufCreateStruct });
|
|
36
|
+
if (ioctlErrno !== undefined) {
|
|
37
|
+
return {
|
|
38
|
+
errno: ioctlErrno,
|
|
39
|
+
dmabufFd: undefined
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const dmabufFd = Number(ret);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
errno: undefined,
|
|
47
|
+
dmabufFd
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const truncateAndSealMemfd = ({ memfd, size }/*: { memfd: number; size: number }*/) => {
|
|
52
|
+
const { error: ftruncateError } = kernelInterface.ftruncate({ fd: memfd, length: size });
|
|
53
|
+
if (ftruncateError !== undefined) {
|
|
54
|
+
throw Error("failed to truncate memfd", { cause: ftruncateError });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const { errno: fcntlErrno } = kernelInterface.fcntl({ fd: memfd, cmd: F_ADD_SEALS, arg: F_SEAL_SHRINK });
|
|
58
|
+
if (fcntlErrno !== undefined) {
|
|
59
|
+
throw Error(`failed to seal memfd, errno: ${fcntlErrno}`);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const createUdmabufAllocator = ({ udmabufFd }/*: { udmabufFd: number }*/)/*: TDmabufAllocator*/ => {
|
|
64
|
+
|
|
65
|
+
const pageSize = kernelInterface.determinePageSize();
|
|
66
|
+
const allocationSizeDeterminer = createDefaultAllocationSizeDeterminer({ pageSize });
|
|
67
|
+
|
|
68
|
+
const determineOptimalAllocationSize/*: TDmabufHeap["determineOptimalAllocationSize"]*/ = ({ minimumSize }) => {
|
|
69
|
+
return allocationSizeDeterminer.determineOptimalAllocationSize({ minimumSize });
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
// eslint-disable-next-line complexity
|
|
74
|
+
const allocate/*: TDmabufAllocator["allocate"]*/ = ({ size }) => {
|
|
75
|
+
|
|
76
|
+
if (size <= 0) {
|
|
77
|
+
throw Error("size must be > 0");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if ((size % pageSize) !== 0) {
|
|
81
|
+
throw Error(`size must be a multiple of ${pageSize}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const { errno: memfdCreateErrno, memfd } = kernelInterface.memfd_create({ name: "dmabuf_alloc", flags: MFD_ALLOW_SEALING });
|
|
85
|
+
if (memfdCreateErrno !== undefined) {
|
|
86
|
+
return {
|
|
87
|
+
error: Error(`failed to create memfd, errno: ${memfdCreateErrno}`),
|
|
88
|
+
dmabufFd: undefined
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
truncateAndSealMemfd({ memfd, size });
|
|
94
|
+
|
|
95
|
+
const { errno: createUdmabufErrno, dmabufFd } = udmabufCreate({ udmabufFd, memfd, size });
|
|
96
|
+
|
|
97
|
+
if (createUdmabufErrno !== undefined) {
|
|
98
|
+
return {
|
|
99
|
+
error: Error(`failed to create udmabuf, errno: ${createUdmabufErrno}`),
|
|
100
|
+
dmabufFd: undefined
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
error: undefined,
|
|
106
|
+
dmabufFd
|
|
107
|
+
};
|
|
108
|
+
} finally {
|
|
109
|
+
kernelInterface.close({ fd: memfd });
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
allocate,
|
|
115
|
+
pageSize,
|
|
116
|
+
determineOptimalAllocationSize
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
createUdmabufAllocator
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export {
|
|
126
|
+
createUdmabufAllocatorFactory
|
|
127
|
+
};
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0.
|
|
2
|
+
"version": "0.0.5",
|
|
3
3
|
"name": "@k13engineering/linux-dmabuf-allocator",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Linux dmabuf allocator module",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"devDependencies": {},
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@k13engineering/po6-ioctl": "^0.0.2",
|
|
14
|
-
"syscall-napi": "^0.1.
|
|
14
|
+
"syscall-napi": "^0.1.6"
|
|
15
15
|
},
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"access": "public"
|