Compare commits
488 Commits
fb-driver
...
feature/mu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7da34dbffb | ||
|
|
90a0eb3c53 | ||
|
|
d1ddbd2cf1 | ||
|
|
81b331e5da | ||
|
|
1ebee17880 | ||
|
|
4649d5f77b | ||
|
|
d3c1d6cc34 | ||
|
|
ee24ec8d5c | ||
|
|
372325fab7 | ||
|
|
8f036d9293 | ||
|
|
e345cdd1a7 | ||
|
|
fca570a163 | ||
|
|
ff64d1989f | ||
|
|
d3f5db2479 | ||
|
|
fa587060f1 | ||
|
|
b137c75eb2 | ||
|
|
05c1361283 | ||
|
|
c6835dad70 | ||
|
|
e7fa1dde97 | ||
|
|
eb62588b79 | ||
|
|
29332cbd45 | ||
|
|
172eb70551 | ||
|
|
7322df98f5 | ||
| 70af5a31cd | |||
| 0ab2f59fe8 | |||
| ab84cdb790 | |||
| da9041823b | |||
| 2d7cfc6c59 | |||
| cee4fe67fc | |||
| 53f90f5a1d | |||
| bab2dd5c69 | |||
| 3b9efc11d0 | |||
| 182d3b0a6a | |||
|
|
ed38e989b1 | ||
|
|
1bc6f422c5 | ||
|
|
4909d15c20 | ||
|
|
e725795a17 | ||
|
|
d8a21608c3 | ||
|
|
396fc131e0 | ||
|
|
40130076b2 | ||
|
|
9f54927a82 | ||
|
|
f7ea46e49e | ||
|
|
bc46c9a7d5 | ||
|
|
a1e2c58afc | ||
|
|
4e73e933db | ||
|
|
9f8e75f680 | ||
|
|
e17119254b | ||
|
|
17261622c6 | ||
|
|
dff9e53658 | ||
|
|
0bf709a339 | ||
|
|
c245949ea4 | ||
|
|
c27f8baa31 | ||
|
|
f51f519c31 | ||
|
|
55a485ee67 | ||
|
|
ba6e8e1349 | ||
|
|
75d30fb56d | ||
|
|
4abcf238a0 | ||
|
|
c05b4211fa | ||
|
|
337b8bb36b | ||
|
|
97433fc7d1 | ||
|
|
fc16ed54b3 | ||
|
|
8cbde13139 | ||
|
|
646a534dfd | ||
|
|
eda816ad90 | ||
|
|
c4bb60299e | ||
|
|
3cfd0cf86b | ||
|
|
8b3fa3ed01 | ||
|
|
a0f91ed0fd | ||
|
|
77590b31a6 | ||
|
|
ce27749705 | ||
|
|
b239bb6df2 | ||
|
|
28379dc0f6 | ||
|
|
c86c0f2ae6 | ||
|
|
bbe27c6b53 | ||
|
|
21916ab869 | ||
|
|
778e766f6b | ||
|
|
5d1fdd0e81 | ||
|
|
f5208d1641 | ||
|
|
a7beb0df18 | ||
|
|
1ec46ee641 | ||
|
|
3ba0600694 | ||
|
|
a449a88395 | ||
|
|
4bf03266a9 | ||
|
|
4bceac3d56 | ||
|
|
350396d70f | ||
|
|
ad3afae315 | ||
|
|
0dc86f2a0d | ||
|
|
2b3c276f33 | ||
|
|
8bf2425c4a | ||
|
|
72530ccb15 | ||
|
|
da14fd123e | ||
|
|
f215b98f74 | ||
|
|
b5662bfd25 | ||
|
|
3b3857548c | ||
|
|
1e2e154747 | ||
|
|
2d8d4fd200 | ||
|
|
459b40ad57 | ||
|
|
90cf1e2220 | ||
|
|
692e0d8656 | ||
|
|
3ab1a6b170 | ||
|
|
069bc63d1f | ||
|
|
373121c455 | ||
|
|
936b12a977 | ||
|
|
2a4c286f2b | ||
|
|
bfab4f085e | ||
|
|
201e7191ef | ||
|
|
9fa588566f | ||
|
|
ed95574c24 | ||
|
|
0c777bc62f | ||
|
|
1d7d5e8015 | ||
|
|
95627ba43c | ||
|
|
841ac41e36 | ||
|
|
a46d8bce37 | ||
|
|
4052911ac4 | ||
|
|
3a7a18011c | ||
|
|
15e2f8abf3 | ||
|
|
6b43ddc8d7 | ||
|
|
508058c3d7 | ||
|
|
4c9ff44b1c | ||
|
|
c092e07832 | ||
|
|
abe7fe37d0 | ||
|
|
cca8e8b3ad | ||
|
|
7c194950bb | ||
|
|
723f7d0330 | ||
|
|
274891854f | ||
|
|
94b2a79f79 | ||
|
|
d2a6113fb7 | ||
|
|
55c88dd943 | ||
|
|
42db1e8899 | ||
|
|
38ca7004a6 | ||
|
|
8817766469 | ||
|
|
e250aaef30 | ||
|
|
7b29ba7d23 | ||
|
|
dc30437ce7 | ||
|
|
2c2398b549 | ||
|
|
bce01591f3 | ||
|
|
847ef1ccfe | ||
|
|
6fa9b33ac0 | ||
|
|
df6d5b3b16 | ||
|
|
4884a624d9 | ||
|
|
ea587076ed | ||
|
|
0eddb002f0 | ||
|
|
8f968f4954 | ||
|
|
094b54d728 | ||
|
|
4125175870 | ||
|
|
1cb8f1258d | ||
|
|
f05a1d3310 | ||
|
|
71069cb38b | ||
|
|
393db1e792 | ||
|
|
0a097ec7d3 | ||
|
|
ada660deeb | ||
|
|
118ee73ff1 | ||
|
|
6a6b75b418 | ||
|
|
9297017688 | ||
|
|
359ee035d8 | ||
|
|
8966380ef9 | ||
|
|
ab31825ab3 | ||
|
|
aba45b9b67 | ||
|
|
86d458fc6c | ||
|
|
eba0127645 | ||
|
|
61199d2f80 | ||
|
|
72db77fb58 | ||
|
|
7771584a18 | ||
|
|
8b29680850 | ||
|
|
933e4e8040 | ||
|
|
5ea5978ee8 | ||
|
|
e2e1696b7e | ||
|
|
6f7dd7fc05 | ||
|
|
1f15d2ef49 | ||
|
|
66abcc57a2 | ||
|
|
6ef15a2721 | ||
|
|
5a3e0ba541 | ||
|
|
3af2d41a7f | ||
|
|
1b0c0b6dbe | ||
|
|
e93f48e2f7 | ||
|
|
7150e11ed0 | ||
|
|
28cd3bb625 | ||
|
|
6ac4ec601d | ||
|
|
99b59393fe | ||
|
|
8c1bb593ce | ||
|
|
372bc1d2e6 | ||
|
|
6583744532 | ||
|
|
2703080df2 | ||
|
|
194776d226 | ||
|
|
c02aa084d1 | ||
|
|
516f4f1920 | ||
|
|
b8323f7e0e | ||
|
|
f5f2076db5 | ||
|
|
1a04310f80 | ||
|
|
e830a3d37b | ||
|
|
c9bcc87511 | ||
|
|
9ac4e51224 | ||
|
|
41bb97b179 | ||
|
|
531e160136 | ||
|
|
ba0ce13fe3 | ||
|
|
48e3f9f9d2 | ||
|
|
19791d1d7f | ||
|
|
d04b2ae315 | ||
|
|
6b20f1fb19 | ||
|
|
e90647d498 | ||
|
|
11b61ab345 | ||
|
|
7b8fd76af0 | ||
|
|
a2b876825a | ||
|
|
9f981ada41 | ||
|
|
b4f13d694f | ||
|
|
5c26308b23 | ||
|
|
7fd39e91c1 | ||
|
|
1d4c66a9a0 | ||
|
|
e2f4dad288 | ||
|
|
31c2053c1c | ||
|
|
d759aae318 | ||
|
|
bb0d30610e | ||
|
|
24f324552a | ||
|
|
5c3943bf38 | ||
|
|
90663a674a | ||
|
|
cca07d97b5 | ||
|
|
1cc22e78e2 | ||
|
|
95252e793c | ||
|
|
54aef00913 | ||
|
|
e2eaf43b4a | ||
|
|
e7ccccad7f | ||
|
|
d08e5dabe4 | ||
|
|
df8eb43074 | ||
|
|
8b5aedd463 | ||
|
|
b0c0dc53b1 | ||
|
|
17dcb961ec | ||
|
|
ef307e8ec6 | ||
|
|
b8684777e0 | ||
|
|
446025fb65 | ||
|
|
19105542e5 | ||
|
|
467c2408c4 | ||
|
|
f87a4fcd4e | ||
|
|
9120318594 | ||
|
|
982442eb00 | ||
|
|
40274f5fac | ||
|
|
a03804b09d | ||
|
|
a9f40cf608 | ||
|
|
82025bacad | ||
|
|
2640cea175 | ||
|
|
63265728d4 | ||
|
|
69a3b6dad7 | ||
|
|
30aed15090 | ||
|
|
f7ae2e2220 | ||
|
|
f93d80b8d2 | ||
|
|
a6632625f4 | ||
|
|
b353d68193 | ||
|
|
b46b6363ff | ||
|
|
3be4b103a2 | ||
|
|
dc5efeecbb | ||
|
|
6dea9a4b63 | ||
|
|
4e5a796e50 | ||
|
|
9620f040cb | ||
|
|
d20c77c618 | ||
|
|
ba610864c7 | ||
|
|
d7bf156b30 | ||
|
|
195b635f74 | ||
|
|
c0ae77cd64 | ||
|
|
57b2d6dbd8 | ||
|
|
4e3ba66b0c | ||
|
|
278876c19d | ||
|
|
68a6007fd9 | ||
|
|
346c172b32 | ||
|
|
5ddac353a0 | ||
|
|
4545256b49 | ||
|
|
db23e4966e | ||
|
|
5146429d19 | ||
|
|
0e80c19d3d | ||
|
|
401e662f0b | ||
|
|
ad5ebae304 | ||
|
|
7d5feb943f | ||
|
|
b6d4fb698c | ||
|
|
e3ecd73cd8 | ||
|
|
5dfc6ae62e | ||
|
|
343622d4e5 | ||
|
|
9945ebab34 | ||
|
|
42774d94c0 | ||
|
|
dd535158f2 | ||
|
|
a7245116b6 | ||
|
|
2aef7176ab | ||
|
|
5e1e056623 | ||
|
|
da5c1e9833 | ||
|
|
b6218a1121 | ||
|
|
17ca402aa0 | ||
|
|
cd037aca15 | ||
|
|
bdae812274 | ||
|
|
f1246f84e0 | ||
|
|
9b75acf0b5 | ||
|
|
42d7f4245d | ||
|
|
fd25d3babc | ||
|
|
3f8dfbd5b2 | ||
|
|
0394f29f70 | ||
|
|
0a07a7af01 | ||
|
|
a30ef5b3dc | ||
|
|
2750ec8ef9 | ||
|
|
850999727c | ||
|
|
3dd029b1ac | ||
|
|
75e7fe941b | ||
|
|
cbd2d9d625 | ||
|
|
1d30322820 | ||
|
|
e0246df26b | ||
|
|
e845379b1e | ||
|
|
c631ec5ef5 | ||
|
|
44d3918e4f | ||
|
|
19f9496889 | ||
|
|
2dd78beb92 | ||
|
|
7bb6b21c65 | ||
|
|
11eef8d892 | ||
|
|
4d9b33ecd4 | ||
|
|
421fe33dc0 | ||
|
|
5c82e5ba1b | ||
|
|
b3aaddadc8 | ||
|
|
939022bb5e | ||
|
|
950360fddc | ||
|
|
2ff7a0864b | ||
|
|
488f2df869 | ||
|
|
6877944d17 | ||
|
|
5083d3d13e | ||
|
|
eeef23c2b7 | ||
|
|
a3fff889d1 | ||
|
|
9f3e682b89 | ||
|
|
411c8c4cb3 | ||
|
|
c1d9b35e7c | ||
|
|
cd9b85b555 | ||
|
|
5f88f5ed02 | ||
|
|
a6ec294f63 | ||
|
|
4d5ed8157c | ||
|
|
042f061d86 | ||
|
|
99de8454cd | ||
|
|
348b64ebb0 | ||
|
|
3c44bf55eb | ||
|
|
af7b9bde29 | ||
|
|
1fb47318c0 | ||
|
|
13b39ae730 | ||
|
|
037e42da1d | ||
|
|
25522a8450 | ||
|
|
300bf9c2c5 | ||
|
|
cade24a7ce | ||
|
|
fd93023440 | ||
|
|
762e755b13 | ||
|
|
c536da7279 | ||
|
|
f250a33e9b | ||
|
|
c23a1bfabb | ||
|
|
d60f8ed8d5 | ||
|
|
6317e3ad00 | ||
|
|
7d8535af22 | ||
|
|
c9d713fc7f | ||
|
|
186724e751 | ||
|
|
80f815c020 | ||
|
|
28068ed36d | ||
|
|
f79fe2e056 | ||
|
|
e19177d3ed | ||
|
|
75b5d11181 | ||
|
|
03d4a9ba3c | ||
|
|
8f529046a9 | ||
|
|
d36b2d8057 | ||
|
|
4dc9675a6c | ||
|
|
2b16b69afa | ||
|
|
76beee62c3 | ||
|
|
59d7271fb5 | ||
|
|
d675d6e54b | ||
|
|
ea9d20a250 | ||
|
|
fce22b0d35 | ||
|
|
363d30eadc | ||
|
|
5e2cfab7ba | ||
|
|
5524ca5b25 | ||
|
|
1802c5ea2e | ||
|
|
269324c553 | ||
|
|
ec9e34c970 | ||
|
|
b88cd1d41f | ||
|
|
0b2df134ce | ||
|
|
12e893e11f | ||
|
|
972a35bdef | ||
|
|
edfc5ab8b4 | ||
|
|
37e385e783 | ||
|
|
746291dc67 | ||
|
|
c07c39f8ed | ||
|
|
9fbbd8b954 | ||
|
|
910fde3b2c | ||
|
|
82333ceb82 | ||
|
|
ec58d1c309 | ||
|
|
e408142ca5 | ||
|
|
55c9faaa79 | ||
|
|
0ae489f49d | ||
|
|
e05e05b13a | ||
|
|
6190b05a13 | ||
|
|
19a799656a | ||
|
|
4436145eaf | ||
|
|
6a41446185 | ||
|
|
2d6987341c | ||
|
|
257158fd95 | ||
|
|
f9a967caf7 | ||
|
|
cf22ed57a2 | ||
|
|
b6772ac2ea | ||
|
|
f0025dbc47 | ||
|
|
2a347942bc | ||
|
|
36da65e15b | ||
|
|
214ff3eff0 | ||
|
|
8c0d52d0fe | ||
|
|
793bba95b5 | ||
|
|
2d4a65c654 | ||
|
|
872f178d94 | ||
|
|
70d6094f46 | ||
|
|
31289436f5 | ||
|
|
5e7792c11f | ||
|
|
e73064a438 | ||
|
|
72787c0652 | ||
|
|
c88170f6e0 | ||
|
|
a65ecb157d | ||
|
|
eb8a3c0e09 | ||
|
|
572fade7ff | ||
|
|
b5885ae35f | ||
|
|
335bc01185 | ||
|
|
c87563a520 | ||
|
|
e4aafca7c3 | ||
|
|
fe05d45cde | ||
|
|
b3861decc3 | ||
|
|
b3f59acf7e | ||
|
|
4f8e35e409 | ||
|
|
b898949ffc | ||
|
|
2244764777 | ||
|
|
e4c8a36577 | ||
|
|
41eb45402e | ||
|
|
33ed95bd8e | ||
|
|
4985b2d1f4 | ||
|
|
68a2250886 | ||
|
|
8575939b20 | ||
|
|
634a1c5f6a | ||
|
|
c364e30240 | ||
|
|
3595c3a440 | ||
|
|
c3dd65457d | ||
|
|
3aa909b917 | ||
|
|
35d8d2ab2d | ||
|
|
e3ebaeb2c8 | ||
|
|
71dc332dae | ||
|
|
211a3c2358 | ||
|
|
16b9d4fd8b | ||
|
|
c0f304559f | ||
|
|
8d325184ad | ||
|
|
0df93eaa98 | ||
|
|
aae18fd035 | ||
|
|
fd8552ca3a | ||
|
|
452457412b | ||
|
|
521df1f4b7 | ||
|
|
0ae2f935af | ||
|
|
3282a3ae34 | ||
|
|
cb612c36ea | ||
|
|
14aad62e02 | ||
|
|
847d7ab38d | ||
|
|
99ef9166ae | ||
|
|
0305830e32 | ||
|
|
9f342dff49 | ||
|
|
02766d82eb | ||
|
|
3e372faf5e | ||
|
|
786b4ea8c0 | ||
|
|
20ff0ed30b | ||
|
|
2a490a1bbc | ||
|
|
89391e5be1 | ||
|
|
c3cb41f78a | ||
|
|
c3a0266354 | ||
|
|
55a5c97034 | ||
|
|
dcb8a3f3fb | ||
|
|
3dffe564af | ||
|
|
1820972fb7 | ||
|
|
67534faa78 | ||
|
|
12605843ce | ||
|
|
8dbdebff3f | ||
|
|
61845b8761 | ||
|
|
1ba44c99d1 | ||
|
|
6716ab251f | ||
|
|
e3b9c0140a | ||
|
|
d1c0723b44 | ||
|
|
14ed6af433 | ||
|
|
1325706c7c | ||
|
|
f5ab00a055 | ||
|
|
dcdfc30c45 | ||
|
|
a0d165c79b | ||
|
|
7b23310d8b | ||
|
|
e477dea5c7 | ||
|
|
dccb136c99 | ||
|
|
6af29a7181 | ||
| 7ca3a19eed | |||
| 7fcb4efab6 | |||
| a8024d3dd3 | |||
| 8bb78c95a8 | |||
| 19cbf1ca67 | |||
|
|
e70eb5a926 | ||
|
|
3daa07e311 | ||
|
|
47fab631d0 |
@@ -1,21 +0,0 @@
|
|||||||
---
|
|
||||||
Language: Cpp
|
|
||||||
BasedOnStyle: LLVM
|
|
||||||
|
|
||||||
ColumnLimit: 100
|
|
||||||
IndentWidth: 4
|
|
||||||
TabWidth: 4
|
|
||||||
UseTab: Always
|
|
||||||
|
|
||||||
AccessModifierOffset: -4
|
|
||||||
|
|
||||||
AlignEscapedNewlinesLeft: true
|
|
||||||
|
|
||||||
AllowShortIfStatementsOnASingleLine: true
|
|
||||||
AllowShortLoopsOnASingleLine: true
|
|
||||||
|
|
||||||
AlwaysBreakAfterReturnType: AllDefinitions
|
|
||||||
AlwaysBreakBeforeMultilineStrings: true
|
|
||||||
AlwaysBreakTemplateDeclarations: true
|
|
||||||
|
|
||||||
BreakBeforeBraces: Linux
|
|
||||||
56
.github/workflows/sphinx_deploy.yml
vendored
Normal file
56
.github/workflows/sphinx_deploy.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
name: Deploy docs site with Sphinx
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["main"]
|
||||||
|
|
||||||
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
||||||
|
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
||||||
|
concurrency:
|
||||||
|
group: "pages"
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
# Default to bash
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: Setup Pages
|
||||||
|
id: pages
|
||||||
|
uses: actions/configure-pages@v4
|
||||||
|
- name: Sphinx build
|
||||||
|
uses: jsix-os/sphinx-action@master
|
||||||
|
with:
|
||||||
|
docs-folder: "docs/"
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
|
with:
|
||||||
|
path: ./docs/_build/html
|
||||||
|
|
||||||
|
# Deployment job
|
||||||
|
deploy:
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
steps:
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,10 +1,19 @@
|
|||||||
|
.cache
|
||||||
.lock*
|
.lock*
|
||||||
/build*
|
/build*
|
||||||
*.bak
|
*.bak
|
||||||
tags
|
tags
|
||||||
jsix.log
|
*.log
|
||||||
|
*.out
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
sysroot
|
sysroot
|
||||||
.gdb_history
|
.gdb_history
|
||||||
.peru
|
.peru
|
||||||
|
__pycache__
|
||||||
|
/venv
|
||||||
|
compile_commands.json
|
||||||
|
buddy_allocs.txt
|
||||||
|
frame_allocs.txt
|
||||||
|
heap_allocs.txt
|
||||||
|
/docs/_build
|
||||||
|
|||||||
19
.vscode/c_cpp_properties.json
vendored
Normal file
19
.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/src/libraries/**",
|
||||||
|
"${workspaceFolder}/build/**",
|
||||||
|
"${workspaceFolder}/sysroot/include"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/clang",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++17",
|
||||||
|
"intelliSenseMode": "linux-clang-x64",
|
||||||
|
"compileCommands": "${workspaceFolder}/compile_commands.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
32
.vscode/launch.json
vendored
Normal file
32
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "QEMU Debug Server",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/build/jsix.elf",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"logging": {
|
||||||
|
//"engineLogging": true,
|
||||||
|
"programOutput": true
|
||||||
|
},
|
||||||
|
"stopAtConnect": true,
|
||||||
|
"stopAtEntry": false,
|
||||||
|
|
||||||
|
"setupCommands": [
|
||||||
|
{"text": "dashboard -enabled off", "ignoreFailures": true}
|
||||||
|
],
|
||||||
|
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"miDebuggerServerAddress": "localhost:1234",
|
||||||
|
"debugServerPath": "${workspaceFolder}/qemu.sh",
|
||||||
|
"debugServerArgs": "--debug --no-build",
|
||||||
|
"serverLaunchTimeout": 5000,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
45
.vscode/tasks.json
vendored
45
.vscode/tasks.json
vendored
@@ -1,28 +1,41 @@
|
|||||||
{
|
{
|
||||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
// for the documentation about the tasks.json format
|
// for the documentation about the tasks.json format
|
||||||
"version": "0.1.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"taskName": "make",
|
"label": "Ninja",
|
||||||
"command": "make.bat",
|
"type": "shell",
|
||||||
"isBuildCommand": true
|
"command": "source ${workspaceFolder}/venv/bin/activate.fish; ninja",
|
||||||
|
"detail": "Build the project",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/build"
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"taskName": "clean",
|
"label": "Run QEMU",
|
||||||
"command": "make.bat",
|
"command": "./qemu.sh",
|
||||||
"args": [ "clean" ],
|
"args": [ "--no-build", "--kvm" ],
|
||||||
"isShellCommand": true
|
"dependsOn": ["Ninja"],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"taskName": "qemu (windowed)",
|
"label": "clean",
|
||||||
"command": "qemu-win.bat",
|
"command": "${workspaceFolder}/venv/bin/ninja",
|
||||||
"showOutput": "never",
|
"options": {
|
||||||
"isTestCommand": true
|
"cwd": "${workspaceFolder}/build"
|
||||||
},
|
},
|
||||||
{
|
"args": [
|
||||||
"taskName": "qemu",
|
"-t",
|
||||||
"command": "qemu.bat"
|
"clean"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
38
NOTES.md
38
NOTES.md
@@ -1,38 +0,0 @@
|
|||||||
# Design / WIP notes
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
|
|
||||||
- Paging manager
|
|
||||||
- Copy-on-write pages
|
|
||||||
- Better page-allocation model?
|
|
||||||
- Allow for more than one IOAPIC in ACPI module
|
|
||||||
- The objects get created, but GSI lookup only uses the one at index 0
|
|
||||||
- mark kernel memory pages global
|
|
||||||
- Serial out based on circular/bip biffer and interrupts, not spinning on
|
|
||||||
`write_ready()`
|
|
||||||
- Split out more code into kutil for testing
|
|
||||||
- AHCI / MSI interrupts on Vbox break?
|
|
||||||
- FXSAVE to save XMM registers.
|
|
||||||
- optimization using #NM (0x7) to detect SSE usage
|
|
||||||
- Clean up of process memory maps
|
|
||||||
- Better stack tracer
|
|
||||||
- Bootloader rewrite
|
|
||||||
- C++ and sharing library code for ELF, initrd, etc
|
|
||||||
- Parse initrd and pre-load certain ELF images, eg the process loader process?
|
|
||||||
- Do initial memory bootstrap?
|
|
||||||
- Calling global ctors
|
|
||||||
- Device Tree
|
|
||||||
- Actual serial driver
|
|
||||||
- Disk driver
|
|
||||||
- File system
|
|
||||||
- Multiprocessing
|
|
||||||
- Fast syscalls using syscall/sysret
|
|
||||||
|
|
||||||
### Build
|
|
||||||
|
|
||||||
- Clean up build generator and its templates
|
|
||||||
- More robust objects to represent modules & targets to pass to templates
|
|
||||||
- Read project setup from a simple JSON/TOML/etc
|
|
||||||
- Better compartmentalizing when doing template inheritance
|
|
||||||
- Move to LLD as sysroot linker
|
|
||||||
|
|
||||||
185
README.md
185
README.md
@@ -1,15 +1,19 @@
|
|||||||
# jsix: A toy OS kernel
|

|
||||||
|
|
||||||
**jsix** is the kernel for the hobby OS that I am currently building. It's
|
# The jsix operating system
|
||||||
far from finished, or even being usable. Instead, it's a sandbox for me to play
|
|
||||||
with kernel-level code and explore architectures.
|
**jsix** is a custom multi-core x64 operating system that I am building from
|
||||||
|
scratch. It's far from finished, or even being usable (see the *Status and
|
||||||
|
Roadmap* section, below) but all currently-planned major kernel features are
|
||||||
|
now implemented to at least a passable level.
|
||||||
|
|
||||||
The design goals of the project are:
|
The design goals of the project are:
|
||||||
|
|
||||||
* Modernity - I'm not interested in designing for legacy systems, or running on
|
* Modernity - I'm not interested in designing for legacy systems, or running on
|
||||||
all hardware out there. My target is only 64 bit architecutres, and modern
|
all hardware out there. My target is only 64 bit architectures, and modern
|
||||||
commodity hardware. Currently that means x64 systems with Nehalem or newer
|
commodity hardware. Currently that means x64 systems with Nehalem or newer
|
||||||
CPUs and UEFI firmware. Eventually I'd like to work on an AArch64 port,
|
CPUs and UEFI firmware. (See [this list][cpu_features] for the currently
|
||||||
|
required CPU features.) Eventually I'd like to work on an AArch64 port,
|
||||||
partly to force myself to factor out the architecture-dependent pieces of the
|
partly to force myself to factor out the architecture-dependent pieces of the
|
||||||
code base.
|
code base.
|
||||||
|
|
||||||
@@ -17,13 +21,11 @@ The design goals of the project are:
|
|||||||
processes as possible, in the microkernel fashion. A sub-goal of this is to
|
processes as possible, in the microkernel fashion. A sub-goal of this is to
|
||||||
explore where the bottlenecks of such a microkernel are now, and whether
|
explore where the bottlenecks of such a microkernel are now, and whether
|
||||||
eschewing legacy hardware will let me design a system that's less bogged down
|
eschewing legacy hardware will let me design a system that's less bogged down
|
||||||
by the traditional microkernel problems. Given that there are no processes
|
by the traditional microkernel problems.
|
||||||
yet, the kernel is monolithic by default.
|
|
||||||
|
|
||||||
* Exploration - I'm really mostly doing this to have fun learning and exploring
|
* Exploration - I'm really mostly doing this to have fun learning and exploring
|
||||||
modern OS development. Modular design may be tossed out (hopefully
|
modern OS development. Initial feature implementations may temporarily throw
|
||||||
temporarily) in some places to allow me to play around with the related
|
away modular design to allow for exploration of the related hardware.
|
||||||
hardware.
|
|
||||||
|
|
||||||
A note on the name: This kernel was originally named Popcorn, but I have since
|
A note on the name: This kernel was originally named Popcorn, but I have since
|
||||||
discovered that the Popcorn Linux project is also developing a kernel with that
|
discovered that the Popcorn Linux project is also developing a kernel with that
|
||||||
@@ -31,48 +33,149 @@ name, started around the same time as this project. So I've renamed this kernel
|
|||||||
jsix (Always styled _jsix_ or `j6`, never capitalized) as an homage to L4, xv6,
|
jsix (Always styled _jsix_ or `j6`, never capitalized) as an homage to L4, xv6,
|
||||||
and my wonderful wife.
|
and my wonderful wife.
|
||||||
|
|
||||||
|
[cpu_features]: https://github.com/justinian/jsix/blob/master/src/libraries/cpu/include/cpu/features.inc
|
||||||
|
|
||||||
|
## Status and Roadmap
|
||||||
|
|
||||||
|
The following major feature areas are targets for jsix development:
|
||||||
|
|
||||||
|
#### UEFI boot loader
|
||||||
|
|
||||||
|
_Done._ The bootloader loads the kernel and initial userspace programs, and
|
||||||
|
sets up necessary kernel arguments about the memory map and EFI GOP
|
||||||
|
framebuffer. Possible future ideas:
|
||||||
|
|
||||||
|
- take over more init-time functions from the kernel
|
||||||
|
- rewrite it in Zig
|
||||||
|
|
||||||
|
#### Memory
|
||||||
|
|
||||||
|
_Virtual memory: Sufficient._ The kernel manages virtual memory with a number
|
||||||
|
of kinds of `vm_area` objects representing mapped areas, which can belong to
|
||||||
|
one or more `vm_space` objects which represent a whole virtual memory space.
|
||||||
|
(Each process has a `vm_space`, and so does the kernel itself.)
|
||||||
|
|
||||||
|
Remaining to do:
|
||||||
|
|
||||||
|
- TLB shootdowns
|
||||||
|
- Page swapping
|
||||||
|
- Large / huge page support
|
||||||
|
|
||||||
|
_Physical page allocation: Sufficient._ The current physical page allocator
|
||||||
|
implementation uses a group of blocks representing up-to-1GiB areas of usable
|
||||||
|
memory as defined by the bootloader. Each block has a three-level bitmap
|
||||||
|
denoting free/used pages.
|
||||||
|
|
||||||
|
Future work:
|
||||||
|
|
||||||
|
- Align blocks so that their first page is 1GiB-aligned, making finding free
|
||||||
|
large/huge pages easier.
|
||||||
|
|
||||||
|
#### Multitasking
|
||||||
|
|
||||||
|
_Sufficient._ The global scheduler object keeps separate ready/blocked lists
|
||||||
|
per core. Cores periodically attempt to balance load via work stealing.
|
||||||
|
|
||||||
|
User-space tasks are able to create threads as well as other processes.
|
||||||
|
|
||||||
|
#### API
|
||||||
|
|
||||||
|
_Syscalls: Sufficient._ User-space tasks are able to make syscalls to the
|
||||||
|
kernel via fast SYSCALL/SYSRET instructions. Syscalls made via `libj6` look to
|
||||||
|
both the callee and the caller like standard SysV ABI function calls. The
|
||||||
|
implementations are wrapped in generated wrapper functions which validate the
|
||||||
|
request, check capabilities, and find the appropriate kernel objects or handles
|
||||||
|
before calling the implementation functions.
|
||||||
|
|
||||||
|
_IPC: Working, needs optimization._ The current IPC primitives are:
|
||||||
|
|
||||||
|
- _Mailboxes_: endpoints for asynchronously-delivered small messages. Currently
|
||||||
|
these messages are double-copied - once from the caller into a kernel buffer,
|
||||||
|
and once from the kernel to the receiver. This works and is not a major cause
|
||||||
|
of slowdown, but will need to be optimized in the future.
|
||||||
|
- _Channels_: endpoints for asynchronous uni-directional streams of bytes.
|
||||||
|
Currently these also suffer from a double-copy problem, and should probably
|
||||||
|
be replaced eventually by userspace shared memory communication.
|
||||||
|
- _Events_: objects that can be signalled to send asynchronous notifications to
|
||||||
|
waiting threads.
|
||||||
|
|
||||||
|
#### Hardware Support
|
||||||
|
|
||||||
|
- Framebuffer driver: _In progress._ Currently on machines with a video
|
||||||
|
device accessible by UEFI, jsix starts a user-space framebuffer driver that
|
||||||
|
only prints out kernel logs.
|
||||||
|
- Serial driver: _In progress._ The current UART currently only exposes COM1
|
||||||
|
as an output channel, but no input or other serial ports are exposed.
|
||||||
|
- USB driver: _To do_
|
||||||
|
- AHCI (SATA) driver: _To do_
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
jsix uses the [Ninja][] build tool, and generates the build files for it with a
|
jsix uses the [Ninja][] build tool, and generates the build files for it with
|
||||||
custom tool called [Bonnibel][]. Bonnibel can be installed with [Cargo][], or
|
the `configure` script. The build also relies on a custom toolchain sysroot, which can be
|
||||||
downloaded as a prebuilt binary from its Github repository.
|
downloaded or built using the scripts in [jsix-os/toolchain][].
|
||||||
|
|
||||||
[Ninja]: https://ninja-build.org
|
[Ninja]: https://ninja-build.org
|
||||||
[Bonnibel]: https://github.com/justinian/bonnibel
|
[jsix-os/toolchain]: https://github.com/jsix-os/toolchain
|
||||||
[Cargo]: https://crates.io/crates/bonnibel
|
|
||||||
|
|
||||||
Requrirements:
|
Other build dependencies:
|
||||||
|
|
||||||
* bonnibel
|
* [clang][]: the C/C++ compiler
|
||||||
* ninja
|
* [nasm][]: the assembler
|
||||||
* clang
|
* [lld][]: the linker
|
||||||
* nasm
|
* [mtools][]: for creating the FAT image
|
||||||
* mtools
|
|
||||||
* curl for downloading the toolchain
|
|
||||||
|
|
||||||
### Setting up the cross toolchain
|
[clang]: https://clang.llvm.org
|
||||||
|
[nasm]: https://www.nasm.us
|
||||||
|
[lld]: https://lld.llvm.org
|
||||||
|
[mtools]: https://www.gnu.org/software/mtools/
|
||||||
|
|
||||||
Running `pb sync` will download and unpack the toolchain into `sysroot`.
|
The `configure` script has some Python dependencies - these can be installed via
|
||||||
|
`pip`, though doing so in a python virtual environment is recommended.
|
||||||
|
Installing via `pip` will also install `ninja`.
|
||||||
|
|
||||||
#### Compiling the toolchain yourself
|
A Debian 11 (Bullseye) system can be configured with the necessary build
|
||||||
|
dependencies by running the following commands from the jsix repository root:
|
||||||
|
|
||||||
If you have `clang` and `curl` installed, runing the `scripts/build_sysroot.sh`
|
```bash
|
||||||
script will download and build a LLVM toolchain configured for building jsix
|
sudo apt install clang lld nasm mtools python3-pip python3-venv
|
||||||
host binaries.
|
python3 -m venv ./venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
peru sync
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setting up the sysroot
|
||||||
|
|
||||||
|
Build or download the toolchain sysroot as mentioned above with
|
||||||
|
[jsix-os/toolchain][], and symlink the built toolchain directory as `sysroot`
|
||||||
|
at the root of this project.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Example if both the toolchain and this project are cloned under ~/src
|
||||||
|
ln -s ~/src/toolchain/toolchains/llvm-13 ~/src/jsix/sysroot
|
||||||
|
```
|
||||||
|
|
||||||
### Building and running jsix
|
### Building and running jsix
|
||||||
|
|
||||||
Once the toolchain has been set up, running Bonnibel's `pb init` command will
|
Once the toolchain has been set up, running the `./configure` script (see
|
||||||
set up the build configuration, and `pb build` will actually run the build. If
|
`./configure --help` for available options) will set up the build configuration,
|
||||||
you have `qemu-system-x86_64` installed, the `qemu.sh` script will to run jsix
|
and `ninja -C build` (or wherever you put the build directory) will actually run
|
||||||
in QEMU `-nographic` mode.
|
the build. If you have `qemu-system-x86_64` installed, the `qemu.sh` script will
|
||||||
|
to run jsix in QEMU `-nographic` mode.
|
||||||
|
|
||||||
I personally run this either from a real debian amd64 testing/buster machine or
|
I personally run this either from a real debian amd64 bullseye machine or
|
||||||
a windows WSL debian testing/buster installation. The following should be
|
a windows WSL debian bullseye installation. Your mileage may vary with other
|
||||||
enough to set up such a system to build the kernel:
|
setups and distros.
|
||||||
|
|
||||||
sudo apt install qemu-system-x86 nasm clang-6.0 mtools curl
|
### Running the test suite
|
||||||
sudo update-alternatives /usr/bin/clang clang /usr/bin/clang-6.0 1000
|
|
||||||
sudo update-alternatives /usr/bin/clang++ clang++ /usr/bin/clang++-6.0 1000
|
|
||||||
curl -L -o pb https://github.com/justinian/bonnibel/releases/download/2.0.0/pb_linux_amd64 && chmod a+x pb
|
|
||||||
|
|
||||||
|
jsix now has the `test_runner` userspace program that runs various automated
|
||||||
|
tests. It is not included in the default build, but if you use the `test.yml`
|
||||||
|
manifest it will be built, and can be run with the `test.sh` script or the
|
||||||
|
`qemu.sh` script.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./configure --manifest=assets/manifests/test.yml
|
||||||
|
if ./test.sh; then echo "All tests passed!"; else echo "Failed."; fi
|
||||||
|
```
|
||||||
|
|||||||
9
assets/build/amd64/config.debug.yaml
Normal file
9
assets/build/amd64/config.debug.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
ccflags: [
|
||||||
|
"-g3",
|
||||||
|
"-ggdb",
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-g",
|
||||||
|
]
|
||||||
3
assets/build/amd64/config.release.yaml
Normal file
3
assets/build/amd64/config.release.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ccflags: [
|
||||||
|
"-O3",
|
||||||
|
]
|
||||||
39
assets/build/amd64/global.yaml
Normal file
39
assets/build/amd64/global.yaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
cc: "${source_root}/sysroot/bin/clang"
|
||||||
|
cxx: "${source_root}/sysroot/bin/clang++"
|
||||||
|
ld: "${source_root}/sysroot/bin/ld.lld"
|
||||||
|
ar: ar
|
||||||
|
nasm: nasm
|
||||||
|
objcopy: objcopy
|
||||||
|
|
||||||
|
ccflags: [
|
||||||
|
"-I${source_root}/src/include",
|
||||||
|
"-fcolor-diagnostics",
|
||||||
|
"-U__STDCPP_THREADS__",
|
||||||
|
"-D_LIBCPP_HAS_NO_THREADS",
|
||||||
|
"-D__jsix_config=${build_config}",
|
||||||
|
"-D__jsix_config_${build_config}",
|
||||||
|
"-DVERSION_MAJOR=${version_major}",
|
||||||
|
"-DVERSION_MINOR=${version_minor}",
|
||||||
|
"-DVERSION_PATCH=${version_patch}",
|
||||||
|
"-DVERSION_GITSHA=0x${version_sha}",
|
||||||
|
'-DGIT_VERSION=\"${version_major}.${version_minor}.${version_patch}+${version_sha}\"',
|
||||||
|
'-DGIT_VERSION_WIDE=L\"${version_major}.${version_minor}.${version_patch}+${version_sha}\"',
|
||||||
|
|
||||||
|
"-Wformat=2", "-Winit-self", "-Winline", "-Wmissing-format-attribute",
|
||||||
|
"-Wmissing-include-dirs", "-Wswitch", "-Wundef", "-Wdisabled-optimization",
|
||||||
|
"-Wpointer-arith", "-Wno-attributes", "-Wno-sign-compare", "-Wno-multichar",
|
||||||
|
"-Wno-div-by-zero", "-Wno-endif-labels", "-Wno-pragmas", "-Wno-format-extra-args",
|
||||||
|
"-Wno-unused-result", "-Wno-deprecated-declarations", "-Wno-unused-function",
|
||||||
|
"-Wno-address-of-packed-member", "-Wno-invalid-offsetof", "-Wno-format-nonliteral",
|
||||||
|
"-Werror" ]
|
||||||
|
|
||||||
|
asflags: [
|
||||||
|
"-DVERSION_MAJOR=${version_major}",
|
||||||
|
"-DVERSION_MINOR=${version_minor}",
|
||||||
|
"-DVERSION_PATCH=${version_patch}",
|
||||||
|
"-DVERSION_GITSHA=0x${version_sha}",
|
||||||
|
"-I${source_root}/src/include" ]
|
||||||
|
|
||||||
|
cflags: [ "-std=c11" ]
|
||||||
|
cxxflags: [ "-std=c++17" ]
|
||||||
91
assets/build/amd64/rules.ninja
Normal file
91
assets/build/amd64/rules.ninja
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
rule compile.c
|
||||||
|
command = $cc -MMD -MF $out.d $cflags $ccflags -o $out -c $in
|
||||||
|
description = Compiling [$target]:$name
|
||||||
|
depfile = $out.d
|
||||||
|
deps = gcc
|
||||||
|
|
||||||
|
rule dump_c_defs
|
||||||
|
command = echo | $cc $ccflags $cflags -dM -E - > $out
|
||||||
|
description = Dumping C defines for $target
|
||||||
|
|
||||||
|
rule dump_c_run
|
||||||
|
command = echo '#!/bin/bash' > $out; echo '$cc $ccflags $cflags $$*' >> $
|
||||||
|
$out; chmod a+x $out
|
||||||
|
description = Dumping C arguments for $target
|
||||||
|
|
||||||
|
rule compile.cpp
|
||||||
|
command = $cxx -MMD -MF $out.d $cxxflags $ccflags -o $out -c $in
|
||||||
|
description = Compiling [$target]:$name
|
||||||
|
depfile = $out.d
|
||||||
|
deps = gcc
|
||||||
|
|
||||||
|
rule dump_cpp_defs
|
||||||
|
command = echo | $cxx -x c++ $ccflags $cxxflags -dM -E - > $out
|
||||||
|
description = Dumping C++ defines for $target
|
||||||
|
|
||||||
|
rule dump_cpp_run
|
||||||
|
command = echo '#!/bin/bash' > $out; echo '$cxx $ccflags $cxxflags $$*' $
|
||||||
|
>> $out; chmod a+x $out
|
||||||
|
description = Dumping C++ arguments for $target
|
||||||
|
|
||||||
|
rule compile.s
|
||||||
|
command = $nasm -o $out -felf64 -MD $out.d $asflags $in
|
||||||
|
description = Assembling [$target]:$name
|
||||||
|
depfile = $out.d
|
||||||
|
deps = gcc
|
||||||
|
|
||||||
|
rule parse.cog
|
||||||
|
command = cog -o $out -d -D target=$target $cogflags $in
|
||||||
|
description = Parsing [$target]:$name
|
||||||
|
|
||||||
|
rule exe
|
||||||
|
command = $ld $ldflags -o $out $in $libs
|
||||||
|
description = Linking exe [$target]:$name
|
||||||
|
|
||||||
|
rule driver
|
||||||
|
command = $ld $ldflags -o $out $in $libs
|
||||||
|
description = Linking driver [$target]:$name
|
||||||
|
|
||||||
|
rule lib
|
||||||
|
command = $ld -shared -soname $soname $ldflags -o $out $in $libs
|
||||||
|
description = Linking [$target]:$name
|
||||||
|
|
||||||
|
rule lib_static
|
||||||
|
command = $ar qcs $out $in
|
||||||
|
description = Archiving [$target]:$name
|
||||||
|
|
||||||
|
rule cp
|
||||||
|
command = cp $in $out
|
||||||
|
description = Copying [$target]:$name
|
||||||
|
|
||||||
|
rule dump
|
||||||
|
command = objdump -DSC -M intel $in > $out
|
||||||
|
description = Dumping decompiled $name
|
||||||
|
|
||||||
|
rule makest
|
||||||
|
description = Making symbol table
|
||||||
|
command = nm -n -S --demangle $in | ${source_root}/scripts/build_symbol_table.py $out
|
||||||
|
|
||||||
|
rule makeinitrd
|
||||||
|
description = Creating $name
|
||||||
|
command = ${source_root}/scripts/mkj6romfs.py -c $format $in $out
|
||||||
|
|
||||||
|
rule makefat
|
||||||
|
description = Creating $name
|
||||||
|
command = $
|
||||||
|
cp $in $out; $
|
||||||
|
mcopy -s -D o -i $out@@1M ${build_root}/fatroot/* ::/
|
||||||
|
|
||||||
|
rule strip
|
||||||
|
description = Stripping $name
|
||||||
|
command = $
|
||||||
|
cp $in $out; $
|
||||||
|
objcopy --only-keep-debug $out $debug; $
|
||||||
|
strip --discard-all -g $out; $
|
||||||
|
objcopy --add-gnu-debuglink=$debug $out
|
||||||
|
|
||||||
|
rule touch
|
||||||
|
command = touch $out
|
||||||
|
|
||||||
|
rule compdb
|
||||||
|
command = ninja -t compdb > $out
|
||||||
26
assets/build/amd64/target.boot.yaml
Normal file
26
assets/build/amd64/target.boot.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
ld: clang++
|
||||||
|
|
||||||
|
ccflags: [
|
||||||
|
"-nostdlib",
|
||||||
|
"-nodefaultlibs",
|
||||||
|
"-fno-builtin",
|
||||||
|
|
||||||
|
"-I${source_root}/external",
|
||||||
|
"--target=x86_64-unknown-windows",
|
||||||
|
"-ffreestanding",
|
||||||
|
"-mno-red-zone",
|
||||||
|
"-fshort-wchar",
|
||||||
|
"-fno-omit-frame-pointer",
|
||||||
|
]
|
||||||
|
|
||||||
|
cxxflags: [ "-fno-exceptions", "-fno-rtti" ]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"--target=x86_64-unknown-windows",
|
||||||
|
"-nostdlib",
|
||||||
|
"-Wl,-entry:efi_main",
|
||||||
|
"-Wl,-subsystem:efi_application",
|
||||||
|
"-fuse-ld=lld-link",
|
||||||
|
]
|
||||||
|
|
||||||
40
assets/build/amd64/target.init.yaml
Normal file
40
assets/build/amd64/target.init.yaml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
ccflags: [
|
||||||
|
"--target=x86_64-jsix-elf",
|
||||||
|
"-fno-omit-frame-pointer",
|
||||||
|
"-fno-stack-protector",
|
||||||
|
|
||||||
|
"-fvisibility=hidden",
|
||||||
|
"-fvisibility-inlines-hidden",
|
||||||
|
|
||||||
|
"-D__ELF__",
|
||||||
|
"-D__jsix__",
|
||||||
|
"-U__linux",
|
||||||
|
"-U__linux__",
|
||||||
|
|
||||||
|
"-DMSPACES",
|
||||||
|
|
||||||
|
"--sysroot='${source_root}/sysroot'"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
cxxflags: [
|
||||||
|
"-fno-exceptions",
|
||||||
|
"-fno-rtti",
|
||||||
|
"-isystem", "${source_root}/sysroot/include/c++/v1",
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-Bstatic",
|
||||||
|
"-m", "elf_x86_64",
|
||||||
|
"--sysroot='${source_root}/sysroot'",
|
||||||
|
"--no-eh-frame-hdr",
|
||||||
|
"-L", "${source_root}/sysroot/lib",
|
||||||
|
"-z", "separate-code",
|
||||||
|
"-lc++", "-lc++abi", "-lunwind",
|
||||||
|
"--no-dependent-libraries",
|
||||||
|
]
|
||||||
|
|
||||||
|
libs: [
|
||||||
|
"${target_dir}/crt0.o",
|
||||||
|
]
|
||||||
52
assets/build/amd64/target.kernel.yaml
Normal file
52
assets/build/amd64/target.kernel.yaml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
asflags: [ "-I${source_root}/src/kernel/" ]
|
||||||
|
|
||||||
|
ccflags: [
|
||||||
|
"--target=x86_64-jsix-elf",
|
||||||
|
"-fno-stack-protector",
|
||||||
|
|
||||||
|
"-I${source_root}/external",
|
||||||
|
|
||||||
|
"-nostdinc",
|
||||||
|
"-nostdlib",
|
||||||
|
"-ffreestanding",
|
||||||
|
"-nodefaultlibs",
|
||||||
|
"-fno-builtin",
|
||||||
|
"-fno-plt",
|
||||||
|
|
||||||
|
"-mno-sse",
|
||||||
|
"-fno-omit-frame-pointer",
|
||||||
|
"-mno-red-zone",
|
||||||
|
"-mcmodel=kernel",
|
||||||
|
"-fvisibility=hidden",
|
||||||
|
"-fvisibility-inlines-hidden",
|
||||||
|
|
||||||
|
"-D__ELF__",
|
||||||
|
"-D__jsix__",
|
||||||
|
"-D__j6kernel",
|
||||||
|
"-U__linux",
|
||||||
|
"-U__linux__",
|
||||||
|
"-DPRINTF_ALIAS_STANDARD_FUNCTION_NAMES=1",
|
||||||
|
"-DPRINTF_INCLUDE_CONFIG_H=1",
|
||||||
|
|
||||||
|
"--sysroot='${source_root}/sysroot'"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
cflags: [ '-nostdinc' ]
|
||||||
|
|
||||||
|
cxxflags: [
|
||||||
|
"-fno-exceptions",
|
||||||
|
"-fno-rtti",
|
||||||
|
"-nostdinc",
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-m", "elf_x86_64",
|
||||||
|
"-nostdlib",
|
||||||
|
"-Bstatic",
|
||||||
|
"--no-eh-frame-hdr",
|
||||||
|
"-z", "norelro",
|
||||||
|
"-z", "separate-code"
|
||||||
|
]
|
||||||
|
|
||||||
15
assets/build/amd64/target.user.exe.yaml
Normal file
15
assets/build/amd64/target.user.exe.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
ccflags: [
|
||||||
|
"-fpie"
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-pie",
|
||||||
|
"--dynamic-linker", "/jsix/lib/ld.so",
|
||||||
|
"--push-state", "--as-needed", "-Bstatic", "-lc++", "-lc++abi", "-lunwind", "--pop-state",
|
||||||
|
]
|
||||||
|
|
||||||
|
libs: [
|
||||||
|
"${target_dir}/crt0.o",
|
||||||
|
]
|
||||||
7
assets/build/amd64/target.user.shared.yaml
Normal file
7
assets/build/amd64/target.user.shared.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
ccflags: [
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-shared",
|
||||||
|
]
|
||||||
34
assets/build/amd64/target.user.yaml
Normal file
34
assets/build/amd64/target.user.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
asflags: []
|
||||||
|
|
||||||
|
ccflags: [
|
||||||
|
"--target=x86_64-jsix-elf",
|
||||||
|
"-fno-omit-frame-pointer",
|
||||||
|
"-fno-stack-protector",
|
||||||
|
|
||||||
|
"-fvisibility=hidden",
|
||||||
|
"-fvisibility-inlines-hidden",
|
||||||
|
|
||||||
|
"-D__ELF__",
|
||||||
|
"-D__jsix__",
|
||||||
|
"-U__linux",
|
||||||
|
"-U__linux__",
|
||||||
|
|
||||||
|
"--sysroot='${source_root}/sysroot'",
|
||||||
|
"-fpic",
|
||||||
|
]
|
||||||
|
|
||||||
|
cxxflags: [
|
||||||
|
"-fno-exceptions",
|
||||||
|
"-fno-rtti",
|
||||||
|
"-isystem", "${source_root}/sysroot/include/c++/v1",
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-m", "elf_x86_64",
|
||||||
|
"--sysroot='${source_root}/sysroot'",
|
||||||
|
"--no-eh-frame-hdr",
|
||||||
|
"-L", "${source_root}/sysroot/lib",
|
||||||
|
"-z", "separate-code",
|
||||||
|
"--no-dependent-libraries",
|
||||||
|
]
|
||||||
9
assets/build/linux/config.debug.yaml
Normal file
9
assets/build/linux/config.debug.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
ccflags: [
|
||||||
|
"-g3",
|
||||||
|
"-ggdb",
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-g",
|
||||||
|
]
|
||||||
3
assets/build/linux/config.release.yaml
Normal file
3
assets/build/linux/config.release.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ccflags: [
|
||||||
|
"-O3",
|
||||||
|
]
|
||||||
39
assets/build/linux/global.yaml
Normal file
39
assets/build/linux/global.yaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
cc: "clang-16"
|
||||||
|
cxx: "clang++-16"
|
||||||
|
ld: "ld.lld-16"
|
||||||
|
ar: ar
|
||||||
|
nasm: nasm
|
||||||
|
objcopy: objcopy
|
||||||
|
|
||||||
|
ccflags: [
|
||||||
|
"-I${source_root}/src/include",
|
||||||
|
"-I${source_root}/sysroot/include/c++/v1",
|
||||||
|
"-fcolor-diagnostics",
|
||||||
|
"-U__STDCPP_THREADS__",
|
||||||
|
"-D__jsix_config=${build_config}",
|
||||||
|
"-D__jsix_config_${build_config}",
|
||||||
|
"-DVERSION_MAJOR=${version_major}",
|
||||||
|
"-DVERSION_MINOR=${version_minor}",
|
||||||
|
"-DVERSION_PATCH=${version_patch}",
|
||||||
|
"-DVERSION_GITSHA=0x${version_sha}",
|
||||||
|
'-DGIT_VERSION=\"${version_major}.${version_minor}.${version_patch}+${version_sha}\"',
|
||||||
|
'-DGIT_VERSION_WIDE=L\"${version_major}.${version_minor}.${version_patch}+${version_sha}\"',
|
||||||
|
|
||||||
|
"-Wformat=2", "-Winit-self", "-Winline", "-Wmissing-format-attribute",
|
||||||
|
"-Wmissing-include-dirs", "-Wswitch", "-Wundef", "-Wdisabled-optimization",
|
||||||
|
"-Wpointer-arith", "-Wno-attributes", "-Wno-sign-compare", "-Wno-multichar",
|
||||||
|
"-Wno-div-by-zero", "-Wno-endif-labels", "-Wno-pragmas", "-Wno-format-extra-args",
|
||||||
|
"-Wno-unused-result", "-Wno-deprecated-declarations", "-Wno-unused-function",
|
||||||
|
"-Wno-address-of-packed-member", "-Wno-invalid-offsetof", "-Wno-format-nonliteral",
|
||||||
|
"-Werror" ]
|
||||||
|
|
||||||
|
asflags: [
|
||||||
|
"-DVERSION_MAJOR=${version_major}",
|
||||||
|
"-DVERSION_MINOR=${version_minor}",
|
||||||
|
"-DVERSION_PATCH=${version_patch}",
|
||||||
|
"-DVERSION_GITSHA=0x${version_sha}",
|
||||||
|
"-I${source_root}/src/include" ]
|
||||||
|
|
||||||
|
cflags: [ "-std=c11" ]
|
||||||
|
cxxflags: [ "-std=c++17" ]
|
||||||
91
assets/build/linux/rules.ninja
Normal file
91
assets/build/linux/rules.ninja
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
rule compile.c
|
||||||
|
command = $cc -MMD -MF $out.d $cflags $ccflags -o $out -c $in
|
||||||
|
description = Compiling [$target]:$name
|
||||||
|
depfile = $out.d
|
||||||
|
deps = gcc
|
||||||
|
|
||||||
|
rule dump_c_defs
|
||||||
|
command = echo | $cc $ccflags $cflags -dM -E - > $out
|
||||||
|
description = Dumping C defines for $target
|
||||||
|
|
||||||
|
rule dump_c_run
|
||||||
|
command = echo '#!/bin/bash' > $out; echo '$cc $ccflags $cflags $$*' >> $
|
||||||
|
$out; chmod a+x $out
|
||||||
|
description = Dumping C arguments for $target
|
||||||
|
|
||||||
|
rule compile.cpp
|
||||||
|
command = $cxx -MMD -MF $out.d $cxxflags $ccflags -o $out -c $in
|
||||||
|
description = Compiling [$target]:$name
|
||||||
|
depfile = $out.d
|
||||||
|
deps = gcc
|
||||||
|
|
||||||
|
rule dump_cpp_defs
|
||||||
|
command = echo | $cxx -x c++ $ccflags $cxxflags -dM -E - > $out
|
||||||
|
description = Dumping C++ defines for $target
|
||||||
|
|
||||||
|
rule dump_cpp_run
|
||||||
|
command = echo '#!/bin/bash' > $out; echo '$cxx $ccflags $cxxflags $$*' $
|
||||||
|
>> $out; chmod a+x $out
|
||||||
|
description = Dumping C++ arguments for $target
|
||||||
|
|
||||||
|
rule compile.s
|
||||||
|
command = $nasm -o $out -felf64 -MD $out.d $asflags $in
|
||||||
|
description = Assembling [$target]:$name
|
||||||
|
depfile = $out.d
|
||||||
|
deps = gcc
|
||||||
|
|
||||||
|
rule parse.cog
|
||||||
|
command = cog -o $out -d -D target=$target $cogflags $in
|
||||||
|
description = Parsing [$target]:$name
|
||||||
|
|
||||||
|
rule exe
|
||||||
|
command = $ld $ldflags -o $out $in $libs
|
||||||
|
description = Linking exe [$target]:$name
|
||||||
|
|
||||||
|
rule driver
|
||||||
|
command = $ld $ldflags -o $out $in $libs
|
||||||
|
description = Linking driver [$target]:$name
|
||||||
|
|
||||||
|
rule lib
|
||||||
|
command = $ld -shared -soname $soname $ldflags -o $out $in $libs
|
||||||
|
description = Linking [$target]:$name
|
||||||
|
|
||||||
|
rule lib_static
|
||||||
|
command = $ar qcs $out $in
|
||||||
|
description = Archiving [$target]:$name
|
||||||
|
|
||||||
|
rule cp
|
||||||
|
command = cp $in $out
|
||||||
|
description = Copying [$target]:$name
|
||||||
|
|
||||||
|
rule dump
|
||||||
|
command = objdump -DSC -M intel $in > $out
|
||||||
|
description = Dumping decompiled $name
|
||||||
|
|
||||||
|
rule makest
|
||||||
|
description = Making symbol table
|
||||||
|
command = nm -n -S --demangle $in | ${source_root}/scripts/build_symbol_table.py $out
|
||||||
|
|
||||||
|
rule makeinitrd
|
||||||
|
description = Creating $name
|
||||||
|
command = ${source_root}/scripts/mkj6romfs.py -c $format $in $out
|
||||||
|
|
||||||
|
rule makefat
|
||||||
|
description = Creating $name
|
||||||
|
command = $
|
||||||
|
cp $in $out; $
|
||||||
|
mcopy -s -D o -i $out@@1M ${build_root}/fatroot/* ::/
|
||||||
|
|
||||||
|
rule strip
|
||||||
|
description = Stripping $name
|
||||||
|
command = $
|
||||||
|
cp $in $out; $
|
||||||
|
objcopy --only-keep-debug $out $debug; $
|
||||||
|
strip --discard-all -g $out; $
|
||||||
|
objcopy --add-gnu-debuglink=$debug $out
|
||||||
|
|
||||||
|
rule touch
|
||||||
|
command = touch $out
|
||||||
|
|
||||||
|
rule compdb
|
||||||
|
command = ninja -t compdb > $out
|
||||||
39
assets/build/linux/target.init.yaml
Normal file
39
assets/build/linux/target.init.yaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
ccflags: [
|
||||||
|
"--target=x86_64-jsix-elf",
|
||||||
|
"-fno-omit-frame-pointer",
|
||||||
|
"-fno-stack-protector",
|
||||||
|
|
||||||
|
"-fvisibility=hidden",
|
||||||
|
"-fvisibility-inlines-hidden",
|
||||||
|
|
||||||
|
"-D__ELF__",
|
||||||
|
"-D__jsix__",
|
||||||
|
"-U__linux",
|
||||||
|
"-U__linux__",
|
||||||
|
|
||||||
|
"-DMSPACES",
|
||||||
|
|
||||||
|
"--sysroot='${source_root}/sysroot'"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
cxxflags: [
|
||||||
|
"-fno-exceptions",
|
||||||
|
"-fno-rtti",
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-Bstatic",
|
||||||
|
"-m", "elf_x86_64",
|
||||||
|
"--sysroot='${source_root}/sysroot'",
|
||||||
|
"--no-eh-frame-hdr",
|
||||||
|
"-L", "${source_root}/sysroot/lib",
|
||||||
|
"-z", "separate-code",
|
||||||
|
"-lc++", "-lc++abi", "-lunwind",
|
||||||
|
"--no-dependent-libraries",
|
||||||
|
]
|
||||||
|
|
||||||
|
libs: [
|
||||||
|
"${target_dir}/crt0.o",
|
||||||
|
]
|
||||||
16
assets/build/linux/target.user.exe.yaml
Normal file
16
assets/build/linux/target.user.exe.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
ccflags: [
|
||||||
|
"-fpie"
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-pie",
|
||||||
|
"-rpath", "${target_dir}",
|
||||||
|
"--dynamic-linker", "/lib64/ld-linux-x86-64.so.2",
|
||||||
|
"--push-state", "--as-needed", "-Bstatic", "-lc++", "-lc++abi", "-lunwind", "--pop-state",
|
||||||
|
]
|
||||||
|
|
||||||
|
libs: [
|
||||||
|
"${target_dir}/crt0.o",
|
||||||
|
]
|
||||||
7
assets/build/linux/target.user.shared.yaml
Normal file
7
assets/build/linux/target.user.shared.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
ccflags: [
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-shared",
|
||||||
|
]
|
||||||
33
assets/build/linux/target.user.yaml
Normal file
33
assets/build/linux/target.user.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
asflags: []
|
||||||
|
|
||||||
|
ccflags: [
|
||||||
|
"--target=x86_64-jsix-elf",
|
||||||
|
"-fno-omit-frame-pointer",
|
||||||
|
"-fno-stack-protector",
|
||||||
|
|
||||||
|
"-fvisibility=hidden",
|
||||||
|
"-fvisibility-inlines-hidden",
|
||||||
|
|
||||||
|
"-D__ELF__",
|
||||||
|
"-D__jsix__",
|
||||||
|
"-U__linux",
|
||||||
|
"-U__linux__",
|
||||||
|
|
||||||
|
"--sysroot='${source_root}/sysroot'",
|
||||||
|
"-fpic",
|
||||||
|
]
|
||||||
|
|
||||||
|
cxxflags: [
|
||||||
|
"-fno-exceptions",
|
||||||
|
"-fno-rtti",
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags: [
|
||||||
|
"-m", "elf_x86_64",
|
||||||
|
"--sysroot='${source_root}/sysroot'",
|
||||||
|
"--no-eh-frame-hdr",
|
||||||
|
"-L", "${source_root}/sysroot/lib",
|
||||||
|
"-z", "separate-code",
|
||||||
|
"--no-dependent-libraries",
|
||||||
|
]
|
||||||
@@ -1,4 +1,14 @@
|
|||||||
import gdb
|
import gdb
|
||||||
|
import gdb.printing
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.path.append('./scripts')
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
Capability = namedtuple("Capability", ["id", "parent", "refcount", "caps", "type", "koid"])
|
||||||
|
LogEntry = namedtuple("LogHeader", ["id", "bytes", "severity", "area", "message"])
|
||||||
|
|
||||||
class PrintStackCommand(gdb.Command):
|
class PrintStackCommand(gdb.Command):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -10,6 +20,7 @@ class PrintStackCommand(gdb.Command):
|
|||||||
base = "$rsp"
|
base = "$rsp"
|
||||||
if len(args) > 0:
|
if len(args) > 0:
|
||||||
base = args[0]
|
base = args[0]
|
||||||
|
base = int(gdb.parse_and_eval(base))
|
||||||
|
|
||||||
depth = 22
|
depth = 22
|
||||||
if len(args) > 1:
|
if len(args) > 1:
|
||||||
@@ -18,14 +29,35 @@ class PrintStackCommand(gdb.Command):
|
|||||||
for i in range(depth-1, -1, -1):
|
for i in range(depth-1, -1, -1):
|
||||||
try:
|
try:
|
||||||
offset = i * 8
|
offset = i * 8
|
||||||
base_addr = gdb.parse_and_eval(base)
|
value = gdb.parse_and_eval(f"*(uint64_t*)({base:#x} + {offset:#x})")
|
||||||
value = gdb.parse_and_eval(f"*(uint64_t*)({base} + {offset})")
|
print("{:016x} (+{:04x}): {:016x}".format(base + offset, offset, int(value)))
|
||||||
print("{:016x} (+{:04x}): {:016x}".format(int(base_addr) + offset, offset, int(value)))
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
def stack_walk(frame, depth):
|
||||||
|
for i in range(depth-1, -1, -1):
|
||||||
|
ret = gdb.parse_and_eval(f"*(uint64_t*)({frame:#x} + 0x8)")
|
||||||
|
|
||||||
|
name = ""
|
||||||
|
try:
|
||||||
|
block = gdb.block_for_pc(int(ret))
|
||||||
|
if block:
|
||||||
|
name = block.function or ""
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
print("{:016x}: {:016x} {}".format(int(frame), int(ret), name))
|
||||||
|
frame = int(gdb.parse_and_eval(f"*(uint64_t*)({frame:#x})"))
|
||||||
|
except gdb.MemoryError:
|
||||||
|
return
|
||||||
|
|
||||||
|
if frame == 0 or ret == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class PrintBacktraceCommand(gdb.Command):
|
class PrintBacktraceCommand(gdb.Command):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("j6bt", gdb.COMMAND_DATA)
|
super().__init__("j6bt", gdb.COMMAND_DATA)
|
||||||
@@ -33,31 +65,477 @@ class PrintBacktraceCommand(gdb.Command):
|
|||||||
def invoke(self, arg, from_tty):
|
def invoke(self, arg, from_tty):
|
||||||
args = gdb.string_to_argv(arg)
|
args = gdb.string_to_argv(arg)
|
||||||
|
|
||||||
depth = 30
|
|
||||||
if len(args) > 0:
|
|
||||||
depth = int(args[0])
|
|
||||||
|
|
||||||
frame = "$rbp"
|
frame = "$rbp"
|
||||||
|
if len(args) > 0:
|
||||||
|
frame = args[0]
|
||||||
|
|
||||||
|
frame = int(gdb.parse_and_eval(f"{frame}"))
|
||||||
|
|
||||||
|
depth = 30
|
||||||
if len(args) > 1:
|
if len(args) > 1:
|
||||||
frame = args[1]
|
depth = int(gdb.parse_and_eval(args[1]))
|
||||||
|
|
||||||
for i in range(depth-1, -1, -1):
|
stack_walk(frame, depth)
|
||||||
ret = gdb.parse_and_eval(f"*(uint64_t*)({frame} + 8)")
|
|
||||||
frame = gdb.parse_and_eval(f"*(uint64_t*)({frame})")
|
|
||||||
|
|
||||||
name = ""
|
|
||||||
block = gdb.block_for_pc(int(ret))
|
|
||||||
if block:
|
|
||||||
name = block.function or ""
|
|
||||||
|
|
||||||
print("{:016x} {}".format(int(ret), name))
|
class TableWalkCommand(gdb.Command):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("j6tw", gdb.COMMAND_DATA)
|
||||||
|
|
||||||
if frame == 0 or ret == 0:
|
def invoke(self, arg, from_tty):
|
||||||
return
|
args = gdb.string_to_argv(arg)
|
||||||
|
if len(args) < 2:
|
||||||
|
raise Exception("Must be: j6tw <pml4> <addr>")
|
||||||
|
|
||||||
|
pml4 = int(gdb.parse_and_eval(args[0]))
|
||||||
|
addr = int(gdb.parse_and_eval(args[1]))
|
||||||
|
|
||||||
|
indices = [
|
||||||
|
(addr >> 39) & 0x1ff,
|
||||||
|
(addr >> 30) & 0x1ff,
|
||||||
|
(addr >> 21) & 0x1ff,
|
||||||
|
(addr >> 12) & 0x1ff,
|
||||||
|
]
|
||||||
|
|
||||||
|
names = ["PML4", "PDP", "PD", "PT"]
|
||||||
|
|
||||||
|
table_flags = [
|
||||||
|
(0x0001, "present"),
|
||||||
|
(0x0002, "write"),
|
||||||
|
(0x0004, "user"),
|
||||||
|
(0x0008, "pwt"),
|
||||||
|
(0x0010, "pcd"),
|
||||||
|
(0x0020, "accessed"),
|
||||||
|
(0x0040, "dirty"),
|
||||||
|
(0x0080, "largepage"),
|
||||||
|
(0x0100, "global"),
|
||||||
|
(0x1080, "pat"),
|
||||||
|
((1<<63), "xd"),
|
||||||
|
]
|
||||||
|
|
||||||
|
page_flags = [
|
||||||
|
(0x0001, "present"),
|
||||||
|
(0x0002, "write"),
|
||||||
|
(0x0004, "user"),
|
||||||
|
(0x0008, "pwt"),
|
||||||
|
(0x0010, "pcd"),
|
||||||
|
(0x0020, "accessed"),
|
||||||
|
(0x0040, "dirty"),
|
||||||
|
(0x0080, "pat"),
|
||||||
|
(0x0100, "global"),
|
||||||
|
((1<<63), "xd"),
|
||||||
|
]
|
||||||
|
|
||||||
|
flagsets = [table_flags, table_flags, table_flags, page_flags]
|
||||||
|
|
||||||
|
table = pml4
|
||||||
|
entry = 0
|
||||||
|
for i in range(len(indices)):
|
||||||
|
entry = int(gdb.parse_and_eval(f'((uint64_t*)0x{table:x})[0x{indices[i]:x}]'))
|
||||||
|
flagset = flagsets[i]
|
||||||
|
flag_names = " | ".join([f[1] for f in flagset if (entry & f[0]) == f[0]])
|
||||||
|
|
||||||
|
print(f"{names[i]:>4}: {table:016x}")
|
||||||
|
print(f" index: {indices[i]:3} {entry:016x}")
|
||||||
|
print(f" flags: {flag_names}")
|
||||||
|
|
||||||
|
if (entry & 1) == 0 or (i < 3 and (entry & 0x80)):
|
||||||
|
break
|
||||||
|
|
||||||
|
table = (entry & 0x7ffffffffffffe00) | 0xffffc00000000000
|
||||||
|
|
||||||
|
|
||||||
|
class GetThreadsCommand(gdb.Command):
|
||||||
|
FLAGS = {
|
||||||
|
"ready": 0x01,
|
||||||
|
"loading": 0x02,
|
||||||
|
"exited": 0x04,
|
||||||
|
"constant": 0x80,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("j6threads", gdb.COMMAND_DATA)
|
||||||
|
|
||||||
|
def get_flags(self, bitset):
|
||||||
|
flags = []
|
||||||
|
for k, v in GetThreadsCommand.FLAGS.items():
|
||||||
|
if bitset & v:
|
||||||
|
flags.append(k)
|
||||||
|
return " ".join(flags)
|
||||||
|
|
||||||
|
def print_thread(self, addr):
|
||||||
|
if addr == 0:
|
||||||
|
print(" <no thread>\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
tcb = f"((TCB*){addr:#x})"
|
||||||
|
thread = f"({tcb}->thread)"
|
||||||
|
stack = int(gdb.parse_and_eval(f"{tcb}->kernel_stack"))
|
||||||
|
rsp = int(gdb.parse_and_eval(f"{tcb}->rsp"))
|
||||||
|
pri = int(gdb.parse_and_eval(f"{tcb}->priority"))
|
||||||
|
flags = int(gdb.parse_and_eval(f"{thread}->m_state"))
|
||||||
|
koid = int(gdb.parse_and_eval(f"{thread}->m_obj_id"))
|
||||||
|
proc = int(gdb.parse_and_eval(f"{thread}->m_parent.m_obj_id"))
|
||||||
|
|
||||||
|
creator = int(gdb.parse_and_eval(f"{thread}->m_creator"))
|
||||||
|
if creator != 0:
|
||||||
|
creator_koid = int(gdb.parse_and_eval(f"{thread}->m_creator->m_obj_id"))
|
||||||
|
creator = f"{creator_koid:x}"
|
||||||
|
else:
|
||||||
|
creator = "<no thread>"
|
||||||
|
|
||||||
|
print(f" Thread {proc:x}:{koid:x}")
|
||||||
|
print(f" creator: {creator}")
|
||||||
|
print(f" priority: {pri}")
|
||||||
|
print(f" flags: {self.get_flags(flags)}")
|
||||||
|
print(f" kstack: {stack:#x}")
|
||||||
|
print(f" rsp: {rsp:#x}")
|
||||||
|
|
||||||
|
if stack == 0: return 0
|
||||||
|
return int(gdb.parse_and_eval(f"{tcb}->rsp"))
|
||||||
|
|
||||||
|
|
||||||
|
def print_thread_list(self, addr, name):
|
||||||
|
if addr == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"=== {name} ===")
|
||||||
|
|
||||||
|
while addr != 0:
|
||||||
|
rsp = self.print_thread(addr)
|
||||||
|
if rsp != 0:
|
||||||
|
print("------------------------------------")
|
||||||
|
stack_walk(rsp + 5*8, 5)
|
||||||
|
|
||||||
|
addr = int(gdb.parse_and_eval(f"((tcb_node*){addr:#x})->m_next"))
|
||||||
|
print()
|
||||||
|
|
||||||
|
def print_cpudata(self, index):
|
||||||
|
cpu = f"(g_cpu_data[{index}])"
|
||||||
|
tss = f"{cpu}->tss"
|
||||||
|
tss_rsp0 = int(gdb.parse_and_eval(f"{tss}->m_rsp[0]"))
|
||||||
|
tss_ist = [int(gdb.parse_and_eval(f"{tss}->m_ist[{i}]")) for i in range(8)]
|
||||||
|
print(f" tss rsp0: {tss_rsp0:#x}")
|
||||||
|
for i in range(1,8):
|
||||||
|
if tss_ist[i] == 0: continue
|
||||||
|
print(f" tss ist{i}: {tss_ist[i]:#x}")
|
||||||
|
|
||||||
|
def invoke(self, arg, from_tty):
|
||||||
|
args = gdb.string_to_argv(arg)
|
||||||
|
if len(args) > 1:
|
||||||
|
raise RuntimeError("Usage: j6threads [cpu]")
|
||||||
|
|
||||||
|
ncpus = int(gdb.parse_and_eval("g_num_cpus"))
|
||||||
|
cpus = list(range(ncpus))
|
||||||
|
if len(args) == 1:
|
||||||
|
cpus = [int(args[0])]
|
||||||
|
|
||||||
|
for cpu in cpus:
|
||||||
|
runlist = f"scheduler::s_instance->m_run_queues.m_elements[{cpu:#x}]"
|
||||||
|
|
||||||
|
print(f"=== CPU {cpu:2}: CURRENT ===")
|
||||||
|
current = int(gdb.parse_and_eval(f"{runlist}.current"))
|
||||||
|
self.print_thread(current)
|
||||||
|
self.print_cpudata(cpu)
|
||||||
|
|
||||||
|
previous = int(gdb.parse_and_eval(f"{runlist}.prev"))
|
||||||
|
print(f" prev: {previous:x}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
for pri in range(8):
|
||||||
|
ready = int(gdb.parse_and_eval(f"{runlist}.ready[{pri:#x}].m_head"))
|
||||||
|
self.print_thread_list(ready, f"CPU {cpu:2}: PRIORITY {pri}")
|
||||||
|
|
||||||
|
blocked = int(gdb.parse_and_eval(f"{runlist}.blocked.m_head"))
|
||||||
|
self.print_thread_list(blocked, f"CPU {cpu:2}: BLOCKED")
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
class PrintProfilesCommand(gdb.Command):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("j6prof", gdb.COMMAND_DATA)
|
||||||
|
|
||||||
|
def invoke(self, arg, from_tty):
|
||||||
|
args = gdb.string_to_argv(arg)
|
||||||
|
if len(args) != 1:
|
||||||
|
raise RuntimeError("Usage: j6prof <profiler class>")
|
||||||
|
|
||||||
|
profclass = args[0]
|
||||||
|
root_type = f"profile_class<{profclass}>"
|
||||||
|
|
||||||
|
try:
|
||||||
|
baseclass = gdb.lookup_type(root_type)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return
|
||||||
|
|
||||||
|
results = {}
|
||||||
|
max_len = 0
|
||||||
|
count = gdb.parse_and_eval(f"{profclass}::count")
|
||||||
|
for i in range(count):
|
||||||
|
name = gdb.parse_and_eval(f"{root_type}::function_names[{i:#x}]")
|
||||||
|
if name == 0: continue
|
||||||
|
|
||||||
|
call_counts = gdb.parse_and_eval(f"{root_type}::call_counts[{i:#x}]")
|
||||||
|
call_durations = gdb.parse_and_eval(f"{root_type}::call_durations[{i:#x}]")
|
||||||
|
results[name.string()] = float(call_durations) / float(call_counts)
|
||||||
|
max_len = max(max_len, len(name.string()))
|
||||||
|
|
||||||
|
for name, avg in results.items():
|
||||||
|
print(f"{name:>{max_len}}: {avg:15.3f}")
|
||||||
|
|
||||||
|
|
||||||
|
class DumpLogCommand(gdb.Command):
|
||||||
|
level_names = ["", "fatal", "error", "warn", "info", "verbose", "spam"]
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("j6log", gdb.COMMAND_DATA)
|
||||||
|
|
||||||
|
from memory import Layout
|
||||||
|
layout = Layout("definitions/memory_layout.yaml")
|
||||||
|
for region in layout.regions:
|
||||||
|
if region.name == "logs":
|
||||||
|
self.base_addr = region.start
|
||||||
|
break
|
||||||
|
|
||||||
|
self.areas = []
|
||||||
|
area_re = re.compile(r"LOG\(\s*(\w+).*")
|
||||||
|
with open("src/libraries/j6/include/j6/tables/log_areas.inc", 'r') as areas_inc:
|
||||||
|
for line in areas_inc:
|
||||||
|
m = area_re.match(line)
|
||||||
|
if m:
|
||||||
|
self.areas.append(m.group(1))
|
||||||
|
|
||||||
|
def get_entry(self, addr):
|
||||||
|
addr = int(addr)
|
||||||
|
size = int(gdb.parse_and_eval(f"((j6_log_entry*){addr:#x})->bytes"))
|
||||||
|
mlen = size - 8
|
||||||
|
|
||||||
|
return LogEntry(
|
||||||
|
int(gdb.parse_and_eval(f"((j6_log_entry*){addr:#x})->id")),
|
||||||
|
size,
|
||||||
|
int(gdb.parse_and_eval(f"((j6_log_entry*){addr:#x})->severity")),
|
||||||
|
int(gdb.parse_and_eval(f"((j6_log_entry*){addr:#x})->area")),
|
||||||
|
gdb.parse_and_eval(f"((j6_log_entry*){addr:#x})->message").string(length=mlen))
|
||||||
|
|
||||||
|
def invoke(self, arg, from_tty):
|
||||||
|
start = gdb.parse_and_eval("g_logger.m_start & (g_logger.m_buffer.count - 1)")
|
||||||
|
end = gdb.parse_and_eval("g_logger.m_end & (g_logger.m_buffer.count - 1)")
|
||||||
|
if end < start:
|
||||||
|
end += gdb.parse_and_eval("g_logger.m_buffer.count")
|
||||||
|
|
||||||
|
print(f"Logs are {start} -> {end}")
|
||||||
|
|
||||||
|
addr = self.base_addr + start
|
||||||
|
end += self.base_addr
|
||||||
|
while addr < end:
|
||||||
|
entry = self.get_entry(addr)
|
||||||
|
if entry.bytes < 8:
|
||||||
|
print(f"Bad log header size: {entry.bytes}")
|
||||||
|
break
|
||||||
|
addr += entry.bytes
|
||||||
|
area = "??"
|
||||||
|
if entry.area < len(self.areas):
|
||||||
|
area = self.areas[entry.area]
|
||||||
|
level = self.level_names[entry.severity]
|
||||||
|
print(f"{area:>7}:{level:7} {entry.message}")
|
||||||
|
|
||||||
|
|
||||||
|
class ShowCurrentProcessCommand(gdb.Command):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("j6current", gdb.COMMAND_DATA)
|
||||||
|
|
||||||
|
def invoke(self, arg, from_tty):
|
||||||
|
def get_obj_and_id(name):
|
||||||
|
obj = int(gdb.parse_and_eval(f"((cpu_data*)$gs_base)->{name}"))
|
||||||
|
oid = -1
|
||||||
|
if obj != 0:
|
||||||
|
oid = int(gdb.parse_and_eval(f"((obj::kobject*){obj:#x})->m_obj_id"))
|
||||||
|
return obj, oid
|
||||||
|
|
||||||
|
process, pid = get_obj_and_id("process")
|
||||||
|
thread, tid = get_obj_and_id("thread")
|
||||||
|
print(f"{pid:02x}/{tid:02x} [ {process:x} / {thread:x} ]")
|
||||||
|
|
||||||
|
|
||||||
|
class CapTablePrinter:
|
||||||
|
def __init__(self, val):
|
||||||
|
node_map = val["m_caps"]
|
||||||
|
self.nodes = node_map["m_nodes"]
|
||||||
|
self.count = int(node_map["m_count"])
|
||||||
|
self.capacity = int(node_map["m_capacity"])
|
||||||
|
|
||||||
|
class _iterator:
|
||||||
|
def __init__(self, nodes, capacity):
|
||||||
|
self.nodes = []
|
||||||
|
|
||||||
|
for i in range(capacity):
|
||||||
|
node = nodes[i]
|
||||||
|
|
||||||
|
node_id = int(node["id"])
|
||||||
|
if node_id == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.nodes.append(Capability(
|
||||||
|
id = node_id,
|
||||||
|
parent = int(node["parent"]),
|
||||||
|
refcount = int(node["holders"]),
|
||||||
|
caps = int(node["caps"]),
|
||||||
|
type = str(node["type"])[14:],
|
||||||
|
koid = node['object']['m_obj_id']))
|
||||||
|
|
||||||
|
self.nodes.sort(key=lambda n: n.id, reverse=True)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if not self.nodes:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
node = self.nodes.pop()
|
||||||
|
|
||||||
|
desc = f'p:{node.parent:016x} refs:{node.refcount:2} caps:{node.caps:04x} {node.type:14} {node.koid}'
|
||||||
|
return (f"{node.id:016x}", desc)
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
return f"Cap table with {self.count}/{self.capacity} nodes.\n"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
return self._iterator(self.nodes, self.capacity)
|
||||||
|
|
||||||
|
|
||||||
|
class VectorPrinter:
|
||||||
|
def __init__(self, vector):
|
||||||
|
self.name = vector.type.tag
|
||||||
|
self.count = vector["m_size"]
|
||||||
|
self.array = vector["m_elements"]
|
||||||
|
|
||||||
|
class _iterator:
|
||||||
|
def __init__(self, array, count, deref):
|
||||||
|
self.array = array
|
||||||
|
self.count = count
|
||||||
|
self.deref = deref
|
||||||
|
self.index = 0
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if self.index >= self.count:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
item = self.array[self.index]
|
||||||
|
if self.deref:
|
||||||
|
item = item.dereference()
|
||||||
|
|
||||||
|
result = (f"{self.index:3}", item)
|
||||||
|
self.index += 1
|
||||||
|
return result
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
return f"{self.name} [{self.count}]"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
deref = self.count > 0 and self.array[0].type.code == gdb.TYPE_CODE_PTR
|
||||||
|
return self._iterator(self.array, int(self.count), deref)
|
||||||
|
|
||||||
|
|
||||||
|
class HandleSetPrinter:
|
||||||
|
def __init__(self, nodeset):
|
||||||
|
self.node_map = nodeset['m_map']
|
||||||
|
self.count = self.node_map['m_count']
|
||||||
|
self.capacity = self.node_map['m_capacity']
|
||||||
|
|
||||||
|
class _iterator:
|
||||||
|
def __init__(self, nodes, capacity):
|
||||||
|
self.items = []
|
||||||
|
self.index = 0
|
||||||
|
for i in range(capacity):
|
||||||
|
item = nodes[i]
|
||||||
|
if int(item) != 0:
|
||||||
|
self.items.append(int(item))
|
||||||
|
self.items.sort()
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if self.index >= len(self.items):
|
||||||
|
raise StopIteration
|
||||||
|
result = (f"{self.index}", f"{self.items[self.index]:016x}")
|
||||||
|
self.index += 1
|
||||||
|
return result
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
return f"node_set[{self.count} / {self.capacity}]:"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
return self._iterator(self.node_map['m_nodes'], self.capacity)
|
||||||
|
|
||||||
|
|
||||||
|
class LinkedListPrinter:
|
||||||
|
def __init__(self, llist):
|
||||||
|
self.name = llist.type.tag
|
||||||
|
self.head = llist['m_head']
|
||||||
|
self.tail = llist['m_tail']
|
||||||
|
|
||||||
|
self.items = []
|
||||||
|
current = self.head
|
||||||
|
while current:
|
||||||
|
item = current.dereference()
|
||||||
|
self.items.append((str(len(self.items)), item))
|
||||||
|
current = item['m_next']
|
||||||
|
|
||||||
|
class _iterator:
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
return f"{self.name}[{len(self.items)}]"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
return self.items
|
||||||
|
|
||||||
|
|
||||||
|
class IsRunning(gdb.Function):
|
||||||
|
def __init__(self):
|
||||||
|
super(IsRunning, self).__init__("is_running")
|
||||||
|
|
||||||
|
def invoke(self):
|
||||||
|
inferior = gdb.selected_inferior()
|
||||||
|
return \
|
||||||
|
inferior is not None and \
|
||||||
|
inferior.is_valid() and \
|
||||||
|
len(inferior.threads()) > 0
|
||||||
|
|
||||||
|
|
||||||
|
def build_pretty_printers():
|
||||||
|
pp = gdb.printing.RegexpCollectionPrettyPrinter("jsix")
|
||||||
|
pp.add_printer("cap table", '^cap_table$', CapTablePrinter)
|
||||||
|
pp.add_printer("handle set", '^util::node_set<unsigned long, 0, heap_allocated>$', HandleSetPrinter)
|
||||||
|
pp.add_printer("vector", '^util::vector<.*>$', VectorPrinter)
|
||||||
|
pp.add_printer("linked list", '^util::linked_list<.*>$', LinkedListPrinter)
|
||||||
|
return pp
|
||||||
|
|
||||||
|
gdb.printing.register_pretty_printer(
|
||||||
|
gdb.current_objfile(),
|
||||||
|
build_pretty_printers())
|
||||||
|
|
||||||
PrintStackCommand()
|
PrintStackCommand()
|
||||||
PrintBacktraceCommand()
|
PrintBacktraceCommand()
|
||||||
|
TableWalkCommand()
|
||||||
|
GetThreadsCommand()
|
||||||
|
PrintProfilesCommand()
|
||||||
|
DumpLogCommand()
|
||||||
|
ShowCurrentProcessCommand()
|
||||||
|
IsRunning()
|
||||||
|
|
||||||
gdb.execute("target remote :1234")
|
|
||||||
gdb.execute("display/i $rip")
|
gdb.execute("display/i $rip")
|
||||||
|
gdb.execute("define hook-quit\nif $is_running()\n kill\nend\nend")
|
||||||
|
if not gdb.selected_inferior().was_attached:
|
||||||
|
gdb.execute("add-symbol-file build/panic.serial.elf")
|
||||||
|
gdb.execute("target remote :1234")
|
||||||
|
|||||||
Binary file not shown.
49
assets/grammars/definitions.g
Normal file
49
assets/grammars/definitions.g
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
start: import_statement* (object|interface)+
|
||||||
|
|
||||||
|
import_statement: "import" PATH
|
||||||
|
|
||||||
|
object: description? "object" name options? super? "{" uid cname? capabilities? method* "}"
|
||||||
|
|
||||||
|
interface: description? "interface" name options? "{" uid interface_param* "}"
|
||||||
|
|
||||||
|
?interface_param: expose | function
|
||||||
|
|
||||||
|
expose: "expose" type
|
||||||
|
|
||||||
|
uid: "uid" UID
|
||||||
|
|
||||||
|
cname: "cname" IDENTIFIER
|
||||||
|
|
||||||
|
capabilities: "capabilities" "[" IDENTIFIER+ "]"
|
||||||
|
|
||||||
|
super: ":" name
|
||||||
|
|
||||||
|
function: description? "function" name options? ("{" param* "}")?
|
||||||
|
|
||||||
|
method: description? "method" name options? ("{" param* "}")?
|
||||||
|
|
||||||
|
param: "param" name type options? description?
|
||||||
|
|
||||||
|
?type: PRIMITIVE | object_name | struct_name
|
||||||
|
|
||||||
|
object_name: "ref" name
|
||||||
|
|
||||||
|
struct_name: "struct" name
|
||||||
|
|
||||||
|
id: NUMBER
|
||||||
|
name: IDENTIFIER
|
||||||
|
options: "[" ( OPTION | IDENTIFIER )+ "]"
|
||||||
|
description: COMMENT+
|
||||||
|
|
||||||
|
PRIMITIVE: INT_TYPE "*"? | "size" | "string" | "buffer" | "address"
|
||||||
|
INT_TYPE: /u?int(8|16|32|64)?/
|
||||||
|
NUMBER: /(0x)?[0-9a-fA-F]+/
|
||||||
|
UID: /[0-9a-fA-F]{16}/
|
||||||
|
OPTION.2: IDENTIFIER ":" IDENTIFIER
|
||||||
|
COMMENT: /#.*/
|
||||||
|
PATH: /"[^"]*"/
|
||||||
|
|
||||||
|
%import common.LETTER
|
||||||
|
%import common.CNAME -> IDENTIFIER
|
||||||
|
%import common.WS
|
||||||
|
%ignore WS
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# This is the manifest for the initial ramdisk, read by the `makerd` tool.
|
|
||||||
# The contents should be a table array of files to add to the ramdistk:
|
|
||||||
#
|
|
||||||
# [[files]]
|
|
||||||
# dest = "foo.bar" # Name of the file in the ramdisk
|
|
||||||
# source = "build/foo/foo.bar" # Location of the file from the project root
|
|
||||||
# executable = true # Optional, default false. Whether this is an
|
|
||||||
# # initial application for the kernel to execute
|
|
||||||
# # on startup
|
|
||||||
|
|
||||||
[[files]]
|
|
||||||
dest = "screenfont.psf"
|
|
||||||
source = "../assets/fonts/tamsyn8x16r.psf"
|
|
||||||
|
|
||||||
[[files]]
|
|
||||||
dest = "symbol_table.dat"
|
|
||||||
source = "symbol_table.dat"
|
|
||||||
symbols = true
|
|
||||||
|
|
||||||
[[files]]
|
|
||||||
dest = "nulldrv1"
|
|
||||||
source = "user/nulldrv"
|
|
||||||
executable = true
|
|
||||||
|
|
||||||
[[files]]
|
|
||||||
dest = "nulldrv2"
|
|
||||||
source = "user/nulldrv"
|
|
||||||
executable = true
|
|
||||||
1
assets/jsix.svg
Executable file
1
assets/jsix.svg
Executable file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="176.562 356.069 211.11 113" width="211.11pt" height="113pt"><g><g><rect x="176.562" y="356.069" width="211.11" height="113" transform="matrix(1,0,0,1,0,0)" fill="rgb(255,255,255)"/><g><path d=" M 212.981 372.36 L 219.564 376.16 L 226.147 379.961 L 226.147 387.563 L 226.147 395.164 L 219.564 398.965 L 212.981 402.766 L 206.398 398.965 L 199.815 395.164 L 199.815 387.563 L 199.815 379.961 L 206.398 376.16 L 212.981 372.36 L 212.981 372.36 L 212.981 372.36 Z M 256.292 397.366 L 262.875 401.166 L 269.458 404.967 L 269.458 412.569 L 269.458 420.17 L 262.875 423.971 L 256.292 427.772 L 249.709 423.971 L 243.126 420.17 L 243.126 412.569 L 243.126 404.967 L 249.709 401.166 L 256.292 397.366 L 256.292 397.366 Z M 183.622 387.283 L 205.52 374.64 L 227.418 361.997 L 249.316 374.64 L 271.214 387.283 L 271.214 412.569 L 271.214 437.854 L 249.316 450.497 L 227.418 463.14 L 205.52 450.497 L 183.622 437.854 L 183.622 412.569 L 183.622 387.283 L 183.622 387.283 L 183.622 387.283 Z M 241.855 372.36 L 248.438 376.16 L 255.021 379.961 L 255.021 387.563 L 255.021 395.164 L 248.438 398.965 L 241.855 402.766 L 235.272 398.965 L 228.689 395.164 L 228.689 387.563 L 228.689 379.961 L 235.272 376.16 L 241.855 372.36 Z " fill-rule="evenodd" fill="rgb(49,79,128)"/><path d=" M 298.642 379.579 L 291.621 379.579 L 291.621 372.558 L 298.642 372.558 L 298.642 379.579 Z M 285.214 446.718 L 285.214 441.452 L 287.32 441.452 L 287.32 441.452 Q 289.339 441.452 290.524 440.092 L 290.524 440.092 L 290.524 440.092 Q 291.708 438.731 291.708 436.625 L 291.708 436.625 L 291.708 387.039 L 298.729 387.039 L 298.729 436.011 L 298.729 436.011 Q 298.729 440.925 295.921 443.822 L 295.921 443.822 L 295.921 443.822 Q 293.113 446.718 288.286 446.718 L 288.286 446.718 L 285.214 446.718 Z M 306.628 432.676 L 306.628 427.41 L 314.088 427.41 L 314.088 427.41 Q 317.862 427.41 319.573 425.347 L 319.573 425.347 L 319.573 425.347 Q 321.285 423.285 321.285 419.95 L 321.285 419.95 L 321.285 419.95 Q 321.285 417.317 319.705 415.474 L 319.705 415.474 L 319.705 415.474 Q 318.125 413.631 314.966 411.174 L 314.966 411.174 L 314.966 411.174 Q 312.245 408.98 310.621 407.356 L 310.621 407.356 L 310.621 407.356 Q 308.998 405.732 307.813 403.319 L 307.813 403.319 L 307.813 403.319 Q 306.628 400.905 306.628 397.746 L 306.628 397.746 L 306.628 397.746 Q 306.628 393.095 309.744 390.067 L 309.744 390.067 L 309.744 390.067 Q 312.859 387.039 318.125 387.039 L 318.125 387.039 L 325.76 387.039 L 325.76 392.305 L 319.441 392.305 L 319.441 392.305 Q 313.21 392.305 313.21 398.185 L 313.21 398.185 L 313.21 398.185 Q 313.21 400.467 314.615 402.134 L 314.615 402.134 L 314.615 402.134 Q 316.019 403.802 319.003 406.083 L 319.003 406.083 L 319.003 406.083 Q 321.723 408.19 323.479 409.901 L 323.479 409.901 L 323.479 409.901 Q 325.234 411.613 326.463 414.202 L 326.463 414.202 L 326.463 414.202 Q 327.691 416.791 327.691 420.301 L 327.691 420.301 L 327.691 420.301 Q 327.691 426.532 324.4 429.604 L 324.4 429.604 L 324.4 429.604 Q 321.109 432.676 315.141 432.676 L 315.141 432.676 L 306.628 432.676 Z M 342.611 379.579 L 335.59 379.579 L 335.59 372.558 L 342.611 372.558 L 342.611 379.579 Z M 342.611 432.676 L 335.59 432.676 L 335.59 387.039 L 342.611 387.039 L 342.611 432.676 Z M 356.126 432.676 L 348.754 432.676 L 361.392 409.77 L 349.632 387.039 L 356.39 387.039 L 364.639 403.187 L 372.977 387.039 L 379.735 387.039 L 367.974 409.77 L 380.612 432.676 L 373.24 432.676 L 364.639 416.001 L 356.126 432.676 Z " fill="rgb(49,79,128)"/></g></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 3.6 KiB |
16
assets/manifests/default.yaml
Normal file
16
assets/manifests/default.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
location: jsix
|
||||||
|
init: srv.init
|
||||||
|
initrd:
|
||||||
|
name: initrd.dat
|
||||||
|
format: zstd
|
||||||
|
panic:
|
||||||
|
- panic.serial
|
||||||
|
services:
|
||||||
|
- srv.logger
|
||||||
|
- testapp
|
||||||
|
drivers:
|
||||||
|
- drv.uart
|
||||||
|
- drv.uefi_fb
|
||||||
|
libs:
|
||||||
|
- ld.so
|
||||||
14
assets/manifests/minimal.yaml
Normal file
14
assets/manifests/minimal.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
location: jsix
|
||||||
|
init: srv.init
|
||||||
|
initrd:
|
||||||
|
name: initrd.dat
|
||||||
|
format: zstd
|
||||||
|
panic:
|
||||||
|
- panic.serial
|
||||||
|
services:
|
||||||
|
- srv.logger
|
||||||
|
drivers:
|
||||||
|
- drv.uart
|
||||||
|
libs:
|
||||||
|
- ld.so
|
||||||
14
assets/manifests/shell.yaml
Normal file
14
assets/manifests/shell.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
location: jsix
|
||||||
|
init: srv.init
|
||||||
|
initrd:
|
||||||
|
name: initrd.dat
|
||||||
|
format: zstd
|
||||||
|
panic:
|
||||||
|
- panic.serial
|
||||||
|
services:
|
||||||
|
- 6s
|
||||||
|
drivers:
|
||||||
|
- drv.uart
|
||||||
|
libs:
|
||||||
|
- ld.so
|
||||||
11
assets/manifests/test.yaml
Normal file
11
assets/manifests/test.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
location: jsix
|
||||||
|
init: srv.init
|
||||||
|
initrd:
|
||||||
|
name: initrd.dat
|
||||||
|
format: zstd
|
||||||
|
flags: ["test"]
|
||||||
|
panic:
|
||||||
|
- panic.serial
|
||||||
|
services:
|
||||||
|
- test_runner
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
82
configure
vendored
Executable file
82
configure
vendored
Executable file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
def generate(output, config, arch, manifest):
|
||||||
|
from os import makedirs
|
||||||
|
from glob import iglob
|
||||||
|
from pathlib import Path
|
||||||
|
from bonnibel.module import Module, ModuleList
|
||||||
|
from bonnibel.project import Project
|
||||||
|
|
||||||
|
root = Path(__file__).parent.resolve()
|
||||||
|
project = Project(root)
|
||||||
|
|
||||||
|
output = root / output
|
||||||
|
manifest = root / manifest
|
||||||
|
|
||||||
|
sources = [
|
||||||
|
str(root / "src/**/*.module"),
|
||||||
|
str(root / "external/*.module"),
|
||||||
|
]
|
||||||
|
|
||||||
|
modules = ModuleList(arch)
|
||||||
|
for source in sources:
|
||||||
|
for modfile in iglob(source, recursive=True):
|
||||||
|
modfile = Path(modfile)
|
||||||
|
path = modfile.parent
|
||||||
|
|
||||||
|
def module_init(name, **kwargs):
|
||||||
|
if not "root" in kwargs:
|
||||||
|
kwargs["root"] = path
|
||||||
|
m = Module(name, modfile, **kwargs)
|
||||||
|
modules.add(m)
|
||||||
|
return m
|
||||||
|
|
||||||
|
glo = {
|
||||||
|
"module": module_init,
|
||||||
|
"source_root": root,
|
||||||
|
"build_root": output,
|
||||||
|
"module_root": path,
|
||||||
|
"config": config,
|
||||||
|
"arch": arch,
|
||||||
|
}
|
||||||
|
code = compile(open(modfile, 'r').read(), modfile, "exec")
|
||||||
|
|
||||||
|
loc = {}
|
||||||
|
exec(code, glo, loc)
|
||||||
|
|
||||||
|
makedirs(output.resolve(), exist_ok=True)
|
||||||
|
project.generate(root, output, modules, config, arch, manifest)
|
||||||
|
modules.generate(output)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent / "scripts"))
|
||||||
|
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
from bonnibel import BonnibelError
|
||||||
|
|
||||||
|
default_arch = "amd64"
|
||||||
|
|
||||||
|
p = ArgumentParser(description="Generate jsix build files")
|
||||||
|
p.add_argument("--manifest", "-m", metavar="FILE", default="assets/manifests/default.yaml",
|
||||||
|
help="File to use as the system manifest")
|
||||||
|
p.add_argument("--conf", "-c", metavar="NAME", default="debug",
|
||||||
|
help="Configuration to build (eg, 'debug' or 'release')")
|
||||||
|
p.add_argument("--arch", "-a", metavar="NAME", default=default_arch,
|
||||||
|
help="Architecture to build (eg, 'amd64' or 'linux')")
|
||||||
|
p.add_argument("--verbose", "-v", action='count', default=0,
|
||||||
|
help="More verbose log output")
|
||||||
|
p.add_argument("output", metavar="DIR", default=None, nargs='?',
|
||||||
|
help="Where to create the build root")
|
||||||
|
|
||||||
|
args = p.parse_args()
|
||||||
|
|
||||||
|
output = args.output or f"build.{args.arch}"
|
||||||
|
try:
|
||||||
|
generate(output, args.conf, args.arch, args.manifest)
|
||||||
|
|
||||||
|
except BonnibelError as be:
|
||||||
|
import sys
|
||||||
|
print(f"Error: {be}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
38
definitions/memory_layout.yaml
Normal file
38
definitions/memory_layout.yaml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
- name: linear
|
||||||
|
desc: Linearly-mapped physical memory
|
||||||
|
size: 64T
|
||||||
|
shared: true
|
||||||
|
|
||||||
|
- name: bitmap
|
||||||
|
desc: Used/free page tracking bitmap
|
||||||
|
size: 1T
|
||||||
|
shared: true
|
||||||
|
|
||||||
|
- name: heapmap
|
||||||
|
desc: Kernel heap accounting structures
|
||||||
|
size: 32G
|
||||||
|
|
||||||
|
- name: heap
|
||||||
|
desc: Kernel heap
|
||||||
|
size: 32G
|
||||||
|
|
||||||
|
- name: capsmap
|
||||||
|
desc: Capabilities accounting structures
|
||||||
|
size: 32G
|
||||||
|
|
||||||
|
- name: caps
|
||||||
|
desc: Capabilities
|
||||||
|
size: 32G
|
||||||
|
|
||||||
|
- name: stacks
|
||||||
|
desc: Kernel thread stacks
|
||||||
|
size: 64G
|
||||||
|
|
||||||
|
- name: buffers
|
||||||
|
desc: Kernel buffers
|
||||||
|
size: 64G
|
||||||
|
|
||||||
|
- name: logs
|
||||||
|
desc: Kernel logs circular buffer
|
||||||
|
size: 2G
|
||||||
25
definitions/objects/event.def
Normal file
25
definitions/objects/event.def
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# An ``event`` is a simple synchronization object. It contains up to 64 signals
|
||||||
|
# that threads can wait for and signal in parallel.
|
||||||
|
|
||||||
|
object event : object {
|
||||||
|
uid f441e03da5516b1a
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
signal
|
||||||
|
wait
|
||||||
|
]
|
||||||
|
|
||||||
|
method create [constructor]
|
||||||
|
|
||||||
|
# Signal events on this object
|
||||||
|
method signal [cap:signal] {
|
||||||
|
param signals uint64 # A bitset of which events to signal
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait for signaled events on this object
|
||||||
|
method wait [cap:wait] {
|
||||||
|
param signals uint64 [out] # A bitset of which events were signaled
|
||||||
|
param timeout uint64 # Wait timeout in nanoseconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
41
definitions/objects/mailbox.def
Normal file
41
definitions/objects/mailbox.def
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Mailboxes are objects that enable synchronous IPC via arbitrary
|
||||||
|
# message-passing of tagged data and/or handles. Not as efficient
|
||||||
|
# as shared memory channels, but more flexible.
|
||||||
|
|
||||||
|
object mailbox : object {
|
||||||
|
uid 99934ad04ece1e07
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
send
|
||||||
|
receive
|
||||||
|
close
|
||||||
|
]
|
||||||
|
|
||||||
|
method create [constructor]
|
||||||
|
method close [destructor cap:close]
|
||||||
|
|
||||||
|
# Send a message to the reciever, and block until a response is
|
||||||
|
# sent. Note that getting this response does not require the
|
||||||
|
# receive capability.
|
||||||
|
method call [cap:send] {
|
||||||
|
param tag uint64 [inout]
|
||||||
|
param data buffer [optional inout]
|
||||||
|
param data_size size # number of total bytes in data buffer
|
||||||
|
param handles ref object [optional inout handle list]
|
||||||
|
param handles_size size # total size of handles buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
# Respond to a message sent using call, and wait for another
|
||||||
|
# message to arrive. Note that this does not require the send
|
||||||
|
# capability. A reply tag of 0 skips the reply and goes directly
|
||||||
|
# to waiting for a new message.
|
||||||
|
method respond [cap:receive] {
|
||||||
|
param tag uint64 [inout]
|
||||||
|
param data buffer [optional inout]
|
||||||
|
param data_size size # number of total bytes in data buffer
|
||||||
|
param handles ref object [optional inout handle list]
|
||||||
|
param handles_size size # total size of handles buffer
|
||||||
|
param reply_tag uint64 [inout]
|
||||||
|
param flags uint64
|
||||||
|
}
|
||||||
|
}
|
||||||
16
definitions/objects/object.def
Normal file
16
definitions/objects/object.def
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# All kernel-exposed objects inherit from the base ``object`` type, so the
|
||||||
|
# ``object`` syscalls can be used with any object's handle.
|
||||||
|
|
||||||
|
object object [virtual] {
|
||||||
|
uid 667f61fb2cd57bb4
|
||||||
|
cname kobject
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
clone
|
||||||
|
]
|
||||||
|
|
||||||
|
# Get the internal kernel object id of an object
|
||||||
|
method koid {
|
||||||
|
param koid uint64 [out]
|
||||||
|
}
|
||||||
|
}
|
||||||
32
definitions/objects/process.def
Normal file
32
definitions/objects/process.def
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import "objects/object.def"
|
||||||
|
|
||||||
|
# A ``process`` object represents a process running on the system, and allows
|
||||||
|
# control over the threads, handles, and virtual memory space of that process.
|
||||||
|
|
||||||
|
object process : object {
|
||||||
|
uid 0c69ee0b7502ba31
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
kill
|
||||||
|
create_thread
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create a new empty process
|
||||||
|
method create [constructor] {
|
||||||
|
param name string
|
||||||
|
}
|
||||||
|
|
||||||
|
# Stop all threads and exit the given process
|
||||||
|
method kill [destructor cap:kill]
|
||||||
|
|
||||||
|
# Stop all threads and exit the current process
|
||||||
|
method exit [static noreturn] {
|
||||||
|
param result int64 # The result to retrun to the parent process
|
||||||
|
}
|
||||||
|
|
||||||
|
# Give the given process a handle that points to the same
|
||||||
|
# object as the specified handle.
|
||||||
|
method give_handle {
|
||||||
|
param target ref object [handle] # A handle in the caller process to send
|
||||||
|
}
|
||||||
|
}
|
||||||
42
definitions/objects/system.def
Normal file
42
definitions/objects/system.def
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# The singular ``system`` object represents a handle to kernel functionality
|
||||||
|
# needed by drivers and other priviledged services.
|
||||||
|
|
||||||
|
object system : object {
|
||||||
|
uid fa72506a2cf71a30
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
get_log
|
||||||
|
bind_irq
|
||||||
|
map_phys
|
||||||
|
change_iopl
|
||||||
|
]
|
||||||
|
|
||||||
|
# Get the next log line from the kernel log
|
||||||
|
method get_log [cap:get_log] {
|
||||||
|
param seen uint64 # Last seen log id
|
||||||
|
param buffer buffer [out zero_ok] # Buffer for the log message data structure
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ask the kernel to send this process messages whenever
|
||||||
|
# the given IRQ fires
|
||||||
|
method bind_irq [cap:bind_irq] {
|
||||||
|
param dest ref event # Event object that will receive messages
|
||||||
|
param irq uint # IRQ number to bind
|
||||||
|
param signal uint # Signal number on the event to bind to
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a VMA and map an area of physical memory into it,
|
||||||
|
# also mapping that VMA into the current process
|
||||||
|
method map_phys [cap:map_phys] {
|
||||||
|
param area ref vma [out] # Receives a handle to the VMA created
|
||||||
|
param phys address # The physical address of the area
|
||||||
|
param size size # Size of the area, in bytes
|
||||||
|
param flags uint32 # Flags to apply to the created VMA
|
||||||
|
}
|
||||||
|
|
||||||
|
# Request the kernel change the IOPL for this process. The only values
|
||||||
|
# that make sense are 0 and 3.
|
||||||
|
method request_iopl [cap:change_iopl] {
|
||||||
|
param iopl uint # The IOPL to set for this process
|
||||||
|
}
|
||||||
|
}
|
||||||
30
definitions/objects/thread.def
Normal file
30
definitions/objects/thread.def
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# A ``thread`` object represents a thread of execution within a process running
|
||||||
|
# on the system. The actual thread does not need to be currently running to
|
||||||
|
# hold a handle to it.
|
||||||
|
|
||||||
|
object thread : object {
|
||||||
|
uid 11f23e593d5761bd
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
kill
|
||||||
|
join
|
||||||
|
]
|
||||||
|
|
||||||
|
method create [constructor] {
|
||||||
|
param process ref process [optional cap:create_thread]
|
||||||
|
param stack_top address
|
||||||
|
param entrypoint address
|
||||||
|
param arg0 uint64
|
||||||
|
param arg1 uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
method kill [destructor cap:kill]
|
||||||
|
|
||||||
|
method join [cap:join]
|
||||||
|
|
||||||
|
method exit [static]
|
||||||
|
|
||||||
|
method sleep [static] {
|
||||||
|
param duration uint64
|
||||||
|
}
|
||||||
|
}
|
||||||
41
definitions/objects/vma.def
Normal file
41
definitions/objects/vma.def
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import "objects/process.def"
|
||||||
|
|
||||||
|
# A ``vma`` object represents a single virtual memory area, which may be shared
|
||||||
|
# between several processes. A process having a handle to a ``vma`` does not
|
||||||
|
# necessarily mean that it is mapped into that process' virtual memory space.
|
||||||
|
|
||||||
|
object vma : object {
|
||||||
|
uid d6a12b63b3ed3937
|
||||||
|
cname vm_area
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
map
|
||||||
|
unmap
|
||||||
|
resize
|
||||||
|
]
|
||||||
|
|
||||||
|
method create [constructor] {
|
||||||
|
param size size
|
||||||
|
param flags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
method create_map [constructor cap:map] {
|
||||||
|
param size size
|
||||||
|
param address address [inout]
|
||||||
|
param flags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
method map [cap:map] {
|
||||||
|
param process ref process [optional]
|
||||||
|
param address address [inout]
|
||||||
|
param flags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
method unmap [cap:unmap] {
|
||||||
|
param process ref process [optional]
|
||||||
|
}
|
||||||
|
|
||||||
|
method resize [cap:resize] {
|
||||||
|
param size size [inout] # New size for the VMA, or 0 to query the current size without changing
|
||||||
|
}
|
||||||
|
}
|
||||||
69
definitions/syscalls.def
Normal file
69
definitions/syscalls.def
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import "objects/object.def"
|
||||||
|
|
||||||
|
import "objects/event.def"
|
||||||
|
import "objects/mailbox.def"
|
||||||
|
import "objects/process.def"
|
||||||
|
import "objects/system.def"
|
||||||
|
import "objects/thread.def"
|
||||||
|
import "objects/vma.def"
|
||||||
|
|
||||||
|
interface syscalls [syscall] {
|
||||||
|
uid 01d9b6a948961097
|
||||||
|
|
||||||
|
expose ref object
|
||||||
|
|
||||||
|
expose ref event
|
||||||
|
expose ref mailbox
|
||||||
|
expose ref process
|
||||||
|
expose ref system
|
||||||
|
expose ref thread
|
||||||
|
expose ref vma
|
||||||
|
|
||||||
|
# Simple no-op syscall for testing
|
||||||
|
function noop
|
||||||
|
|
||||||
|
# Write a message to the kernel log
|
||||||
|
function log {
|
||||||
|
param area uint8
|
||||||
|
param severity uint8
|
||||||
|
param message string
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get a list of handles owned by this process. If the
|
||||||
|
# supplied list is not big enough, will set the size
|
||||||
|
# needed in `size` and return j6_err_insufficient
|
||||||
|
function handle_list {
|
||||||
|
param handles struct handle_descriptor [list inout zero_ok] # A list of handles to be filled
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a clone of an existing handle, possibly with
|
||||||
|
# some capabilities masked out.
|
||||||
|
function handle_clone {
|
||||||
|
param orig ref object [handle cap:clone] # The handle to clone
|
||||||
|
param clone ref object [out] # The new handle
|
||||||
|
param mask uint32 # The capability bitmask
|
||||||
|
}
|
||||||
|
|
||||||
|
# Close the handle to an object
|
||||||
|
function handle_close {
|
||||||
|
param hnd ref object [handle] # The handle to close
|
||||||
|
}
|
||||||
|
|
||||||
|
# Block waiting on a futex
|
||||||
|
function futex_wait [static] {
|
||||||
|
param address uint32* # Address of the futex value
|
||||||
|
param current uint32 # Current value of the futex
|
||||||
|
param timeout uint64 # Wait timeout in nanoseconds
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wake threads waiting on a futex
|
||||||
|
function futex_wake [static] {
|
||||||
|
param address uint32* # Address of the futex value
|
||||||
|
param count uint64 # Number of threads to wake, or 0 for all
|
||||||
|
}
|
||||||
|
|
||||||
|
# Testing mode only: Have the kernel finish and exit QEMU with the given exit code
|
||||||
|
function test_finish [test] {
|
||||||
|
param exit_code uint32
|
||||||
|
}
|
||||||
|
}
|
||||||
34
definitions/sysconf.yaml
Normal file
34
definitions/sysconf.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
address: 0x6a360000
|
||||||
|
vars:
|
||||||
|
- name: version_major
|
||||||
|
section: kernel
|
||||||
|
type: uint8_t
|
||||||
|
|
||||||
|
- name: version_minor
|
||||||
|
section: kernel
|
||||||
|
type: uint8_t
|
||||||
|
|
||||||
|
- name: version_patch
|
||||||
|
section: kernel
|
||||||
|
type: uint16_t
|
||||||
|
|
||||||
|
- name: version_gitsha
|
||||||
|
section: kernel
|
||||||
|
type: uint32_t
|
||||||
|
|
||||||
|
- name: page_size
|
||||||
|
section: sys
|
||||||
|
type: size_t
|
||||||
|
|
||||||
|
- name: large_page_size
|
||||||
|
section: sys
|
||||||
|
type: size_t
|
||||||
|
|
||||||
|
- name: huge_page_size
|
||||||
|
section: sys
|
||||||
|
type: size_t
|
||||||
|
|
||||||
|
- name: num_cpus
|
||||||
|
section: sys
|
||||||
|
type: uint32_t
|
||||||
23
docs/Makefile
Normal file
23
docs/Makefile
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Minimal makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line, and also
|
||||||
|
# from the environment for the first two.
|
||||||
|
SPHINXOPTS ?=
|
||||||
|
SPHINXBUILD ?= sphinx-build
|
||||||
|
SOURCEDIR = .
|
||||||
|
BUILDDIR = _build
|
||||||
|
ROOTDIR = $(SOURCEDIR)/..
|
||||||
|
|
||||||
|
# Put it first so that "make" without argument is like "make help".
|
||||||
|
help:
|
||||||
|
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
|
|
||||||
|
.PHONY: help Makefile
|
||||||
|
|
||||||
|
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||||
|
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||||
|
%: Makefile
|
||||||
|
PYTHONPATH=$(ROOTDIR)/scripts cog -r -D definitions_path=$(ROOTDIR)/definitions -c syscall_interface.rst
|
||||||
|
PYTHONPATH=$(ROOTDIR)/scripts cog -r -D definitions_path=$(ROOTDIR)/definitions -c kernel_memory.rst
|
||||||
|
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
254
docs/_static/custom.css
vendored
Normal file
254
docs/_static/custom.css
vendored
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
/* custom.css - jsix version */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--background-color: #181820;
|
||||||
|
--link-color: #7070e0;
|
||||||
|
--link-hover-color: #9090ff;
|
||||||
|
--text-color: #3d3d3d;
|
||||||
|
--text-literal-color: #d26a98;
|
||||||
|
}
|
||||||
|
.wy-nav-side {
|
||||||
|
background: var(--background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 1100px) {
|
||||||
|
.wy-nav-content-wrap {
|
||||||
|
background: var(--background-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: var(--link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color: var(--link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rst-content {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rst-content code.literal {
|
||||||
|
color: var(--text-literal-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rst-content tt.literal {
|
||||||
|
color: var(--text-literal-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rst-content .note {
|
||||||
|
color: #003274;
|
||||||
|
background: #ccddf3;
|
||||||
|
padding: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rst-content .note .admonition-title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rst-content .warning {
|
||||||
|
color: #605000;
|
||||||
|
background: #fcf4cc;
|
||||||
|
padding: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rst-content .warning .admonition-title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rst-content .highlight {
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-side-scroll {
|
||||||
|
background-color: var(--background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-side-nav-search {
|
||||||
|
background-color: var(--background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-side-nav-search input[type="text"] {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 0px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-color: var(--background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical a {
|
||||||
|
font-size: 100%;
|
||||||
|
color: #d9d9d9;
|
||||||
|
padding-top: 0.6rem;
|
||||||
|
padding-bottom: 0.6rem;
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical a:hover {
|
||||||
|
background-color: unset;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.current > a {
|
||||||
|
background-color: var(--background-color);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.current > a span.toctree-expand {
|
||||||
|
display: block;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.current > a span.toctree-expand:before {
|
||||||
|
display: block;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.current > a span.toctree-expand:hover {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.current > a:hover {
|
||||||
|
background-color: var(--background-color);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.current > a:hover span.toctree-expand {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical .toctree-l1 {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical .toctree-l1:hover {
|
||||||
|
opacity: 1;
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l1.current {
|
||||||
|
opacity: 1;
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l1.current > a {
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical .toctree-l2:hover {
|
||||||
|
background-color: #566673;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2.current > a {
|
||||||
|
background-color: #566673;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2.current li.toctree-l3 > a {
|
||||||
|
background-color: #e4e7ea;
|
||||||
|
color: #838383;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2.current li.toctree-l3 > a:hover {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2.current li.toctree-l3 > a:hover span.toctree-expand {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2.current li.toctree-l3.current > a {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2 a {
|
||||||
|
border: 0px;
|
||||||
|
background-color: #566673;
|
||||||
|
color: #d9d9d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2 a span.toctree-expand {
|
||||||
|
display: block;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2 a span.toctree-expand:before {
|
||||||
|
display: block;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2 a span.toctree-expand:hover {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2 a:hover {
|
||||||
|
color: white;
|
||||||
|
background-color: #566673;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l3.current > a {
|
||||||
|
background-color: #e4e7ea;
|
||||||
|
color: #838383;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l3.current li.toctree-l4 > a {
|
||||||
|
background-color: #e4e7ea;
|
||||||
|
color: #838383;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-menu-vertical li.toctree-l3.current li.toctree-l4.current > a {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-nav-top {
|
||||||
|
background-color: var(--background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--text-color);
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
padding: 0.375rem 0.75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
border-radius: 0;
|
||||||
|
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||||
|
box-shadow: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-neutral {
|
||||||
|
background: unset !important;
|
||||||
|
color: #838383 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-neutral:active {
|
||||||
|
padding: 0.375rem 0.75rem;
|
||||||
|
box-shadow: unset;
|
||||||
|
}
|
||||||
50
docs/conf.py
Normal file
50
docs/conf.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# For the full list of built-in configuration values, see the documentation:
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
|
# -- Project information -----------------------------------------------------
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||||
|
|
||||||
|
project = 'jsix'
|
||||||
|
copyright = '2024, Justin C. Miller'
|
||||||
|
author = 'Justin C. Miller'
|
||||||
|
release = '0.8'
|
||||||
|
|
||||||
|
# -- General configuration ---------------------------------------------------
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||||
|
|
||||||
|
extensions = ['sphinx.ext.todo']
|
||||||
|
primary_domain = 'cpp'
|
||||||
|
todo_include_todos = True
|
||||||
|
|
||||||
|
templates_path = ['_templates']
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||||
|
|
||||||
|
html_theme = 'renku'
|
||||||
|
html_title = 'jsix'
|
||||||
|
html_logo = 'jsix_transparent.svg'
|
||||||
|
html_static_path = ['_static']
|
||||||
|
html_css_files = ['custom.css']
|
||||||
|
html_theme_options = {
|
||||||
|
"description": "The jsix description",
|
||||||
|
"github_repo": "https://github.com/justinian/jsix",
|
||||||
|
"logo_only": True,
|
||||||
|
"footer_icons": [
|
||||||
|
{
|
||||||
|
"name": "GitHub",
|
||||||
|
"url": "https://github.com/justinian/jsix",
|
||||||
|
"html": """
|
||||||
|
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path>
|
||||||
|
</svg>
|
||||||
|
""",
|
||||||
|
"class": "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
81
docs/index.rst
Normal file
81
docs/index.rst
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
.. jsix documentation master file
|
||||||
|
.. |amd64| replace:: :abbr:`amd64 (aka x86_64)`
|
||||||
|
|
||||||
|
The jsix Operating System
|
||||||
|
=========================
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
**jsix** is a custom multi-core x64 operating system being built from scratch,
|
||||||
|
supporting modern [#]_ Intel or AMD CPUs, and UEFI firmware. It was initially
|
||||||
|
created out of a desire to explore UEFI and to explore what's possible with a
|
||||||
|
microkernel architecture on modern 64-bit architectures.
|
||||||
|
|
||||||
|
Most of jsix is written in C++ (C++17, using `LLVM <https://llvm.org>`_), but
|
||||||
|
you'll also find some assembly (in `NASM <https://nasm.us>`_ syntax) and Python
|
||||||
|
for development tooling.
|
||||||
|
|
||||||
|
jsix can be found `on GitHub <https://github.com/justinian/jsix>`_, and is
|
||||||
|
released under the terms of the `MPL 2.0 <https://mozilla.org/MPL/2.0/>`_.
|
||||||
|
|
||||||
|
.. admonition:: A note on the name
|
||||||
|
|
||||||
|
This kernel was originally named Popcorn, but I have since discovered that
|
||||||
|
the Popcorn Linux project is also developing a kernel with that name,
|
||||||
|
started around the same time as this project. So I've renamed this kernel
|
||||||
|
jsix as an homage to L4, xv6, and my wonderful wife.
|
||||||
|
|
||||||
|
The name jsix is always styled *jsix* or ``j6``, never capitalized.
|
||||||
|
|
||||||
|
.. [#] jsix aims to support amd64 (x86_64) CPUs released in the last 10 years.
|
||||||
|
|
||||||
|
Current Features
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The jsix kernel is quite far along now, but the userland systems are still lacking.
|
||||||
|
|
||||||
|
- Platform: |amd64|
|
||||||
|
- UEFI bootloader
|
||||||
|
- Multi-core & multi-tasking microkernel
|
||||||
|
|
||||||
|
- Work-stealing SMP scheduler
|
||||||
|
- Pluggable panic handler modules
|
||||||
|
|
||||||
|
- Capability-style object-oriented syscall API
|
||||||
|
|
||||||
|
- Custom IDL for specifying and documenting syscalls
|
||||||
|
|
||||||
|
- Virtual memory based on sharable Virtual Memory Area objects (VMAs)
|
||||||
|
- Kernel API library (libj6), also provides features built on kernel primitives:
|
||||||
|
|
||||||
|
- Channels (async stream IPC) built on shared memory and futexes
|
||||||
|
- Ring buffers via doubly-mapped pages
|
||||||
|
|
||||||
|
- Custom libc
|
||||||
|
- Runtime dynamic linker
|
||||||
|
- Init service
|
||||||
|
|
||||||
|
- Built-in VFS service for the initrd
|
||||||
|
- ELF loader
|
||||||
|
- Service-lookup protocol service
|
||||||
|
|
||||||
|
- Userland UART driver
|
||||||
|
- Userland UEFI framebuffer driver
|
||||||
|
- Userland kernel log output service
|
||||||
|
- Userland unit test runner
|
||||||
|
- Build configuration system (bonnibel)
|
||||||
|
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
:caption: Site Contents:
|
||||||
|
|
||||||
|
syscall_interface
|
||||||
|
kernel_memory
|
||||||
|
process_initialization
|
||||||
|
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`search`
|
||||||
|
|
||||||
|
|
||||||
12
docs/jsix_transparent.svg
Normal file
12
docs/jsix_transparent.svg
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Gravit.io -->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="176.562 356.069 211.11 113" width="211.11pt" height="113pt">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d=" M 212.981 372.36 L 219.564 376.16 L 226.147 379.961 L 226.147 387.563 L 226.147 395.164 L 219.564 398.965 L 212.981 402.766 L 206.398 398.965 L 199.815 395.164 L 199.815 387.563 L 199.815 379.961 L 206.398 376.16 L 212.981 372.36 L 212.981 372.36 L 212.981 372.36 Z M 256.292 397.366 L 262.875 401.166 L 269.458 404.967 L 269.458 412.569 L 269.458 420.17 L 262.875 423.971 L 256.292 427.772 L 249.709 423.971 L 243.126 420.17 L 243.126 412.569 L 243.126 404.967 L 249.709 401.166 L 256.292 397.366 L 256.292 397.366 Z M 183.622 387.283 L 205.52 374.64 L 227.418 361.997 L 249.316 374.64 L 271.214 387.283 L 271.214 412.569 L 271.214 437.854 L 249.316 450.497 L 227.418 463.14 L 205.52 450.497 L 183.622 437.854 L 183.622 412.569 L 183.622 387.283 L 183.622 387.283 L 183.622 387.283 Z M 241.855 372.36 L 248.438 376.16 L 255.021 379.961 L 255.021 387.563 L 255.021 395.164 L 248.438 398.965 L 241.855 402.766 L 235.272 398.965 L 228.689 395.164 L 228.689 387.563 L 228.689 379.961 L 235.272 376.16 L 241.855 372.36 Z " fill-rule="evenodd" fill="rgb(49,79,128)"/>
|
||||||
|
<path d=" M 298.642 379.579 L 291.621 379.579 L 291.621 372.558 L 298.642 372.558 L 298.642 379.579 Z M 285.214 446.718 L 285.214 441.452 L 287.32 441.452 L 287.32 441.452 Q 289.339 441.452 290.524 440.092 L 290.524 440.092 L 290.524 440.092 Q 291.708 438.731 291.708 436.625 L 291.708 436.625 L 291.708 387.039 L 298.729 387.039 L 298.729 436.011 L 298.729 436.011 Q 298.729 440.925 295.921 443.822 L 295.921 443.822 L 295.921 443.822 Q 293.113 446.718 288.286 446.718 L 288.286 446.718 L 285.214 446.718 Z M 306.628 432.676 L 306.628 427.41 L 314.088 427.41 L 314.088 427.41 Q 317.862 427.41 319.573 425.347 L 319.573 425.347 L 319.573 425.347 Q 321.285 423.285 321.285 419.95 L 321.285 419.95 L 321.285 419.95 Q 321.285 417.317 319.705 415.474 L 319.705 415.474 L 319.705 415.474 Q 318.125 413.631 314.966 411.174 L 314.966 411.174 L 314.966 411.174 Q 312.245 408.98 310.621 407.356 L 310.621 407.356 L 310.621 407.356 Q 308.998 405.732 307.813 403.319 L 307.813 403.319 L 307.813 403.319 Q 306.628 400.905 306.628 397.746 L 306.628 397.746 L 306.628 397.746 Q 306.628 393.095 309.744 390.067 L 309.744 390.067 L 309.744 390.067 Q 312.859 387.039 318.125 387.039 L 318.125 387.039 L 325.76 387.039 L 325.76 392.305 L 319.441 392.305 L 319.441 392.305 Q 313.21 392.305 313.21 398.185 L 313.21 398.185 L 313.21 398.185 Q 313.21 400.467 314.615 402.134 L 314.615 402.134 L 314.615 402.134 Q 316.019 403.802 319.003 406.083 L 319.003 406.083 L 319.003 406.083 Q 321.723 408.19 323.479 409.901 L 323.479 409.901 L 323.479 409.901 Q 325.234 411.613 326.463 414.202 L 326.463 414.202 L 326.463 414.202 Q 327.691 416.791 327.691 420.301 L 327.691 420.301 L 327.691 420.301 Q 327.691 426.532 324.4 429.604 L 324.4 429.604 L 324.4 429.604 Q 321.109 432.676 315.141 432.676 L 315.141 432.676 L 306.628 432.676 Z M 342.611 379.579 L 335.59 379.579 L 335.59 372.558 L 342.611 372.558 L 342.611 379.579 Z M 342.611 432.676 L 335.59 432.676 L 335.59 387.039 L 342.611 387.039 L 342.611 432.676 Z M 356.126 432.676 L 348.754 432.676 L 361.392 409.77 L 349.632 387.039 L 356.39 387.039 L 364.639 403.187 L 372.977 387.039 L 379.735 387.039 L 367.974 409.77 L 380.612 432.676 L 373.24 432.676 L 364.639 416.001 L 356.126 432.676 Z " fill="rgb(49,79,128)"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.6 KiB |
178
docs/kernel_memory.rst
Normal file
178
docs/kernel_memory.rst
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
.. jsix syscall interface.
|
||||||
|
.. Automatically updated from the definition files using cog!
|
||||||
|
|
||||||
|
.. [[[cog code generation
|
||||||
|
.. from os.path import join
|
||||||
|
.. from memory import Layout, unit
|
||||||
|
..
|
||||||
|
.. layout = Layout(join(definitions_path, "memory_layout.yaml"))
|
||||||
|
.. l = max([len(r.name) for r in layout.regions])
|
||||||
|
.. ]]]
|
||||||
|
.. [[[end]]] (checksum: d41d8cd98f00b204e9800998ecf8427e)
|
||||||
|
|
||||||
|
Kernel memory
|
||||||
|
=============
|
||||||
|
|
||||||
|
While jsix probably should eventually use KASLR to randomize its memory layout,
|
||||||
|
currently the layout is mostly fixed. (Kernel code locations are not consistent
|
||||||
|
but aren't explicitly randomized.)
|
||||||
|
|
||||||
|
.. [[[cog code generation
|
||||||
|
.. line_size = 128 * 1024**3 # Each line represents up to 32 GiB
|
||||||
|
.. max_lines = 32
|
||||||
|
.. totals = sum([r.size for r in layout.regions])
|
||||||
|
.. remain = unit((128 * 1024**4) - totals)
|
||||||
|
..
|
||||||
|
.. def split(val):
|
||||||
|
.. return f"0x {val >> 48:04x} {(val >> 32) & 0xffff:04x} {(val >> 16) & 0xffff:04x} {val & 0xffff:04x}"
|
||||||
|
..
|
||||||
|
.. cog.outl()
|
||||||
|
.. cog.outl(f"+-+-----------------------------+----------+---------------------------------------+")
|
||||||
|
.. cog.outl(f"| | Address | Size | Use |")
|
||||||
|
.. cog.outl(f"+=+=============================+==========+=======================================+")
|
||||||
|
..
|
||||||
|
.. for region in layout.regions:
|
||||||
|
.. cog.outl(f"| | ``{split(region.start)}`` | {unit(region.size):>8} | {region.desc:37} |")
|
||||||
|
.. lines = min(max_lines, region.size // line_size)
|
||||||
|
.. for i in range(1, lines):
|
||||||
|
.. cog.outl(f"+-+ | | |")
|
||||||
|
.. cog.outl(f"| | | | |")
|
||||||
|
.. cog.outl(f"+-+-----------------------------+----------+---------------------------------------+")
|
||||||
|
..
|
||||||
|
.. cog.outl(f"| | ... | | |")
|
||||||
|
.. cog.outl(f"+-+-----------------------------+----------+---------------------------------------+")
|
||||||
|
.. cog.outl(f"| | ``0x ffff 0000 0000 0000`` | | Kernel code / headers |")
|
||||||
|
.. cog.outl(f"+-+-----------------------------+----------+---------------------------------------+")
|
||||||
|
.. cog.outl("")
|
||||||
|
.. cog.outl("")
|
||||||
|
.. cog.outl(f"Un-reserved virtual memory address space in the higher half: {remain}")
|
||||||
|
.. cog.outl("")
|
||||||
|
..
|
||||||
|
.. ]]]
|
||||||
|
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | Address | Size | Use |
|
||||||
|
+=+=============================+==========+=======================================+
|
||||||
|
| | ``0x ffff c000 0000 0000`` | 64 TiB | Linearly-mapped physical memory |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ``0x ffff bf00 0000 0000`` | 1 TiB | Used/free page tracking bitmap |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ``0x ffff be00 0000 0000`` | 1 TiB | Per-page state tracking structures |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+ | | |
|
||||||
|
| | | | |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ``0x ffff bdf8 0000 0000`` | 32 GiB | Kernel heap accounting structures |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ``0x ffff bdf0 0000 0000`` | 32 GiB | Kernel heap |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ``0x ffff bde8 0000 0000`` | 32 GiB | Capabilities accounting structures |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ``0x ffff bde0 0000 0000`` | 32 GiB | Capabilities |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ``0x ffff bdd0 0000 0000`` | 64 GiB | Kernel thread stacks |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ``0x ffff bdc0 0000 0000`` | 64 GiB | Kernel buffers |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ``0x ffff bdbf 8000 0000`` | 2 GiB | Kernel logs circular buffer |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ... | | |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
| | ``0x ffff 0000 0000 0000`` | | Kernel code / headers |
|
||||||
|
+-+-----------------------------+----------+---------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
Un-reserved virtual memory address space in the higher half: 61 TiB
|
||||||
|
|
||||||
|
.. [[[end]]] (checksum: 8c336cc8151beba1a79c8d3b653f1109)
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`search`
|
||||||
|
|
||||||
7
docs/modd.conf
Normal file
7
docs/modd.conf
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
** !_build/** ../definitions/**.def {
|
||||||
|
prep: rm -rf _build; make html
|
||||||
|
}
|
||||||
|
|
||||||
|
_build/html/** {
|
||||||
|
daemon: devd -m _build/html
|
||||||
|
}
|
||||||
42
docs/process_initialization.rst
Normal file
42
docs/process_initialization.rst
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
.. jsix process initialization in userspace
|
||||||
|
|
||||||
|
Process Initialization
|
||||||
|
======================
|
||||||
|
|
||||||
|
jsix follows the `System V ABI`_ on the ``amd64`` architecture. All arguments
|
||||||
|
needed for program initialization are passed to the program's initial thread on
|
||||||
|
the stack.
|
||||||
|
|
||||||
|
Note that jsix adds a number of additional auxiliary vector entry types for
|
||||||
|
passing jsix-specific data to a program. The jsix-specific auxiliary vector type
|
||||||
|
codes (what the ABI document refers to as ``a_type``) start from ``0xf000``. See
|
||||||
|
the header file ``<j6/init.h>`` for more detail.
|
||||||
|
|
||||||
|
.. _System V ABI: https://gitlab.com/x86-psABIs/x86-64-ABI
|
||||||
|
|
||||||
|
The initial stack frame
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
============== ==================== ============ =======
|
||||||
|
Address Value Bytes Notes
|
||||||
|
============== ==================== ============ =======
|
||||||
|
``top`` Stack top (out of stack bounds)
|
||||||
|
``top`` - 16 0 16 Stack sentinel
|
||||||
|
\ ``envp`` string data ?
|
||||||
|
\ ``argv`` string data ?
|
||||||
|
\ ... ? Possible padding
|
||||||
|
\ 0, 0 (``AT_NULL``) 16 Aux vector sentinel
|
||||||
|
\ Aux vectors 16 * `m` ``AT_NULL``-terminated array of Aux vectors
|
||||||
|
\ 0 8 Environment sentinel
|
||||||
|
\ ``envp`` 8 * `n` 0-terminated array of environment
|
||||||
|
string pointers
|
||||||
|
\ 0 8 Args sentinel
|
||||||
|
\ ``argv`` 8 * ``argc`` Pointers to argument strings
|
||||||
|
``rsp`` ``argc`` 8 Number of elements in argv
|
||||||
|
============== ==================== ============ =======
|
||||||
|
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`search`
|
||||||
|
|
||||||
|
|
||||||
5
docs/requirements.txt
Normal file
5
docs/requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
cogapp >= 3
|
||||||
|
pyyaml >= 5.4
|
||||||
|
lark == 0.12.0
|
||||||
|
sphinx
|
||||||
|
renku-sphinx-theme
|
||||||
444
docs/syscall_interface.rst
Normal file
444
docs/syscall_interface.rst
Normal file
@@ -0,0 +1,444 @@
|
|||||||
|
.. jsix syscall interface.
|
||||||
|
.. Automatically updated from the definition files using cog!
|
||||||
|
|
||||||
|
.. [[[cog code generation
|
||||||
|
.. from textwrap import indent
|
||||||
|
.. from definitions.context import Context
|
||||||
|
..
|
||||||
|
.. ctx = Context(definitions_path)
|
||||||
|
.. ctx.parse("syscalls.def")
|
||||||
|
.. syscalls = ctx.interfaces["syscalls"]
|
||||||
|
..
|
||||||
|
.. def caplist(caps):
|
||||||
|
.. return ', '.join([f"``{c}``" for c in caps])
|
||||||
|
.. ]]]
|
||||||
|
.. [[[end]]] (checksum: d41d8cd98f00b204e9800998ecf8427e)
|
||||||
|
|
||||||
|
Syscall interface
|
||||||
|
=================
|
||||||
|
|
||||||
|
The jsix kernel's syscall design is based around object handles. Object handles
|
||||||
|
are also a collection of capabilities, encoding certain rights over the object
|
||||||
|
they reference.
|
||||||
|
|
||||||
|
Very few syscalls in jsix can be made without some handle, and most of them are
|
||||||
|
requests to the kernel to create a given kind of object. This is analogous to
|
||||||
|
methods on an object in an object-oriented programming language.
|
||||||
|
|
||||||
|
.. [[[cog code generation
|
||||||
|
.. cog.outl()
|
||||||
|
.. for obj in syscalls.exposes:
|
||||||
|
.. cog.outl(f"``{obj.name}`` syscalls")
|
||||||
|
.. cog.outl(f"-------------------------")
|
||||||
|
.. desc = obj.desc or "Undocumented"
|
||||||
|
.. cog.outl(desc)
|
||||||
|
.. cog.outl()
|
||||||
|
.. cog.outl(f":capabilites: {caplist(obj.caps)}")
|
||||||
|
.. cog.outl()
|
||||||
|
.. for method in obj.methods:
|
||||||
|
.. args = []
|
||||||
|
.. if method.constructor:
|
||||||
|
.. args.append("j6_handle_t *self")
|
||||||
|
.. elif not method.static:
|
||||||
|
.. args.append("j6_handle_t self")
|
||||||
|
..
|
||||||
|
.. for param in method.params:
|
||||||
|
.. for type, suffix in param.type.c_names(param.options):
|
||||||
|
.. args.append(f"{type} {param.name}{suffix}")
|
||||||
|
..
|
||||||
|
.. cog.outl(f".. cpp:function:: j6_result_t j6_{obj.name}_{method.name} ({', '.join(args)})")
|
||||||
|
.. cog.outl()
|
||||||
|
.. desc = method.desc or "Undocumented"
|
||||||
|
.. cog.outl(indent(desc, " "))
|
||||||
|
.. cog.outl()
|
||||||
|
.. if "cap" in method.options:
|
||||||
|
.. cog.outl(f" :capabilities: {caplist(method.options['cap'])}")
|
||||||
|
.. cog.outl()
|
||||||
|
.. if method.constructor:
|
||||||
|
.. cog.outl(f" :param self: *[out]* Handle to the new {obj.name} object")
|
||||||
|
.. elif not method.static:
|
||||||
|
.. cog.outl(f" :param self: Handle to the {obj.name} object")
|
||||||
|
.. for param in method.params:
|
||||||
|
.. opts = param.options and f"*[{', '.join(param.options)}]*" or ""
|
||||||
|
.. desc = param.desc or 'Undocumented'
|
||||||
|
.. cog.outl(f" :param {param.name}: {opts} {desc}")
|
||||||
|
.. cog.outl()
|
||||||
|
.. ]]]
|
||||||
|
|
||||||
|
``object`` syscalls
|
||||||
|
-------------------------
|
||||||
|
All kernel-exposed objects inherit from the base ``object`` type, so the
|
||||||
|
``object`` syscalls can be used with any object's handle.
|
||||||
|
|
||||||
|
:capabilites: ``clone``
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_object_koid (j6_handle_t self, uint64_t * koid)
|
||||||
|
|
||||||
|
Get the internal kernel object id of an object
|
||||||
|
|
||||||
|
:param self: Handle to the object object
|
||||||
|
:param koid: *[out]* Undocumented
|
||||||
|
|
||||||
|
``event`` syscalls
|
||||||
|
-------------------------
|
||||||
|
An ``event`` is a simple synchronization object. It contains up to 64 signals
|
||||||
|
that threads can wait for and signal in parallel.
|
||||||
|
|
||||||
|
:capabilites: ``signal``, ``wait``
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_event_create (j6_handle_t *self)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:param self: *[out]* Handle to the new event object
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_event_signal (j6_handle_t self, uint64_t signals)
|
||||||
|
|
||||||
|
Signal events on this object
|
||||||
|
|
||||||
|
:capabilities: ``signal``
|
||||||
|
|
||||||
|
:param self: Handle to the event object
|
||||||
|
:param signals: A bitset of which events to signal
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_event_wait (j6_handle_t self, uint64_t * signals, uint64_t timeout)
|
||||||
|
|
||||||
|
Wait for signaled events on this object
|
||||||
|
|
||||||
|
:capabilities: ``wait``
|
||||||
|
|
||||||
|
:param self: Handle to the event object
|
||||||
|
:param signals: *[out]* A bitset of which events were signaled
|
||||||
|
:param timeout: Wait timeout in nanoseconds
|
||||||
|
|
||||||
|
``mailbox`` syscalls
|
||||||
|
-------------------------
|
||||||
|
Mailboxes are objects that enable synchronous IPC via arbitrary
|
||||||
|
message-passing of tagged data and/or handles. Not as efficient
|
||||||
|
as shared memory channels, but more flexible.
|
||||||
|
|
||||||
|
:capabilites: ``send``, ``receive``, ``close``
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_mailbox_create (j6_handle_t *self)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:param self: *[out]* Handle to the new mailbox object
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_mailbox_close (j6_handle_t self)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:capabilities: ``close``
|
||||||
|
|
||||||
|
:param self: Handle to the mailbox object
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_mailbox_call (j6_handle_t self, uint64_t * tag, void * data, size_t * data_len, size_t data_size, j6_handle_t * handles, size_t * handles_count, size_t handles_size)
|
||||||
|
|
||||||
|
Send a message to the reciever, and block until a response is
|
||||||
|
sent. Note that getting this response does not require the
|
||||||
|
receive capability.
|
||||||
|
|
||||||
|
:capabilities: ``send``
|
||||||
|
|
||||||
|
:param self: Handle to the mailbox object
|
||||||
|
:param tag: *[inout]* Undocumented
|
||||||
|
:param data: *[optional, inout]* Undocumented
|
||||||
|
:param data_size: number of total bytes in data buffer
|
||||||
|
:param handles: *[optional, inout, handle, list]* Undocumented
|
||||||
|
:param handles_size: total size of handles buffer
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_mailbox_respond (j6_handle_t self, uint64_t * tag, void * data, size_t * data_len, size_t data_size, j6_handle_t * handles, size_t * handles_count, size_t handles_size, uint64_t * reply_tag, uint64_t flags)
|
||||||
|
|
||||||
|
Respond to a message sent using call, and wait for another
|
||||||
|
message to arrive. Note that this does not require the send
|
||||||
|
capability. A reply tag of 0 skips the reply and goes directly
|
||||||
|
to waiting for a new message.
|
||||||
|
|
||||||
|
:capabilities: ``receive``
|
||||||
|
|
||||||
|
:param self: Handle to the mailbox object
|
||||||
|
:param tag: *[inout]* Undocumented
|
||||||
|
:param data: *[optional, inout]* Undocumented
|
||||||
|
:param data_size: number of total bytes in data buffer
|
||||||
|
:param handles: *[optional, inout, handle, list]* Undocumented
|
||||||
|
:param handles_size: total size of handles buffer
|
||||||
|
:param reply_tag: *[inout]* Undocumented
|
||||||
|
:param flags: Undocumented
|
||||||
|
|
||||||
|
``process`` syscalls
|
||||||
|
-------------------------
|
||||||
|
A ``process`` object represents a process running on the system, and allows
|
||||||
|
control over the threads, handles, and virtual memory space of that process.
|
||||||
|
|
||||||
|
:capabilites: ``kill``, ``create_thread``
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_process_create (j6_handle_t *self)
|
||||||
|
|
||||||
|
Create a new empty process
|
||||||
|
|
||||||
|
:param self: *[out]* Handle to the new process object
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_process_kill (j6_handle_t self)
|
||||||
|
|
||||||
|
Stop all threads and exit the given process
|
||||||
|
|
||||||
|
:capabilities: ``kill``
|
||||||
|
|
||||||
|
:param self: Handle to the process object
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_process_exit (int64_t result)
|
||||||
|
|
||||||
|
Stop all threads and exit the current process
|
||||||
|
|
||||||
|
:param result: The result to retrun to the parent process
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_process_give_handle (j6_handle_t self, j6_handle_t target)
|
||||||
|
|
||||||
|
Give the given process a handle that points to the same
|
||||||
|
object as the specified handle.
|
||||||
|
|
||||||
|
:param self: Handle to the process object
|
||||||
|
:param target: *[handle]* A handle in the caller process to send
|
||||||
|
|
||||||
|
``system`` syscalls
|
||||||
|
-------------------------
|
||||||
|
The singular ``system`` object represents a handle to kernel functionality
|
||||||
|
needed by drivers and other priviledged services.
|
||||||
|
|
||||||
|
:capabilites: ``get_log``, ``bind_irq``, ``map_phys``, ``change_iopl``
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_system_get_log (j6_handle_t self, uint64_t seen, void * buffer, size_t * buffer_len)
|
||||||
|
|
||||||
|
Get the next log line from the kernel log
|
||||||
|
|
||||||
|
:capabilities: ``get_log``
|
||||||
|
|
||||||
|
:param self: Handle to the system object
|
||||||
|
:param seen: Last seen log id
|
||||||
|
:param buffer: *[out, zero_ok]* Buffer for the log message data structure
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_system_bind_irq (j6_handle_t self, j6_handle_t dest, unsigned irq, unsigned signal)
|
||||||
|
|
||||||
|
Ask the kernel to send this process messages whenever
|
||||||
|
the given IRQ fires
|
||||||
|
|
||||||
|
:capabilities: ``bind_irq``
|
||||||
|
|
||||||
|
:param self: Handle to the system object
|
||||||
|
:param dest: Event object that will receive messages
|
||||||
|
:param irq: IRQ number to bind
|
||||||
|
:param signal: Signal number on the event to bind to
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_system_map_phys (j6_handle_t self, j6_handle_t * area, uintptr_t phys, size_t size, uint32_t flags)
|
||||||
|
|
||||||
|
Create a VMA and map an area of physical memory into it,
|
||||||
|
also mapping that VMA into the current process
|
||||||
|
|
||||||
|
:capabilities: ``map_phys``
|
||||||
|
|
||||||
|
:param self: Handle to the system object
|
||||||
|
:param area: *[out]* Receives a handle to the VMA created
|
||||||
|
:param phys: The physical address of the area
|
||||||
|
:param size: Size of the area, in bytes
|
||||||
|
:param flags: Flags to apply to the created VMA
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_system_request_iopl (j6_handle_t self, unsigned iopl)
|
||||||
|
|
||||||
|
Request the kernel change the IOPL for this process. The only values
|
||||||
|
that make sense are 0 and 3.
|
||||||
|
|
||||||
|
:capabilities: ``change_iopl``
|
||||||
|
|
||||||
|
:param self: Handle to the system object
|
||||||
|
:param iopl: The IOPL to set for this process
|
||||||
|
|
||||||
|
``thread`` syscalls
|
||||||
|
-------------------------
|
||||||
|
A ``thread`` object represents a thread of execution within a process running
|
||||||
|
on the system. The actual thread does not need to be currently running to
|
||||||
|
hold a handle to it.
|
||||||
|
|
||||||
|
:capabilites: ``kill``, ``join``
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_thread_create (j6_handle_t *self, j6_handle_t process, uintptr_t stack_top, uintptr_t entrypoint, uint64_t arg0, uint64_t arg1)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:param self: *[out]* Handle to the new thread object
|
||||||
|
:param process: *[optional, cap]* Undocumented
|
||||||
|
:param stack_top: Undocumented
|
||||||
|
:param entrypoint: Undocumented
|
||||||
|
:param arg0: Undocumented
|
||||||
|
:param arg1: Undocumented
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_thread_kill (j6_handle_t self)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:capabilities: ``kill``
|
||||||
|
|
||||||
|
:param self: Handle to the thread object
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_thread_join (j6_handle_t self)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:capabilities: ``join``
|
||||||
|
|
||||||
|
:param self: Handle to the thread object
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_thread_exit ()
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_thread_sleep (uint64_t duration)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:param duration: Undocumented
|
||||||
|
|
||||||
|
``vma`` syscalls
|
||||||
|
-------------------------
|
||||||
|
A ``vma`` object represents a single virtual memory area, which may be shared
|
||||||
|
between several processes. A process having a handle to a ``vma`` does not
|
||||||
|
necessarily mean that it is mapped into that process' virtual memory space.
|
||||||
|
|
||||||
|
:capabilites: ``map``, ``unmap``, ``resize``
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_vma_create (j6_handle_t *self, size_t size, uint32_t flags)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:param self: *[out]* Handle to the new vma object
|
||||||
|
:param size: Undocumented
|
||||||
|
:param flags: Undocumented
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_vma_create_map (j6_handle_t *self, size_t size, uintptr_t * address, uint32_t flags)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:capabilities: ``map``
|
||||||
|
|
||||||
|
:param self: *[out]* Handle to the new vma object
|
||||||
|
:param size: Undocumented
|
||||||
|
:param address: *[inout]* Undocumented
|
||||||
|
:param flags: Undocumented
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_vma_map (j6_handle_t self, j6_handle_t process, uintptr_t * address, uint32_t flags)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:capabilities: ``map``
|
||||||
|
|
||||||
|
:param self: Handle to the vma object
|
||||||
|
:param process: *[optional]* Undocumented
|
||||||
|
:param address: *[inout]* Undocumented
|
||||||
|
:param flags: Undocumented
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_vma_unmap (j6_handle_t self, j6_handle_t process)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:capabilities: ``unmap``
|
||||||
|
|
||||||
|
:param self: Handle to the vma object
|
||||||
|
:param process: *[optional]* Undocumented
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_vma_resize (j6_handle_t self, size_t * size)
|
||||||
|
|
||||||
|
Undocumented
|
||||||
|
|
||||||
|
:capabilities: ``resize``
|
||||||
|
|
||||||
|
:param self: Handle to the vma object
|
||||||
|
:param size: *[inout]* New size for the VMA, or 0 to query the current size without changing
|
||||||
|
|
||||||
|
.. [[[end]]] (checksum: cb17f54e443d1d3b85995870f3e8dbf2)
|
||||||
|
|
||||||
|
Non-object syscalls
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The following are the system calls that aren't constructors for objects, and
|
||||||
|
either do not require an object handle, or operate generically on handles.
|
||||||
|
|
||||||
|
.. [[[cog code generation
|
||||||
|
.. cog.outl()
|
||||||
|
.. for func in syscalls.functions:
|
||||||
|
.. args = []
|
||||||
|
.. for param in func.params:
|
||||||
|
.. for type, suffix in param.type.c_names(param.options):
|
||||||
|
.. args.append(f"{type} {param.name}{suffix}")
|
||||||
|
..
|
||||||
|
.. cog.outl(f".. cpp:function:: j6_result_t j6_{func.name} ({', '.join(args)})")
|
||||||
|
.. cog.outl()
|
||||||
|
.. desc = func.desc or "Undocumented"
|
||||||
|
.. cog.outl(indent(desc, " "))
|
||||||
|
.. cog.outl()
|
||||||
|
.. for param in func.params:
|
||||||
|
.. opts = param.options and f"*[{', '.join(param.options)}]*" or ""
|
||||||
|
.. desc = param.desc or 'Undocumented'
|
||||||
|
.. cog.outl(f" :param {param.name}: {opts} {desc}")
|
||||||
|
.. cog.outl()
|
||||||
|
.. ]]]
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_noop ()
|
||||||
|
|
||||||
|
Simple no-op syscall for testing
|
||||||
|
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_log (uint8_t area, uint8_t severity, const char * message)
|
||||||
|
|
||||||
|
Write a message to the kernel log
|
||||||
|
|
||||||
|
:param area: Undocumented
|
||||||
|
:param severity: Undocumented
|
||||||
|
:param message: Undocumented
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_handle_list (struct j6_handle_descriptor * handles, size_t * handles_size)
|
||||||
|
|
||||||
|
Get a list of handles owned by this process. If the
|
||||||
|
supplied list is not big enough, will set the size
|
||||||
|
needed in `size` and return j6_err_insufficient
|
||||||
|
|
||||||
|
:param handles: *[list, inout, zero_ok]* A list of handles to be filled
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_handle_clone (j6_handle_t orig, j6_handle_t * clone, uint32_t mask)
|
||||||
|
|
||||||
|
Create a clone of an existing handle, possibly with
|
||||||
|
some capabilities masked out.
|
||||||
|
|
||||||
|
:param orig: *[handle, cap]* The handle to clone
|
||||||
|
:param clone: *[out]* The new handle
|
||||||
|
:param mask: The capability bitmask
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_handle_close (j6_handle_t hnd)
|
||||||
|
|
||||||
|
Close the handle to an object
|
||||||
|
|
||||||
|
:param hnd: *[handle]* The handle to close
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_futex_wait (const uint32_t * address, uint32_t current, uint64_t timeout)
|
||||||
|
|
||||||
|
Block waiting on a futex
|
||||||
|
|
||||||
|
:param address: Address of the futex value
|
||||||
|
:param current: Current value of the futex
|
||||||
|
:param timeout: Wait timeout in nanoseconds
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_futex_wake (const uint32_t * address, uint64_t count)
|
||||||
|
|
||||||
|
Wake threads waiting on a futex
|
||||||
|
|
||||||
|
:param address: Address of the futex value
|
||||||
|
:param count: Number of threads to wake, or 0 for all
|
||||||
|
|
||||||
|
.. cpp:function:: j6_result_t j6_test_finish (uint32_t exit_code)
|
||||||
|
|
||||||
|
Testing mode only: Have the kernel finish and exit QEMU with the given exit code
|
||||||
|
|
||||||
|
:param exit_code: Undocumented
|
||||||
|
|
||||||
|
.. [[[end]]] (checksum: 0b9d051972abcbb6de408f411331785f)
|
||||||
|
|
||||||
3669
external/cpptoml/cpptoml.h
vendored
3669
external/cpptoml/cpptoml.h
vendored
File diff suppressed because it is too large
Load Diff
8
external/uefi/boot_services.h
vendored
8
external/uefi/boot_services.h
vendored
@@ -14,13 +14,15 @@
|
|||||||
namespace uefi {
|
namespace uefi {
|
||||||
namespace bs_impl {
|
namespace bs_impl {
|
||||||
using allocate_pages = status (*)(allocate_type, memory_type, size_t, void**);
|
using allocate_pages = status (*)(allocate_type, memory_type, size_t, void**);
|
||||||
|
using free_pages = status (*)(void*, size_t);
|
||||||
using get_memory_map = status (*)(size_t*, memory_descriptor*, size_t*, size_t*, uint32_t*);
|
using get_memory_map = status (*)(size_t*, memory_descriptor*, size_t*, size_t*, uint32_t*);
|
||||||
using allocate_pool = status (*)(memory_type, uint64_t, void**);
|
using allocate_pool = status (*)(memory_type, uint64_t, void**);
|
||||||
|
using free_pool = status (*)(void*);
|
||||||
using handle_protocol = status (*)(handle, const guid*, void**);
|
using handle_protocol = status (*)(handle, const guid*, void**);
|
||||||
using create_event = status (*)(evt, tpl, event_notify, void*, event*);
|
using create_event = status (*)(evt, tpl, event_notify, void*, event*);
|
||||||
using exit_boot_services = status (*)(handle, size_t);
|
using exit_boot_services = status (*)(handle, size_t);
|
||||||
using locate_protocol = status (*)(const guid*, void*, void**);
|
using locate_protocol = status (*)(const guid*, void*, void**);
|
||||||
using copy_mem = void (*)(void*, void*, size_t);
|
using copy_mem = void (*)(void*, const void*, size_t);
|
||||||
using set_mem = void (*)(void*, uint64_t, uint8_t);
|
using set_mem = void (*)(void*, uint64_t, uint8_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,10 +37,10 @@ struct boot_services {
|
|||||||
|
|
||||||
// Memory Services
|
// Memory Services
|
||||||
bs_impl::allocate_pages allocate_pages;
|
bs_impl::allocate_pages allocate_pages;
|
||||||
void *free_pages;
|
bs_impl::free_pages free_pages;
|
||||||
bs_impl::get_memory_map get_memory_map;
|
bs_impl::get_memory_map get_memory_map;
|
||||||
bs_impl::allocate_pool allocate_pool;
|
bs_impl::allocate_pool allocate_pool;
|
||||||
void *free_pool;
|
bs_impl::free_pool free_pool;
|
||||||
|
|
||||||
// Event & Timer Services
|
// Event & Timer Services
|
||||||
bs_impl::create_event create_event;
|
bs_impl::create_event create_event;
|
||||||
|
|||||||
390
external/uefi/networking.h
vendored
Normal file
390
external/uefi/networking.h
vendored
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _uefi_networking_h_
|
||||||
|
#define _uefi_networking_h_
|
||||||
|
|
||||||
|
// This Source Code Form is part of the j6-uefi-headers project and is subject
|
||||||
|
// to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was
|
||||||
|
// not distributed with this file, You can obtain one at
|
||||||
|
// http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <uefi/types.h>
|
||||||
|
|
||||||
|
namespace uefi {
|
||||||
|
|
||||||
|
//
|
||||||
|
// IPv4 definitions
|
||||||
|
//
|
||||||
|
struct ipv4_address
|
||||||
|
{
|
||||||
|
uint8_t addr[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// IPv6 definitions
|
||||||
|
//
|
||||||
|
struct ipv6_address
|
||||||
|
{
|
||||||
|
uint8_t addr[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_address_info
|
||||||
|
{
|
||||||
|
ipv6_address address;
|
||||||
|
uint8_t prefix_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_route_table
|
||||||
|
{
|
||||||
|
ipv6_address gateway;
|
||||||
|
ipv6_address destination;
|
||||||
|
uint8_t prefix_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ip6_neighbor_state : int {
|
||||||
|
incomplete,
|
||||||
|
reachable,
|
||||||
|
stale,
|
||||||
|
delay,
|
||||||
|
probe,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ip6_neighbor_cache
|
||||||
|
{
|
||||||
|
ipv6_address neighbor;
|
||||||
|
mac_address link_address;
|
||||||
|
ip6_neighbor_state state;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class icmpv6_type : uint8_t
|
||||||
|
{
|
||||||
|
dest_unreachable = 0x1,
|
||||||
|
packet_too_big = 0x2,
|
||||||
|
time_exceeded = 0x3,
|
||||||
|
parameter_problem = 0x4,
|
||||||
|
echo_request = 0x80,
|
||||||
|
echo_reply = 0x81,
|
||||||
|
listener_query = 0x82,
|
||||||
|
listener_report = 0x83,
|
||||||
|
listener_done = 0x84,
|
||||||
|
router_solicit = 0x85,
|
||||||
|
router_advertise = 0x86,
|
||||||
|
neighbor_solicit = 0x87,
|
||||||
|
neighbor_advertise = 0x88,
|
||||||
|
redirect = 0x89,
|
||||||
|
listener_report_2 = 0x8f,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class icmpv6_code : uint8_t
|
||||||
|
{
|
||||||
|
// codes for icmpv6_type::dest_unreachable
|
||||||
|
no_route_to_dest = 0x0,
|
||||||
|
comm_prohibited = 0x1,
|
||||||
|
beyond_scope = 0x2,
|
||||||
|
addr_unreachable = 0x3,
|
||||||
|
port_unreachable = 0x4,
|
||||||
|
source_addr_failed = 0x5,
|
||||||
|
route_rejected = 0x6,
|
||||||
|
|
||||||
|
// codes for icmpv6_type::time_exceeded
|
||||||
|
timeout_hop_limit = 0x0,
|
||||||
|
timeout_reassemble = 0x1,
|
||||||
|
|
||||||
|
// codes for icmpv6_type::parameter_problem
|
||||||
|
erroneous_header = 0x0,
|
||||||
|
unrecognize_next_hdr = 0x1,
|
||||||
|
unrecognize_option = 0x2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_icmp_type
|
||||||
|
{
|
||||||
|
icmpv6_type type;
|
||||||
|
icmpv6_code code;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_config_data
|
||||||
|
{
|
||||||
|
uint8_t default_protocol;
|
||||||
|
bool accept_any_protocol;
|
||||||
|
bool accept_icmp_errors;
|
||||||
|
bool accept_promiscuous;
|
||||||
|
ipv6_address destination_address;
|
||||||
|
ipv6_address station_address;
|
||||||
|
uint8_t traffic_class;
|
||||||
|
uint8_t hop_limit;
|
||||||
|
uint32_t flow_label;
|
||||||
|
uint32_t receive_timeout;
|
||||||
|
uint32_t transmit_timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_mode_data
|
||||||
|
{
|
||||||
|
bool is_started;
|
||||||
|
uint32_t max_packet_size;
|
||||||
|
ip6_config_data config_data;
|
||||||
|
bool is_configured;
|
||||||
|
uint32_t address_count;
|
||||||
|
ip6_address_info * address_list;
|
||||||
|
uint32_t group_count;
|
||||||
|
ipv6_address * group_table;
|
||||||
|
uint32_t route_count;
|
||||||
|
ip6_route_table * route_table;
|
||||||
|
uint32_t neighbor_count;
|
||||||
|
ip6_neighbor_cache * neighbor_cache;
|
||||||
|
uint32_t prefix_count;
|
||||||
|
ip6_address_info * prefix_table;
|
||||||
|
uint32_t icmp_type_count;
|
||||||
|
* icmp_type_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_header
|
||||||
|
{
|
||||||
|
uint8_t traffic_class_h : 4;
|
||||||
|
uint8_t version : 4;
|
||||||
|
uint8_t flow_label_h : 4;
|
||||||
|
uint8_t traffic_class_l : 4;
|
||||||
|
uint16_t flow_label_l;
|
||||||
|
uint16_t payload_length;
|
||||||
|
uint8_t next_header;
|
||||||
|
uint8_t hop_limit;
|
||||||
|
ipv6_address source_address;
|
||||||
|
ipv6_address destination_address;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct ip6_fragment_data
|
||||||
|
{
|
||||||
|
uint32_t fragment_length;
|
||||||
|
void *fragment_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_override_data
|
||||||
|
{
|
||||||
|
uint8_t protocol;
|
||||||
|
uint8_t hop_limit;
|
||||||
|
uint32_t flow_label;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_receive_data
|
||||||
|
{
|
||||||
|
time time_stamp;
|
||||||
|
event recycle_signal;
|
||||||
|
uint32_t header_length;
|
||||||
|
ip6_header *header;
|
||||||
|
uint32_t data_length;
|
||||||
|
uint32_t fragment_count;
|
||||||
|
ip6_fragment_data fragment_table[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_transmit_data
|
||||||
|
{
|
||||||
|
ipv6_address destination_address;
|
||||||
|
ip6_override_data *override_data;
|
||||||
|
|
||||||
|
uint32_t ext_hdrs_length;
|
||||||
|
void *ext_hdrs;
|
||||||
|
uint8_t next_header;
|
||||||
|
uint32_t data_length;
|
||||||
|
uint32_t fragment_count;
|
||||||
|
ip6_fragment_data fragment_table[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_completion_token
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
status status;
|
||||||
|
union {
|
||||||
|
ip6_receive_data *rx_data;
|
||||||
|
ip6_transmit_data *tx_data;
|
||||||
|
} packet;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ip6_config_data_type : int
|
||||||
|
{
|
||||||
|
interface_info,
|
||||||
|
alt_interface_id,
|
||||||
|
policy,
|
||||||
|
dup_addr_detect_transmits,
|
||||||
|
manual_address,
|
||||||
|
gateway,
|
||||||
|
dns_server,
|
||||||
|
maximum
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_config_interface_info
|
||||||
|
{
|
||||||
|
wchar_t name[32];
|
||||||
|
uint8_t if_type;
|
||||||
|
uint32_t hw_address_size;
|
||||||
|
mac_address hw_address;
|
||||||
|
uint32_t address_info_count;
|
||||||
|
ip6_address_info *address_info;
|
||||||
|
uint32_t route_count;
|
||||||
|
ip6_route_table *route_table;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_config_interface_id
|
||||||
|
{
|
||||||
|
uint8_t id[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ip6_config_policy : int
|
||||||
|
{
|
||||||
|
manual,
|
||||||
|
automatic
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_config_dup_addr_detect_transmits
|
||||||
|
{
|
||||||
|
uint32_t dup_addr_detect_transmits;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ip6_config_manual_address
|
||||||
|
{
|
||||||
|
ipv6_address address;
|
||||||
|
bool is_anycast;
|
||||||
|
uint8_t prefix_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// IP definitions
|
||||||
|
//
|
||||||
|
union ip_address
|
||||||
|
{
|
||||||
|
uint8_t addr[4];
|
||||||
|
ipv4_address v4;
|
||||||
|
ipv6_address v6;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// HTTP definitions
|
||||||
|
//
|
||||||
|
struct httpv4_access_point
|
||||||
|
{
|
||||||
|
bool use_default_address;
|
||||||
|
ipv4_address local_address;
|
||||||
|
ipv4_address local_subnet;
|
||||||
|
uint16_t local_port;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct httpv6_access_point
|
||||||
|
{
|
||||||
|
ipv6_address local_address;
|
||||||
|
uint16_t local_port;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class http_version : int {
|
||||||
|
v10,
|
||||||
|
v11,
|
||||||
|
unsupported,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct http_config_data
|
||||||
|
{
|
||||||
|
http_version http_version;
|
||||||
|
uint32_t time_out_millisec;
|
||||||
|
bool local_address_is_ipv6;
|
||||||
|
union {
|
||||||
|
httpv4_access_point *ipv4_node;
|
||||||
|
httpv6_access_point *ipv6_node;
|
||||||
|
} access_point;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class http_method : int {
|
||||||
|
get,
|
||||||
|
post,
|
||||||
|
patch,
|
||||||
|
options,
|
||||||
|
connect,
|
||||||
|
head,
|
||||||
|
put,
|
||||||
|
delete_,
|
||||||
|
trace,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct http_request_data
|
||||||
|
{
|
||||||
|
http_method method;
|
||||||
|
wchar_t *url;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class http_status_code : int {
|
||||||
|
unsupported,
|
||||||
|
continue_,
|
||||||
|
switching_protocols,
|
||||||
|
ok,
|
||||||
|
created,
|
||||||
|
accepted,
|
||||||
|
non_authoritative_information,
|
||||||
|
no_content,
|
||||||
|
reset_content,
|
||||||
|
partial_content,
|
||||||
|
multiple_choices,
|
||||||
|
moved_permanently,
|
||||||
|
found,
|
||||||
|
see_other,
|
||||||
|
not_modified,
|
||||||
|
use_proxy,
|
||||||
|
temporary_redirect,
|
||||||
|
bad_request,
|
||||||
|
unauthorized,
|
||||||
|
payment_required,
|
||||||
|
forbidden,
|
||||||
|
not_found,
|
||||||
|
method_not_allowed,
|
||||||
|
not_acceptable,
|
||||||
|
proxy_authentication_required,
|
||||||
|
request_time_out,
|
||||||
|
conflict,
|
||||||
|
gone,
|
||||||
|
length_required,
|
||||||
|
precondition_failed,
|
||||||
|
request_entity_too_large,
|
||||||
|
request_uri_too_large,
|
||||||
|
unsupported_media_type,
|
||||||
|
requested_range_not_satisfied,
|
||||||
|
expectation_failed,
|
||||||
|
internal_server_error,
|
||||||
|
not_implemented,
|
||||||
|
bad_gateway,
|
||||||
|
service_unavailable,
|
||||||
|
gateway_timeout,
|
||||||
|
http_version_not_supported,
|
||||||
|
permanent_redirect, // I hate your decisions, uefi.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct http_response_data
|
||||||
|
{
|
||||||
|
http_status_code status_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct http_header
|
||||||
|
{
|
||||||
|
char *field_name;
|
||||||
|
char *field_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct http_message
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
http_request_data *request;
|
||||||
|
http_response_data *response;
|
||||||
|
} data;
|
||||||
|
|
||||||
|
size_t header_count;
|
||||||
|
http_header *headers;
|
||||||
|
|
||||||
|
size_t body_length;
|
||||||
|
void *body;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct http_token
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
status status;
|
||||||
|
http_message *message;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace uefi
|
||||||
|
|
||||||
|
#endif
|
||||||
3
external/uefi/protos/device_path.h
vendored
3
external/uefi/protos/device_path.h
vendored
@@ -16,6 +16,7 @@ struct device_path
|
|||||||
{
|
{
|
||||||
static constexpr uefi::guid guid{ 0x09576e91,0x6d3f,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
static constexpr uefi::guid guid{ 0x09576e91,0x6d3f,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
||||||
|
|
||||||
|
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t sub_type;
|
uint8_t sub_type;
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
@@ -27,4 +28,4 @@ public:
|
|||||||
} // namespace protos
|
} // namespace protos
|
||||||
} // namespace uefi
|
} // namespace uefi
|
||||||
|
|
||||||
#endif // _uefi_protos_device_path_h_
|
#endif // _uefi_protos_device_path_h_
|
||||||
4
external/uefi/protos/file.h
vendored
4
external/uefi/protos/file.h
vendored
@@ -14,7 +14,7 @@ struct file;
|
|||||||
|
|
||||||
struct file
|
struct file
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
inline uefi::status open(file ** new_handle, const wchar_t * file_name, file_mode open_mode, file_attr attributes) {
|
inline uefi::status open(file ** new_handle, const wchar_t * file_name, file_mode open_mode, file_attr attributes) {
|
||||||
return _open(this, new_handle, file_name, open_mode, attributes);
|
return _open(this, new_handle, file_name, open_mode, attributes);
|
||||||
@@ -123,4 +123,4 @@ public:
|
|||||||
} // namespace protos
|
} // namespace protos
|
||||||
} // namespace uefi
|
} // namespace uefi
|
||||||
|
|
||||||
#endif // _uefi_protos_file_h_
|
#endif // _uefi_protos_file_h_
|
||||||
3
external/uefi/protos/file_info.h
vendored
3
external/uefi/protos/file_info.h
vendored
@@ -16,6 +16,7 @@ struct file_info
|
|||||||
{
|
{
|
||||||
static constexpr uefi::guid guid{ 0x09576e92,0x6d3f,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
static constexpr uefi::guid guid{ 0x09576e92,0x6d3f,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
||||||
|
|
||||||
|
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
uint64_t file_size;
|
uint64_t file_size;
|
||||||
uint64_t physical_size;
|
uint64_t physical_size;
|
||||||
@@ -32,4 +33,4 @@ public:
|
|||||||
} // namespace protos
|
} // namespace protos
|
||||||
} // namespace uefi
|
} // namespace uefi
|
||||||
|
|
||||||
#endif // _uefi_protos_file_info_h_
|
#endif // _uefi_protos_file_info_h_
|
||||||
3
external/uefi/protos/graphics_output.h
vendored
3
external/uefi/protos/graphics_output.h
vendored
@@ -17,6 +17,7 @@ struct graphics_output
|
|||||||
{
|
{
|
||||||
static constexpr uefi::guid guid{ 0x9042a9de,0x23dc,0x4a38,{0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a} };
|
static constexpr uefi::guid guid{ 0x9042a9de,0x23dc,0x4a38,{0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a} };
|
||||||
|
|
||||||
|
|
||||||
inline uefi::status query_mode(uint32_t mode_number, uint64_t * size_of_info, uefi::graphics_output_mode_info ** info) {
|
inline uefi::status query_mode(uint32_t mode_number, uint64_t * size_of_info, uefi::graphics_output_mode_info ** info) {
|
||||||
return _query_mode(this, mode_number, size_of_info, info);
|
return _query_mode(this, mode_number, size_of_info, info);
|
||||||
}
|
}
|
||||||
@@ -47,4 +48,4 @@ public:
|
|||||||
} // namespace protos
|
} // namespace protos
|
||||||
} // namespace uefi
|
} // namespace uefi
|
||||||
|
|
||||||
#endif // _uefi_protos_graphics_output_h_
|
#endif // _uefi_protos_graphics_output_h_
|
||||||
72
external/uefi/protos/http.h
vendored
Normal file
72
external/uefi/protos/http.h
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _uefi_protos_http_h_
|
||||||
|
#define _uefi_protos_http_h_
|
||||||
|
|
||||||
|
// This file was auto generated by the j6-uefi-headers project. Please see
|
||||||
|
// https://github.com/justinian/j6-uefi-headers for more information.
|
||||||
|
|
||||||
|
#include <uefi/guid.h>
|
||||||
|
#include <uefi/types.h>
|
||||||
|
#include <uefi/networking.h>
|
||||||
|
|
||||||
|
namespace uefi {
|
||||||
|
namespace protos {
|
||||||
|
struct http;
|
||||||
|
|
||||||
|
struct http
|
||||||
|
{
|
||||||
|
static constexpr uefi::guid guid{ 0x7a59b29b,0x910b,0x4171,{0x82,0x42,0xa8,0x5a,0x0d,0xf2,0x5b,0x5b} };
|
||||||
|
static constexpr uefi::guid service_binding{ 0xbdc8e6af,0xd9bc,0x4379,{0xa7,0x2a,0xe0,0xc4,0xe7,0x5d,0xae,0x1c} };
|
||||||
|
|
||||||
|
|
||||||
|
inline uefi::status get_mode_data(uefi::http_config_data * http_config_data) {
|
||||||
|
return _get_mode_data(this, http_config_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status configure(uefi::http_config_data * http_config_data) {
|
||||||
|
return _configure(this, http_config_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status request(uefi::http_token * token) {
|
||||||
|
return _request(this, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status cancel(uefi::http_token * token) {
|
||||||
|
return _cancel(this, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status response(uefi::http_token * token) {
|
||||||
|
return _response(this, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status poll() {
|
||||||
|
return _poll(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using _get_mode_data_def = uefi::status (*)(uefi::protos::http *, uefi::http_config_data *);
|
||||||
|
_get_mode_data_def _get_mode_data;
|
||||||
|
|
||||||
|
using _configure_def = uefi::status (*)(uefi::protos::http *, uefi::http_config_data *);
|
||||||
|
_configure_def _configure;
|
||||||
|
|
||||||
|
using _request_def = uefi::status (*)(uefi::protos::http *, uefi::http_token *);
|
||||||
|
_request_def _request;
|
||||||
|
|
||||||
|
using _cancel_def = uefi::status (*)(uefi::protos::http *, uefi::http_token *);
|
||||||
|
_cancel_def _cancel;
|
||||||
|
|
||||||
|
using _response_def = uefi::status (*)(uefi::protos::http *, uefi::http_token *);
|
||||||
|
_response_def _response;
|
||||||
|
|
||||||
|
using _poll_def = uefi::status (*)(uefi::protos::http *);
|
||||||
|
_poll_def _poll;
|
||||||
|
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace protos
|
||||||
|
} // namespace uefi
|
||||||
|
|
||||||
|
#endif // _uefi_protos_http_h_
|
||||||
93
external/uefi/protos/ip6.h
vendored
Normal file
93
external/uefi/protos/ip6.h
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _uefi_protos_ip6_h_
|
||||||
|
#define _uefi_protos_ip6_h_
|
||||||
|
|
||||||
|
// This file was auto generated by the j6-uefi-headers project. Please see
|
||||||
|
// https://github.com/justinian/j6-uefi-headers for more information.
|
||||||
|
|
||||||
|
#include <uefi/guid.h>
|
||||||
|
#include <uefi/types.h>
|
||||||
|
#include <uefi/networking.h>
|
||||||
|
|
||||||
|
namespace uefi {
|
||||||
|
namespace protos {
|
||||||
|
struct ip6;
|
||||||
|
|
||||||
|
struct ip6
|
||||||
|
{
|
||||||
|
static constexpr uefi::guid guid{ 0x2c8759d5,0x5c2d,0x66ef,{0x92,0x5f,0xb6,0x6c,0x10,0x19,0x57,0xe2} };
|
||||||
|
static constexpr uefi::guid service_binding{ 0xec835dd3,0xfe0f,0x617b,{0xa6,0x21,0xb3,0x50,0xc3,0xe1,0x33,0x88} };
|
||||||
|
|
||||||
|
|
||||||
|
inline uefi::status get_mode_data(uefi::ip6_mode_data * ip6_mode_data, uefi::managed_network_config_data * mnp_config_data, uefi::simple_network_mode * snp_config_data) {
|
||||||
|
return _get_mode_data(this, ip6_mode_data, mnp_config_data, snp_config_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status configure(uefi::ip6_config_data * ip6_config_data) {
|
||||||
|
return _configure(this, ip6_config_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status groups(bool join_flag, uefi::ipv6_address * group_address) {
|
||||||
|
return _groups(this, join_flag, group_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status routes(bool delete_route, uefi::ipv6_address * destination, uint8_t prefix_length, uefi::ipv6_address * gateway_address) {
|
||||||
|
return _routes(this, delete_route, destination, prefix_length, gateway_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status neighbors(bool delete_flag, uefi::ipv6_address * target_ip6_address, uefi::mac_address * target_link_address, uint32_t timeout, bool override) {
|
||||||
|
return _neighbors(this, delete_flag, target_ip6_address, target_link_address, timeout, override);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status transmit(uefi::ip6_completion_token * token) {
|
||||||
|
return _transmit(this, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status receive(uefi::ip6_completion_token * token) {
|
||||||
|
return _receive(this, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status cancel(uefi::ip6_completion_token * token) {
|
||||||
|
return _cancel(this, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status poll() {
|
||||||
|
return _poll(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using _get_mode_data_def = uefi::status (*)(uefi::protos::ip6 *, uefi::ip6_mode_data *, uefi::managed_network_config_data *, uefi::simple_network_mode *);
|
||||||
|
_get_mode_data_def _get_mode_data;
|
||||||
|
|
||||||
|
using _configure_def = uefi::status (*)(uefi::protos::ip6 *, uefi::ip6_config_data *);
|
||||||
|
_configure_def _configure;
|
||||||
|
|
||||||
|
using _groups_def = uefi::status (*)(uefi::protos::ip6 *, bool, uefi::ipv6_address *);
|
||||||
|
_groups_def _groups;
|
||||||
|
|
||||||
|
using _routes_def = uefi::status (*)(uefi::protos::ip6 *, bool, uefi::ipv6_address *, uint8_t, uefi::ipv6_address *);
|
||||||
|
_routes_def _routes;
|
||||||
|
|
||||||
|
using _neighbors_def = uefi::status (*)(uefi::protos::ip6 *, bool, uefi::ipv6_address *, uefi::mac_address *, uint32_t, bool);
|
||||||
|
_neighbors_def _neighbors;
|
||||||
|
|
||||||
|
using _transmit_def = uefi::status (*)(uefi::protos::ip6 *, uefi::ip6_completion_token *);
|
||||||
|
_transmit_def _transmit;
|
||||||
|
|
||||||
|
using _receive_def = uefi::status (*)(uefi::protos::ip6 *, uefi::ip6_completion_token *);
|
||||||
|
_receive_def _receive;
|
||||||
|
|
||||||
|
using _cancel_def = uefi::status (*)(uefi::protos::ip6 *, uefi::ip6_completion_token *);
|
||||||
|
_cancel_def _cancel;
|
||||||
|
|
||||||
|
using _poll_def = uefi::status (*)(uefi::protos::ip6 *);
|
||||||
|
_poll_def _poll;
|
||||||
|
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace protos
|
||||||
|
} // namespace uefi
|
||||||
|
|
||||||
|
#endif // _uefi_protos_ip6_h_
|
||||||
57
external/uefi/protos/ip6_config.h
vendored
Normal file
57
external/uefi/protos/ip6_config.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _uefi_protos_ip6_config_h_
|
||||||
|
#define _uefi_protos_ip6_config_h_
|
||||||
|
|
||||||
|
// This file was auto generated by the j6-uefi-headers project. Please see
|
||||||
|
// https://github.com/justinian/j6-uefi-headers for more information.
|
||||||
|
|
||||||
|
#include <uefi/guid.h>
|
||||||
|
#include <uefi/types.h>
|
||||||
|
#include <uefi/networking.h>
|
||||||
|
|
||||||
|
namespace uefi {
|
||||||
|
namespace protos {
|
||||||
|
struct ip6_config;
|
||||||
|
|
||||||
|
struct ip6_config
|
||||||
|
{
|
||||||
|
static constexpr uefi::guid guid{ 0x937fe521,0x95ae,0x4d1a,{0x89,0x29,0x48,0xbc,0xd9,0x0a,0xd3,0x1a} };
|
||||||
|
|
||||||
|
|
||||||
|
inline uefi::status set_data(uefi::ip6_config_data_type data_type, size_t data_size, void * data) {
|
||||||
|
return _set_data(this, data_type, data_size, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status get_data(uefi::ip6_config_data_type data_type, size_t data_size, void * data) {
|
||||||
|
return _get_data(this, data_type, data_size, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status register_data_notify(uefi::ip6_config_data_type data_type, uefi::event event) {
|
||||||
|
return _register_data_notify(this, data_type, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status unregister_data_notify(uefi::ip6_config_data_type data_type, uefi::event event) {
|
||||||
|
return _unregister_data_notify(this, data_type, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using _set_data_def = uefi::status (*)(uefi::protos::ip6_config *, uefi::ip6_config_data_type, size_t, void *);
|
||||||
|
_set_data_def _set_data;
|
||||||
|
|
||||||
|
using _get_data_def = uefi::status (*)(uefi::protos::ip6_config *, uefi::ip6_config_data_type, size_t, void *);
|
||||||
|
_get_data_def _get_data;
|
||||||
|
|
||||||
|
using _register_data_notify_def = uefi::status (*)(uefi::protos::ip6_config *, uefi::ip6_config_data_type, uefi::event);
|
||||||
|
_register_data_notify_def _register_data_notify;
|
||||||
|
|
||||||
|
using _unregister_data_notify_def = uefi::status (*)(uefi::protos::ip6_config *, uefi::ip6_config_data_type, uefi::event);
|
||||||
|
_unregister_data_notify_def _unregister_data_notify;
|
||||||
|
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace protos
|
||||||
|
} // namespace uefi
|
||||||
|
|
||||||
|
#endif // _uefi_protos_ip6_config_h_
|
||||||
36
external/uefi/protos/load_file.h
vendored
Normal file
36
external/uefi/protos/load_file.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _uefi_protos_load_file_h_
|
||||||
|
#define _uefi_protos_load_file_h_
|
||||||
|
|
||||||
|
// This file was auto generated by the j6-uefi-headers project. Please see
|
||||||
|
// https://github.com/justinian/j6-uefi-headers for more information.
|
||||||
|
|
||||||
|
#include <uefi/guid.h>
|
||||||
|
#include <uefi/types.h>
|
||||||
|
#include <uefi/protos/device_path.h>
|
||||||
|
|
||||||
|
namespace uefi {
|
||||||
|
namespace protos {
|
||||||
|
struct load_file;
|
||||||
|
|
||||||
|
struct load_file
|
||||||
|
{
|
||||||
|
static constexpr uefi::guid guid{ {0x56ec3091,0x954c,0x11d2,{0x8e,0x3f,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
||||||
|
|
||||||
|
|
||||||
|
inline uefi::status load_file(uefi::protos::device_path * file_path, bool boot_policy, size_t * buffer_size, void * buffer) {
|
||||||
|
return _load_file(this, file_path, boot_policy, buffer_size, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using _load_file_def = uefi::status (*)(uefi::protos::load_file *, uefi::protos::device_path *, bool, size_t *, void *);
|
||||||
|
_load_file_def _load_file;
|
||||||
|
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace protos
|
||||||
|
} // namespace uefi
|
||||||
|
|
||||||
|
#endif // _uefi_protos_load_file_h_
|
||||||
3
external/uefi/protos/loaded_image.h
vendored
3
external/uefi/protos/loaded_image.h
vendored
@@ -18,6 +18,7 @@ struct loaded_image
|
|||||||
{
|
{
|
||||||
static constexpr uefi::guid guid{ 0x5b1b31a1,0x9562,0x11d2,{0x8e,0x3f,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
static constexpr uefi::guid guid{ 0x5b1b31a1,0x9562,0x11d2,{0x8e,0x3f,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
||||||
|
|
||||||
|
|
||||||
inline uefi::status unload(uefi::handle image_handle) {
|
inline uefi::status unload(uefi::handle image_handle) {
|
||||||
return _unload(image_handle);
|
return _unload(image_handle);
|
||||||
}
|
}
|
||||||
@@ -45,4 +46,4 @@ public:
|
|||||||
} // namespace protos
|
} // namespace protos
|
||||||
} // namespace uefi
|
} // namespace uefi
|
||||||
|
|
||||||
#endif // _uefi_protos_loaded_image_h_
|
#endif // _uefi_protos_loaded_image_h_
|
||||||
41
external/uefi/protos/service_binding.h
vendored
Normal file
41
external/uefi/protos/service_binding.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _uefi_protos_service_binding_h_
|
||||||
|
#define _uefi_protos_service_binding_h_
|
||||||
|
|
||||||
|
// This file was auto generated by the j6-uefi-headers project. Please see
|
||||||
|
// https://github.com/justinian/j6-uefi-headers for more information.
|
||||||
|
|
||||||
|
#include <uefi/guid.h>
|
||||||
|
#include <uefi/types.h>
|
||||||
|
|
||||||
|
namespace uefi {
|
||||||
|
namespace protos {
|
||||||
|
struct service_binding;
|
||||||
|
|
||||||
|
struct service_binding
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
inline uefi::status create_child(uefi::handle * child_handle) {
|
||||||
|
return _create_child(this, child_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uefi::status destroy_child(uefi::handle child_handle) {
|
||||||
|
return _destroy_child(this, child_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using _create_child_def = uefi::status (*)(uefi::protos::service_binding *, uefi::handle *);
|
||||||
|
_create_child_def _create_child;
|
||||||
|
|
||||||
|
using _destroy_child_def = uefi::status (*)(uefi::protos::service_binding *, uefi::handle);
|
||||||
|
_destroy_child_def _destroy_child;
|
||||||
|
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace protos
|
||||||
|
} // namespace uefi
|
||||||
|
|
||||||
|
#endif // _uefi_protos_service_binding_h_
|
||||||
3
external/uefi/protos/simple_file_system.h
vendored
3
external/uefi/protos/simple_file_system.h
vendored
@@ -17,6 +17,7 @@ struct simple_file_system
|
|||||||
{
|
{
|
||||||
static constexpr uefi::guid guid{ 0x0964e5b22,0x6459,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
static constexpr uefi::guid guid{ 0x0964e5b22,0x6459,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
||||||
|
|
||||||
|
|
||||||
inline uefi::status open_volume(uefi::protos::file ** root) {
|
inline uefi::status open_volume(uefi::protos::file ** root) {
|
||||||
return _open_volume(this, root);
|
return _open_volume(this, root);
|
||||||
}
|
}
|
||||||
@@ -33,4 +34,4 @@ public:
|
|||||||
} // namespace protos
|
} // namespace protos
|
||||||
} // namespace uefi
|
} // namespace uefi
|
||||||
|
|
||||||
#endif // _uefi_protos_simple_file_system_h_
|
#endif // _uefi_protos_simple_file_system_h_
|
||||||
3
external/uefi/protos/simple_text_output.h
vendored
3
external/uefi/protos/simple_text_output.h
vendored
@@ -17,6 +17,7 @@ struct simple_text_output
|
|||||||
{
|
{
|
||||||
static constexpr uefi::guid guid{ 0x387477c2,0x69c7,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
static constexpr uefi::guid guid{ 0x387477c2,0x69c7,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
|
||||||
|
|
||||||
|
|
||||||
inline uefi::status reset(bool extended_verification) {
|
inline uefi::status reset(bool extended_verification) {
|
||||||
return _reset(this, extended_verification);
|
return _reset(this, extended_verification);
|
||||||
}
|
}
|
||||||
@@ -89,4 +90,4 @@ public:
|
|||||||
} // namespace protos
|
} // namespace protos
|
||||||
} // namespace uefi
|
} // namespace uefi
|
||||||
|
|
||||||
#endif // _uefi_protos_simple_text_output_h_
|
#endif // _uefi_protos_simple_text_output_h_
|
||||||
33
external/zstd.module
vendored
Normal file
33
external/zstd.module
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# vim: ft=python
|
||||||
|
|
||||||
|
zstd = module("zstd",
|
||||||
|
root = "${source_root}/external/zstd",
|
||||||
|
kind = "lib",
|
||||||
|
copy_headers = True,
|
||||||
|
deps = [ "libc" ],
|
||||||
|
sources = [
|
||||||
|
"decompress/zstd_decompress.c",
|
||||||
|
"decompress/zstd_ddict.c",
|
||||||
|
"decompress/huf_decompress.c",
|
||||||
|
"decompress/zstd_decompress_block.c",
|
||||||
|
"common/threading.c",
|
||||||
|
"common/fse_decompress.c",
|
||||||
|
"common/debug.c",
|
||||||
|
"common/xxhash.c",
|
||||||
|
"common/pool.c",
|
||||||
|
"common/error_private.c",
|
||||||
|
"common/entropy_common.c",
|
||||||
|
"common/zstd_common.c",
|
||||||
|
],
|
||||||
|
public_headers = [
|
||||||
|
"zdict.h",
|
||||||
|
"zstd.h",
|
||||||
|
"zstd_errors.h",
|
||||||
|
])
|
||||||
|
|
||||||
|
zstd.variables['ccflags'] = [
|
||||||
|
"${ccflags}",
|
||||||
|
"-DXXH_NAMESPACE=ZSTD_",
|
||||||
|
"-DDEBUGLEVEL=0",
|
||||||
|
"-DZSTD_DISABLE_ASM",
|
||||||
|
]
|
||||||
3
external/zstd/.gitignore
vendored
Normal file
3
external/zstd/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# make install artefact
|
||||||
|
libzstd.pc
|
||||||
|
libzstd-nomt
|
||||||
232
external/zstd/BUCK
vendored
Normal file
232
external/zstd/BUCK
vendored
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
cxx_library(
|
||||||
|
name='zstd',
|
||||||
|
header_namespace='',
|
||||||
|
exported_headers=['zstd.h'],
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
deps=[
|
||||||
|
':common',
|
||||||
|
':compress',
|
||||||
|
':decompress',
|
||||||
|
':deprecated',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='compress',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('compress', 'zstd*.h'),
|
||||||
|
]),
|
||||||
|
srcs=glob(['compress/zstd*.c', 'compress/hist.c']),
|
||||||
|
deps=[':common'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='decompress',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
headers=subdir_glob([
|
||||||
|
('decompress', '*_impl.h'),
|
||||||
|
]),
|
||||||
|
srcs=glob(['decompress/zstd*.c']),
|
||||||
|
deps=[
|
||||||
|
':common',
|
||||||
|
':legacy',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='deprecated',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('deprecated', '*.h'),
|
||||||
|
]),
|
||||||
|
srcs=glob(['deprecated/*.c']),
|
||||||
|
deps=[':common'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='legacy',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('legacy', '*.h'),
|
||||||
|
]),
|
||||||
|
srcs=glob(['legacy/*.c']),
|
||||||
|
deps=[':common'],
|
||||||
|
exported_preprocessor_flags=[
|
||||||
|
'-DZSTD_LEGACY_SUPPORT=4',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='zdict',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=['zdict.h'],
|
||||||
|
headers=subdir_glob([
|
||||||
|
('dictBuilder', 'divsufsort.h'),
|
||||||
|
('dictBuilder', 'cover.h'),
|
||||||
|
]),
|
||||||
|
srcs=glob(['dictBuilder/*.c']),
|
||||||
|
deps=[':common'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='compiler',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'compiler.h'),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='cpu',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'cpu.h'),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='bitstream',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'bitstream.h'),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='entropy',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'fse.h'),
|
||||||
|
('common', 'huf.h'),
|
||||||
|
]),
|
||||||
|
srcs=[
|
||||||
|
'common/entropy_common.c',
|
||||||
|
'common/fse_decompress.c',
|
||||||
|
'compress/fse_compress.c',
|
||||||
|
'compress/huf_compress.c',
|
||||||
|
'decompress/huf_decompress.c',
|
||||||
|
],
|
||||||
|
deps=[
|
||||||
|
':debug',
|
||||||
|
':bitstream',
|
||||||
|
':compiler',
|
||||||
|
':errors',
|
||||||
|
':mem',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='errors',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=[
|
||||||
|
'zstd_errors.h',
|
||||||
|
'common/error_private.h',
|
||||||
|
]
|
||||||
|
srcs=['common/error_private.c'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='mem',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'mem.h'),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='pool',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'pool.h'),
|
||||||
|
]),
|
||||||
|
srcs=['common/pool.c'],
|
||||||
|
deps=[
|
||||||
|
':threading',
|
||||||
|
':zstd_common',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='threading',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'threading.h'),
|
||||||
|
]),
|
||||||
|
srcs=['common/threading.c'],
|
||||||
|
exported_preprocessor_flags=[
|
||||||
|
'-DZSTD_MULTITHREAD',
|
||||||
|
],
|
||||||
|
exported_linker_flags=[
|
||||||
|
'-pthread',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='xxhash',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'xxhash.h'),
|
||||||
|
]),
|
||||||
|
srcs=['common/xxhash.c'],
|
||||||
|
exported_preprocessor_flags=[
|
||||||
|
'-DXXH_NAMESPACE=ZSTD_',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='zstd_common',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('', 'zstd.h'),
|
||||||
|
('common', 'zstd_internal.h'),
|
||||||
|
]),
|
||||||
|
srcs=['common/zstd_common.c'],
|
||||||
|
deps=[
|
||||||
|
':compiler',
|
||||||
|
':errors',
|
||||||
|
':mem',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='debug',
|
||||||
|
header_namespace='',
|
||||||
|
visibility=['PUBLIC'],
|
||||||
|
exported_headers=subdir_glob([
|
||||||
|
('common', 'debug.h'),
|
||||||
|
]),
|
||||||
|
srcs=['common/debug.c'],
|
||||||
|
)
|
||||||
|
|
||||||
|
cxx_library(
|
||||||
|
name='common',
|
||||||
|
deps=[
|
||||||
|
':debug',
|
||||||
|
':bitstream',
|
||||||
|
':compiler',
|
||||||
|
':cpu',
|
||||||
|
':entropy',
|
||||||
|
':errors',
|
||||||
|
':mem',
|
||||||
|
':pool',
|
||||||
|
':threading',
|
||||||
|
':xxhash',
|
||||||
|
':zstd_common',
|
||||||
|
]
|
||||||
|
)
|
||||||
30
external/zstd/LICENSE
vendored
Normal file
30
external/zstd/LICENSE
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
BSD License
|
||||||
|
|
||||||
|
For Zstandard software
|
||||||
|
|
||||||
|
Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name Facebook, nor Meta, nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
357
external/zstd/Makefile
vendored
Normal file
357
external/zstd/Makefile
vendored
Normal file
@@ -0,0 +1,357 @@
|
|||||||
|
# ################################################################
|
||||||
|
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# This source code is licensed under both the BSD-style license (found in the
|
||||||
|
# LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
# in the COPYING file in the root directory of this source tree).
|
||||||
|
# You may select, at your option, one of the above-listed licenses.
|
||||||
|
# ################################################################
|
||||||
|
|
||||||
|
# Modules
|
||||||
|
ZSTD_LIB_COMPRESSION ?= 1
|
||||||
|
ZSTD_LIB_DECOMPRESSION ?= 1
|
||||||
|
ZSTD_LIB_DICTBUILDER ?= 1
|
||||||
|
ZSTD_LIB_DEPRECATED ?= 0
|
||||||
|
|
||||||
|
# Input variables for libzstd.mk
|
||||||
|
ifeq ($(ZSTD_LIB_COMPRESSION), 0)
|
||||||
|
ZSTD_LIB_DICTBUILDER = 0
|
||||||
|
ZSTD_LIB_DEPRECATED = 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ZSTD_LIB_DECOMPRESSION), 0)
|
||||||
|
ZSTD_LEGACY_SUPPORT = 0
|
||||||
|
ZSTD_LIB_DEPRECATED = 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
include libzstd.mk
|
||||||
|
|
||||||
|
ZSTD_FILES := $(ZSTD_COMMON_FILES) $(ZSTD_LEGACY_FILES)
|
||||||
|
|
||||||
|
ifneq ($(ZSTD_LIB_COMPRESSION), 0)
|
||||||
|
ZSTD_FILES += $(ZSTD_COMPRESS_FILES)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(ZSTD_LIB_DECOMPRESSION), 0)
|
||||||
|
ZSTD_FILES += $(ZSTD_DECOMPRESS_FILES)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(ZSTD_LIB_DEPRECATED), 0)
|
||||||
|
ZSTD_FILES += $(ZSTD_DEPRECATED_FILES)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(ZSTD_LIB_DICTBUILDER), 0)
|
||||||
|
ZSTD_FILES += $(ZSTD_DICTBUILDER_FILES)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ZSTD_LOCAL_SRC := $(notdir $(ZSTD_FILES))
|
||||||
|
ZSTD_LOCAL_OBJ0 := $(ZSTD_LOCAL_SRC:.c=.o)
|
||||||
|
ZSTD_LOCAL_OBJ := $(ZSTD_LOCAL_OBJ0:.S=.o)
|
||||||
|
|
||||||
|
VERSION := $(ZSTD_VERSION)
|
||||||
|
|
||||||
|
# Note: by default, the static library is built single-threaded and dynamic library is built
|
||||||
|
# multi-threaded. It is possible to force multi or single threaded builds by appending
|
||||||
|
# -mt or -nomt to the build target (like lib-mt for multi-threaded, lib-nomt for single-threaded).
|
||||||
|
.PHONY: default
|
||||||
|
default: lib-release
|
||||||
|
|
||||||
|
CPPFLAGS_DYNLIB += -DZSTD_MULTITHREAD # dynamic library build defaults to multi-threaded
|
||||||
|
LDFLAGS_DYNLIB += -pthread
|
||||||
|
CPPFLAGS_STATLIB += # static library build defaults to single-threaded
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(findstring GCC,$(CCVER)),GCC)
|
||||||
|
decompress/zstd_decompress_block.o : CFLAGS+=-fno-tree-vectorize
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
# macOS linker doesn't support -soname, and use different extension
|
||||||
|
# see : https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html
|
||||||
|
ifeq ($(UNAME), Darwin)
|
||||||
|
SHARED_EXT = dylib
|
||||||
|
SHARED_EXT_MAJOR = $(LIBVER_MAJOR).$(SHARED_EXT)
|
||||||
|
SHARED_EXT_VER = $(LIBVER).$(SHARED_EXT)
|
||||||
|
SONAME_FLAGS = -install_name $(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR) -compatibility_version $(LIBVER_MAJOR) -current_version $(LIBVER)
|
||||||
|
else
|
||||||
|
ifeq ($(UNAME), AIX)
|
||||||
|
SONAME_FLAGS =
|
||||||
|
else
|
||||||
|
SONAME_FLAGS = -Wl,-soname=libzstd.$(SHARED_EXT).$(LIBVER_MAJOR)
|
||||||
|
endif
|
||||||
|
SHARED_EXT = so
|
||||||
|
SHARED_EXT_MAJOR = $(SHARED_EXT).$(LIBVER_MAJOR)
|
||||||
|
SHARED_EXT_VER = $(SHARED_EXT).$(LIBVER)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: lib
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: libzstd.a # must be run every time
|
||||||
|
libzstd.a: CPPFLAGS += $(CPPFLAGS_STATLIB)
|
||||||
|
|
||||||
|
SET_CACHE_DIRECTORY = \
|
||||||
|
+$(MAKE) --no-print-directory $@ \
|
||||||
|
BUILD_DIR=obj/$(HASH_DIR) \
|
||||||
|
CPPFLAGS="$(CPPFLAGS)" \
|
||||||
|
CFLAGS="$(CFLAGS)" \
|
||||||
|
LDFLAGS="$(LDFLAGS)"
|
||||||
|
|
||||||
|
ifndef BUILD_DIR
|
||||||
|
# determine BUILD_DIR from compilation flags
|
||||||
|
|
||||||
|
libzstd.a:
|
||||||
|
$(SET_CACHE_DIRECTORY)
|
||||||
|
|
||||||
|
else
|
||||||
|
# BUILD_DIR is defined
|
||||||
|
|
||||||
|
ZSTD_STATLIB_DIR := $(BUILD_DIR)/static
|
||||||
|
ZSTD_STATLIB := $(ZSTD_STATLIB_DIR)/libzstd.a
|
||||||
|
ZSTD_STATLIB_OBJ := $(addprefix $(ZSTD_STATLIB_DIR)/,$(ZSTD_LOCAL_OBJ))
|
||||||
|
$(ZSTD_STATLIB): ARFLAGS = rcs
|
||||||
|
$(ZSTD_STATLIB): | $(ZSTD_STATLIB_DIR)
|
||||||
|
$(ZSTD_STATLIB): $(ZSTD_STATLIB_OBJ)
|
||||||
|
# Check for multithread flag at target execution time
|
||||||
|
$(if $(filter -DZSTD_MULTITHREAD,$(CPPFLAGS)),\
|
||||||
|
@echo compiling multi-threaded static library $(LIBVER),\
|
||||||
|
@echo compiling single-threaded static library $(LIBVER))
|
||||||
|
$(AR) $(ARFLAGS) $@ $^
|
||||||
|
|
||||||
|
libzstd.a: $(ZSTD_STATLIB)
|
||||||
|
cp -f $< $@
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter Windows%,$(TARGET_SYSTEM)))
|
||||||
|
|
||||||
|
LIBZSTD = dll/libzstd.dll
|
||||||
|
$(LIBZSTD): $(ZSTD_FILES)
|
||||||
|
@echo compiling dynamic library $(LIBVER)
|
||||||
|
$(CC) $(FLAGS) -DZSTD_DLL_EXPORT=1 -Wl,--out-implib,dll/libzstd.dll.a -shared $^ -o $@
|
||||||
|
|
||||||
|
else # not Windows
|
||||||
|
|
||||||
|
LIBZSTD = libzstd.$(SHARED_EXT_VER)
|
||||||
|
.PHONY: $(LIBZSTD) # must be run every time
|
||||||
|
$(LIBZSTD): CPPFLAGS += $(CPPFLAGS_DYNLIB)
|
||||||
|
$(LIBZSTD): CFLAGS += -fPIC -fvisibility=hidden
|
||||||
|
$(LIBZSTD): LDFLAGS += -shared $(LDFLAGS_DYNLIB)
|
||||||
|
|
||||||
|
ifndef BUILD_DIR
|
||||||
|
# determine BUILD_DIR from compilation flags
|
||||||
|
|
||||||
|
$(LIBZSTD):
|
||||||
|
$(SET_CACHE_DIRECTORY)
|
||||||
|
|
||||||
|
else
|
||||||
|
# BUILD_DIR is defined
|
||||||
|
|
||||||
|
ZSTD_DYNLIB_DIR := $(BUILD_DIR)/dynamic
|
||||||
|
ZSTD_DYNLIB := $(ZSTD_DYNLIB_DIR)/$(LIBZSTD)
|
||||||
|
ZSTD_DYNLIB_OBJ := $(addprefix $(ZSTD_DYNLIB_DIR)/,$(ZSTD_LOCAL_OBJ))
|
||||||
|
|
||||||
|
$(ZSTD_DYNLIB): | $(ZSTD_DYNLIB_DIR)
|
||||||
|
$(ZSTD_DYNLIB): $(ZSTD_DYNLIB_OBJ)
|
||||||
|
# Check for multithread flag at target execution time
|
||||||
|
$(if $(filter -DZSTD_MULTITHREAD,$(CPPFLAGS)),\
|
||||||
|
@echo compiling multi-threaded dynamic library $(LIBVER),\
|
||||||
|
@echo compiling single-threaded dynamic library $(LIBVER))
|
||||||
|
$(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@
|
||||||
|
@echo creating versioned links
|
||||||
|
ln -sf $@ libzstd.$(SHARED_EXT_MAJOR)
|
||||||
|
ln -sf $@ libzstd.$(SHARED_EXT)
|
||||||
|
|
||||||
|
$(LIBZSTD): $(ZSTD_DYNLIB)
|
||||||
|
cp -f $< $@
|
||||||
|
|
||||||
|
endif # ifndef BUILD_DIR
|
||||||
|
endif # if windows
|
||||||
|
|
||||||
|
.PHONY: libzstd
|
||||||
|
libzstd : $(LIBZSTD)
|
||||||
|
|
||||||
|
.PHONY: lib
|
||||||
|
lib : libzstd.a libzstd
|
||||||
|
|
||||||
|
|
||||||
|
# note : do not define lib-mt or lib-release as .PHONY
|
||||||
|
# make does not consider implicit pattern rule for .PHONY target
|
||||||
|
|
||||||
|
%-mt : CPPFLAGS_DYNLIB := -DZSTD_MULTITHREAD
|
||||||
|
%-mt : CPPFLAGS_STATLIB := -DZSTD_MULTITHREAD
|
||||||
|
%-mt : LDFLAGS_DYNLIB := -pthread
|
||||||
|
%-mt : %
|
||||||
|
@echo multi-threaded build completed
|
||||||
|
|
||||||
|
%-nomt : CPPFLAGS_DYNLIB :=
|
||||||
|
%-nomt : LDFLAGS_DYNLIB :=
|
||||||
|
%-nomt : CPPFLAGS_STATLIB :=
|
||||||
|
%-nomt : %
|
||||||
|
@echo single-threaded build completed
|
||||||
|
|
||||||
|
%-release : DEBUGFLAGS :=
|
||||||
|
%-release : %
|
||||||
|
@echo release build completed
|
||||||
|
|
||||||
|
|
||||||
|
# Generate .h dependencies automatically
|
||||||
|
|
||||||
|
DEPFLAGS = -MT $@ -MMD -MP -MF
|
||||||
|
|
||||||
|
$(ZSTD_DYNLIB_DIR)/%.o : %.c $(ZSTD_DYNLIB_DIR)/%.d | $(ZSTD_DYNLIB_DIR)
|
||||||
|
@echo CC $@
|
||||||
|
$(COMPILE.c) $(DEPFLAGS) $(ZSTD_DYNLIB_DIR)/$*.d $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
|
$(ZSTD_STATLIB_DIR)/%.o : %.c $(ZSTD_STATLIB_DIR)/%.d | $(ZSTD_STATLIB_DIR)
|
||||||
|
@echo CC $@
|
||||||
|
$(COMPILE.c) $(DEPFLAGS) $(ZSTD_STATLIB_DIR)/$*.d $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
|
$(ZSTD_DYNLIB_DIR)/%.o : %.S | $(ZSTD_DYNLIB_DIR)
|
||||||
|
@echo AS $@
|
||||||
|
$(COMPILE.S) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
|
$(ZSTD_STATLIB_DIR)/%.o : %.S | $(ZSTD_STATLIB_DIR)
|
||||||
|
@echo AS $@
|
||||||
|
$(COMPILE.S) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
|
MKDIR ?= mkdir
|
||||||
|
$(BUILD_DIR) $(ZSTD_DYNLIB_DIR) $(ZSTD_STATLIB_DIR):
|
||||||
|
$(MKDIR) -p $@
|
||||||
|
|
||||||
|
DEPFILES := $(ZSTD_DYNLIB_OBJ:.o=.d) $(ZSTD_STATLIB_OBJ:.o=.d)
|
||||||
|
$(DEPFILES):
|
||||||
|
|
||||||
|
include $(wildcard $(DEPFILES))
|
||||||
|
|
||||||
|
|
||||||
|
# Special case : building library in single-thread mode _and_ without zstdmt_compress.c
|
||||||
|
ZSTDMT_FILES = compress/zstdmt_compress.c
|
||||||
|
ZSTD_NOMT_FILES = $(filter-out $(ZSTDMT_FILES),$(ZSTD_FILES))
|
||||||
|
libzstd-nomt: CFLAGS += -fPIC -fvisibility=hidden
|
||||||
|
libzstd-nomt: LDFLAGS += -shared
|
||||||
|
libzstd-nomt: $(ZSTD_NOMT_FILES)
|
||||||
|
@echo compiling single-thread dynamic library $(LIBVER)
|
||||||
|
@echo files : $(ZSTD_NOMT_FILES)
|
||||||
|
$(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(RM) -r *.dSYM # macOS-specific
|
||||||
|
$(RM) core *.o *.a *.gcda *.$(SHARED_EXT) *.$(SHARED_EXT).* libzstd.pc
|
||||||
|
$(RM) dll/libzstd.dll dll/libzstd.lib libzstd-nomt*
|
||||||
|
$(RM) -r obj/*
|
||||||
|
@echo Cleaning library completed
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# make install is validated only for below listed environments
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
ifneq (,$(filter $(UNAME),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX))
|
||||||
|
|
||||||
|
lib: libzstd.pc
|
||||||
|
|
||||||
|
HAS_EXPLICIT_EXEC_PREFIX := $(if $(or $(EXEC_PREFIX),$(exec_prefix)),1,)
|
||||||
|
|
||||||
|
DESTDIR ?=
|
||||||
|
# directory variables : GNU conventions prefer lowercase
|
||||||
|
# see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html
|
||||||
|
# support both lower and uppercase (BSD), use uppercase in script
|
||||||
|
prefix ?= /usr/local
|
||||||
|
PREFIX ?= $(prefix)
|
||||||
|
exec_prefix ?= $(PREFIX)
|
||||||
|
EXEC_PREFIX ?= $(exec_prefix)
|
||||||
|
libdir ?= $(EXEC_PREFIX)/lib
|
||||||
|
LIBDIR ?= $(libdir)
|
||||||
|
includedir ?= $(PREFIX)/include
|
||||||
|
INCLUDEDIR ?= $(includedir)
|
||||||
|
|
||||||
|
PCINCDIR := $(patsubst $(PREFIX)%,%,$(INCLUDEDIR))
|
||||||
|
PCLIBDIR := $(patsubst $(EXEC_PREFIX)%,%,$(LIBDIR))
|
||||||
|
|
||||||
|
# If we successfully stripped off a prefix, we'll add a reference to the
|
||||||
|
# relevant pc variable.
|
||||||
|
PCINCPREFIX := $(if $(findstring $(INCLUDEDIR),$(PCINCDIR)),,$${prefix})
|
||||||
|
PCLIBPREFIX := $(if $(findstring $(LIBDIR),$(PCLIBDIR)),,$${exec_prefix})
|
||||||
|
|
||||||
|
# If no explicit EXEC_PREFIX was set by the caller, write it out as a reference
|
||||||
|
# to PREFIX, rather than as a resolved value.
|
||||||
|
PCEXEC_PREFIX := $(if $(HAS_EXPLICIT_EXEC_PREFIX),$(EXEC_PREFIX),$${prefix})
|
||||||
|
|
||||||
|
ifneq (,$(filter $(UNAME),FreeBSD NetBSD DragonFly))
|
||||||
|
PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig
|
||||||
|
else
|
||||||
|
PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter $(UNAME),SunOS))
|
||||||
|
INSTALL ?= ginstall
|
||||||
|
else
|
||||||
|
INSTALL ?= install
|
||||||
|
endif
|
||||||
|
|
||||||
|
INSTALL_PROGRAM ?= $(INSTALL)
|
||||||
|
INSTALL_DATA ?= $(INSTALL) -m 644
|
||||||
|
|
||||||
|
|
||||||
|
libzstd.pc: libzstd.pc.in
|
||||||
|
@echo creating pkgconfig
|
||||||
|
@sed \
|
||||||
|
-e 's|@PREFIX@|$(PREFIX)|' \
|
||||||
|
-e 's|@EXEC_PREFIX@|$(PCEXEC_PREFIX)|' \
|
||||||
|
-e 's|@INCLUDEDIR@|$(PCINCPREFIX)$(PCINCDIR)|' \
|
||||||
|
-e 's|@LIBDIR@|$(PCLIBPREFIX)$(PCLIBDIR)|' \
|
||||||
|
-e 's|@VERSION@|$(VERSION)|' \
|
||||||
|
-e 's|@LIBS_PRIVATE@|$(LDFLAGS_DYNLIB)|' \
|
||||||
|
$< >$@
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install: install-pc install-static install-shared install-includes
|
||||||
|
@echo zstd static and shared library installed
|
||||||
|
|
||||||
|
.PHONY: install-pc
|
||||||
|
install-pc: libzstd.pc
|
||||||
|
[ -e $(DESTDIR)$(PKGCONFIGDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(PKGCONFIGDIR)/
|
||||||
|
$(INSTALL_DATA) libzstd.pc $(DESTDIR)$(PKGCONFIGDIR)/
|
||||||
|
|
||||||
|
.PHONY: install-static
|
||||||
|
install-static:
|
||||||
|
# only generate libzstd.a if it's not already present
|
||||||
|
[ -e libzstd.a ] || $(MAKE) libzstd.a-release
|
||||||
|
[ -e $(DESTDIR)$(LIBDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)/
|
||||||
|
@echo Installing static library
|
||||||
|
$(INSTALL_DATA) libzstd.a $(DESTDIR)$(LIBDIR)
|
||||||
|
|
||||||
|
.PHONY: install-shared
|
||||||
|
install-shared:
|
||||||
|
# only generate libzstd.so if it's not already present
|
||||||
|
[ -e $(LIBZSTD) ] || $(MAKE) libzstd-release
|
||||||
|
[ -e $(DESTDIR)$(LIBDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)/
|
||||||
|
@echo Installing shared library
|
||||||
|
$(INSTALL_PROGRAM) $(LIBZSTD) $(DESTDIR)$(LIBDIR)
|
||||||
|
ln -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR)
|
||||||
|
ln -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT)
|
||||||
|
|
||||||
|
.PHONY: install-includes
|
||||||
|
install-includes:
|
||||||
|
[ -e $(DESTDIR)$(INCLUDEDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/
|
||||||
|
@echo Installing includes
|
||||||
|
$(INSTALL_DATA) zstd.h $(DESTDIR)$(INCLUDEDIR)
|
||||||
|
$(INSTALL_DATA) zstd_errors.h $(DESTDIR)$(INCLUDEDIR)
|
||||||
|
$(INSTALL_DATA) zdict.h $(DESTDIR)$(INCLUDEDIR)
|
||||||
|
|
||||||
|
.PHONY: uninstall
|
||||||
|
uninstall:
|
||||||
|
$(RM) $(DESTDIR)$(LIBDIR)/libzstd.a
|
||||||
|
$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT)
|
||||||
|
$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR)
|
||||||
|
$(RM) $(DESTDIR)$(LIBDIR)/$(LIBZSTD)
|
||||||
|
$(RM) $(DESTDIR)$(PKGCONFIGDIR)/libzstd.pc
|
||||||
|
$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd.h
|
||||||
|
$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd_errors.h
|
||||||
|
$(RM) $(DESTDIR)$(INCLUDEDIR)/zdict.h
|
||||||
|
@echo zstd libraries successfully uninstalled
|
||||||
|
|
||||||
|
endif
|
||||||
224
external/zstd/README.md
vendored
Normal file
224
external/zstd/README.md
vendored
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
Zstandard library files
|
||||||
|
================================
|
||||||
|
|
||||||
|
The __lib__ directory is split into several sub-directories,
|
||||||
|
in order to make it easier to select or exclude features.
|
||||||
|
|
||||||
|
|
||||||
|
#### Building
|
||||||
|
|
||||||
|
`Makefile` script is provided, supporting [Makefile conventions](https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html#Makefile-Conventions),
|
||||||
|
including commands variables, staged install, directory variables and standard targets.
|
||||||
|
- `make` : generates both static and dynamic libraries
|
||||||
|
- `make install` : install libraries and headers in target system directories
|
||||||
|
|
||||||
|
`libzstd` default scope is pretty large, including compression, decompression, dictionary builder,
|
||||||
|
and support for decoding legacy formats >= v0.5.0.
|
||||||
|
The scope can be reduced on demand (see paragraph _modular build_).
|
||||||
|
|
||||||
|
|
||||||
|
#### Multithreading support
|
||||||
|
|
||||||
|
When building with `make`, by default the dynamic library is multithreaded and static library is single-threaded (for compatibility reasons).
|
||||||
|
|
||||||
|
Enabling multithreading requires 2 conditions :
|
||||||
|
- set build macro `ZSTD_MULTITHREAD` (`-DZSTD_MULTITHREAD` for `gcc`)
|
||||||
|
- for POSIX systems : compile with pthread (`-pthread` compilation flag for `gcc`)
|
||||||
|
|
||||||
|
For convenience, we provide a build target to generate multi and single threaded libraries:
|
||||||
|
- Force enable multithreading on both dynamic and static libraries by appending `-mt` to the target, e.g. `make lib-mt`.
|
||||||
|
- Force disable multithreading on both dynamic and static libraries by appending `-nomt` to the target, e.g. `make lib-nomt`.
|
||||||
|
- By default, as mentioned before, dynamic library is multithreaded, and static library is single-threaded, e.g. `make lib`.
|
||||||
|
|
||||||
|
When linking a POSIX program with a multithreaded version of `libzstd`,
|
||||||
|
note that it's necessary to invoke the `-pthread` flag during link stage.
|
||||||
|
|
||||||
|
Multithreading capabilities are exposed
|
||||||
|
via the [advanced API defined in `lib/zstd.h`](https://github.com/facebook/zstd/blob/v1.4.3/lib/zstd.h#L351).
|
||||||
|
|
||||||
|
|
||||||
|
#### API
|
||||||
|
|
||||||
|
Zstandard's stable API is exposed within [lib/zstd.h](zstd.h).
|
||||||
|
|
||||||
|
|
||||||
|
#### Advanced API
|
||||||
|
|
||||||
|
Optional advanced features are exposed via :
|
||||||
|
|
||||||
|
- `lib/zstd_errors.h` : translates `size_t` function results
|
||||||
|
into a `ZSTD_ErrorCode`, for accurate error handling.
|
||||||
|
|
||||||
|
- `ZSTD_STATIC_LINKING_ONLY` : if this macro is defined _before_ including `zstd.h`,
|
||||||
|
it unlocks access to the experimental API,
|
||||||
|
exposed in the second part of `zstd.h`.
|
||||||
|
All definitions in the experimental APIs are unstable,
|
||||||
|
they may still change in the future, or even be removed.
|
||||||
|
As a consequence, experimental definitions shall ___never be used with dynamic library___ !
|
||||||
|
Only static linking is allowed.
|
||||||
|
|
||||||
|
|
||||||
|
#### Modular build
|
||||||
|
|
||||||
|
It's possible to compile only a limited set of features within `libzstd`.
|
||||||
|
The file structure is designed to make this selection manually achievable for any build system :
|
||||||
|
|
||||||
|
- Directory `lib/common` is always required, for all variants.
|
||||||
|
|
||||||
|
- Compression source code lies in `lib/compress`
|
||||||
|
|
||||||
|
- Decompression source code lies in `lib/decompress`
|
||||||
|
|
||||||
|
- It's possible to include only `compress` or only `decompress`, they don't depend on each other.
|
||||||
|
|
||||||
|
- `lib/dictBuilder` : makes it possible to generate dictionaries from a set of samples.
|
||||||
|
The API is exposed in `lib/dictBuilder/zdict.h`.
|
||||||
|
This module depends on both `lib/common` and `lib/compress` .
|
||||||
|
|
||||||
|
- `lib/legacy` : makes it possible to decompress legacy zstd formats, starting from `v0.1.0`.
|
||||||
|
This module depends on `lib/common` and `lib/decompress`.
|
||||||
|
To enable this feature, define `ZSTD_LEGACY_SUPPORT` during compilation.
|
||||||
|
Specifying a number limits versions supported to that version onward.
|
||||||
|
For example, `ZSTD_LEGACY_SUPPORT=2` means : "support legacy formats >= v0.2.0".
|
||||||
|
Conversely, `ZSTD_LEGACY_SUPPORT=0` means "do __not__ support legacy formats".
|
||||||
|
By default, this build macro is set as `ZSTD_LEGACY_SUPPORT=5`.
|
||||||
|
Decoding supported legacy format is a transparent capability triggered within decompression functions.
|
||||||
|
It's also allowed to invoke legacy API directly, exposed in `lib/legacy/zstd_legacy.h`.
|
||||||
|
Each version does also provide its own set of advanced API.
|
||||||
|
For example, advanced API for version `v0.4` is exposed in `lib/legacy/zstd_v04.h` .
|
||||||
|
|
||||||
|
- While invoking `make libzstd`, it's possible to define build macros
|
||||||
|
`ZSTD_LIB_COMPRESSION, ZSTD_LIB_DECOMPRESSION`, `ZSTD_LIB_DICTBUILDER`,
|
||||||
|
and `ZSTD_LIB_DEPRECATED` as `0` to forgo compilation of the
|
||||||
|
corresponding features. This will also disable compilation of all
|
||||||
|
dependencies (e.g. `ZSTD_LIB_COMPRESSION=0` will also disable
|
||||||
|
dictBuilder).
|
||||||
|
|
||||||
|
- There are a number of options that can help minimize the binary size of
|
||||||
|
`libzstd`.
|
||||||
|
|
||||||
|
The first step is to select the components needed (using the above-described
|
||||||
|
`ZSTD_LIB_COMPRESSION` etc.).
|
||||||
|
|
||||||
|
The next step is to set `ZSTD_LIB_MINIFY` to `1` when invoking `make`. This
|
||||||
|
disables various optional components and changes the compilation flags to
|
||||||
|
prioritize space-saving.
|
||||||
|
|
||||||
|
Detailed options: Zstandard's code and build environment is set up by default
|
||||||
|
to optimize above all else for performance. In pursuit of this goal, Zstandard
|
||||||
|
makes significant trade-offs in code size. For example, Zstandard often has
|
||||||
|
more than one implementation of a particular component, with each
|
||||||
|
implementation optimized for different scenarios. For example, the Huffman
|
||||||
|
decoder has complementary implementations that decode the stream one symbol at
|
||||||
|
a time or two symbols at a time. Zstd normally includes both (and dispatches
|
||||||
|
between them at runtime), but by defining `HUF_FORCE_DECOMPRESS_X1` or
|
||||||
|
`HUF_FORCE_DECOMPRESS_X2`, you can force the use of one or the other, avoiding
|
||||||
|
compilation of the other. Similarly, `ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT`
|
||||||
|
and `ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG` force the compilation and use of
|
||||||
|
only one or the other of two decompression implementations. The smallest
|
||||||
|
binary is achieved by using `HUF_FORCE_DECOMPRESS_X1` and
|
||||||
|
`ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT` (implied by `ZSTD_LIB_MINIFY`).
|
||||||
|
|
||||||
|
For squeezing the last ounce of size out, you can also define
|
||||||
|
`ZSTD_NO_INLINE`, which disables inlining, and `ZSTD_STRIP_ERROR_STRINGS`,
|
||||||
|
which removes the error messages that are otherwise returned by
|
||||||
|
`ZSTD_getErrorName` (implied by `ZSTD_LIB_MINIFY`).
|
||||||
|
|
||||||
|
Finally, when integrating into your application, make sure you're doing link-
|
||||||
|
time optimization and unused symbol garbage collection (via some combination of,
|
||||||
|
e.g., `-flto`, `-ffat-lto-objects`, `-fuse-linker-plugin`,
|
||||||
|
`-ffunction-sections`, `-fdata-sections`, `-fmerge-all-constants`,
|
||||||
|
`-Wl,--gc-sections`, `-Wl,-z,norelro`, and an archiver that understands
|
||||||
|
the compiler's intermediate representation, e.g., `AR=gcc-ar`). Consult your
|
||||||
|
compiler's documentation.
|
||||||
|
|
||||||
|
- While invoking `make libzstd`, the build macro `ZSTD_LEGACY_MULTITHREADED_API=1`
|
||||||
|
will expose the deprecated `ZSTDMT` API exposed by `zstdmt_compress.h` in
|
||||||
|
the shared library, which is now hidden by default.
|
||||||
|
|
||||||
|
- The build macro `DYNAMIC_BMI2` can be set to 1 or 0 in order to generate binaries
|
||||||
|
which can detect at runtime the presence of BMI2 instructions, and use them only if present.
|
||||||
|
These instructions contribute to better performance, notably on the decoder side.
|
||||||
|
By default, this feature is automatically enabled on detecting
|
||||||
|
the right instruction set (x64) and compiler (clang or gcc >= 5).
|
||||||
|
It's obviously disabled for different cpus,
|
||||||
|
or when BMI2 instruction set is _required_ by the compiler command line
|
||||||
|
(in this case, only the BMI2 code path is generated).
|
||||||
|
Setting this macro will either force to generate the BMI2 dispatcher (1)
|
||||||
|
or prevent it (0). It overrides automatic detection.
|
||||||
|
|
||||||
|
- The build macro `ZSTD_NO_UNUSED_FUNCTIONS` can be defined to hide the definitions of functions
|
||||||
|
that zstd does not use. Not all unused functions are hidden, but they can be if needed.
|
||||||
|
Currently, this macro will hide function definitions in FSE and HUF that use an excessive
|
||||||
|
amount of stack space.
|
||||||
|
|
||||||
|
- The build macro `ZSTD_NO_INTRINSICS` can be defined to disable all explicit intrinsics.
|
||||||
|
Compiler builtins are still used.
|
||||||
|
|
||||||
|
- The build macro `ZSTD_DECODER_INTERNAL_BUFFER` can be set to control
|
||||||
|
the amount of extra memory used during decompression to store literals.
|
||||||
|
This defaults to 64kB. Reducing this value reduces the memory footprint of
|
||||||
|
`ZSTD_DCtx` decompression contexts,
|
||||||
|
but might also result in a small decompression speed cost.
|
||||||
|
|
||||||
|
- The C compiler macros `ZSTDLIB_VISIBLE`, `ZSTDERRORLIB_VISIBLE` and `ZDICTLIB_VISIBLE`
|
||||||
|
can be overridden to control the visibility of zstd's API. Additionally,
|
||||||
|
`ZSTDLIB_STATIC_API` and `ZDICTLIB_STATIC_API` can be overridden to control the visibility
|
||||||
|
of zstd's static API. Specifically, it can be set to `ZSTDLIB_HIDDEN` to hide the symbols
|
||||||
|
from the shared library. These macros default to `ZSTDLIB_VISIBILITY`,
|
||||||
|
`ZSTDERRORLIB_VSIBILITY`, and `ZDICTLIB_VISIBILITY` if unset, for backwards compatibility
|
||||||
|
with the old macro names.
|
||||||
|
|
||||||
|
#### Windows : using MinGW+MSYS to create DLL
|
||||||
|
|
||||||
|
DLL can be created using MinGW+MSYS with the `make libzstd` command.
|
||||||
|
This command creates `dll\libzstd.dll` and the import library `dll\libzstd.lib`.
|
||||||
|
The import library is only required with Visual C++.
|
||||||
|
The header file `zstd.h` and the dynamic library `dll\libzstd.dll` are required to
|
||||||
|
compile a project using gcc/MinGW.
|
||||||
|
The dynamic library has to be added to linking options.
|
||||||
|
It means that if a project that uses ZSTD consists of a single `test-dll.c`
|
||||||
|
file it should be linked with `dll\libzstd.dll`. For example:
|
||||||
|
```
|
||||||
|
gcc $(CFLAGS) -Iinclude/ test-dll.c -o test-dll dll\libzstd.dll
|
||||||
|
```
|
||||||
|
The compiled executable will require ZSTD DLL which is available at `dll\libzstd.dll`.
|
||||||
|
|
||||||
|
|
||||||
|
#### Advanced Build options
|
||||||
|
|
||||||
|
The build system requires a hash function in order to
|
||||||
|
separate object files created with different compilation flags.
|
||||||
|
By default, it tries to use `md5sum` or equivalent.
|
||||||
|
The hash function can be manually switched by setting the `HASH` variable.
|
||||||
|
For example : `make HASH=xxhsum`
|
||||||
|
The hash function needs to generate at least 64-bit using hexadecimal format.
|
||||||
|
When no hash function is found,
|
||||||
|
the Makefile just generates all object files into the same default directory,
|
||||||
|
irrespective of compilation flags.
|
||||||
|
This functionality only matters if `libzstd` is compiled multiple times
|
||||||
|
with different build flags.
|
||||||
|
|
||||||
|
The build directory, where object files are stored
|
||||||
|
can also be manually controlled using variable `BUILD_DIR`,
|
||||||
|
for example `make BUILD_DIR=objectDir/v1`.
|
||||||
|
In which case, the hash function doesn't matter.
|
||||||
|
|
||||||
|
|
||||||
|
#### Deprecated API
|
||||||
|
|
||||||
|
Obsolete API on their way out are stored in directory `lib/deprecated`.
|
||||||
|
At this stage, it contains older streaming prototypes, in `lib/deprecated/zbuff.h`.
|
||||||
|
These prototypes will be removed in some future version.
|
||||||
|
Consider migrating code towards supported streaming API exposed in `zstd.h`.
|
||||||
|
|
||||||
|
|
||||||
|
#### Miscellaneous
|
||||||
|
|
||||||
|
The other files are not source code. There are :
|
||||||
|
|
||||||
|
- `BUCK` : support for `buck` build system (https://buckbuild.com/)
|
||||||
|
- `Makefile` : `make` script to build and install zstd library (static and dynamic)
|
||||||
|
- `README.md` : this file
|
||||||
|
- `dll/` : resources directory for Windows compilation
|
||||||
|
- `libzstd.pc.in` : script for `pkg-config` (used in `make install`)
|
||||||
175
external/zstd/common/bits.h
vendored
Normal file
175
external/zstd/common/bits.h
vendored
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZSTD_BITS_H
|
||||||
|
#define ZSTD_BITS_H
|
||||||
|
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
MEM_STATIC unsigned ZSTD_countTrailingZeros32_fallback(U32 val)
|
||||||
|
{
|
||||||
|
assert(val != 0);
|
||||||
|
{
|
||||||
|
static const int DeBruijnBytePos[32] = {0, 1, 28, 2, 29, 14, 24, 3,
|
||||||
|
30, 22, 20, 15, 25, 17, 4, 8,
|
||||||
|
31, 27, 13, 23, 21, 19, 16, 7,
|
||||||
|
26, 12, 18, 6, 11, 5, 10, 9};
|
||||||
|
return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> 27];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val)
|
||||||
|
{
|
||||||
|
assert(val != 0);
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# if STATIC_BMI2 == 1
|
||||||
|
return _tzcnt_u32(val);
|
||||||
|
# else
|
||||||
|
if (val != 0) {
|
||||||
|
unsigned long r;
|
||||||
|
_BitScanForward(&r, val);
|
||||||
|
return (unsigned)r;
|
||||||
|
} else {
|
||||||
|
/* Should not reach this code path */
|
||||||
|
__assume(0);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# elif defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
return (unsigned)__builtin_ctz(val);
|
||||||
|
# else
|
||||||
|
return ZSTD_countTrailingZeros32_fallback(val);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val) {
|
||||||
|
assert(val != 0);
|
||||||
|
{
|
||||||
|
static const U32 DeBruijnClz[32] = {0, 9, 1, 10, 13, 21, 2, 29,
|
||||||
|
11, 14, 16, 18, 22, 25, 3, 30,
|
||||||
|
8, 12, 20, 28, 15, 17, 24, 7,
|
||||||
|
19, 27, 23, 6, 26, 5, 4, 31};
|
||||||
|
val |= val >> 1;
|
||||||
|
val |= val >> 2;
|
||||||
|
val |= val >> 4;
|
||||||
|
val |= val >> 8;
|
||||||
|
val |= val >> 16;
|
||||||
|
return 31 - DeBruijnClz[(val * 0x07C4ACDDU) >> 27];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val)
|
||||||
|
{
|
||||||
|
assert(val != 0);
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# if STATIC_BMI2 == 1
|
||||||
|
return _lzcnt_u32(val);
|
||||||
|
# else
|
||||||
|
if (val != 0) {
|
||||||
|
unsigned long r;
|
||||||
|
_BitScanReverse(&r, val);
|
||||||
|
return (unsigned)(31 - r);
|
||||||
|
} else {
|
||||||
|
/* Should not reach this code path */
|
||||||
|
__assume(0);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# elif defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
return (unsigned)__builtin_clz(val);
|
||||||
|
# else
|
||||||
|
return ZSTD_countLeadingZeros32_fallback(val);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val)
|
||||||
|
{
|
||||||
|
assert(val != 0);
|
||||||
|
# if defined(_MSC_VER) && defined(_WIN64)
|
||||||
|
# if STATIC_BMI2 == 1
|
||||||
|
return _tzcnt_u64(val);
|
||||||
|
# else
|
||||||
|
if (val != 0) {
|
||||||
|
unsigned long r;
|
||||||
|
_BitScanForward64(&r, val);
|
||||||
|
return (unsigned)r;
|
||||||
|
} else {
|
||||||
|
/* Should not reach this code path */
|
||||||
|
__assume(0);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__)
|
||||||
|
return (unsigned)__builtin_ctzll(val);
|
||||||
|
# else
|
||||||
|
{
|
||||||
|
U32 mostSignificantWord = (U32)(val >> 32);
|
||||||
|
U32 leastSignificantWord = (U32)val;
|
||||||
|
if (leastSignificantWord == 0) {
|
||||||
|
return 32 + ZSTD_countTrailingZeros32(mostSignificantWord);
|
||||||
|
} else {
|
||||||
|
return ZSTD_countTrailingZeros32(leastSignificantWord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val)
|
||||||
|
{
|
||||||
|
assert(val != 0);
|
||||||
|
# if defined(_MSC_VER) && defined(_WIN64)
|
||||||
|
# if STATIC_BMI2 == 1
|
||||||
|
return _lzcnt_u64(val);
|
||||||
|
# else
|
||||||
|
if (val != 0) {
|
||||||
|
unsigned long r;
|
||||||
|
_BitScanReverse64(&r, val);
|
||||||
|
return (unsigned)(63 - r);
|
||||||
|
} else {
|
||||||
|
/* Should not reach this code path */
|
||||||
|
__assume(0);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# elif defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
return (unsigned)(__builtin_clzll(val));
|
||||||
|
# else
|
||||||
|
{
|
||||||
|
U32 mostSignificantWord = (U32)(val >> 32);
|
||||||
|
U32 leastSignificantWord = (U32)val;
|
||||||
|
if (mostSignificantWord == 0) {
|
||||||
|
return 32 + ZSTD_countLeadingZeros32(leastSignificantWord);
|
||||||
|
} else {
|
||||||
|
return ZSTD_countLeadingZeros32(mostSignificantWord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC unsigned ZSTD_NbCommonBytes(size_t val)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian()) {
|
||||||
|
if (MEM_64bits()) {
|
||||||
|
return ZSTD_countTrailingZeros64((U64)val) >> 3;
|
||||||
|
} else {
|
||||||
|
return ZSTD_countTrailingZeros32((U32)val) >> 3;
|
||||||
|
}
|
||||||
|
} else { /* Big Endian CPU */
|
||||||
|
if (MEM_64bits()) {
|
||||||
|
return ZSTD_countLeadingZeros64((U64)val) >> 3;
|
||||||
|
} else {
|
||||||
|
return ZSTD_countLeadingZeros32((U32)val) >> 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC unsigned ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */
|
||||||
|
{
|
||||||
|
assert(val != 0);
|
||||||
|
return 31 - ZSTD_countLeadingZeros32(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ZSTD_BITS_H */
|
||||||
437
external/zstd/common/bitstream.h
vendored
Normal file
437
external/zstd/common/bitstream.h
vendored
Normal file
@@ -0,0 +1,437 @@
|
|||||||
|
/* ******************************************************************
|
||||||
|
* bitstream
|
||||||
|
* Part of FSE library
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* You can contact the author at :
|
||||||
|
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
****************************************************************** */
|
||||||
|
#ifndef BITSTREAM_H_MODULE
|
||||||
|
#define BITSTREAM_H_MODULE
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* This API consists of small unitary functions, which must be inlined for best performance.
|
||||||
|
* Since link-time-optimization is not available for all compilers,
|
||||||
|
* these functions are defined into a .h to be included.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-****************************************
|
||||||
|
* Dependencies
|
||||||
|
******************************************/
|
||||||
|
#include "mem.h" /* unaligned access routines */
|
||||||
|
#include "compiler.h" /* UNLIKELY() */
|
||||||
|
#include "debug.h" /* assert(), DEBUGLOG(), RAWLOG() */
|
||||||
|
#include "error_private.h" /* error codes and messages */
|
||||||
|
#include "bits.h" /* ZSTD_highbit32 */
|
||||||
|
|
||||||
|
|
||||||
|
/*=========================================
|
||||||
|
* Target specific
|
||||||
|
=========================================*/
|
||||||
|
#ifndef ZSTD_NO_INTRINSICS
|
||||||
|
# if (defined(__BMI__) || defined(__BMI2__)) && defined(__GNUC__)
|
||||||
|
# include <immintrin.h> /* support for bextr (experimental)/bzhi */
|
||||||
|
# elif defined(__ICCARM__)
|
||||||
|
# include <intrinsics.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STREAM_ACCUMULATOR_MIN_32 25
|
||||||
|
#define STREAM_ACCUMULATOR_MIN_64 57
|
||||||
|
#define STREAM_ACCUMULATOR_MIN ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
|
||||||
|
|
||||||
|
|
||||||
|
/*-******************************************
|
||||||
|
* bitStream encoding API (write forward)
|
||||||
|
********************************************/
|
||||||
|
/* bitStream can mix input from multiple sources.
|
||||||
|
* A critical property of these streams is that they encode and decode in **reverse** direction.
|
||||||
|
* So the first bit sequence you add will be the last to be read, like a LIFO stack.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
size_t bitContainer;
|
||||||
|
unsigned bitPos;
|
||||||
|
char* startPtr;
|
||||||
|
char* ptr;
|
||||||
|
char* endPtr;
|
||||||
|
} BIT_CStream_t;
|
||||||
|
|
||||||
|
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);
|
||||||
|
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
|
||||||
|
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC);
|
||||||
|
MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
|
||||||
|
|
||||||
|
/* Start with initCStream, providing the size of buffer to write into.
|
||||||
|
* bitStream will never write outside of this buffer.
|
||||||
|
* `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
|
||||||
|
*
|
||||||
|
* bits are first added to a local register.
|
||||||
|
* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
|
||||||
|
* Writing data into memory is an explicit operation, performed by the flushBits function.
|
||||||
|
* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
|
||||||
|
* After a flushBits, a maximum of 7 bits might still be stored into local register.
|
||||||
|
*
|
||||||
|
* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
|
||||||
|
*
|
||||||
|
* Last operation is to close the bitStream.
|
||||||
|
* The function returns the final size of CStream in bytes.
|
||||||
|
* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*-********************************************
|
||||||
|
* bitStream decoding API (read backward)
|
||||||
|
**********************************************/
|
||||||
|
typedef struct {
|
||||||
|
size_t bitContainer;
|
||||||
|
unsigned bitsConsumed;
|
||||||
|
const char* ptr;
|
||||||
|
const char* start;
|
||||||
|
const char* limitPtr;
|
||||||
|
} BIT_DStream_t;
|
||||||
|
|
||||||
|
typedef enum { BIT_DStream_unfinished = 0,
|
||||||
|
BIT_DStream_endOfBuffer = 1,
|
||||||
|
BIT_DStream_completed = 2,
|
||||||
|
BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */
|
||||||
|
/* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
|
||||||
|
|
||||||
|
MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
|
||||||
|
MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
|
||||||
|
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
|
||||||
|
MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
|
||||||
|
|
||||||
|
|
||||||
|
/* Start by invoking BIT_initDStream().
|
||||||
|
* A chunk of the bitStream is then stored into a local register.
|
||||||
|
* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
|
||||||
|
* You can then retrieve bitFields stored into the local register, **in reverse order**.
|
||||||
|
* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
|
||||||
|
* A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
|
||||||
|
* Otherwise, it can be less than that, so proceed accordingly.
|
||||||
|
* Checking if DStream has reached its end can be performed with BIT_endOfDStream().
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*-****************************************
|
||||||
|
* unsafe API
|
||||||
|
******************************************/
|
||||||
|
MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
|
||||||
|
/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
|
||||||
|
|
||||||
|
MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);
|
||||||
|
/* unsafe version; does not check buffer overflow */
|
||||||
|
|
||||||
|
MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
|
||||||
|
/* faster, but works only if nbBits >= 1 */
|
||||||
|
|
||||||
|
/*===== Local Constants =====*/
|
||||||
|
static const unsigned BIT_mask[] = {
|
||||||
|
0, 1, 3, 7, 0xF, 0x1F,
|
||||||
|
0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF,
|
||||||
|
0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF,
|
||||||
|
0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
|
||||||
|
0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF,
|
||||||
|
0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */
|
||||||
|
#define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0]))
|
||||||
|
|
||||||
|
/*-**************************************************************
|
||||||
|
* bitStream encoding
|
||||||
|
****************************************************************/
|
||||||
|
/*! BIT_initCStream() :
|
||||||
|
* `dstCapacity` must be > sizeof(size_t)
|
||||||
|
* @return : 0 if success,
|
||||||
|
* otherwise an error code (can be tested using ERR_isError()) */
|
||||||
|
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
|
||||||
|
void* startPtr, size_t dstCapacity)
|
||||||
|
{
|
||||||
|
bitC->bitContainer = 0;
|
||||||
|
bitC->bitPos = 0;
|
||||||
|
bitC->startPtr = (char*)startPtr;
|
||||||
|
bitC->ptr = bitC->startPtr;
|
||||||
|
bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);
|
||||||
|
if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
|
||||||
|
{
|
||||||
|
#if defined(STATIC_BMI2) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS)
|
||||||
|
return _bzhi_u64(bitContainer, nbBits);
|
||||||
|
#else
|
||||||
|
assert(nbBits < BIT_MASK_SIZE);
|
||||||
|
return bitContainer & BIT_mask[nbBits];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_addBits() :
|
||||||
|
* can add up to 31 bits into `bitC`.
|
||||||
|
* Note : does not check for register overflow ! */
|
||||||
|
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
|
||||||
|
size_t value, unsigned nbBits)
|
||||||
|
{
|
||||||
|
DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32);
|
||||||
|
assert(nbBits < BIT_MASK_SIZE);
|
||||||
|
assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
|
||||||
|
bitC->bitContainer |= BIT_getLowerBits(value, nbBits) << bitC->bitPos;
|
||||||
|
bitC->bitPos += nbBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_addBitsFast() :
|
||||||
|
* works only if `value` is _clean_,
|
||||||
|
* meaning all high bits above nbBits are 0 */
|
||||||
|
MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
|
||||||
|
size_t value, unsigned nbBits)
|
||||||
|
{
|
||||||
|
assert((value>>nbBits) == 0);
|
||||||
|
assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
|
||||||
|
bitC->bitContainer |= value << bitC->bitPos;
|
||||||
|
bitC->bitPos += nbBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_flushBitsFast() :
|
||||||
|
* assumption : bitContainer has not overflowed
|
||||||
|
* unsafe version; does not check buffer overflow */
|
||||||
|
MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
|
||||||
|
{
|
||||||
|
size_t const nbBytes = bitC->bitPos >> 3;
|
||||||
|
assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
|
||||||
|
assert(bitC->ptr <= bitC->endPtr);
|
||||||
|
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
||||||
|
bitC->ptr += nbBytes;
|
||||||
|
bitC->bitPos &= 7;
|
||||||
|
bitC->bitContainer >>= nbBytes*8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_flushBits() :
|
||||||
|
* assumption : bitContainer has not overflowed
|
||||||
|
* safe version; check for buffer overflow, and prevents it.
|
||||||
|
* note : does not signal buffer overflow.
|
||||||
|
* overflow will be revealed later on using BIT_closeCStream() */
|
||||||
|
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
|
||||||
|
{
|
||||||
|
size_t const nbBytes = bitC->bitPos >> 3;
|
||||||
|
assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
|
||||||
|
assert(bitC->ptr <= bitC->endPtr);
|
||||||
|
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
||||||
|
bitC->ptr += nbBytes;
|
||||||
|
if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
|
||||||
|
bitC->bitPos &= 7;
|
||||||
|
bitC->bitContainer >>= nbBytes*8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_closeCStream() :
|
||||||
|
* @return : size of CStream, in bytes,
|
||||||
|
* or 0 if it could not fit into dstBuffer */
|
||||||
|
MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
|
||||||
|
{
|
||||||
|
BIT_addBitsFast(bitC, 1, 1); /* endMark */
|
||||||
|
BIT_flushBits(bitC);
|
||||||
|
if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
|
||||||
|
return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-********************************************************
|
||||||
|
* bitStream decoding
|
||||||
|
**********************************************************/
|
||||||
|
/*! BIT_initDStream() :
|
||||||
|
* Initialize a BIT_DStream_t.
|
||||||
|
* `bitD` : a pointer to an already allocated BIT_DStream_t structure.
|
||||||
|
* `srcSize` must be the *exact* size of the bitStream, in bytes.
|
||||||
|
* @return : size of stream (== srcSize), or an errorCode if a problem is detected
|
||||||
|
*/
|
||||||
|
MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
|
||||||
|
{
|
||||||
|
if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
|
||||||
|
|
||||||
|
bitD->start = (const char*)srcBuffer;
|
||||||
|
bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
|
||||||
|
|
||||||
|
if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
|
||||||
|
bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
|
||||||
|
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
||||||
|
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||||
|
bitD->bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
|
||||||
|
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
|
||||||
|
} else {
|
||||||
|
bitD->ptr = bitD->start;
|
||||||
|
bitD->bitContainer = *(const BYTE*)(bitD->start);
|
||||||
|
switch(srcSize)
|
||||||
|
{
|
||||||
|
case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
|
||||||
|
ZSTD_FALLTHROUGH;
|
||||||
|
|
||||||
|
case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
|
||||||
|
ZSTD_FALLTHROUGH;
|
||||||
|
|
||||||
|
case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
|
||||||
|
ZSTD_FALLTHROUGH;
|
||||||
|
|
||||||
|
case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
|
||||||
|
ZSTD_FALLTHROUGH;
|
||||||
|
|
||||||
|
case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
|
||||||
|
ZSTD_FALLTHROUGH;
|
||||||
|
|
||||||
|
case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
|
||||||
|
ZSTD_FALLTHROUGH;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||||
|
bitD->bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0;
|
||||||
|
if (lastByte == 0) return ERROR(corruption_detected); /* endMark not present */
|
||||||
|
}
|
||||||
|
bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return srcSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
|
||||||
|
{
|
||||||
|
return bitContainer >> start;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
|
||||||
|
{
|
||||||
|
U32 const regMask = sizeof(bitContainer)*8 - 1;
|
||||||
|
/* if start > regMask, bitstream is corrupted, and result is undefined */
|
||||||
|
assert(nbBits < BIT_MASK_SIZE);
|
||||||
|
/* x86 transform & ((1 << nbBits) - 1) to bzhi instruction, it is better
|
||||||
|
* than accessing memory. When bmi2 instruction is not present, we consider
|
||||||
|
* such cpus old (pre-Haswell, 2013) and their performance is not of that
|
||||||
|
* importance.
|
||||||
|
*/
|
||||||
|
#if defined(__x86_64__) || defined(_M_X86)
|
||||||
|
return (bitContainer >> (start & regMask)) & ((((U64)1) << nbBits) - 1);
|
||||||
|
#else
|
||||||
|
return (bitContainer >> (start & regMask)) & BIT_mask[nbBits];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_lookBits() :
|
||||||
|
* Provides next n bits from local register.
|
||||||
|
* local register is not modified.
|
||||||
|
* On 32-bits, maxNbBits==24.
|
||||||
|
* On 64-bits, maxNbBits==56.
|
||||||
|
* @return : value extracted */
|
||||||
|
MEM_STATIC FORCE_INLINE_ATTR size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
|
||||||
|
{
|
||||||
|
/* arbitrate between double-shift and shift+mask */
|
||||||
|
#if 1
|
||||||
|
/* if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8,
|
||||||
|
* bitstream is likely corrupted, and result is undefined */
|
||||||
|
return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
|
||||||
|
#else
|
||||||
|
/* this code path is slower on my os-x laptop */
|
||||||
|
U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||||
|
return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_lookBitsFast() :
|
||||||
|
* unsafe version; only works if nbBits >= 1 */
|
||||||
|
MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
|
||||||
|
{
|
||||||
|
U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||||
|
assert(nbBits >= 1);
|
||||||
|
return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||||
|
{
|
||||||
|
bitD->bitsConsumed += nbBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_readBits() :
|
||||||
|
* Read (consume) next n bits from local register and update.
|
||||||
|
* Pay attention to not read more than nbBits contained into local register.
|
||||||
|
* @return : extracted value. */
|
||||||
|
MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
|
||||||
|
{
|
||||||
|
size_t const value = BIT_lookBits(bitD, nbBits);
|
||||||
|
BIT_skipBits(bitD, nbBits);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_readBitsFast() :
|
||||||
|
* unsafe version; only works if nbBits >= 1 */
|
||||||
|
MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)
|
||||||
|
{
|
||||||
|
size_t const value = BIT_lookBitsFast(bitD, nbBits);
|
||||||
|
assert(nbBits >= 1);
|
||||||
|
BIT_skipBits(bitD, nbBits);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_reloadDStreamFast() :
|
||||||
|
* Similar to BIT_reloadDStream(), but with two differences:
|
||||||
|
* 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!
|
||||||
|
* 2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this
|
||||||
|
* point you must use BIT_reloadDStream() to reload.
|
||||||
|
*/
|
||||||
|
MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD)
|
||||||
|
{
|
||||||
|
if (UNLIKELY(bitD->ptr < bitD->limitPtr))
|
||||||
|
return BIT_DStream_overflow;
|
||||||
|
assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);
|
||||||
|
bitD->ptr -= bitD->bitsConsumed >> 3;
|
||||||
|
bitD->bitsConsumed &= 7;
|
||||||
|
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
||||||
|
return BIT_DStream_unfinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_reloadDStream() :
|
||||||
|
* Refill `bitD` from buffer previously set in BIT_initDStream() .
|
||||||
|
* This function is safe, it guarantees it will not read beyond src buffer.
|
||||||
|
* @return : status of `BIT_DStream_t` internal register.
|
||||||
|
* when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
|
||||||
|
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
||||||
|
{
|
||||||
|
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
|
||||||
|
return BIT_DStream_overflow;
|
||||||
|
|
||||||
|
if (bitD->ptr >= bitD->limitPtr) {
|
||||||
|
return BIT_reloadDStreamFast(bitD);
|
||||||
|
}
|
||||||
|
if (bitD->ptr == bitD->start) {
|
||||||
|
if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
|
||||||
|
return BIT_DStream_completed;
|
||||||
|
}
|
||||||
|
/* start < ptr < limitPtr */
|
||||||
|
{ U32 nbBytes = bitD->bitsConsumed >> 3;
|
||||||
|
BIT_DStream_status result = BIT_DStream_unfinished;
|
||||||
|
if (bitD->ptr - nbBytes < bitD->start) {
|
||||||
|
nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
|
||||||
|
result = BIT_DStream_endOfBuffer;
|
||||||
|
}
|
||||||
|
bitD->ptr -= nbBytes;
|
||||||
|
bitD->bitsConsumed -= nbBytes*8;
|
||||||
|
bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! BIT_endOfDStream() :
|
||||||
|
* @return : 1 if DStream has _exactly_ reached its end (all bits consumed).
|
||||||
|
*/
|
||||||
|
MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
|
||||||
|
{
|
||||||
|
return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* BITSTREAM_H_MODULE */
|
||||||
343
external/zstd/common/compiler.h
vendored
Normal file
343
external/zstd/common/compiler.h
vendored
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZSTD_COMPILER_H
|
||||||
|
#define ZSTD_COMPILER_H
|
||||||
|
|
||||||
|
#include "portability_macros.h"
|
||||||
|
|
||||||
|
/*-*******************************************************
|
||||||
|
* Compiler specifics
|
||||||
|
*********************************************************/
|
||||||
|
/* force inlining */
|
||||||
|
|
||||||
|
#if !defined(ZSTD_NO_INLINE)
|
||||||
|
#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||||
|
# define INLINE_KEYWORD inline
|
||||||
|
#else
|
||||||
|
# define INLINE_KEYWORD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(__ICCARM__)
|
||||||
|
# define FORCE_INLINE_ATTR __attribute__((always_inline))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define FORCE_INLINE_ATTR __forceinline
|
||||||
|
#else
|
||||||
|
# define FORCE_INLINE_ATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define INLINE_KEYWORD
|
||||||
|
#define FORCE_INLINE_ATTR
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC).
|
||||||
|
This explicitly marks such functions as __cdecl so that the code will still compile
|
||||||
|
if a CC other than __cdecl has been made the default.
|
||||||
|
*/
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define WIN_CDECL __cdecl
|
||||||
|
#else
|
||||||
|
# define WIN_CDECL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
|
||||||
|
* parameters. They must be inlined for the compiler to eliminate the constant
|
||||||
|
* branches.
|
||||||
|
*/
|
||||||
|
#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
|
||||||
|
/**
|
||||||
|
* HINT_INLINE is used to help the compiler generate better code. It is *not*
|
||||||
|
* used for "templates", so it can be tweaked based on the compilers
|
||||||
|
* performance.
|
||||||
|
*
|
||||||
|
* gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the
|
||||||
|
* always_inline attribute.
|
||||||
|
*
|
||||||
|
* clang up to 5.0.0 (trunk) benefit tremendously from the always_inline
|
||||||
|
* attribute.
|
||||||
|
*/
|
||||||
|
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5
|
||||||
|
# define HINT_INLINE static INLINE_KEYWORD
|
||||||
|
#else
|
||||||
|
# define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* UNUSED_ATTR tells the compiler it is okay if the function is unused. */
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define UNUSED_ATTR __attribute__((unused))
|
||||||
|
#else
|
||||||
|
# define UNUSED_ATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* force no inlining */
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# define FORCE_NOINLINE static __declspec(noinline)
|
||||||
|
#else
|
||||||
|
# if defined(__GNUC__) || defined(__ICCARM__)
|
||||||
|
# define FORCE_NOINLINE static __attribute__((__noinline__))
|
||||||
|
# else
|
||||||
|
# define FORCE_NOINLINE static
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* target attribute */
|
||||||
|
#if defined(__GNUC__) || defined(__ICCARM__)
|
||||||
|
# define TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))
|
||||||
|
#else
|
||||||
|
# define TARGET_ATTRIBUTE(target)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Target attribute for BMI2 dynamic dispatch.
|
||||||
|
* Enable lzcnt, bmi, and bmi2.
|
||||||
|
* We test for bmi1 & bmi2. lzcnt is included in bmi1.
|
||||||
|
*/
|
||||||
|
#define BMI2_TARGET_ATTRIBUTE TARGET_ATTRIBUTE("lzcnt,bmi,bmi2")
|
||||||
|
|
||||||
|
/* prefetch
|
||||||
|
* can be disabled, by declaring NO_PREFETCH build macro */
|
||||||
|
#if defined(NO_PREFETCH)
|
||||||
|
# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */
|
||||||
|
# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */
|
||||||
|
#else
|
||||||
|
# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */
|
||||||
|
# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
|
||||||
|
# define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0)
|
||||||
|
# define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1)
|
||||||
|
# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )
|
||||||
|
# define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
|
||||||
|
# define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)
|
||||||
|
# elif defined(__aarch64__)
|
||||||
|
# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr)))
|
||||||
|
# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr)))
|
||||||
|
# else
|
||||||
|
# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */
|
||||||
|
# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */
|
||||||
|
# endif
|
||||||
|
#endif /* NO_PREFETCH */
|
||||||
|
|
||||||
|
#define CACHELINE_SIZE 64
|
||||||
|
|
||||||
|
#define PREFETCH_AREA(p, s) { \
|
||||||
|
const char* const _ptr = (const char*)(p); \
|
||||||
|
size_t const _size = (size_t)(s); \
|
||||||
|
size_t _pos; \
|
||||||
|
for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \
|
||||||
|
PREFETCH_L2(_ptr + _pos); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vectorization
|
||||||
|
* older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax,
|
||||||
|
* and some compilers, like Intel ICC and MCST LCC, do not support it at all. */
|
||||||
|
#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) && !defined(__LCC__)
|
||||||
|
# if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5)
|
||||||
|
# define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
|
||||||
|
# else
|
||||||
|
# define DONT_VECTORIZE _Pragma("GCC optimize(\"no-tree-vectorize\")")
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define DONT_VECTORIZE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Tell the compiler that a branch is likely or unlikely.
|
||||||
|
* Only use these macros if it causes the compiler to generate better code.
|
||||||
|
* If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc
|
||||||
|
* and clang, please do.
|
||||||
|
*/
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define LIKELY(x) (__builtin_expect((x), 1))
|
||||||
|
#define UNLIKELY(x) (__builtin_expect((x), 0))
|
||||||
|
#else
|
||||||
|
#define LIKELY(x) (x)
|
||||||
|
#define UNLIKELY(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_builtin(__builtin_unreachable) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)))
|
||||||
|
# define ZSTD_UNREACHABLE { assert(0), __builtin_unreachable(); }
|
||||||
|
#else
|
||||||
|
# define ZSTD_UNREACHABLE { assert(0); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* disable warnings */
|
||||||
|
#ifdef _MSC_VER /* Visual Studio */
|
||||||
|
# include <intrin.h> /* For Visual 2005 */
|
||||||
|
# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */
|
||||||
|
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||||
|
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
|
||||||
|
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
|
||||||
|
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/
|
||||||
|
#ifndef STATIC_BMI2
|
||||||
|
# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86))
|
||||||
|
# ifdef __AVX2__ //MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2
|
||||||
|
# define STATIC_BMI2 1
|
||||||
|
# endif
|
||||||
|
# elif defined(__BMI2__) && defined(__x86_64__) && defined(__GNUC__)
|
||||||
|
# define STATIC_BMI2 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STATIC_BMI2
|
||||||
|
#define STATIC_BMI2 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* compile time determination of SIMD support */
|
||||||
|
#if !defined(ZSTD_NO_INTRINSICS)
|
||||||
|
# if defined(__SSE2__) || defined(_M_AMD64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2))
|
||||||
|
# define ZSTD_ARCH_X86_SSE2
|
||||||
|
# endif
|
||||||
|
# if defined(__ARM_NEON) || defined(_M_ARM64)
|
||||||
|
# define ZSTD_ARCH_ARM_NEON
|
||||||
|
# endif
|
||||||
|
#
|
||||||
|
# if defined(ZSTD_ARCH_X86_SSE2)
|
||||||
|
# include <emmintrin.h>
|
||||||
|
# elif defined(ZSTD_ARCH_ARM_NEON)
|
||||||
|
# include <arm_neon.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* C-language Attributes are added in C23. */
|
||||||
|
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute)
|
||||||
|
# define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
|
||||||
|
#else
|
||||||
|
# define ZSTD_HAS_C_ATTRIBUTE(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Only use C++ attributes in C++. Some compilers report support for C++
|
||||||
|
* attributes when compiling with C.
|
||||||
|
*/
|
||||||
|
#if defined(__cplusplus) && defined(__has_cpp_attribute)
|
||||||
|
# define ZSTD_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
|
||||||
|
#else
|
||||||
|
# define ZSTD_HAS_CPP_ATTRIBUTE(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define ZSTD_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute.
|
||||||
|
* - C23: https://en.cppreference.com/w/c/language/attributes/fallthrough
|
||||||
|
* - CPP17: https://en.cppreference.com/w/cpp/language/attributes/fallthrough
|
||||||
|
* - Else: __attribute__((__fallthrough__))
|
||||||
|
*/
|
||||||
|
#ifndef ZSTD_FALLTHROUGH
|
||||||
|
# if ZSTD_HAS_C_ATTRIBUTE(fallthrough)
|
||||||
|
# define ZSTD_FALLTHROUGH [[fallthrough]]
|
||||||
|
# elif ZSTD_HAS_CPP_ATTRIBUTE(fallthrough)
|
||||||
|
# define ZSTD_FALLTHROUGH [[fallthrough]]
|
||||||
|
# elif __has_attribute(__fallthrough__)
|
||||||
|
/* Leading semicolon is to satisfy gcc-11 with -pedantic. Without the semicolon
|
||||||
|
* gcc complains about: a label can only be part of a statement and a declaration is not a statement.
|
||||||
|
*/
|
||||||
|
# define ZSTD_FALLTHROUGH ; __attribute__((__fallthrough__))
|
||||||
|
# else
|
||||||
|
# define ZSTD_FALLTHROUGH
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-**************************************************************
|
||||||
|
* Alignment check
|
||||||
|
*****************************************************************/
|
||||||
|
|
||||||
|
/* this test was initially positioned in mem.h,
|
||||||
|
* but this file is removed (or replaced) for linux kernel
|
||||||
|
* so it's now hosted in compiler.h,
|
||||||
|
* which remains valid for both user & kernel spaces.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZSTD_ALIGNOF
|
||||||
|
# if defined(__GNUC__) || defined(_MSC_VER)
|
||||||
|
/* covers gcc, clang & MSVC */
|
||||||
|
/* note : this section must come first, before C11,
|
||||||
|
* due to a limitation in the kernel source generator */
|
||||||
|
# define ZSTD_ALIGNOF(T) __alignof(T)
|
||||||
|
|
||||||
|
# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
||||||
|
/* C11 support */
|
||||||
|
# include <stdalign.h>
|
||||||
|
# define ZSTD_ALIGNOF(T) alignof(T)
|
||||||
|
|
||||||
|
# else
|
||||||
|
/* No known support for alignof() - imperfect backup */
|
||||||
|
# define ZSTD_ALIGNOF(T) (sizeof(void*) < sizeof(T) ? sizeof(void*) : sizeof(T))
|
||||||
|
|
||||||
|
# endif
|
||||||
|
#endif /* ZSTD_ALIGNOF */
|
||||||
|
|
||||||
|
/*-**************************************************************
|
||||||
|
* Sanitizer
|
||||||
|
*****************************************************************/
|
||||||
|
|
||||||
|
#if ZSTD_MEMORY_SANITIZER
|
||||||
|
/* Not all platforms that support msan provide sanitizers/msan_interface.h.
|
||||||
|
* We therefore declare the functions we need ourselves, rather than trying to
|
||||||
|
* include the header file... */
|
||||||
|
#include <stddef.h> /* size_t */
|
||||||
|
#define ZSTD_DEPS_NEED_STDINT
|
||||||
|
#include "zstd_deps.h" /* intptr_t */
|
||||||
|
|
||||||
|
/* Make memory region fully initialized (without changing its contents). */
|
||||||
|
void __msan_unpoison(const volatile void *a, size_t size);
|
||||||
|
|
||||||
|
/* Make memory region fully uninitialized (without changing its contents).
|
||||||
|
This is a legacy interface that does not update origin information. Use
|
||||||
|
__msan_allocated_memory() instead. */
|
||||||
|
void __msan_poison(const volatile void *a, size_t size);
|
||||||
|
|
||||||
|
/* Returns the offset of the first (at least partially) poisoned byte in the
|
||||||
|
memory range, or -1 if the whole range is good. */
|
||||||
|
intptr_t __msan_test_shadow(const volatile void *x, size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ZSTD_ADDRESS_SANITIZER
|
||||||
|
/* Not all platforms that support asan provide sanitizers/asan_interface.h.
|
||||||
|
* We therefore declare the functions we need ourselves, rather than trying to
|
||||||
|
* include the header file... */
|
||||||
|
#include <stddef.h> /* size_t */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable.
|
||||||
|
*
|
||||||
|
* This memory must be previously allocated by your program. Instrumented
|
||||||
|
* code is forbidden from accessing addresses in this region until it is
|
||||||
|
* unpoisoned. This function is not guaranteed to poison the entire region -
|
||||||
|
* it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan
|
||||||
|
* alignment restrictions.
|
||||||
|
*
|
||||||
|
* \note This function is not thread-safe because no two threads can poison or
|
||||||
|
* unpoison memory in the same memory region simultaneously.
|
||||||
|
*
|
||||||
|
* \param addr Start of memory region.
|
||||||
|
* \param size Size of memory region. */
|
||||||
|
void __asan_poison_memory_region(void const volatile *addr, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks a memory region (<c>[addr, addr+size)</c>) as addressable.
|
||||||
|
*
|
||||||
|
* This memory must be previously allocated by your program. Accessing
|
||||||
|
* addresses in this region is allowed until this region is poisoned again.
|
||||||
|
* This function could unpoison a super-region of <c>[addr, addr+size)</c> due
|
||||||
|
* to ASan alignment restrictions.
|
||||||
|
*
|
||||||
|
* \note This function is not thread-safe because no two threads can
|
||||||
|
* poison or unpoison memory in the same memory region simultaneously.
|
||||||
|
*
|
||||||
|
* \param addr Start of memory region.
|
||||||
|
* \param size Size of memory region. */
|
||||||
|
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZSTD_COMPILER_H */
|
||||||
213
external/zstd/common/cpu.h
vendored
Normal file
213
external/zstd/common/cpu.h
vendored
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZSTD_COMMON_CPU_H
|
||||||
|
#define ZSTD_COMMON_CPU_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation taken from folly/CpuId.h
|
||||||
|
* https://github.com/facebook/folly/blob/master/folly/CpuId.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
U32 f1c;
|
||||||
|
U32 f1d;
|
||||||
|
U32 f7b;
|
||||||
|
U32 f7c;
|
||||||
|
} ZSTD_cpuid_t;
|
||||||
|
|
||||||
|
MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
|
||||||
|
U32 f1c = 0;
|
||||||
|
U32 f1d = 0;
|
||||||
|
U32 f7b = 0;
|
||||||
|
U32 f7c = 0;
|
||||||
|
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
|
||||||
|
int reg[4];
|
||||||
|
__cpuid((int*)reg, 0);
|
||||||
|
{
|
||||||
|
int const n = reg[0];
|
||||||
|
if (n >= 1) {
|
||||||
|
__cpuid((int*)reg, 1);
|
||||||
|
f1c = (U32)reg[2];
|
||||||
|
f1d = (U32)reg[3];
|
||||||
|
}
|
||||||
|
if (n >= 7) {
|
||||||
|
__cpuidex((int*)reg, 7, 0);
|
||||||
|
f7b = (U32)reg[1];
|
||||||
|
f7c = (U32)reg[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
|
||||||
|
/* The following block like the normal cpuid branch below, but gcc
|
||||||
|
* reserves ebx for use of its pic register so we must specially
|
||||||
|
* handle the save and restore to avoid clobbering the register
|
||||||
|
*/
|
||||||
|
U32 n;
|
||||||
|
__asm__(
|
||||||
|
"pushl %%ebx\n\t"
|
||||||
|
"cpuid\n\t"
|
||||||
|
"popl %%ebx\n\t"
|
||||||
|
: "=a"(n)
|
||||||
|
: "a"(0)
|
||||||
|
: "ecx", "edx");
|
||||||
|
if (n >= 1) {
|
||||||
|
U32 f1a;
|
||||||
|
__asm__(
|
||||||
|
"pushl %%ebx\n\t"
|
||||||
|
"cpuid\n\t"
|
||||||
|
"popl %%ebx\n\t"
|
||||||
|
: "=a"(f1a), "=c"(f1c), "=d"(f1d)
|
||||||
|
: "a"(1));
|
||||||
|
}
|
||||||
|
if (n >= 7) {
|
||||||
|
__asm__(
|
||||||
|
"pushl %%ebx\n\t"
|
||||||
|
"cpuid\n\t"
|
||||||
|
"movl %%ebx, %%eax\n\t"
|
||||||
|
"popl %%ebx"
|
||||||
|
: "=a"(f7b), "=c"(f7c)
|
||||||
|
: "a"(7), "c"(0)
|
||||||
|
: "edx");
|
||||||
|
}
|
||||||
|
#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__)
|
||||||
|
U32 n;
|
||||||
|
__asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
|
||||||
|
if (n >= 1) {
|
||||||
|
U32 f1a;
|
||||||
|
__asm__("cpuid" : "=a"(f1a), "=c"(f1c), "=d"(f1d) : "a"(1) : "ebx");
|
||||||
|
}
|
||||||
|
if (n >= 7) {
|
||||||
|
U32 f7a;
|
||||||
|
__asm__("cpuid"
|
||||||
|
: "=a"(f7a), "=b"(f7b), "=c"(f7c)
|
||||||
|
: "a"(7), "c"(0)
|
||||||
|
: "edx");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
ZSTD_cpuid_t cpuid;
|
||||||
|
cpuid.f1c = f1c;
|
||||||
|
cpuid.f1d = f1d;
|
||||||
|
cpuid.f7b = f7b;
|
||||||
|
cpuid.f7c = f7c;
|
||||||
|
return cpuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define X(name, r, bit) \
|
||||||
|
MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) { \
|
||||||
|
return ((cpuid.r) & (1U << bit)) != 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cpuid(1): Processor Info and Feature Bits. */
|
||||||
|
#define C(name, bit) X(name, f1c, bit)
|
||||||
|
C(sse3, 0)
|
||||||
|
C(pclmuldq, 1)
|
||||||
|
C(dtes64, 2)
|
||||||
|
C(monitor, 3)
|
||||||
|
C(dscpl, 4)
|
||||||
|
C(vmx, 5)
|
||||||
|
C(smx, 6)
|
||||||
|
C(eist, 7)
|
||||||
|
C(tm2, 8)
|
||||||
|
C(ssse3, 9)
|
||||||
|
C(cnxtid, 10)
|
||||||
|
C(fma, 12)
|
||||||
|
C(cx16, 13)
|
||||||
|
C(xtpr, 14)
|
||||||
|
C(pdcm, 15)
|
||||||
|
C(pcid, 17)
|
||||||
|
C(dca, 18)
|
||||||
|
C(sse41, 19)
|
||||||
|
C(sse42, 20)
|
||||||
|
C(x2apic, 21)
|
||||||
|
C(movbe, 22)
|
||||||
|
C(popcnt, 23)
|
||||||
|
C(tscdeadline, 24)
|
||||||
|
C(aes, 25)
|
||||||
|
C(xsave, 26)
|
||||||
|
C(osxsave, 27)
|
||||||
|
C(avx, 28)
|
||||||
|
C(f16c, 29)
|
||||||
|
C(rdrand, 30)
|
||||||
|
#undef C
|
||||||
|
#define D(name, bit) X(name, f1d, bit)
|
||||||
|
D(fpu, 0)
|
||||||
|
D(vme, 1)
|
||||||
|
D(de, 2)
|
||||||
|
D(pse, 3)
|
||||||
|
D(tsc, 4)
|
||||||
|
D(msr, 5)
|
||||||
|
D(pae, 6)
|
||||||
|
D(mce, 7)
|
||||||
|
D(cx8, 8)
|
||||||
|
D(apic, 9)
|
||||||
|
D(sep, 11)
|
||||||
|
D(mtrr, 12)
|
||||||
|
D(pge, 13)
|
||||||
|
D(mca, 14)
|
||||||
|
D(cmov, 15)
|
||||||
|
D(pat, 16)
|
||||||
|
D(pse36, 17)
|
||||||
|
D(psn, 18)
|
||||||
|
D(clfsh, 19)
|
||||||
|
D(ds, 21)
|
||||||
|
D(acpi, 22)
|
||||||
|
D(mmx, 23)
|
||||||
|
D(fxsr, 24)
|
||||||
|
D(sse, 25)
|
||||||
|
D(sse2, 26)
|
||||||
|
D(ss, 27)
|
||||||
|
D(htt, 28)
|
||||||
|
D(tm, 29)
|
||||||
|
D(pbe, 31)
|
||||||
|
#undef D
|
||||||
|
|
||||||
|
/* cpuid(7): Extended Features. */
|
||||||
|
#define B(name, bit) X(name, f7b, bit)
|
||||||
|
B(bmi1, 3)
|
||||||
|
B(hle, 4)
|
||||||
|
B(avx2, 5)
|
||||||
|
B(smep, 7)
|
||||||
|
B(bmi2, 8)
|
||||||
|
B(erms, 9)
|
||||||
|
B(invpcid, 10)
|
||||||
|
B(rtm, 11)
|
||||||
|
B(mpx, 14)
|
||||||
|
B(avx512f, 16)
|
||||||
|
B(avx512dq, 17)
|
||||||
|
B(rdseed, 18)
|
||||||
|
B(adx, 19)
|
||||||
|
B(smap, 20)
|
||||||
|
B(avx512ifma, 21)
|
||||||
|
B(pcommit, 22)
|
||||||
|
B(clflushopt, 23)
|
||||||
|
B(clwb, 24)
|
||||||
|
B(avx512pf, 26)
|
||||||
|
B(avx512er, 27)
|
||||||
|
B(avx512cd, 28)
|
||||||
|
B(sha, 29)
|
||||||
|
B(avx512bw, 30)
|
||||||
|
B(avx512vl, 31)
|
||||||
|
#undef B
|
||||||
|
#define C(name, bit) X(name, f7c, bit)
|
||||||
|
C(prefetchwt1, 0)
|
||||||
|
C(avx512vbmi, 1)
|
||||||
|
#undef C
|
||||||
|
|
||||||
|
#undef X
|
||||||
|
|
||||||
|
#endif /* ZSTD_COMMON_CPU_H */
|
||||||
24
external/zstd/common/debug.c
vendored
Normal file
24
external/zstd/common/debug.c
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/* ******************************************************************
|
||||||
|
* debug
|
||||||
|
* Part of FSE library
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* You can contact the author at :
|
||||||
|
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
****************************************************************** */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This module only hosts one global variable
|
||||||
|
* which can be used to dynamically influence the verbosity of traces,
|
||||||
|
* such as DEBUGLOG and RAWLOG
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
int g_debuglevel = DEBUGLEVEL;
|
||||||
107
external/zstd/common/debug.h
vendored
Normal file
107
external/zstd/common/debug.h
vendored
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/* ******************************************************************
|
||||||
|
* debug
|
||||||
|
* Part of FSE library
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* You can contact the author at :
|
||||||
|
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
****************************************************************** */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The purpose of this header is to enable debug functions.
|
||||||
|
* They regroup assert(), DEBUGLOG() and RAWLOG() for run-time,
|
||||||
|
* and DEBUG_STATIC_ASSERT() for compile-time.
|
||||||
|
*
|
||||||
|
* By default, DEBUGLEVEL==0, which means run-time debug is disabled.
|
||||||
|
*
|
||||||
|
* Level 1 enables assert() only.
|
||||||
|
* Starting level 2, traces can be generated and pushed to stderr.
|
||||||
|
* The higher the level, the more verbose the traces.
|
||||||
|
*
|
||||||
|
* It's possible to dynamically adjust level using variable g_debug_level,
|
||||||
|
* which is only declared if DEBUGLEVEL>=2,
|
||||||
|
* and is a global variable, not multi-thread protected (use with care)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEBUG_H_12987983217
|
||||||
|
#define DEBUG_H_12987983217
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* static assert is triggered at compile time, leaving no runtime artefact.
|
||||||
|
* static assert only works with compile-time constants.
|
||||||
|
* Also, this variant can only be used inside a function. */
|
||||||
|
#define DEBUG_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1])
|
||||||
|
|
||||||
|
|
||||||
|
/* DEBUGLEVEL is expected to be defined externally,
|
||||||
|
* typically through compiler command line.
|
||||||
|
* Value must be a number. */
|
||||||
|
#ifndef DEBUGLEVEL
|
||||||
|
# define DEBUGLEVEL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* recommended values for DEBUGLEVEL :
|
||||||
|
* 0 : release mode, no debug, all run-time checks disabled
|
||||||
|
* 1 : enables assert() only, no display
|
||||||
|
* 2 : reserved, for currently active debug path
|
||||||
|
* 3 : events once per object lifetime (CCtx, CDict, etc.)
|
||||||
|
* 4 : events once per frame
|
||||||
|
* 5 : events once per block
|
||||||
|
* 6 : events once per sequence (verbose)
|
||||||
|
* 7+: events at every position (*very* verbose)
|
||||||
|
*
|
||||||
|
* It's generally inconvenient to output traces > 5.
|
||||||
|
* In which case, it's possible to selectively trigger high verbosity levels
|
||||||
|
* by modifying g_debug_level.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (DEBUGLEVEL>=1)
|
||||||
|
# define ZSTD_DEPS_NEED_ASSERT
|
||||||
|
# include "zstd_deps.h"
|
||||||
|
#else
|
||||||
|
# ifndef assert /* assert may be already defined, due to prior #include <assert.h> */
|
||||||
|
# define assert(condition) ((void)0) /* disable assert (default) */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (DEBUGLEVEL>=2)
|
||||||
|
# define ZSTD_DEPS_NEED_IO
|
||||||
|
# include "zstd_deps.h"
|
||||||
|
extern int g_debuglevel; /* the variable is only declared,
|
||||||
|
it actually lives in debug.c,
|
||||||
|
and is shared by the whole process.
|
||||||
|
It's not thread-safe.
|
||||||
|
It's useful when enabling very verbose levels
|
||||||
|
on selective conditions (such as position in src) */
|
||||||
|
|
||||||
|
# define RAWLOG(l, ...) { \
|
||||||
|
if (l<=g_debuglevel) { \
|
||||||
|
ZSTD_DEBUG_PRINT(__VA_ARGS__); \
|
||||||
|
} }
|
||||||
|
# define DEBUGLOG(l, ...) { \
|
||||||
|
if (l<=g_debuglevel) { \
|
||||||
|
ZSTD_DEBUG_PRINT(__FILE__ ": " __VA_ARGS__); \
|
||||||
|
ZSTD_DEBUG_PRINT(" \n"); \
|
||||||
|
} }
|
||||||
|
#else
|
||||||
|
# define RAWLOG(l, ...) {} /* disabled */
|
||||||
|
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DEBUG_H_12987983217 */
|
||||||
341
external/zstd/common/entropy_common.c
vendored
Normal file
341
external/zstd/common/entropy_common.c
vendored
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
/* ******************************************************************
|
||||||
|
* Common functions of New Generation Entropy library
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* You can contact the author at :
|
||||||
|
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
* - Public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
****************************************************************** */
|
||||||
|
|
||||||
|
/* *************************************
|
||||||
|
* Dependencies
|
||||||
|
***************************************/
|
||||||
|
#include "mem.h"
|
||||||
|
#include "error_private.h" /* ERR_*, ERROR */
|
||||||
|
#define FSE_STATIC_LINKING_ONLY /* FSE_MIN_TABLELOG */
|
||||||
|
#include "fse.h"
|
||||||
|
#define HUF_STATIC_LINKING_ONLY /* HUF_TABLELOG_ABSOLUTEMAX */
|
||||||
|
#include "huf.h"
|
||||||
|
#include "bits.h" /* ZSDT_highbit32, ZSTD_countTrailingZeros32 */
|
||||||
|
|
||||||
|
|
||||||
|
/*=== Version ===*/
|
||||||
|
unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }
|
||||||
|
|
||||||
|
|
||||||
|
/*=== Error Management ===*/
|
||||||
|
unsigned FSE_isError(size_t code) { return ERR_isError(code); }
|
||||||
|
const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); }
|
||||||
|
|
||||||
|
unsigned HUF_isError(size_t code) { return ERR_isError(code); }
|
||||||
|
const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); }
|
||||||
|
|
||||||
|
|
||||||
|
/*-**************************************************************
|
||||||
|
* FSE NCount encoding-decoding
|
||||||
|
****************************************************************/
|
||||||
|
FORCE_INLINE_TEMPLATE
|
||||||
|
size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
|
||||||
|
const void* headerBuffer, size_t hbSize)
|
||||||
|
{
|
||||||
|
const BYTE* const istart = (const BYTE*) headerBuffer;
|
||||||
|
const BYTE* const iend = istart + hbSize;
|
||||||
|
const BYTE* ip = istart;
|
||||||
|
int nbBits;
|
||||||
|
int remaining;
|
||||||
|
int threshold;
|
||||||
|
U32 bitStream;
|
||||||
|
int bitCount;
|
||||||
|
unsigned charnum = 0;
|
||||||
|
unsigned const maxSV1 = *maxSVPtr + 1;
|
||||||
|
int previous0 = 0;
|
||||||
|
|
||||||
|
if (hbSize < 8) {
|
||||||
|
/* This function only works when hbSize >= 8 */
|
||||||
|
char buffer[8] = {0};
|
||||||
|
ZSTD_memcpy(buffer, headerBuffer, hbSize);
|
||||||
|
{ size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr,
|
||||||
|
buffer, sizeof(buffer));
|
||||||
|
if (FSE_isError(countSize)) return countSize;
|
||||||
|
if (countSize > hbSize) return ERROR(corruption_detected);
|
||||||
|
return countSize;
|
||||||
|
} }
|
||||||
|
assert(hbSize >= 8);
|
||||||
|
|
||||||
|
/* init */
|
||||||
|
ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */
|
||||||
|
bitStream = MEM_readLE32(ip);
|
||||||
|
nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */
|
||||||
|
if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
|
||||||
|
bitStream >>= 4;
|
||||||
|
bitCount = 4;
|
||||||
|
*tableLogPtr = nbBits;
|
||||||
|
remaining = (1<<nbBits)+1;
|
||||||
|
threshold = 1<<nbBits;
|
||||||
|
nbBits++;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (previous0) {
|
||||||
|
/* Count the number of repeats. Each time the
|
||||||
|
* 2-bit repeat code is 0b11 there is another
|
||||||
|
* repeat.
|
||||||
|
* Avoid UB by setting the high bit to 1.
|
||||||
|
*/
|
||||||
|
int repeats = ZSTD_countTrailingZeros32(~bitStream | 0x80000000) >> 1;
|
||||||
|
while (repeats >= 12) {
|
||||||
|
charnum += 3 * 12;
|
||||||
|
if (LIKELY(ip <= iend-7)) {
|
||||||
|
ip += 3;
|
||||||
|
} else {
|
||||||
|
bitCount -= (int)(8 * (iend - 7 - ip));
|
||||||
|
bitCount &= 31;
|
||||||
|
ip = iend - 4;
|
||||||
|
}
|
||||||
|
bitStream = MEM_readLE32(ip) >> bitCount;
|
||||||
|
repeats = ZSTD_countTrailingZeros32(~bitStream | 0x80000000) >> 1;
|
||||||
|
}
|
||||||
|
charnum += 3 * repeats;
|
||||||
|
bitStream >>= 2 * repeats;
|
||||||
|
bitCount += 2 * repeats;
|
||||||
|
|
||||||
|
/* Add the final repeat which isn't 0b11. */
|
||||||
|
assert((bitStream & 3) < 3);
|
||||||
|
charnum += bitStream & 3;
|
||||||
|
bitCount += 2;
|
||||||
|
|
||||||
|
/* This is an error, but break and return an error
|
||||||
|
* at the end, because returning out of a loop makes
|
||||||
|
* it harder for the compiler to optimize.
|
||||||
|
*/
|
||||||
|
if (charnum >= maxSV1) break;
|
||||||
|
|
||||||
|
/* We don't need to set the normalized count to 0
|
||||||
|
* because we already memset the whole buffer to 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
|
||||||
|
assert((bitCount >> 3) <= 3); /* For first condition to work */
|
||||||
|
ip += bitCount>>3;
|
||||||
|
bitCount &= 7;
|
||||||
|
} else {
|
||||||
|
bitCount -= (int)(8 * (iend - 4 - ip));
|
||||||
|
bitCount &= 31;
|
||||||
|
ip = iend - 4;
|
||||||
|
}
|
||||||
|
bitStream = MEM_readLE32(ip) >> bitCount;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int const max = (2*threshold-1) - remaining;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
if ((bitStream & (threshold-1)) < (U32)max) {
|
||||||
|
count = bitStream & (threshold-1);
|
||||||
|
bitCount += nbBits-1;
|
||||||
|
} else {
|
||||||
|
count = bitStream & (2*threshold-1);
|
||||||
|
if (count >= threshold) count -= max;
|
||||||
|
bitCount += nbBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
count--; /* extra accuracy */
|
||||||
|
/* When it matters (small blocks), this is a
|
||||||
|
* predictable branch, because we don't use -1.
|
||||||
|
*/
|
||||||
|
if (count >= 0) {
|
||||||
|
remaining -= count;
|
||||||
|
} else {
|
||||||
|
assert(count == -1);
|
||||||
|
remaining += count;
|
||||||
|
}
|
||||||
|
normalizedCounter[charnum++] = (short)count;
|
||||||
|
previous0 = !count;
|
||||||
|
|
||||||
|
assert(threshold > 1);
|
||||||
|
if (remaining < threshold) {
|
||||||
|
/* This branch can be folded into the
|
||||||
|
* threshold update condition because we
|
||||||
|
* know that threshold > 1.
|
||||||
|
*/
|
||||||
|
if (remaining <= 1) break;
|
||||||
|
nbBits = ZSTD_highbit32(remaining) + 1;
|
||||||
|
threshold = 1 << (nbBits - 1);
|
||||||
|
}
|
||||||
|
if (charnum >= maxSV1) break;
|
||||||
|
|
||||||
|
if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
|
||||||
|
ip += bitCount>>3;
|
||||||
|
bitCount &= 7;
|
||||||
|
} else {
|
||||||
|
bitCount -= (int)(8 * (iend - 4 - ip));
|
||||||
|
bitCount &= 31;
|
||||||
|
ip = iend - 4;
|
||||||
|
}
|
||||||
|
bitStream = MEM_readLE32(ip) >> bitCount;
|
||||||
|
} }
|
||||||
|
if (remaining != 1) return ERROR(corruption_detected);
|
||||||
|
/* Only possible when there are too many zeros. */
|
||||||
|
if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall);
|
||||||
|
if (bitCount > 32) return ERROR(corruption_detected);
|
||||||
|
*maxSVPtr = charnum-1;
|
||||||
|
|
||||||
|
ip += (bitCount+7)>>3;
|
||||||
|
return ip-istart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Avoids the FORCE_INLINE of the _body() function. */
|
||||||
|
static size_t FSE_readNCount_body_default(
|
||||||
|
short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
|
||||||
|
const void* headerBuffer, size_t hbSize)
|
||||||
|
{
|
||||||
|
return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DYNAMIC_BMI2
|
||||||
|
BMI2_TARGET_ATTRIBUTE static size_t FSE_readNCount_body_bmi2(
|
||||||
|
short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
|
||||||
|
const void* headerBuffer, size_t hbSize)
|
||||||
|
{
|
||||||
|
return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t FSE_readNCount_bmi2(
|
||||||
|
short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
|
||||||
|
const void* headerBuffer, size_t hbSize, int bmi2)
|
||||||
|
{
|
||||||
|
#if DYNAMIC_BMI2
|
||||||
|
if (bmi2) {
|
||||||
|
return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
(void)bmi2;
|
||||||
|
return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FSE_readNCount(
|
||||||
|
short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
|
||||||
|
const void* headerBuffer, size_t hbSize)
|
||||||
|
{
|
||||||
|
return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! HUF_readStats() :
|
||||||
|
Read compact Huffman tree, saved by HUF_writeCTable().
|
||||||
|
`huffWeight` is destination buffer.
|
||||||
|
`rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.
|
||||||
|
@return : size read from `src` , or an error Code .
|
||||||
|
Note : Needed by HUF_readCTable() and HUF_readDTableX?() .
|
||||||
|
*/
|
||||||
|
size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||||
|
U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||||
|
const void* src, size_t srcSize)
|
||||||
|
{
|
||||||
|
U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
|
||||||
|
return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* bmi2 */ 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_TEMPLATE size_t
|
||||||
|
HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||||
|
U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
void* workSpace, size_t wkspSize,
|
||||||
|
int bmi2)
|
||||||
|
{
|
||||||
|
U32 weightTotal;
|
||||||
|
const BYTE* ip = (const BYTE*) src;
|
||||||
|
size_t iSize;
|
||||||
|
size_t oSize;
|
||||||
|
|
||||||
|
if (!srcSize) return ERROR(srcSize_wrong);
|
||||||
|
iSize = ip[0];
|
||||||
|
/* ZSTD_memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */
|
||||||
|
|
||||||
|
if (iSize >= 128) { /* special header */
|
||||||
|
oSize = iSize - 127;
|
||||||
|
iSize = ((oSize+1)/2);
|
||||||
|
if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
|
||||||
|
if (oSize >= hwSize) return ERROR(corruption_detected);
|
||||||
|
ip += 1;
|
||||||
|
{ U32 n;
|
||||||
|
for (n=0; n<oSize; n+=2) {
|
||||||
|
huffWeight[n] = ip[n/2] >> 4;
|
||||||
|
huffWeight[n+1] = ip[n/2] & 15;
|
||||||
|
} } }
|
||||||
|
else { /* header compressed with FSE (normal case) */
|
||||||
|
if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
|
||||||
|
/* max (hwSize-1) values decoded, as last one is implied */
|
||||||
|
oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2);
|
||||||
|
if (FSE_isError(oSize)) return oSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* collect weight stats */
|
||||||
|
ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
|
||||||
|
weightTotal = 0;
|
||||||
|
{ U32 n; for (n=0; n<oSize; n++) {
|
||||||
|
if (huffWeight[n] > HUF_TABLELOG_MAX) return ERROR(corruption_detected);
|
||||||
|
rankStats[huffWeight[n]]++;
|
||||||
|
weightTotal += (1 << huffWeight[n]) >> 1;
|
||||||
|
} }
|
||||||
|
if (weightTotal == 0) return ERROR(corruption_detected);
|
||||||
|
|
||||||
|
/* get last non-null symbol weight (implied, total must be 2^n) */
|
||||||
|
{ U32 const tableLog = ZSTD_highbit32(weightTotal) + 1;
|
||||||
|
if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected);
|
||||||
|
*tableLogPtr = tableLog;
|
||||||
|
/* determine last weight */
|
||||||
|
{ U32 const total = 1 << tableLog;
|
||||||
|
U32 const rest = total - weightTotal;
|
||||||
|
U32 const verif = 1 << ZSTD_highbit32(rest);
|
||||||
|
U32 const lastWeight = ZSTD_highbit32(rest) + 1;
|
||||||
|
if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */
|
||||||
|
huffWeight[oSize] = (BYTE)lastWeight;
|
||||||
|
rankStats[lastWeight]++;
|
||||||
|
} }
|
||||||
|
|
||||||
|
/* check tree construction validity */
|
||||||
|
if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */
|
||||||
|
|
||||||
|
/* results */
|
||||||
|
*nbSymbolsPtr = (U32)(oSize+1);
|
||||||
|
return iSize+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Avoids the FORCE_INLINE of the _body() function. */
|
||||||
|
static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||||
|
U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
void* workSpace, size_t wkspSize)
|
||||||
|
{
|
||||||
|
return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DYNAMIC_BMI2
|
||||||
|
static BMI2_TARGET_ATTRIBUTE size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||||
|
U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
void* workSpace, size_t wkspSize)
|
||||||
|
{
|
||||||
|
return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||||
|
U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
void* workSpace, size_t wkspSize,
|
||||||
|
int bmi2)
|
||||||
|
{
|
||||||
|
#if DYNAMIC_BMI2
|
||||||
|
if (bmi2) {
|
||||||
|
return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
(void)bmi2;
|
||||||
|
return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
|
||||||
|
}
|
||||||
60
external/zstd/common/error_private.c
vendored
Normal file
60
external/zstd/common/error_private.c
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The purpose of this file is to have a single list of error strings embedded in binary */
|
||||||
|
|
||||||
|
#include "error_private.h"
|
||||||
|
|
||||||
|
const char* ERR_getErrorString(ERR_enum code)
|
||||||
|
{
|
||||||
|
#ifdef ZSTD_STRIP_ERROR_STRINGS
|
||||||
|
(void)code;
|
||||||
|
return "Error strings stripped";
|
||||||
|
#else
|
||||||
|
static const char* const notErrorCode = "Unspecified error code";
|
||||||
|
switch( code )
|
||||||
|
{
|
||||||
|
case PREFIX(no_error): return "No error detected";
|
||||||
|
case PREFIX(GENERIC): return "Error (generic)";
|
||||||
|
case PREFIX(prefix_unknown): return "Unknown frame descriptor";
|
||||||
|
case PREFIX(version_unsupported): return "Version not supported";
|
||||||
|
case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
|
||||||
|
case PREFIX(frameParameter_windowTooLarge): return "Frame requires too much memory for decoding";
|
||||||
|
case PREFIX(corruption_detected): return "Data corruption detected";
|
||||||
|
case PREFIX(checksum_wrong): return "Restored data doesn't match checksum";
|
||||||
|
case PREFIX(literals_headerWrong): return "Header of Literals' block doesn't respect format specification";
|
||||||
|
case PREFIX(parameter_unsupported): return "Unsupported parameter";
|
||||||
|
case PREFIX(parameter_combination_unsupported): return "Unsupported combination of parameters";
|
||||||
|
case PREFIX(parameter_outOfBound): return "Parameter is out of bound";
|
||||||
|
case PREFIX(init_missing): return "Context should be init first";
|
||||||
|
case PREFIX(memory_allocation): return "Allocation error : not enough memory";
|
||||||
|
case PREFIX(workSpace_tooSmall): return "workSpace buffer is not large enough";
|
||||||
|
case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
|
||||||
|
case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported";
|
||||||
|
case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large";
|
||||||
|
case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small";
|
||||||
|
case PREFIX(stabilityCondition_notRespected): return "pledged buffer stability condition is not respected";
|
||||||
|
case PREFIX(dictionary_corrupted): return "Dictionary is corrupted";
|
||||||
|
case PREFIX(dictionary_wrong): return "Dictionary mismatch";
|
||||||
|
case PREFIX(dictionaryCreation_failed): return "Cannot create Dictionary from provided samples";
|
||||||
|
case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
|
||||||
|
case PREFIX(srcSize_wrong): return "Src size is incorrect";
|
||||||
|
case PREFIX(dstBuffer_null): return "Operation on NULL destination buffer";
|
||||||
|
/* following error codes are not stable and may be removed or changed in a future version */
|
||||||
|
case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
|
||||||
|
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
|
||||||
|
case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong";
|
||||||
|
case PREFIX(srcBuffer_wrong): return "Source buffer is wrong";
|
||||||
|
case PREFIX(externalMatchFinder_failed): return "External matchfinder returned an error code";
|
||||||
|
case PREFIX(maxCode):
|
||||||
|
default: return notErrorCode;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
159
external/zstd/common/error_private.h
vendored
Normal file
159
external/zstd/common/error_private.h
vendored
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Note : this module is expected to remain private, do not expose it */
|
||||||
|
|
||||||
|
#ifndef ERROR_H_MODULE
|
||||||
|
#define ERROR_H_MODULE
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ****************************************
|
||||||
|
* Dependencies
|
||||||
|
******************************************/
|
||||||
|
#include "../zstd_errors.h" /* enum list */
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "zstd_deps.h" /* size_t */
|
||||||
|
|
||||||
|
|
||||||
|
/* ****************************************
|
||||||
|
* Compiler-specific
|
||||||
|
******************************************/
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define ERR_STATIC static __attribute__((unused))
|
||||||
|
#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||||
|
# define ERR_STATIC static inline
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define ERR_STATIC static __inline
|
||||||
|
#else
|
||||||
|
# define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*-****************************************
|
||||||
|
* Customization (error_public.h)
|
||||||
|
******************************************/
|
||||||
|
typedef ZSTD_ErrorCode ERR_enum;
|
||||||
|
#define PREFIX(name) ZSTD_error_##name
|
||||||
|
|
||||||
|
|
||||||
|
/*-****************************************
|
||||||
|
* Error codes handling
|
||||||
|
******************************************/
|
||||||
|
#undef ERROR /* already defined on Visual Studio */
|
||||||
|
#define ERROR(name) ZSTD_ERROR(name)
|
||||||
|
#define ZSTD_ERROR(name) ((size_t)-PREFIX(name))
|
||||||
|
|
||||||
|
ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
|
||||||
|
|
||||||
|
ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
|
||||||
|
|
||||||
|
/* check and forward error code */
|
||||||
|
#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
|
||||||
|
#define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
|
||||||
|
|
||||||
|
|
||||||
|
/*-****************************************
|
||||||
|
* Error Strings
|
||||||
|
******************************************/
|
||||||
|
|
||||||
|
const char* ERR_getErrorString(ERR_enum code); /* error_private.c */
|
||||||
|
|
||||||
|
ERR_STATIC const char* ERR_getErrorName(size_t code)
|
||||||
|
{
|
||||||
|
return ERR_getErrorString(ERR_getErrorCode(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ignore: this is an internal helper.
|
||||||
|
*
|
||||||
|
* This is a helper function to help force C99-correctness during compilation.
|
||||||
|
* Under strict compilation modes, variadic macro arguments can't be empty.
|
||||||
|
* However, variadic function arguments can be. Using a function therefore lets
|
||||||
|
* us statically check that at least one (string) argument was passed,
|
||||||
|
* independent of the compilation flags.
|
||||||
|
*/
|
||||||
|
static INLINE_KEYWORD UNUSED_ATTR
|
||||||
|
void _force_has_format_string(const char *format, ...) {
|
||||||
|
(void)format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ignore: this is an internal helper.
|
||||||
|
*
|
||||||
|
* We want to force this function invocation to be syntactically correct, but
|
||||||
|
* we don't want to force runtime evaluation of its arguments.
|
||||||
|
*/
|
||||||
|
#define _FORCE_HAS_FORMAT_STRING(...) \
|
||||||
|
if (0) { \
|
||||||
|
_force_has_format_string(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ERR_QUOTE(str) #str
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the specified error if the condition evaluates to true.
|
||||||
|
*
|
||||||
|
* In debug modes, prints additional information.
|
||||||
|
* In order to do that (particularly, printing the conditional that failed),
|
||||||
|
* this can't just wrap RETURN_ERROR().
|
||||||
|
*/
|
||||||
|
#define RETURN_ERROR_IF(cond, err, ...) \
|
||||||
|
if (cond) { \
|
||||||
|
RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \
|
||||||
|
__FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \
|
||||||
|
_FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
|
||||||
|
RAWLOG(3, ": " __VA_ARGS__); \
|
||||||
|
RAWLOG(3, "\n"); \
|
||||||
|
return ERROR(err); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unconditionally return the specified error.
|
||||||
|
*
|
||||||
|
* In debug modes, prints additional information.
|
||||||
|
*/
|
||||||
|
#define RETURN_ERROR(err, ...) \
|
||||||
|
do { \
|
||||||
|
RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
|
||||||
|
__FILE__, __LINE__, ERR_QUOTE(ERROR(err))); \
|
||||||
|
_FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
|
||||||
|
RAWLOG(3, ": " __VA_ARGS__); \
|
||||||
|
RAWLOG(3, "\n"); \
|
||||||
|
return ERROR(err); \
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the provided expression evaluates to an error code, returns that error code.
|
||||||
|
*
|
||||||
|
* In debug modes, prints additional information.
|
||||||
|
*/
|
||||||
|
#define FORWARD_IF_ERROR(err, ...) \
|
||||||
|
do { \
|
||||||
|
size_t const err_code = (err); \
|
||||||
|
if (ERR_isError(err_code)) { \
|
||||||
|
RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \
|
||||||
|
__FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \
|
||||||
|
_FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
|
||||||
|
RAWLOG(3, ": " __VA_ARGS__); \
|
||||||
|
RAWLOG(3, "\n"); \
|
||||||
|
return err_code; \
|
||||||
|
} \
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ERROR_H_MODULE */
|
||||||
717
external/zstd/common/fse.h
vendored
Normal file
717
external/zstd/common/fse.h
vendored
Normal file
@@ -0,0 +1,717 @@
|
|||||||
|
/* ******************************************************************
|
||||||
|
* FSE : Finite State Entropy codec
|
||||||
|
* Public Prototypes declaration
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* You can contact the author at :
|
||||||
|
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
****************************************************************** */
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FSE_H
|
||||||
|
#define FSE_H
|
||||||
|
|
||||||
|
|
||||||
|
/*-*****************************************
|
||||||
|
* Dependencies
|
||||||
|
******************************************/
|
||||||
|
#include "zstd_deps.h" /* size_t, ptrdiff_t */
|
||||||
|
|
||||||
|
|
||||||
|
/*-*****************************************
|
||||||
|
* FSE_PUBLIC_API : control library symbols visibility
|
||||||
|
******************************************/
|
||||||
|
#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
# define FSE_PUBLIC_API __attribute__ ((visibility ("default")))
|
||||||
|
#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */
|
||||||
|
# define FSE_PUBLIC_API __declspec(dllexport)
|
||||||
|
#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
|
||||||
|
# define FSE_PUBLIC_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||||
|
#else
|
||||||
|
# define FSE_PUBLIC_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*------ Version ------*/
|
||||||
|
#define FSE_VERSION_MAJOR 0
|
||||||
|
#define FSE_VERSION_MINOR 9
|
||||||
|
#define FSE_VERSION_RELEASE 0
|
||||||
|
|
||||||
|
#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE
|
||||||
|
#define FSE_QUOTE(str) #str
|
||||||
|
#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)
|
||||||
|
#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)
|
||||||
|
|
||||||
|
#define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE)
|
||||||
|
FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */
|
||||||
|
|
||||||
|
|
||||||
|
/*-****************************************
|
||||||
|
* FSE simple functions
|
||||||
|
******************************************/
|
||||||
|
/*! FSE_compress() :
|
||||||
|
Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'.
|
||||||
|
'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= FSE_compressBound(srcSize).
|
||||||
|
@return : size of compressed data (<= dstCapacity).
|
||||||
|
Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
|
||||||
|
if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead.
|
||||||
|
if FSE_isError(return), compression failed (more details using FSE_getErrorName())
|
||||||
|
*/
|
||||||
|
FSE_PUBLIC_API size_t FSE_compress(void* dst, size_t dstCapacity,
|
||||||
|
const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
/*! FSE_decompress():
|
||||||
|
Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',
|
||||||
|
into already allocated destination buffer 'dst', of size 'dstCapacity'.
|
||||||
|
@return : size of regenerated data (<= maxDstSize),
|
||||||
|
or an error code, which can be tested using FSE_isError() .
|
||||||
|
|
||||||
|
** Important ** : FSE_decompress() does not decompress non-compressible nor RLE data !!!
|
||||||
|
Why ? : making this distinction requires a header.
|
||||||
|
Header management is intentionally delegated to the user layer, which can better manage special cases.
|
||||||
|
*/
|
||||||
|
FSE_PUBLIC_API size_t FSE_decompress(void* dst, size_t dstCapacity,
|
||||||
|
const void* cSrc, size_t cSrcSize);
|
||||||
|
|
||||||
|
|
||||||
|
/*-*****************************************
|
||||||
|
* Tool functions
|
||||||
|
******************************************/
|
||||||
|
FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */
|
||||||
|
|
||||||
|
/* Error Management */
|
||||||
|
FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */
|
||||||
|
FSE_PUBLIC_API const char* FSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */
|
||||||
|
|
||||||
|
|
||||||
|
/*-*****************************************
|
||||||
|
* FSE advanced functions
|
||||||
|
******************************************/
|
||||||
|
/*! FSE_compress2() :
|
||||||
|
Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog'
|
||||||
|
Both parameters can be defined as '0' to mean : use default value
|
||||||
|
@return : size of compressed data
|
||||||
|
Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!!
|
||||||
|
if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression.
|
||||||
|
if FSE_isError(return), it's an error code.
|
||||||
|
*/
|
||||||
|
FSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
|
||||||
|
|
||||||
|
|
||||||
|
/*-*****************************************
|
||||||
|
* FSE detailed API
|
||||||
|
******************************************/
|
||||||
|
/*!
|
||||||
|
FSE_compress() does the following:
|
||||||
|
1. count symbol occurrence from source[] into table count[] (see hist.h)
|
||||||
|
2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
|
||||||
|
3. save normalized counters to memory buffer using writeNCount()
|
||||||
|
4. build encoding table 'CTable' from normalized counters
|
||||||
|
5. encode the data stream using encoding table 'CTable'
|
||||||
|
|
||||||
|
FSE_decompress() does the following:
|
||||||
|
1. read normalized counters with readNCount()
|
||||||
|
2. build decoding table 'DTable' from normalized counters
|
||||||
|
3. decode the data stream using decoding table 'DTable'
|
||||||
|
|
||||||
|
The following API allows targeting specific sub-functions for advanced tasks.
|
||||||
|
For example, it's possible to compress several blocks using the same 'CTable',
|
||||||
|
or to save and provide normalized distribution using external method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* *** COMPRESSION *** */
|
||||||
|
|
||||||
|
/*! FSE_optimalTableLog():
|
||||||
|
dynamically downsize 'tableLog' when conditions are met.
|
||||||
|
It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.
|
||||||
|
@return : recommended tableLog (necessarily <= 'maxTableLog') */
|
||||||
|
FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
|
||||||
|
|
||||||
|
/*! FSE_normalizeCount():
|
||||||
|
normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)
|
||||||
|
'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
|
||||||
|
useLowProbCount is a boolean parameter which trades off compressed size for
|
||||||
|
faster header decoding. When it is set to 1, the compressed data will be slightly
|
||||||
|
smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be
|
||||||
|
faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0
|
||||||
|
is a good default, since header deserialization makes a big speed difference.
|
||||||
|
Otherwise, useLowProbCount=1 is a good default, since the speed difference is small.
|
||||||
|
@return : tableLog,
|
||||||
|
or an errorCode, which can be tested using FSE_isError() */
|
||||||
|
FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog,
|
||||||
|
const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount);
|
||||||
|
|
||||||
|
/*! FSE_NCountWriteBound():
|
||||||
|
Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
|
||||||
|
Typically useful for allocation purpose. */
|
||||||
|
FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);
|
||||||
|
|
||||||
|
/*! FSE_writeNCount():
|
||||||
|
Compactly save 'normalizedCounter' into 'buffer'.
|
||||||
|
@return : size of the compressed table,
|
||||||
|
or an errorCode, which can be tested using FSE_isError(). */
|
||||||
|
FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize,
|
||||||
|
const short* normalizedCounter,
|
||||||
|
unsigned maxSymbolValue, unsigned tableLog);
|
||||||
|
|
||||||
|
/*! Constructor and Destructor of FSE_CTable.
|
||||||
|
Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
|
||||||
|
typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
|
||||||
|
FSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog);
|
||||||
|
FSE_PUBLIC_API void FSE_freeCTable (FSE_CTable* ct);
|
||||||
|
|
||||||
|
/*! FSE_buildCTable():
|
||||||
|
Builds `ct`, which must be already allocated, using FSE_createCTable().
|
||||||
|
@return : 0, or an errorCode, which can be tested using FSE_isError() */
|
||||||
|
FSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
|
||||||
|
|
||||||
|
/*! FSE_compress_usingCTable():
|
||||||
|
Compress `src` using `ct` into `dst` which must be already allocated.
|
||||||
|
@return : size of compressed data (<= `dstCapacity`),
|
||||||
|
or 0 if compressed data could not fit into `dst`,
|
||||||
|
or an errorCode, which can be tested using FSE_isError() */
|
||||||
|
FSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Tutorial :
|
||||||
|
----------
|
||||||
|
The first step is to count all symbols. FSE_count() does this job very fast.
|
||||||
|
Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.
|
||||||
|
'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]
|
||||||
|
maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)
|
||||||
|
FSE_count() will return the number of occurrence of the most frequent symbol.
|
||||||
|
This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.
|
||||||
|
If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
|
||||||
|
|
||||||
|
The next step is to normalize the frequencies.
|
||||||
|
FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.
|
||||||
|
It also guarantees a minimum of 1 to any Symbol with frequency >= 1.
|
||||||
|
You can use 'tableLog'==0 to mean "use default tableLog value".
|
||||||
|
If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),
|
||||||
|
which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default").
|
||||||
|
|
||||||
|
The result of FSE_normalizeCount() will be saved into a table,
|
||||||
|
called 'normalizedCounter', which is a table of signed short.
|
||||||
|
'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.
|
||||||
|
The return value is tableLog if everything proceeded as expected.
|
||||||
|
It is 0 if there is a single symbol within distribution.
|
||||||
|
If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).
|
||||||
|
|
||||||
|
'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().
|
||||||
|
'buffer' must be already allocated.
|
||||||
|
For guaranteed success, buffer size must be at least FSE_headerBound().
|
||||||
|
The result of the function is the number of bytes written into 'buffer'.
|
||||||
|
If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).
|
||||||
|
|
||||||
|
'normalizedCounter' can then be used to create the compression table 'CTable'.
|
||||||
|
The space required by 'CTable' must be already allocated, using FSE_createCTable().
|
||||||
|
You can then use FSE_buildCTable() to fill 'CTable'.
|
||||||
|
If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).
|
||||||
|
|
||||||
|
'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().
|
||||||
|
Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'
|
||||||
|
The function returns the size of compressed data (without header), necessarily <= `dstCapacity`.
|
||||||
|
If it returns '0', compressed data could not fit into 'dst'.
|
||||||
|
If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* *** DECOMPRESSION *** */
|
||||||
|
|
||||||
|
/*! FSE_readNCount():
|
||||||
|
Read compactly saved 'normalizedCounter' from 'rBuffer'.
|
||||||
|
@return : size read from 'rBuffer',
|
||||||
|
or an errorCode, which can be tested using FSE_isError().
|
||||||
|
maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
|
||||||
|
FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter,
|
||||||
|
unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
|
||||||
|
const void* rBuffer, size_t rBuffSize);
|
||||||
|
|
||||||
|
/*! FSE_readNCount_bmi2():
|
||||||
|
* Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise.
|
||||||
|
*/
|
||||||
|
FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter,
|
||||||
|
unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
|
||||||
|
const void* rBuffer, size_t rBuffSize, int bmi2);
|
||||||
|
|
||||||
|
/*! Constructor and Destructor of FSE_DTable.
|
||||||
|
Note that its size depends on 'tableLog' */
|
||||||
|
typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
|
||||||
|
FSE_PUBLIC_API FSE_DTable* FSE_createDTable(unsigned tableLog);
|
||||||
|
FSE_PUBLIC_API void FSE_freeDTable(FSE_DTable* dt);
|
||||||
|
|
||||||
|
/*! FSE_buildDTable():
|
||||||
|
Builds 'dt', which must be already allocated, using FSE_createDTable().
|
||||||
|
return : 0, or an errorCode, which can be tested using FSE_isError() */
|
||||||
|
FSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
|
||||||
|
|
||||||
|
/*! FSE_decompress_usingDTable():
|
||||||
|
Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
|
||||||
|
into `dst` which must be already allocated.
|
||||||
|
@return : size of regenerated data (necessarily <= `dstCapacity`),
|
||||||
|
or an errorCode, which can be tested using FSE_isError() */
|
||||||
|
FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Tutorial :
|
||||||
|
----------
|
||||||
|
(Note : these functions only decompress FSE-compressed blocks.
|
||||||
|
If block is uncompressed, use memcpy() instead
|
||||||
|
If block is a single repeated byte, use memset() instead )
|
||||||
|
|
||||||
|
The first step is to obtain the normalized frequencies of symbols.
|
||||||
|
This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().
|
||||||
|
'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
|
||||||
|
In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
|
||||||
|
or size the table to handle worst case situations (typically 256).
|
||||||
|
FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
|
||||||
|
The result of FSE_readNCount() is the number of bytes read from 'rBuffer'.
|
||||||
|
Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
|
||||||
|
If there is an error, the function will return an error code, which can be tested using FSE_isError().
|
||||||
|
|
||||||
|
The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.
|
||||||
|
This is performed by the function FSE_buildDTable().
|
||||||
|
The space required by 'FSE_DTable' must be already allocated using FSE_createDTable().
|
||||||
|
If there is an error, the function will return an error code, which can be tested using FSE_isError().
|
||||||
|
|
||||||
|
`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable().
|
||||||
|
`cSrcSize` must be strictly correct, otherwise decompression will fail.
|
||||||
|
FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).
|
||||||
|
If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* FSE_H */
|
||||||
|
|
||||||
|
#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
|
||||||
|
#define FSE_H_FSE_STATIC_LINKING_ONLY
|
||||||
|
|
||||||
|
/* *** Dependency *** */
|
||||||
|
#include "bitstream.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* *****************************************
|
||||||
|
* Static allocation
|
||||||
|
*******************************************/
|
||||||
|
/* FSE buffer bounds */
|
||||||
|
#define FSE_NCOUNTBOUND 512
|
||||||
|
#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */)
|
||||||
|
#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
|
||||||
|
|
||||||
|
/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */
|
||||||
|
#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2))
|
||||||
|
#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<(maxTableLog)))
|
||||||
|
|
||||||
|
/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */
|
||||||
|
#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable))
|
||||||
|
#define FSE_DTABLE_SIZE(maxTableLog) (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable))
|
||||||
|
|
||||||
|
|
||||||
|
/* *****************************************
|
||||||
|
* FSE advanced API
|
||||||
|
***************************************** */
|
||||||
|
|
||||||
|
unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
|
||||||
|
/**< same as FSE_optimalTableLog(), which used `minus==2` */
|
||||||
|
|
||||||
|
/* FSE_compress_wksp() :
|
||||||
|
* Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).
|
||||||
|
* FSE_COMPRESS_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable.
|
||||||
|
*/
|
||||||
|
#define FSE_COMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) )
|
||||||
|
size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
|
||||||
|
|
||||||
|
size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits);
|
||||||
|
/**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */
|
||||||
|
|
||||||
|
size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);
|
||||||
|
/**< build a fake FSE_CTable, designed to compress always the same symbolValue */
|
||||||
|
|
||||||
|
/* FSE_buildCTable_wksp() :
|
||||||
|
* Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
|
||||||
|
* `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`.
|
||||||
|
* See FSE_buildCTable_wksp() for breakdown of workspace usage.
|
||||||
|
*/
|
||||||
|
#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (((maxSymbolValue + 2) + (1ull << (tableLog)))/2 + sizeof(U64)/sizeof(U32) /* additional 8 bytes for potential table overwrite */)
|
||||||
|
#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog))
|
||||||
|
size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
|
||||||
|
|
||||||
|
#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8)
|
||||||
|
#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned))
|
||||||
|
FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
|
||||||
|
/**< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */
|
||||||
|
|
||||||
|
size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);
|
||||||
|
/**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */
|
||||||
|
|
||||||
|
size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);
|
||||||
|
/**< build a fake FSE_DTable, designed to always generate the same symbolValue */
|
||||||
|
|
||||||
|
#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + 1 + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1)
|
||||||
|
#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned))
|
||||||
|
size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize);
|
||||||
|
/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */
|
||||||
|
|
||||||
|
size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2);
|
||||||
|
/**< Same as FSE_decompress_wksp() but with dynamic BMI2 support. Pass 1 if your CPU supports BMI2 or 0 if it doesn't. */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FSE_repeat_none, /**< Cannot use the previous table */
|
||||||
|
FSE_repeat_check, /**< Can use the previous table but it must be checked */
|
||||||
|
FSE_repeat_valid /**< Can use the previous table and it is assumed to be valid */
|
||||||
|
} FSE_repeat;
|
||||||
|
|
||||||
|
/* *****************************************
|
||||||
|
* FSE symbol compression API
|
||||||
|
*******************************************/
|
||||||
|
/*!
|
||||||
|
This API consists of small unitary functions, which highly benefit from being inlined.
|
||||||
|
Hence their body are included in next section.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
ptrdiff_t value;
|
||||||
|
const void* stateTable;
|
||||||
|
const void* symbolTT;
|
||||||
|
unsigned stateLog;
|
||||||
|
} FSE_CState_t;
|
||||||
|
|
||||||
|
static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct);
|
||||||
|
|
||||||
|
static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol);
|
||||||
|
|
||||||
|
static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr);
|
||||||
|
|
||||||
|
/**<
|
||||||
|
These functions are inner components of FSE_compress_usingCTable().
|
||||||
|
They allow the creation of custom streams, mixing multiple tables and bit sources.
|
||||||
|
|
||||||
|
A key property to keep in mind is that encoding and decoding are done **in reverse direction**.
|
||||||
|
So the first symbol you will encode is the last you will decode, like a LIFO stack.
|
||||||
|
|
||||||
|
You will need a few variables to track your CStream. They are :
|
||||||
|
|
||||||
|
FSE_CTable ct; // Provided by FSE_buildCTable()
|
||||||
|
BIT_CStream_t bitStream; // bitStream tracking structure
|
||||||
|
FSE_CState_t state; // State tracking structure (can have several)
|
||||||
|
|
||||||
|
|
||||||
|
The first thing to do is to init bitStream and state.
|
||||||
|
size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);
|
||||||
|
FSE_initCState(&state, ct);
|
||||||
|
|
||||||
|
Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();
|
||||||
|
You can then encode your input data, byte after byte.
|
||||||
|
FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.
|
||||||
|
Remember decoding will be done in reverse direction.
|
||||||
|
FSE_encodeByte(&bitStream, &state, symbol);
|
||||||
|
|
||||||
|
At any time, you can also add any bit sequence.
|
||||||
|
Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders
|
||||||
|
BIT_addBits(&bitStream, bitField, nbBits);
|
||||||
|
|
||||||
|
The above methods don't commit data to memory, they just store it into local register, for speed.
|
||||||
|
Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
|
||||||
|
Writing data to memory is a manual operation, performed by the flushBits function.
|
||||||
|
BIT_flushBits(&bitStream);
|
||||||
|
|
||||||
|
Your last FSE encoding operation shall be to flush your last state value(s).
|
||||||
|
FSE_flushState(&bitStream, &state);
|
||||||
|
|
||||||
|
Finally, you must close the bitStream.
|
||||||
|
The function returns the size of CStream in bytes.
|
||||||
|
If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)
|
||||||
|
If there is an error, it returns an errorCode (which can be tested using FSE_isError()).
|
||||||
|
size_t size = BIT_closeCStream(&bitStream);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* *****************************************
|
||||||
|
* FSE symbol decompression API
|
||||||
|
*******************************************/
|
||||||
|
typedef struct {
|
||||||
|
size_t state;
|
||||||
|
const void* table; /* precise table may vary, depending on U16 */
|
||||||
|
} FSE_DState_t;
|
||||||
|
|
||||||
|
|
||||||
|
static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);
|
||||||
|
|
||||||
|
static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
|
||||||
|
|
||||||
|
static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);
|
||||||
|
|
||||||
|
/**<
|
||||||
|
Let's now decompose FSE_decompress_usingDTable() into its unitary components.
|
||||||
|
You will decode FSE-encoded symbols from the bitStream,
|
||||||
|
and also any other bitFields you put in, **in reverse order**.
|
||||||
|
|
||||||
|
You will need a few variables to track your bitStream. They are :
|
||||||
|
|
||||||
|
BIT_DStream_t DStream; // Stream context
|
||||||
|
FSE_DState_t DState; // State context. Multiple ones are possible
|
||||||
|
FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable()
|
||||||
|
|
||||||
|
The first thing to do is to init the bitStream.
|
||||||
|
errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);
|
||||||
|
|
||||||
|
You should then retrieve your initial state(s)
|
||||||
|
(in reverse flushing order if you have several ones) :
|
||||||
|
errorCode = FSE_initDState(&DState, &DStream, DTablePtr);
|
||||||
|
|
||||||
|
You can then decode your data, symbol after symbol.
|
||||||
|
For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.
|
||||||
|
Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).
|
||||||
|
unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);
|
||||||
|
|
||||||
|
You can retrieve any bitfield you eventually stored into the bitStream (in reverse order)
|
||||||
|
Note : maximum allowed nbBits is 25, for 32-bits compatibility
|
||||||
|
size_t bitField = BIT_readBits(&DStream, nbBits);
|
||||||
|
|
||||||
|
All above operations only read from local register (which size depends on size_t).
|
||||||
|
Refueling the register from memory is manually performed by the reload method.
|
||||||
|
endSignal = FSE_reloadDStream(&DStream);
|
||||||
|
|
||||||
|
BIT_reloadDStream() result tells if there is still some more data to read from DStream.
|
||||||
|
BIT_DStream_unfinished : there is still some data left into the DStream.
|
||||||
|
BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.
|
||||||
|
BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.
|
||||||
|
BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.
|
||||||
|
|
||||||
|
When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,
|
||||||
|
to properly detect the exact end of stream.
|
||||||
|
After each decoded symbol, check if DStream is fully consumed using this simple test :
|
||||||
|
BIT_reloadDStream(&DStream) >= BIT_DStream_completed
|
||||||
|
|
||||||
|
When it's done, verify decompression is fully completed, by checking both DStream and the relevant states.
|
||||||
|
Checking if DStream has reached its end is performed by :
|
||||||
|
BIT_endOfDStream(&DStream);
|
||||||
|
Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.
|
||||||
|
FSE_endOfDState(&DState);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* *****************************************
|
||||||
|
* FSE unsafe API
|
||||||
|
*******************************************/
|
||||||
|
static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
|
||||||
|
/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
|
||||||
|
|
||||||
|
|
||||||
|
/* *****************************************
|
||||||
|
* Implementation of inlined functions
|
||||||
|
*******************************************/
|
||||||
|
typedef struct {
|
||||||
|
int deltaFindState;
|
||||||
|
U32 deltaNbBits;
|
||||||
|
} FSE_symbolCompressionTransform; /* total 8 bytes */
|
||||||
|
|
||||||
|
MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct)
|
||||||
|
{
|
||||||
|
const void* ptr = ct;
|
||||||
|
const U16* u16ptr = (const U16*) ptr;
|
||||||
|
const U32 tableLog = MEM_read16(ptr);
|
||||||
|
statePtr->value = (ptrdiff_t)1<<tableLog;
|
||||||
|
statePtr->stateTable = u16ptr+2;
|
||||||
|
statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1);
|
||||||
|
statePtr->stateLog = tableLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! FSE_initCState2() :
|
||||||
|
* Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)
|
||||||
|
* uses the smallest state value possible, saving the cost of this symbol */
|
||||||
|
MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol)
|
||||||
|
{
|
||||||
|
FSE_initCState(statePtr, ct);
|
||||||
|
{ const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
|
||||||
|
const U16* stateTable = (const U16*)(statePtr->stateTable);
|
||||||
|
U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16);
|
||||||
|
statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
|
||||||
|
statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol)
|
||||||
|
{
|
||||||
|
FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
|
||||||
|
const U16* const stateTable = (const U16*)(statePtr->stateTable);
|
||||||
|
U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
|
||||||
|
BIT_addBits(bitC, statePtr->value, nbBitsOut);
|
||||||
|
statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr)
|
||||||
|
{
|
||||||
|
BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
|
||||||
|
BIT_flushBits(bitC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* FSE_getMaxNbBits() :
|
||||||
|
* Approximate maximum cost of a symbol, in bits.
|
||||||
|
* Fractional get rounded up (i.e. a symbol with a normalized frequency of 3 gives the same result as a frequency of 2)
|
||||||
|
* note 1 : assume symbolValue is valid (<= maxSymbolValue)
|
||||||
|
* note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
|
||||||
|
MEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue)
|
||||||
|
{
|
||||||
|
const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
|
||||||
|
return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FSE_bitCost() :
|
||||||
|
* Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits)
|
||||||
|
* note 1 : assume symbolValue is valid (<= maxSymbolValue)
|
||||||
|
* note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
|
||||||
|
MEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog)
|
||||||
|
{
|
||||||
|
const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
|
||||||
|
U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16;
|
||||||
|
U32 const threshold = (minNbBits+1) << 16;
|
||||||
|
assert(tableLog < 16);
|
||||||
|
assert(accuracyLog < 31-tableLog); /* ensure enough room for renormalization double shift */
|
||||||
|
{ U32 const tableSize = 1 << tableLog;
|
||||||
|
U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize);
|
||||||
|
U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog; /* linear interpolation (very approximate) */
|
||||||
|
U32 const bitMultiplier = 1 << accuracyLog;
|
||||||
|
assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold);
|
||||||
|
assert(normalizedDeltaFromThreshold <= bitMultiplier);
|
||||||
|
return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ====== Decompression ====== */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
U16 tableLog;
|
||||||
|
U16 fastMode;
|
||||||
|
} FSE_DTableHeader; /* sizeof U32 */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned short newState;
|
||||||
|
unsigned char symbol;
|
||||||
|
unsigned char nbBits;
|
||||||
|
} FSE_decode_t; /* size == U32 */
|
||||||
|
|
||||||
|
MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)
|
||||||
|
{
|
||||||
|
const void* ptr = dt;
|
||||||
|
const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;
|
||||||
|
DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
|
||||||
|
BIT_reloadDStream(bitD);
|
||||||
|
DStatePtr->table = dt + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr)
|
||||||
|
{
|
||||||
|
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||||
|
return DInfo.symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
|
||||||
|
{
|
||||||
|
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||||
|
U32 const nbBits = DInfo.nbBits;
|
||||||
|
size_t const lowBits = BIT_readBits(bitD, nbBits);
|
||||||
|
DStatePtr->state = DInfo.newState + lowBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
|
||||||
|
{
|
||||||
|
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||||
|
U32 const nbBits = DInfo.nbBits;
|
||||||
|
BYTE const symbol = DInfo.symbol;
|
||||||
|
size_t const lowBits = BIT_readBits(bitD, nbBits);
|
||||||
|
|
||||||
|
DStatePtr->state = DInfo.newState + lowBits;
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! FSE_decodeSymbolFast() :
|
||||||
|
unsafe, only works if no symbol has a probability > 50% */
|
||||||
|
MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
|
||||||
|
{
|
||||||
|
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||||
|
U32 const nbBits = DInfo.nbBits;
|
||||||
|
BYTE const symbol = DInfo.symbol;
|
||||||
|
size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
|
||||||
|
|
||||||
|
DStatePtr->state = DInfo.newState + lowBits;
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
|
||||||
|
{
|
||||||
|
return DStatePtr->state == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FSE_COMMONDEFS_ONLY
|
||||||
|
|
||||||
|
/* **************************************************************
|
||||||
|
* Tuning parameters
|
||||||
|
****************************************************************/
|
||||||
|
/*!MEMORY_USAGE :
|
||||||
|
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
|
||||||
|
* Increasing memory usage improves compression ratio
|
||||||
|
* Reduced memory usage can improve speed, due to cache effect
|
||||||
|
* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
|
||||||
|
#ifndef FSE_MAX_MEMORY_USAGE
|
||||||
|
# define FSE_MAX_MEMORY_USAGE 14
|
||||||
|
#endif
|
||||||
|
#ifndef FSE_DEFAULT_MEMORY_USAGE
|
||||||
|
# define FSE_DEFAULT_MEMORY_USAGE 13
|
||||||
|
#endif
|
||||||
|
#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE)
|
||||||
|
# error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!FSE_MAX_SYMBOL_VALUE :
|
||||||
|
* Maximum symbol value authorized.
|
||||||
|
* Required for proper stack allocation */
|
||||||
|
#ifndef FSE_MAX_SYMBOL_VALUE
|
||||||
|
# define FSE_MAX_SYMBOL_VALUE 255
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* **************************************************************
|
||||||
|
* template functions type & suffix
|
||||||
|
****************************************************************/
|
||||||
|
#define FSE_FUNCTION_TYPE BYTE
|
||||||
|
#define FSE_FUNCTION_EXTENSION
|
||||||
|
#define FSE_DECODE_TYPE FSE_decode_t
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !FSE_COMMONDEFS_ONLY */
|
||||||
|
|
||||||
|
|
||||||
|
/* ***************************************************************
|
||||||
|
* Constants
|
||||||
|
*****************************************************************/
|
||||||
|
#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2)
|
||||||
|
#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)
|
||||||
|
#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)
|
||||||
|
#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)
|
||||||
|
#define FSE_MIN_TABLELOG 5
|
||||||
|
|
||||||
|
#define FSE_TABLELOG_ABSOLUTE_MAX 15
|
||||||
|
#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
|
||||||
|
# error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSE_STATIC_LINKING_ONLY */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
405
external/zstd/common/fse_decompress.c
vendored
Normal file
405
external/zstd/common/fse_decompress.c
vendored
Normal file
@@ -0,0 +1,405 @@
|
|||||||
|
/* ******************************************************************
|
||||||
|
* FSE : Finite State Entropy decoder
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* You can contact the author at :
|
||||||
|
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
* - Public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
****************************************************************** */
|
||||||
|
|
||||||
|
|
||||||
|
/* **************************************************************
|
||||||
|
* Includes
|
||||||
|
****************************************************************/
|
||||||
|
#include "debug.h" /* assert */
|
||||||
|
#include "bitstream.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#define FSE_STATIC_LINKING_ONLY
|
||||||
|
#include "fse.h"
|
||||||
|
#include "error_private.h"
|
||||||
|
#define ZSTD_DEPS_NEED_MALLOC
|
||||||
|
#include "zstd_deps.h"
|
||||||
|
#include "bits.h" /* ZSTD_highbit32 */
|
||||||
|
|
||||||
|
|
||||||
|
/* **************************************************************
|
||||||
|
* Error Management
|
||||||
|
****************************************************************/
|
||||||
|
#define FSE_isError ERR_isError
|
||||||
|
#define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */
|
||||||
|
|
||||||
|
|
||||||
|
/* **************************************************************
|
||||||
|
* Templates
|
||||||
|
****************************************************************/
|
||||||
|
/*
|
||||||
|
designed to be included
|
||||||
|
for type-specific functions (template emulation in C)
|
||||||
|
Objective is to write these functions only once, for improved maintenance
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* safety checks */
|
||||||
|
#ifndef FSE_FUNCTION_EXTENSION
|
||||||
|
# error "FSE_FUNCTION_EXTENSION must be defined"
|
||||||
|
#endif
|
||||||
|
#ifndef FSE_FUNCTION_TYPE
|
||||||
|
# error "FSE_FUNCTION_TYPE must be defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Function names */
|
||||||
|
#define FSE_CAT(X,Y) X##Y
|
||||||
|
#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)
|
||||||
|
#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)
|
||||||
|
|
||||||
|
|
||||||
|
/* Function templates */
|
||||||
|
FSE_DTable* FSE_createDTable (unsigned tableLog)
|
||||||
|
{
|
||||||
|
if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
|
||||||
|
return (FSE_DTable*)ZSTD_malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSE_freeDTable (FSE_DTable* dt)
|
||||||
|
{
|
||||||
|
ZSTD_free(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
|
||||||
|
{
|
||||||
|
void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
|
||||||
|
FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr);
|
||||||
|
U16* symbolNext = (U16*)workSpace;
|
||||||
|
BYTE* spread = (BYTE*)(symbolNext + maxSymbolValue + 1);
|
||||||
|
|
||||||
|
U32 const maxSV1 = maxSymbolValue + 1;
|
||||||
|
U32 const tableSize = 1 << tableLog;
|
||||||
|
U32 highThreshold = tableSize-1;
|
||||||
|
|
||||||
|
/* Sanity Checks */
|
||||||
|
if (FSE_BUILD_DTABLE_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(maxSymbolValue_tooLarge);
|
||||||
|
if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);
|
||||||
|
if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
|
||||||
|
|
||||||
|
/* Init, lay down lowprob symbols */
|
||||||
|
{ FSE_DTableHeader DTableH;
|
||||||
|
DTableH.tableLog = (U16)tableLog;
|
||||||
|
DTableH.fastMode = 1;
|
||||||
|
{ S16 const largeLimit= (S16)(1 << (tableLog-1));
|
||||||
|
U32 s;
|
||||||
|
for (s=0; s<maxSV1; s++) {
|
||||||
|
if (normalizedCounter[s]==-1) {
|
||||||
|
tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;
|
||||||
|
symbolNext[s] = 1;
|
||||||
|
} else {
|
||||||
|
if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
|
||||||
|
symbolNext[s] = normalizedCounter[s];
|
||||||
|
} } }
|
||||||
|
ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spread symbols */
|
||||||
|
if (highThreshold == tableSize - 1) {
|
||||||
|
size_t const tableMask = tableSize-1;
|
||||||
|
size_t const step = FSE_TABLESTEP(tableSize);
|
||||||
|
/* First lay down the symbols in order.
|
||||||
|
* We use a uint64_t to lay down 8 bytes at a time. This reduces branch
|
||||||
|
* misses since small blocks generally have small table logs, so nearly
|
||||||
|
* all symbols have counts <= 8. We ensure we have 8 bytes at the end of
|
||||||
|
* our buffer to handle the over-write.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
U64 const add = 0x0101010101010101ull;
|
||||||
|
size_t pos = 0;
|
||||||
|
U64 sv = 0;
|
||||||
|
U32 s;
|
||||||
|
for (s=0; s<maxSV1; ++s, sv += add) {
|
||||||
|
int i;
|
||||||
|
int const n = normalizedCounter[s];
|
||||||
|
MEM_write64(spread + pos, sv);
|
||||||
|
for (i = 8; i < n; i += 8) {
|
||||||
|
MEM_write64(spread + pos + i, sv);
|
||||||
|
}
|
||||||
|
pos += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Now we spread those positions across the table.
|
||||||
|
* The benefit of doing it in two stages is that we avoid the
|
||||||
|
* variable size inner loop, which caused lots of branch misses.
|
||||||
|
* Now we can run through all the positions without any branch misses.
|
||||||
|
* We unroll the loop twice, since that is what empirically worked best.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
size_t position = 0;
|
||||||
|
size_t s;
|
||||||
|
size_t const unroll = 2;
|
||||||
|
assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */
|
||||||
|
for (s = 0; s < (size_t)tableSize; s += unroll) {
|
||||||
|
size_t u;
|
||||||
|
for (u = 0; u < unroll; ++u) {
|
||||||
|
size_t const uPosition = (position + (u * step)) & tableMask;
|
||||||
|
tableDecode[uPosition].symbol = spread[s + u];
|
||||||
|
}
|
||||||
|
position = (position + (unroll * step)) & tableMask;
|
||||||
|
}
|
||||||
|
assert(position == 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
U32 const tableMask = tableSize-1;
|
||||||
|
U32 const step = FSE_TABLESTEP(tableSize);
|
||||||
|
U32 s, position = 0;
|
||||||
|
for (s=0; s<maxSV1; s++) {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<normalizedCounter[s]; i++) {
|
||||||
|
tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
|
||||||
|
position = (position + step) & tableMask;
|
||||||
|
while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
|
||||||
|
} }
|
||||||
|
if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build Decoding table */
|
||||||
|
{ U32 u;
|
||||||
|
for (u=0; u<tableSize; u++) {
|
||||||
|
FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);
|
||||||
|
U32 const nextState = symbolNext[symbol]++;
|
||||||
|
tableDecode[u].nbBits = (BYTE) (tableLog - ZSTD_highbit32(nextState) );
|
||||||
|
tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
|
||||||
|
} }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
|
||||||
|
{
|
||||||
|
return FSE_buildDTable_internal(dt, normalizedCounter, maxSymbolValue, tableLog, workSpace, wkspSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FSE_COMMONDEFS_ONLY
|
||||||
|
|
||||||
|
/*-*******************************************************
|
||||||
|
* Decompression (Byte symbols)
|
||||||
|
*********************************************************/
|
||||||
|
size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)
|
||||||
|
{
|
||||||
|
void* ptr = dt;
|
||||||
|
FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
|
||||||
|
void* dPtr = dt + 1;
|
||||||
|
FSE_decode_t* const cell = (FSE_decode_t*)dPtr;
|
||||||
|
|
||||||
|
DTableH->tableLog = 0;
|
||||||
|
DTableH->fastMode = 0;
|
||||||
|
|
||||||
|
cell->newState = 0;
|
||||||
|
cell->symbol = symbolValue;
|
||||||
|
cell->nbBits = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)
|
||||||
|
{
|
||||||
|
void* ptr = dt;
|
||||||
|
FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
|
||||||
|
void* dPtr = dt + 1;
|
||||||
|
FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr;
|
||||||
|
const unsigned tableSize = 1 << nbBits;
|
||||||
|
const unsigned tableMask = tableSize - 1;
|
||||||
|
const unsigned maxSV1 = tableMask+1;
|
||||||
|
unsigned s;
|
||||||
|
|
||||||
|
/* Sanity checks */
|
||||||
|
if (nbBits < 1) return ERROR(GENERIC); /* min size */
|
||||||
|
|
||||||
|
/* Build Decoding Table */
|
||||||
|
DTableH->tableLog = (U16)nbBits;
|
||||||
|
DTableH->fastMode = 1;
|
||||||
|
for (s=0; s<maxSV1; s++) {
|
||||||
|
dinfo[s].newState = 0;
|
||||||
|
dinfo[s].symbol = (BYTE)s;
|
||||||
|
dinfo[s].nbBits = (BYTE)nbBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic(
|
||||||
|
void* dst, size_t maxDstSize,
|
||||||
|
const void* cSrc, size_t cSrcSize,
|
||||||
|
const FSE_DTable* dt, const unsigned fast)
|
||||||
|
{
|
||||||
|
BYTE* const ostart = (BYTE*) dst;
|
||||||
|
BYTE* op = ostart;
|
||||||
|
BYTE* const omax = op + maxDstSize;
|
||||||
|
BYTE* const olimit = omax-3;
|
||||||
|
|
||||||
|
BIT_DStream_t bitD;
|
||||||
|
FSE_DState_t state1;
|
||||||
|
FSE_DState_t state2;
|
||||||
|
|
||||||
|
/* Init */
|
||||||
|
CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize));
|
||||||
|
|
||||||
|
FSE_initDState(&state1, &bitD, dt);
|
||||||
|
FSE_initDState(&state2, &bitD, dt);
|
||||||
|
|
||||||
|
#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)
|
||||||
|
|
||||||
|
/* 4 symbols per loop */
|
||||||
|
for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) & (op<olimit) ; op+=4) {
|
||||||
|
op[0] = FSE_GETSYMBOL(&state1);
|
||||||
|
|
||||||
|
if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
|
||||||
|
BIT_reloadDStream(&bitD);
|
||||||
|
|
||||||
|
op[1] = FSE_GETSYMBOL(&state2);
|
||||||
|
|
||||||
|
if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
|
||||||
|
{ if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }
|
||||||
|
|
||||||
|
op[2] = FSE_GETSYMBOL(&state1);
|
||||||
|
|
||||||
|
if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
|
||||||
|
BIT_reloadDStream(&bitD);
|
||||||
|
|
||||||
|
op[3] = FSE_GETSYMBOL(&state2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tail */
|
||||||
|
/* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */
|
||||||
|
while (1) {
|
||||||
|
if (op>(omax-2)) return ERROR(dstSize_tooSmall);
|
||||||
|
*op++ = FSE_GETSYMBOL(&state1);
|
||||||
|
if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {
|
||||||
|
*op++ = FSE_GETSYMBOL(&state2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op>(omax-2)) return ERROR(dstSize_tooSmall);
|
||||||
|
*op++ = FSE_GETSYMBOL(&state2);
|
||||||
|
if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {
|
||||||
|
*op++ = FSE_GETSYMBOL(&state1);
|
||||||
|
break;
|
||||||
|
} }
|
||||||
|
|
||||||
|
return op-ostart;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,
|
||||||
|
const void* cSrc, size_t cSrcSize,
|
||||||
|
const FSE_DTable* dt)
|
||||||
|
{
|
||||||
|
const void* ptr = dt;
|
||||||
|
const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
|
||||||
|
const U32 fastMode = DTableH->fastMode;
|
||||||
|
|
||||||
|
/* select fast mode (static) */
|
||||||
|
if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
|
||||||
|
return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
|
||||||
|
{
|
||||||
|
return FSE_decompress_wksp_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, /* bmi2 */ 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short ncount[FSE_MAX_SYMBOL_VALUE + 1];
|
||||||
|
FSE_DTable dtable[1]; /* Dynamically sized */
|
||||||
|
} FSE_DecompressWksp;
|
||||||
|
|
||||||
|
|
||||||
|
FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(
|
||||||
|
void* dst, size_t dstCapacity,
|
||||||
|
const void* cSrc, size_t cSrcSize,
|
||||||
|
unsigned maxLog, void* workSpace, size_t wkspSize,
|
||||||
|
int bmi2)
|
||||||
|
{
|
||||||
|
const BYTE* const istart = (const BYTE*)cSrc;
|
||||||
|
const BYTE* ip = istart;
|
||||||
|
unsigned tableLog;
|
||||||
|
unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
|
||||||
|
FSE_DecompressWksp* const wksp = (FSE_DecompressWksp*)workSpace;
|
||||||
|
|
||||||
|
DEBUG_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0);
|
||||||
|
if (wkspSize < sizeof(*wksp)) return ERROR(GENERIC);
|
||||||
|
|
||||||
|
/* normal FSE decoding mode */
|
||||||
|
{
|
||||||
|
size_t const NCountLength = FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2);
|
||||||
|
if (FSE_isError(NCountLength)) return NCountLength;
|
||||||
|
if (tableLog > maxLog) return ERROR(tableLog_tooLarge);
|
||||||
|
assert(NCountLength <= cSrcSize);
|
||||||
|
ip += NCountLength;
|
||||||
|
cSrcSize -= NCountLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge);
|
||||||
|
assert(sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog) <= wkspSize);
|
||||||
|
workSpace = (BYTE*)workSpace + sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);
|
||||||
|
wkspSize -= sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);
|
||||||
|
|
||||||
|
CHECK_F( FSE_buildDTable_internal(wksp->dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) );
|
||||||
|
|
||||||
|
{
|
||||||
|
const void* ptr = wksp->dtable;
|
||||||
|
const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
|
||||||
|
const U32 fastMode = DTableH->fastMode;
|
||||||
|
|
||||||
|
/* select fast mode (static) */
|
||||||
|
if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 1);
|
||||||
|
return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Avoids the FORCE_INLINE of the _body() function. */
|
||||||
|
static size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
|
||||||
|
{
|
||||||
|
return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DYNAMIC_BMI2
|
||||||
|
BMI2_TARGET_ATTRIBUTE static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
|
||||||
|
{
|
||||||
|
return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2)
|
||||||
|
{
|
||||||
|
#if DYNAMIC_BMI2
|
||||||
|
if (bmi2) {
|
||||||
|
return FSE_decompress_wksp_body_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
(void)bmi2;
|
||||||
|
return FSE_decompress_wksp_body_default(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];
|
||||||
|
|
||||||
|
#ifndef ZSTD_NO_UNUSED_FUNCTIONS
|
||||||
|
size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) {
|
||||||
|
U32 wksp[FSE_BUILD_DTABLE_WKSP_SIZE_U32(FSE_TABLELOG_ABSOLUTE_MAX, FSE_MAX_SYMBOL_VALUE)];
|
||||||
|
return FSE_buildDTable_wksp(dt, normalizedCounter, maxSymbolValue, tableLog, wksp, sizeof(wksp));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FSE_decompress(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize)
|
||||||
|
{
|
||||||
|
/* Static analyzer seems unable to understand this table will be properly initialized later */
|
||||||
|
U32 wksp[FSE_DECOMPRESS_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)];
|
||||||
|
return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, FSE_MAX_TABLELOG, wksp, sizeof(wksp));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSE_COMMONDEFS_ONLY */
|
||||||
377
external/zstd/common/huf.h
vendored
Normal file
377
external/zstd/common/huf.h
vendored
Normal file
@@ -0,0 +1,377 @@
|
|||||||
|
/* ******************************************************************
|
||||||
|
* huff0 huffman codec,
|
||||||
|
* part of Finite State Entropy library
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* You can contact the author at :
|
||||||
|
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
****************************************************************** */
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HUF_H_298734234
|
||||||
|
#define HUF_H_298734234
|
||||||
|
|
||||||
|
/* *** Dependencies *** */
|
||||||
|
#include "zstd_deps.h" /* size_t */
|
||||||
|
|
||||||
|
|
||||||
|
/* *** library symbols visibility *** */
|
||||||
|
/* Note : when linking with -fvisibility=hidden on gcc, or by default on Visual,
|
||||||
|
* HUF symbols remain "private" (internal symbols for library only).
|
||||||
|
* Set macro FSE_DLL_EXPORT to 1 if you want HUF symbols visible on DLL interface */
|
||||||
|
#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
# define HUF_PUBLIC_API __attribute__ ((visibility ("default")))
|
||||||
|
#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */
|
||||||
|
# define HUF_PUBLIC_API __declspec(dllexport)
|
||||||
|
#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
|
||||||
|
# define HUF_PUBLIC_API __declspec(dllimport) /* not required, just to generate faster code (saves a function pointer load from IAT and an indirect jump) */
|
||||||
|
#else
|
||||||
|
# define HUF_PUBLIC_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ========================== */
|
||||||
|
/* *** simple functions *** */
|
||||||
|
/* ========================== */
|
||||||
|
|
||||||
|
/** HUF_compress() :
|
||||||
|
* Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'.
|
||||||
|
* 'dst' buffer must be already allocated.
|
||||||
|
* Compression runs faster if `dstCapacity` >= HUF_compressBound(srcSize).
|
||||||
|
* `srcSize` must be <= `HUF_BLOCKSIZE_MAX` == 128 KB.
|
||||||
|
* @return : size of compressed data (<= `dstCapacity`).
|
||||||
|
* Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
|
||||||
|
* if HUF_isError(return), compression failed (more details using HUF_getErrorName())
|
||||||
|
*/
|
||||||
|
HUF_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity,
|
||||||
|
const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
/** HUF_decompress() :
|
||||||
|
* Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',
|
||||||
|
* into already allocated buffer 'dst', of minimum size 'dstSize'.
|
||||||
|
* `originalSize` : **must** be the ***exact*** size of original (uncompressed) data.
|
||||||
|
* Note : in contrast with FSE, HUF_decompress can regenerate
|
||||||
|
* RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
|
||||||
|
* because it knows size to regenerate (originalSize).
|
||||||
|
* @return : size of regenerated data (== originalSize),
|
||||||
|
* or an error code, which can be tested using HUF_isError()
|
||||||
|
*/
|
||||||
|
HUF_PUBLIC_API size_t HUF_decompress(void* dst, size_t originalSize,
|
||||||
|
const void* cSrc, size_t cSrcSize);
|
||||||
|
|
||||||
|
|
||||||
|
/* *** Tool functions *** */
|
||||||
|
#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */
|
||||||
|
HUF_PUBLIC_API size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */
|
||||||
|
|
||||||
|
/* Error Management */
|
||||||
|
HUF_PUBLIC_API unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */
|
||||||
|
HUF_PUBLIC_API const char* HUF_getErrorName(size_t code); /**< provides error code string (useful for debugging) */
|
||||||
|
|
||||||
|
|
||||||
|
/* *** Advanced function *** */
|
||||||
|
|
||||||
|
/** HUF_compress2() :
|
||||||
|
* Same as HUF_compress(), but offers control over `maxSymbolValue` and `tableLog`.
|
||||||
|
* `maxSymbolValue` must be <= HUF_SYMBOLVALUE_MAX .
|
||||||
|
* `tableLog` must be `<= HUF_TABLELOG_MAX` . */
|
||||||
|
HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
unsigned maxSymbolValue, unsigned tableLog);
|
||||||
|
|
||||||
|
/** HUF_compress4X_wksp() :
|
||||||
|
* Same as HUF_compress2(), but uses externally allocated @workSpace.
|
||||||
|
* @workSpace's size, aka @wkspSize, must be >= HUF_WORKSPACE_SIZE
|
||||||
|
* @srcSize must be >= 6
|
||||||
|
*/
|
||||||
|
#define HUF_WORKSPACE_SIZE ((8 << 10) + 512 /* sorting scratch space */)
|
||||||
|
#define HUF_WORKSPACE_SIZE_U64 (HUF_WORKSPACE_SIZE / sizeof(U64))
|
||||||
|
HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
unsigned maxSymbolValue, unsigned tableLog,
|
||||||
|
void* workSpace, size_t wkspSize);
|
||||||
|
|
||||||
|
#endif /* HUF_H_298734234 */
|
||||||
|
|
||||||
|
/* ******************************************************************
|
||||||
|
* WARNING !!
|
||||||
|
* The following section contains advanced and experimental definitions
|
||||||
|
* which shall never be used in the context of a dynamic library,
|
||||||
|
* because they are not guaranteed to remain stable in the future.
|
||||||
|
* Only consider them in association with static linking.
|
||||||
|
* *****************************************************************/
|
||||||
|
#if defined(HUF_STATIC_LINKING_ONLY) && !defined(HUF_H_HUF_STATIC_LINKING_ONLY)
|
||||||
|
#define HUF_H_HUF_STATIC_LINKING_ONLY
|
||||||
|
|
||||||
|
/* *** Dependencies *** */
|
||||||
|
#include "mem.h" /* U32 */
|
||||||
|
#define FSE_STATIC_LINKING_ONLY
|
||||||
|
#include "fse.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* *** Constants *** */
|
||||||
|
#define HUF_TABLELOG_MAX 12 /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_TABLELOG_ABSOLUTEMAX */
|
||||||
|
#define HUF_TABLELOG_DEFAULT 11 /* default tableLog value when none specified */
|
||||||
|
#define HUF_SYMBOLVALUE_MAX 255
|
||||||
|
|
||||||
|
#define HUF_TABLELOG_ABSOLUTEMAX 12 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
|
||||||
|
#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)
|
||||||
|
# error "HUF_TABLELOG_MAX is too large !"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ****************************************
|
||||||
|
* Static allocation
|
||||||
|
******************************************/
|
||||||
|
/* HUF buffer bounds */
|
||||||
|
#define HUF_CTABLEBOUND 129
|
||||||
|
#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true when incompressible is pre-filtered with fast heuristic */
|
||||||
|
#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
|
||||||
|
|
||||||
|
/* static allocation of HUF's Compression Table */
|
||||||
|
/* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */
|
||||||
|
typedef size_t HUF_CElt; /* consider it an incomplete type */
|
||||||
|
#define HUF_CTABLE_SIZE_ST(maxSymbolValue) ((maxSymbolValue)+2) /* Use tables of size_t, for proper alignment */
|
||||||
|
#define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_ST(maxSymbolValue) * sizeof(size_t))
|
||||||
|
#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
|
||||||
|
HUF_CElt name[HUF_CTABLE_SIZE_ST(maxSymbolValue)] /* no final ; */
|
||||||
|
|
||||||
|
/* static allocation of HUF's DTable */
|
||||||
|
typedef U32 HUF_DTable;
|
||||||
|
#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog)))
|
||||||
|
#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \
|
||||||
|
HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) }
|
||||||
|
#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \
|
||||||
|
HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) }
|
||||||
|
|
||||||
|
|
||||||
|
/* ****************************************
|
||||||
|
* Advanced decompression functions
|
||||||
|
******************************************/
|
||||||
|
size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||||
|
size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */
|
||||||
|
size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */
|
||||||
|
size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< considers RLE and uncompressed as errors */
|
||||||
|
size_t HUF_decompress4X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
|
||||||
|
size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||||
|
size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
|
||||||
|
size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ****************************************
|
||||||
|
* HUF detailed API
|
||||||
|
* ****************************************/
|
||||||
|
#define HUF_OPTIMAL_DEPTH_THRESHOLD ZSTD_btultra
|
||||||
|
typedef enum {
|
||||||
|
HUF_depth_fast, /** Use heuristic to find the table depth**/
|
||||||
|
HUF_depth_optimal /** Test possible table depths to find the one that produces the smallest header + encoded size**/
|
||||||
|
} HUF_depth_mode;
|
||||||
|
|
||||||
|
/*! HUF_compress() does the following:
|
||||||
|
* 1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within "fse.h")
|
||||||
|
* 2. (optional) refine tableLog using HUF_optimalTableLog()
|
||||||
|
* 3. build Huffman table from count using HUF_buildCTable()
|
||||||
|
* 4. save Huffman table to memory buffer using HUF_writeCTable()
|
||||||
|
* 5. encode the data stream using HUF_compress4X_usingCTable()
|
||||||
|
*
|
||||||
|
* The following API allows targeting specific sub-functions for advanced tasks.
|
||||||
|
* For example, it's possible to compress several blocks using the same 'CTable',
|
||||||
|
* or to save and regenerate 'CTable' using external methods.
|
||||||
|
*/
|
||||||
|
unsigned HUF_minTableLog(unsigned symbolCardinality);
|
||||||
|
unsigned HUF_cardinality(const unsigned* count, unsigned maxSymbolValue);
|
||||||
|
unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, void* workSpace,
|
||||||
|
size_t wkspSize, HUF_CElt* table, const unsigned* count, HUF_depth_mode depthMode); /* table is used as scratch space for building and testing tables, not a return value */
|
||||||
|
size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */
|
||||||
|
size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
|
||||||
|
size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, void* workspace, size_t workspaceSize);
|
||||||
|
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
|
||||||
|
size_t HUF_compress4X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2);
|
||||||
|
size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
|
||||||
|
int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HUF_repeat_none, /**< Cannot use the previous table */
|
||||||
|
HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */
|
||||||
|
HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */
|
||||||
|
} HUF_repeat;
|
||||||
|
|
||||||
|
/** HUF_compress4X_repeat() :
|
||||||
|
* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
|
||||||
|
* If it uses hufTable it does not modify hufTable or repeat.
|
||||||
|
* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
|
||||||
|
* If preferRepeat then the old table will always be used if valid.
|
||||||
|
* If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */
|
||||||
|
size_t HUF_compress4X_repeat(void* dst, size_t dstSize,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
unsigned maxSymbolValue, unsigned tableLog,
|
||||||
|
void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
|
||||||
|
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2,
|
||||||
|
int suspectUncompressible, HUF_depth_mode depthMode);
|
||||||
|
|
||||||
|
/** HUF_buildCTable_wksp() :
|
||||||
|
* Same as HUF_buildCTable(), but using externally allocated scratch buffer.
|
||||||
|
* `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE.
|
||||||
|
*/
|
||||||
|
#define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1)
|
||||||
|
#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned))
|
||||||
|
size_t HUF_buildCTable_wksp (HUF_CElt* tree,
|
||||||
|
const unsigned* count, U32 maxSymbolValue, U32 maxNbBits,
|
||||||
|
void* workSpace, size_t wkspSize);
|
||||||
|
|
||||||
|
/*! HUF_readStats() :
|
||||||
|
* Read compact Huffman tree, saved by HUF_writeCTable().
|
||||||
|
* `huffWeight` is destination buffer.
|
||||||
|
* @return : size read from `src` , or an error Code .
|
||||||
|
* Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */
|
||||||
|
size_t HUF_readStats(BYTE* huffWeight, size_t hwSize,
|
||||||
|
U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||||
|
const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
/*! HUF_readStats_wksp() :
|
||||||
|
* Same as HUF_readStats() but takes an external workspace which must be
|
||||||
|
* 4-byte aligned and its size must be >= HUF_READ_STATS_WORKSPACE_SIZE.
|
||||||
|
* If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.
|
||||||
|
*/
|
||||||
|
#define HUF_READ_STATS_WORKSPACE_SIZE_U32 FSE_DECOMPRESS_WKSP_SIZE_U32(6, HUF_TABLELOG_MAX-1)
|
||||||
|
#define HUF_READ_STATS_WORKSPACE_SIZE (HUF_READ_STATS_WORKSPACE_SIZE_U32 * sizeof(unsigned))
|
||||||
|
size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize,
|
||||||
|
U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
void* workspace, size_t wkspSize,
|
||||||
|
int bmi2);
|
||||||
|
|
||||||
|
/** HUF_readCTable() :
|
||||||
|
* Loading a CTable saved with HUF_writeCTable() */
|
||||||
|
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights);
|
||||||
|
|
||||||
|
/** HUF_getNbBitsFromCTable() :
|
||||||
|
* Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX
|
||||||
|
* Note 1 : is not inlined, as HUF_CElt definition is private */
|
||||||
|
U32 HUF_getNbBitsFromCTable(const HUF_CElt* symbolTable, U32 symbolValue);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HUF_decompress() does the following:
|
||||||
|
* 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics
|
||||||
|
* 2. build Huffman table from save, using HUF_readDTableX?()
|
||||||
|
* 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** HUF_selectDecoder() :
|
||||||
|
* Tells which decoder is likely to decode faster,
|
||||||
|
* based on a set of pre-computed metrics.
|
||||||
|
* @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .
|
||||||
|
* Assumption : 0 < dstSize <= 128 KB */
|
||||||
|
U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum workspace size for the `workSpace` used in
|
||||||
|
* HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp().
|
||||||
|
*
|
||||||
|
* The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when
|
||||||
|
* HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15.
|
||||||
|
* Buffer overflow errors may potentially occur if code modifications result in
|
||||||
|
* a required workspace size greater than that specified in the following
|
||||||
|
* macro.
|
||||||
|
*/
|
||||||
|
#define HUF_DECOMPRESS_WORKSPACE_SIZE ((2 << 10) + (1 << 9))
|
||||||
|
#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
|
||||||
|
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||||
|
size_t HUF_readDTableX1 (HUF_DTable* DTable, const void* src, size_t srcSize);
|
||||||
|
size_t HUF_readDTableX1_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
|
||||||
|
#endif
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||||
|
size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize);
|
||||||
|
size_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||||
|
size_t HUF_decompress4X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
|
||||||
|
#endif
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||||
|
size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ====================== */
|
||||||
|
/* single stream variants */
|
||||||
|
/* ====================== */
|
||||||
|
|
||||||
|
size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
|
||||||
|
size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U64 U64 */
|
||||||
|
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
|
||||||
|
size_t HUF_compress1X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2);
|
||||||
|
/** HUF_compress1X_repeat() :
|
||||||
|
* Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
|
||||||
|
* If it uses hufTable it does not modify hufTable or repeat.
|
||||||
|
* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
|
||||||
|
* If preferRepeat then the old table will always be used if valid.
|
||||||
|
* If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */
|
||||||
|
size_t HUF_compress1X_repeat(void* dst, size_t dstSize,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
unsigned maxSymbolValue, unsigned tableLog,
|
||||||
|
void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
|
||||||
|
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2,
|
||||||
|
int suspectUncompressible, HUF_depth_mode depthMode);
|
||||||
|
|
||||||
|
size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||||
|
size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
|
||||||
|
size_t HUF_decompress1X_DCtx_wksp (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||||
|
size_t HUF_decompress1X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
|
||||||
|
size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */
|
||||||
|
#endif
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||||
|
size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
|
||||||
|
size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||||
|
size_t HUF_decompress1X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
|
||||||
|
#endif
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||||
|
size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* BMI2 variants.
|
||||||
|
* If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.
|
||||||
|
*/
|
||||||
|
size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||||
|
size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
|
||||||
|
#endif
|
||||||
|
size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
|
||||||
|
size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||||
|
size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2);
|
||||||
|
#endif
|
||||||
|
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||||
|
size_t HUF_readDTableX2_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HUF_STATIC_LINKING_ONLY */
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
435
external/zstd/common/mem.h
vendored
Normal file
435
external/zstd/common/mem.h
vendored
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEM_H_MODULE
|
||||||
|
#define MEM_H_MODULE
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-****************************************
|
||||||
|
* Dependencies
|
||||||
|
******************************************/
|
||||||
|
#include <stddef.h> /* size_t, ptrdiff_t */
|
||||||
|
#include "compiler.h" /* __has_builtin */
|
||||||
|
#include "debug.h" /* DEBUG_STATIC_ASSERT */
|
||||||
|
#include "zstd_deps.h" /* ZSTD_memcpy */
|
||||||
|
|
||||||
|
|
||||||
|
/*-****************************************
|
||||||
|
* Compiler specifics
|
||||||
|
******************************************/
|
||||||
|
#if defined(_MSC_VER) /* Visual Studio */
|
||||||
|
# include <stdlib.h> /* _byteswap_ulong */
|
||||||
|
# include <intrin.h> /* _byteswap_* */
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define MEM_STATIC static __inline __attribute__((unused))
|
||||||
|
#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||||
|
# define MEM_STATIC static inline
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define MEM_STATIC static __inline
|
||||||
|
#else
|
||||||
|
# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-**************************************************************
|
||||||
|
* Basic Types
|
||||||
|
*****************************************************************/
|
||||||
|
#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
|
||||||
|
# if defined(_AIX)
|
||||||
|
# include <inttypes.h>
|
||||||
|
# else
|
||||||
|
# include <stdint.h> /* intptr_t */
|
||||||
|
# endif
|
||||||
|
typedef uint8_t BYTE;
|
||||||
|
typedef uint8_t U8;
|
||||||
|
typedef int8_t S8;
|
||||||
|
typedef uint16_t U16;
|
||||||
|
typedef int16_t S16;
|
||||||
|
typedef uint32_t U32;
|
||||||
|
typedef int32_t S32;
|
||||||
|
typedef uint64_t U64;
|
||||||
|
typedef int64_t S64;
|
||||||
|
#else
|
||||||
|
# include <limits.h>
|
||||||
|
#if CHAR_BIT != 8
|
||||||
|
# error "this implementation requires char to be exactly 8-bit type"
|
||||||
|
#endif
|
||||||
|
typedef unsigned char BYTE;
|
||||||
|
typedef unsigned char U8;
|
||||||
|
typedef signed char S8;
|
||||||
|
#if USHRT_MAX != 65535
|
||||||
|
# error "this implementation requires short to be exactly 16-bit type"
|
||||||
|
#endif
|
||||||
|
typedef unsigned short U16;
|
||||||
|
typedef signed short S16;
|
||||||
|
#if UINT_MAX != 4294967295
|
||||||
|
# error "this implementation requires int to be exactly 32-bit type"
|
||||||
|
#endif
|
||||||
|
typedef unsigned int U32;
|
||||||
|
typedef signed int S32;
|
||||||
|
/* note : there are no limits defined for long long type in C90.
|
||||||
|
* limits exist in C99, however, in such case, <stdint.h> is preferred */
|
||||||
|
typedef unsigned long long U64;
|
||||||
|
typedef signed long long S64;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*-**************************************************************
|
||||||
|
* Memory I/O API
|
||||||
|
*****************************************************************/
|
||||||
|
/*=== Static platform detection ===*/
|
||||||
|
MEM_STATIC unsigned MEM_32bits(void);
|
||||||
|
MEM_STATIC unsigned MEM_64bits(void);
|
||||||
|
MEM_STATIC unsigned MEM_isLittleEndian(void);
|
||||||
|
|
||||||
|
/*=== Native unaligned read/write ===*/
|
||||||
|
MEM_STATIC U16 MEM_read16(const void* memPtr);
|
||||||
|
MEM_STATIC U32 MEM_read32(const void* memPtr);
|
||||||
|
MEM_STATIC U64 MEM_read64(const void* memPtr);
|
||||||
|
MEM_STATIC size_t MEM_readST(const void* memPtr);
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_write16(void* memPtr, U16 value);
|
||||||
|
MEM_STATIC void MEM_write32(void* memPtr, U32 value);
|
||||||
|
MEM_STATIC void MEM_write64(void* memPtr, U64 value);
|
||||||
|
|
||||||
|
/*=== Little endian unaligned read/write ===*/
|
||||||
|
MEM_STATIC U16 MEM_readLE16(const void* memPtr);
|
||||||
|
MEM_STATIC U32 MEM_readLE24(const void* memPtr);
|
||||||
|
MEM_STATIC U32 MEM_readLE32(const void* memPtr);
|
||||||
|
MEM_STATIC U64 MEM_readLE64(const void* memPtr);
|
||||||
|
MEM_STATIC size_t MEM_readLEST(const void* memPtr);
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val);
|
||||||
|
MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val);
|
||||||
|
MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32);
|
||||||
|
MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64);
|
||||||
|
MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val);
|
||||||
|
|
||||||
|
/*=== Big endian unaligned read/write ===*/
|
||||||
|
MEM_STATIC U32 MEM_readBE32(const void* memPtr);
|
||||||
|
MEM_STATIC U64 MEM_readBE64(const void* memPtr);
|
||||||
|
MEM_STATIC size_t MEM_readBEST(const void* memPtr);
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32);
|
||||||
|
MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64);
|
||||||
|
MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val);
|
||||||
|
|
||||||
|
/*=== Byteswap ===*/
|
||||||
|
MEM_STATIC U32 MEM_swap32(U32 in);
|
||||||
|
MEM_STATIC U64 MEM_swap64(U64 in);
|
||||||
|
MEM_STATIC size_t MEM_swapST(size_t in);
|
||||||
|
|
||||||
|
|
||||||
|
/*-**************************************************************
|
||||||
|
* Memory I/O Implementation
|
||||||
|
*****************************************************************/
|
||||||
|
/* MEM_FORCE_MEMORY_ACCESS : For accessing unaligned memory:
|
||||||
|
* Method 0 : always use `memcpy()`. Safe and portable.
|
||||||
|
* Method 1 : Use compiler extension to set unaligned access.
|
||||||
|
* Method 2 : direct access. This method is portable but violate C standard.
|
||||||
|
* It can generate buggy code on targets depending on alignment.
|
||||||
|
* Default : method 1 if supported, else method 0
|
||||||
|
*/
|
||||||
|
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||||
|
# ifdef __GNUC__
|
||||||
|
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }
|
||||||
|
MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }
|
||||||
|
|
||||||
|
MEM_STATIC unsigned MEM_isLittleEndian(void)
|
||||||
|
{
|
||||||
|
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||||
|
return 1;
|
||||||
|
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||||
|
return 0;
|
||||||
|
#elif defined(__clang__) && __LITTLE_ENDIAN__
|
||||||
|
return 1;
|
||||||
|
#elif defined(__clang__) && __BIG_ENDIAN__
|
||||||
|
return 0;
|
||||||
|
#elif defined(_MSC_VER) && (_M_AMD64 || _M_IX86)
|
||||||
|
return 1;
|
||||||
|
#elif defined(__DMC__) && defined(_M_IX86)
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
|
||||||
|
return one.c[0];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
|
||||||
|
|
||||||
|
/* violates C standard, by lying on structure alignment.
|
||||||
|
Only use if no other choice to achieve best performance on target platform */
|
||||||
|
MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
|
||||||
|
MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||||
|
MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||||
|
MEM_STATIC size_t MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
|
||||||
|
MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
|
||||||
|
MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
|
||||||
|
|
||||||
|
#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
|
||||||
|
|
||||||
|
typedef __attribute__((aligned(1))) U16 unalign16;
|
||||||
|
typedef __attribute__((aligned(1))) U32 unalign32;
|
||||||
|
typedef __attribute__((aligned(1))) U64 unalign64;
|
||||||
|
typedef __attribute__((aligned(1))) size_t unalignArch;
|
||||||
|
|
||||||
|
MEM_STATIC U16 MEM_read16(const void* ptr) { return *(const unalign16*)ptr; }
|
||||||
|
MEM_STATIC U32 MEM_read32(const void* ptr) { return *(const unalign32*)ptr; }
|
||||||
|
MEM_STATIC U64 MEM_read64(const void* ptr) { return *(const unalign64*)ptr; }
|
||||||
|
MEM_STATIC size_t MEM_readST(const void* ptr) { return *(const unalignArch*)ptr; }
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(unalign16*)memPtr = value; }
|
||||||
|
MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(unalign32*)memPtr = value; }
|
||||||
|
MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(unalign64*)memPtr = value; }
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* default method, safe and standard.
|
||||||
|
can sometimes prove slower */
|
||||||
|
|
||||||
|
MEM_STATIC U16 MEM_read16(const void* memPtr)
|
||||||
|
{
|
||||||
|
U16 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC U32 MEM_read32(const void* memPtr)
|
||||||
|
{
|
||||||
|
U32 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC U64 MEM_read64(const void* memPtr)
|
||||||
|
{
|
||||||
|
U64 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC size_t MEM_readST(const void* memPtr)
|
||||||
|
{
|
||||||
|
size_t val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_write16(void* memPtr, U16 value)
|
||||||
|
{
|
||||||
|
ZSTD_memcpy(memPtr, &value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_write32(void* memPtr, U32 value)
|
||||||
|
{
|
||||||
|
ZSTD_memcpy(memPtr, &value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_write64(void* memPtr, U64 value)
|
||||||
|
{
|
||||||
|
ZSTD_memcpy(memPtr, &value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MEM_FORCE_MEMORY_ACCESS */
|
||||||
|
|
||||||
|
MEM_STATIC U32 MEM_swap32_fallback(U32 in)
|
||||||
|
{
|
||||||
|
return ((in << 24) & 0xff000000 ) |
|
||||||
|
((in << 8) & 0x00ff0000 ) |
|
||||||
|
((in >> 8) & 0x0000ff00 ) |
|
||||||
|
((in >> 24) & 0x000000ff );
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC U32 MEM_swap32(U32 in)
|
||||||
|
{
|
||||||
|
#if defined(_MSC_VER) /* Visual Studio */
|
||||||
|
return _byteswap_ulong(in);
|
||||||
|
#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
|
||||||
|
|| (defined(__clang__) && __has_builtin(__builtin_bswap32))
|
||||||
|
return __builtin_bswap32(in);
|
||||||
|
#else
|
||||||
|
return MEM_swap32_fallback(in);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC U64 MEM_swap64_fallback(U64 in)
|
||||||
|
{
|
||||||
|
return ((in << 56) & 0xff00000000000000ULL) |
|
||||||
|
((in << 40) & 0x00ff000000000000ULL) |
|
||||||
|
((in << 24) & 0x0000ff0000000000ULL) |
|
||||||
|
((in << 8) & 0x000000ff00000000ULL) |
|
||||||
|
((in >> 8) & 0x00000000ff000000ULL) |
|
||||||
|
((in >> 24) & 0x0000000000ff0000ULL) |
|
||||||
|
((in >> 40) & 0x000000000000ff00ULL) |
|
||||||
|
((in >> 56) & 0x00000000000000ffULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC U64 MEM_swap64(U64 in)
|
||||||
|
{
|
||||||
|
#if defined(_MSC_VER) /* Visual Studio */
|
||||||
|
return _byteswap_uint64(in);
|
||||||
|
#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
|
||||||
|
|| (defined(__clang__) && __has_builtin(__builtin_bswap64))
|
||||||
|
return __builtin_bswap64(in);
|
||||||
|
#else
|
||||||
|
return MEM_swap64_fallback(in);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC size_t MEM_swapST(size_t in)
|
||||||
|
{
|
||||||
|
if (MEM_32bits())
|
||||||
|
return (size_t)MEM_swap32((U32)in);
|
||||||
|
else
|
||||||
|
return (size_t)MEM_swap64((U64)in);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=== Little endian r/w ===*/
|
||||||
|
|
||||||
|
MEM_STATIC U16 MEM_readLE16(const void* memPtr)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian())
|
||||||
|
return MEM_read16(memPtr);
|
||||||
|
else {
|
||||||
|
const BYTE* p = (const BYTE*)memPtr;
|
||||||
|
return (U16)(p[0] + (p[1]<<8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian()) {
|
||||||
|
MEM_write16(memPtr, val);
|
||||||
|
} else {
|
||||||
|
BYTE* p = (BYTE*)memPtr;
|
||||||
|
p[0] = (BYTE)val;
|
||||||
|
p[1] = (BYTE)(val>>8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC U32 MEM_readLE24(const void* memPtr)
|
||||||
|
{
|
||||||
|
return (U32)MEM_readLE16(memPtr) + ((U32)(((const BYTE*)memPtr)[2]) << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)
|
||||||
|
{
|
||||||
|
MEM_writeLE16(memPtr, (U16)val);
|
||||||
|
((BYTE*)memPtr)[2] = (BYTE)(val>>16);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC U32 MEM_readLE32(const void* memPtr)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian())
|
||||||
|
return MEM_read32(memPtr);
|
||||||
|
else
|
||||||
|
return MEM_swap32(MEM_read32(memPtr));
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian())
|
||||||
|
MEM_write32(memPtr, val32);
|
||||||
|
else
|
||||||
|
MEM_write32(memPtr, MEM_swap32(val32));
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC U64 MEM_readLE64(const void* memPtr)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian())
|
||||||
|
return MEM_read64(memPtr);
|
||||||
|
else
|
||||||
|
return MEM_swap64(MEM_read64(memPtr));
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian())
|
||||||
|
MEM_write64(memPtr, val64);
|
||||||
|
else
|
||||||
|
MEM_write64(memPtr, MEM_swap64(val64));
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC size_t MEM_readLEST(const void* memPtr)
|
||||||
|
{
|
||||||
|
if (MEM_32bits())
|
||||||
|
return (size_t)MEM_readLE32(memPtr);
|
||||||
|
else
|
||||||
|
return (size_t)MEM_readLE64(memPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val)
|
||||||
|
{
|
||||||
|
if (MEM_32bits())
|
||||||
|
MEM_writeLE32(memPtr, (U32)val);
|
||||||
|
else
|
||||||
|
MEM_writeLE64(memPtr, (U64)val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=== Big endian r/w ===*/
|
||||||
|
|
||||||
|
MEM_STATIC U32 MEM_readBE32(const void* memPtr)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian())
|
||||||
|
return MEM_swap32(MEM_read32(memPtr));
|
||||||
|
else
|
||||||
|
return MEM_read32(memPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian())
|
||||||
|
MEM_write32(memPtr, MEM_swap32(val32));
|
||||||
|
else
|
||||||
|
MEM_write32(memPtr, val32);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC U64 MEM_readBE64(const void* memPtr)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian())
|
||||||
|
return MEM_swap64(MEM_read64(memPtr));
|
||||||
|
else
|
||||||
|
return MEM_read64(memPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64)
|
||||||
|
{
|
||||||
|
if (MEM_isLittleEndian())
|
||||||
|
MEM_write64(memPtr, MEM_swap64(val64));
|
||||||
|
else
|
||||||
|
MEM_write64(memPtr, val64);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC size_t MEM_readBEST(const void* memPtr)
|
||||||
|
{
|
||||||
|
if (MEM_32bits())
|
||||||
|
return (size_t)MEM_readBE32(memPtr);
|
||||||
|
else
|
||||||
|
return (size_t)MEM_readBE64(memPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)
|
||||||
|
{
|
||||||
|
if (MEM_32bits())
|
||||||
|
MEM_writeBE32(memPtr, (U32)val);
|
||||||
|
else
|
||||||
|
MEM_writeBE64(memPtr, (U64)val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* code only tested on 32 and 64 bits systems */
|
||||||
|
MEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* MEM_H_MODULE */
|
||||||
369
external/zstd/common/pool.c
vendored
Normal file
369
external/zstd/common/pool.c
vendored
Normal file
@@ -0,0 +1,369 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* ====== Dependencies ======= */
|
||||||
|
#include "zstd_deps.h" /* size_t */
|
||||||
|
#include "debug.h" /* assert */
|
||||||
|
#include "zstd_internal.h" /* ZSTD_customCalloc, ZSTD_customFree */
|
||||||
|
#include "pool.h"
|
||||||
|
|
||||||
|
/* ====== Compiler specifics ====== */
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ZSTD_MULTITHREAD
|
||||||
|
|
||||||
|
#include "threading.h" /* pthread adaptation */
|
||||||
|
|
||||||
|
/* A job is a function and an opaque argument */
|
||||||
|
typedef struct POOL_job_s {
|
||||||
|
POOL_function function;
|
||||||
|
void *opaque;
|
||||||
|
} POOL_job;
|
||||||
|
|
||||||
|
struct POOL_ctx_s {
|
||||||
|
ZSTD_customMem customMem;
|
||||||
|
/* Keep track of the threads */
|
||||||
|
ZSTD_pthread_t* threads;
|
||||||
|
size_t threadCapacity;
|
||||||
|
size_t threadLimit;
|
||||||
|
|
||||||
|
/* The queue is a circular buffer */
|
||||||
|
POOL_job *queue;
|
||||||
|
size_t queueHead;
|
||||||
|
size_t queueTail;
|
||||||
|
size_t queueSize;
|
||||||
|
|
||||||
|
/* The number of threads working on jobs */
|
||||||
|
size_t numThreadsBusy;
|
||||||
|
/* Indicates if the queue is empty */
|
||||||
|
int queueEmpty;
|
||||||
|
|
||||||
|
/* The mutex protects the queue */
|
||||||
|
ZSTD_pthread_mutex_t queueMutex;
|
||||||
|
/* Condition variable for pushers to wait on when the queue is full */
|
||||||
|
ZSTD_pthread_cond_t queuePushCond;
|
||||||
|
/* Condition variables for poppers to wait on when the queue is empty */
|
||||||
|
ZSTD_pthread_cond_t queuePopCond;
|
||||||
|
/* Indicates if the queue is shutting down */
|
||||||
|
int shutdown;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* POOL_thread() :
|
||||||
|
* Work thread for the thread pool.
|
||||||
|
* Waits for jobs and executes them.
|
||||||
|
* @returns : NULL on failure else non-null.
|
||||||
|
*/
|
||||||
|
static void* POOL_thread(void* opaque) {
|
||||||
|
POOL_ctx* const ctx = (POOL_ctx*)opaque;
|
||||||
|
if (!ctx) { return NULL; }
|
||||||
|
for (;;) {
|
||||||
|
/* Lock the mutex and wait for a non-empty queue or until shutdown */
|
||||||
|
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
||||||
|
|
||||||
|
while ( ctx->queueEmpty
|
||||||
|
|| (ctx->numThreadsBusy >= ctx->threadLimit) ) {
|
||||||
|
if (ctx->shutdown) {
|
||||||
|
/* even if !queueEmpty, (possible if numThreadsBusy >= threadLimit),
|
||||||
|
* a few threads will be shutdown while !queueEmpty,
|
||||||
|
* but enough threads will remain active to finish the queue */
|
||||||
|
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
return opaque;
|
||||||
|
}
|
||||||
|
ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
|
||||||
|
}
|
||||||
|
/* Pop a job off the queue */
|
||||||
|
{ POOL_job const job = ctx->queue[ctx->queueHead];
|
||||||
|
ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;
|
||||||
|
ctx->numThreadsBusy++;
|
||||||
|
ctx->queueEmpty = (ctx->queueHead == ctx->queueTail);
|
||||||
|
/* Unlock the mutex, signal a pusher, and run the job */
|
||||||
|
ZSTD_pthread_cond_signal(&ctx->queuePushCond);
|
||||||
|
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
|
||||||
|
job.function(job.opaque);
|
||||||
|
|
||||||
|
/* If the intended queue size was 0, signal after finishing job */
|
||||||
|
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
||||||
|
ctx->numThreadsBusy--;
|
||||||
|
ZSTD_pthread_cond_signal(&ctx->queuePushCond);
|
||||||
|
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
}
|
||||||
|
} /* for (;;) */
|
||||||
|
assert(0); /* Unreachable */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ZSTD_createThreadPool() : public access point */
|
||||||
|
POOL_ctx* ZSTD_createThreadPool(size_t numThreads) {
|
||||||
|
return POOL_create (numThreads, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
|
||||||
|
return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
|
||||||
|
ZSTD_customMem customMem)
|
||||||
|
{
|
||||||
|
POOL_ctx* ctx;
|
||||||
|
/* Check parameters */
|
||||||
|
if (!numThreads) { return NULL; }
|
||||||
|
/* Allocate the context and zero initialize */
|
||||||
|
ctx = (POOL_ctx*)ZSTD_customCalloc(sizeof(POOL_ctx), customMem);
|
||||||
|
if (!ctx) { return NULL; }
|
||||||
|
/* Initialize the job queue.
|
||||||
|
* It needs one extra space since one space is wasted to differentiate
|
||||||
|
* empty and full queues.
|
||||||
|
*/
|
||||||
|
ctx->queueSize = queueSize + 1;
|
||||||
|
ctx->queue = (POOL_job*)ZSTD_customCalloc(ctx->queueSize * sizeof(POOL_job), customMem);
|
||||||
|
ctx->queueHead = 0;
|
||||||
|
ctx->queueTail = 0;
|
||||||
|
ctx->numThreadsBusy = 0;
|
||||||
|
ctx->queueEmpty = 1;
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
error |= ZSTD_pthread_mutex_init(&ctx->queueMutex, NULL);
|
||||||
|
error |= ZSTD_pthread_cond_init(&ctx->queuePushCond, NULL);
|
||||||
|
error |= ZSTD_pthread_cond_init(&ctx->queuePopCond, NULL);
|
||||||
|
if (error) { POOL_free(ctx); return NULL; }
|
||||||
|
}
|
||||||
|
ctx->shutdown = 0;
|
||||||
|
/* Allocate space for the thread handles */
|
||||||
|
ctx->threads = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), customMem);
|
||||||
|
ctx->threadCapacity = 0;
|
||||||
|
ctx->customMem = customMem;
|
||||||
|
/* Check for errors */
|
||||||
|
if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }
|
||||||
|
/* Initialize the threads */
|
||||||
|
{ size_t i;
|
||||||
|
for (i = 0; i < numThreads; ++i) {
|
||||||
|
if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {
|
||||||
|
ctx->threadCapacity = i;
|
||||||
|
POOL_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
} }
|
||||||
|
ctx->threadCapacity = numThreads;
|
||||||
|
ctx->threadLimit = numThreads;
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! POOL_join() :
|
||||||
|
Shutdown the queue, wake any sleeping threads, and join all of the threads.
|
||||||
|
*/
|
||||||
|
static void POOL_join(POOL_ctx* ctx) {
|
||||||
|
/* Shut down the queue */
|
||||||
|
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
||||||
|
ctx->shutdown = 1;
|
||||||
|
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
/* Wake up sleeping threads */
|
||||||
|
ZSTD_pthread_cond_broadcast(&ctx->queuePushCond);
|
||||||
|
ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
|
||||||
|
/* Join all of the threads */
|
||||||
|
{ size_t i;
|
||||||
|
for (i = 0; i < ctx->threadCapacity; ++i) {
|
||||||
|
ZSTD_pthread_join(ctx->threads[i]); /* note : could fail */
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
|
void POOL_free(POOL_ctx *ctx) {
|
||||||
|
if (!ctx) { return; }
|
||||||
|
POOL_join(ctx);
|
||||||
|
ZSTD_pthread_mutex_destroy(&ctx->queueMutex);
|
||||||
|
ZSTD_pthread_cond_destroy(&ctx->queuePushCond);
|
||||||
|
ZSTD_pthread_cond_destroy(&ctx->queuePopCond);
|
||||||
|
ZSTD_customFree(ctx->queue, ctx->customMem);
|
||||||
|
ZSTD_customFree(ctx->threads, ctx->customMem);
|
||||||
|
ZSTD_customFree(ctx, ctx->customMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! POOL_joinJobs() :
|
||||||
|
* Waits for all queued jobs to finish executing.
|
||||||
|
*/
|
||||||
|
void POOL_joinJobs(POOL_ctx* ctx) {
|
||||||
|
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
||||||
|
while(!ctx->queueEmpty || ctx->numThreadsBusy > 0) {
|
||||||
|
ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
|
||||||
|
}
|
||||||
|
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZSTD_freeThreadPool (ZSTD_threadPool* pool) {
|
||||||
|
POOL_free (pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t POOL_sizeof(const POOL_ctx* ctx) {
|
||||||
|
if (ctx==NULL) return 0; /* supports sizeof NULL */
|
||||||
|
return sizeof(*ctx)
|
||||||
|
+ ctx->queueSize * sizeof(POOL_job)
|
||||||
|
+ ctx->threadCapacity * sizeof(ZSTD_pthread_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* @return : 0 on success, 1 on error */
|
||||||
|
static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)
|
||||||
|
{
|
||||||
|
if (numThreads <= ctx->threadCapacity) {
|
||||||
|
if (!numThreads) return 1;
|
||||||
|
ctx->threadLimit = numThreads;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* numThreads > threadCapacity */
|
||||||
|
{ ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);
|
||||||
|
if (!threadPool) return 1;
|
||||||
|
/* replace existing thread pool */
|
||||||
|
ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool));
|
||||||
|
ZSTD_customFree(ctx->threads, ctx->customMem);
|
||||||
|
ctx->threads = threadPool;
|
||||||
|
/* Initialize additional threads */
|
||||||
|
{ size_t threadId;
|
||||||
|
for (threadId = ctx->threadCapacity; threadId < numThreads; ++threadId) {
|
||||||
|
if (ZSTD_pthread_create(&threadPool[threadId], NULL, &POOL_thread, ctx)) {
|
||||||
|
ctx->threadCapacity = threadId;
|
||||||
|
return 1;
|
||||||
|
} }
|
||||||
|
} }
|
||||||
|
/* successfully expanded */
|
||||||
|
ctx->threadCapacity = numThreads;
|
||||||
|
ctx->threadLimit = numThreads;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @return : 0 on success, 1 on error */
|
||||||
|
int POOL_resize(POOL_ctx* ctx, size_t numThreads)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if (ctx==NULL) return 1;
|
||||||
|
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
||||||
|
result = POOL_resize_internal(ctx, numThreads);
|
||||||
|
ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
|
||||||
|
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns 1 if the queue is full and 0 otherwise.
|
||||||
|
*
|
||||||
|
* When queueSize is 1 (pool was created with an intended queueSize of 0),
|
||||||
|
* then a queue is empty if there is a thread free _and_ no job is waiting.
|
||||||
|
*/
|
||||||
|
static int isQueueFull(POOL_ctx const* ctx) {
|
||||||
|
if (ctx->queueSize > 1) {
|
||||||
|
return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize);
|
||||||
|
} else {
|
||||||
|
return (ctx->numThreadsBusy == ctx->threadLimit) ||
|
||||||
|
!ctx->queueEmpty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
|
||||||
|
{
|
||||||
|
POOL_job const job = {function, opaque};
|
||||||
|
assert(ctx != NULL);
|
||||||
|
if (ctx->shutdown) return;
|
||||||
|
|
||||||
|
ctx->queueEmpty = 0;
|
||||||
|
ctx->queue[ctx->queueTail] = job;
|
||||||
|
ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
|
||||||
|
ZSTD_pthread_cond_signal(&ctx->queuePopCond);
|
||||||
|
}
|
||||||
|
|
||||||
|
void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque)
|
||||||
|
{
|
||||||
|
assert(ctx != NULL);
|
||||||
|
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
||||||
|
/* Wait until there is space in the queue for the new job */
|
||||||
|
while (isQueueFull(ctx) && (!ctx->shutdown)) {
|
||||||
|
ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
|
||||||
|
}
|
||||||
|
POOL_add_internal(ctx, function, opaque);
|
||||||
|
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque)
|
||||||
|
{
|
||||||
|
assert(ctx != NULL);
|
||||||
|
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
||||||
|
if (isQueueFull(ctx)) {
|
||||||
|
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
POOL_add_internal(ctx, function, opaque);
|
||||||
|
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else /* ZSTD_MULTITHREAD not defined */
|
||||||
|
|
||||||
|
/* ========================== */
|
||||||
|
/* No multi-threading support */
|
||||||
|
/* ========================== */
|
||||||
|
|
||||||
|
|
||||||
|
/* We don't need any data, but if it is empty, malloc() might return NULL. */
|
||||||
|
struct POOL_ctx_s {
|
||||||
|
int dummy;
|
||||||
|
};
|
||||||
|
static POOL_ctx g_poolCtx;
|
||||||
|
|
||||||
|
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
|
||||||
|
return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
POOL_ctx*
|
||||||
|
POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem)
|
||||||
|
{
|
||||||
|
(void)numThreads;
|
||||||
|
(void)queueSize;
|
||||||
|
(void)customMem;
|
||||||
|
return &g_poolCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void POOL_free(POOL_ctx* ctx) {
|
||||||
|
assert(!ctx || ctx == &g_poolCtx);
|
||||||
|
(void)ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void POOL_joinJobs(POOL_ctx* ctx){
|
||||||
|
assert(!ctx || ctx == &g_poolCtx);
|
||||||
|
(void)ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int POOL_resize(POOL_ctx* ctx, size_t numThreads) {
|
||||||
|
(void)ctx; (void)numThreads;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) {
|
||||||
|
(void)ctx;
|
||||||
|
function(opaque);
|
||||||
|
}
|
||||||
|
|
||||||
|
int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {
|
||||||
|
(void)ctx;
|
||||||
|
function(opaque);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t POOL_sizeof(const POOL_ctx* ctx) {
|
||||||
|
if (ctx==NULL) return 0; /* supports sizeof NULL */
|
||||||
|
assert(ctx == &g_poolCtx);
|
||||||
|
return sizeof(*ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ZSTD_MULTITHREAD */
|
||||||
90
external/zstd/common/pool.h
vendored
Normal file
90
external/zstd/common/pool.h
vendored
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef POOL_H
|
||||||
|
#define POOL_H
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "zstd_deps.h"
|
||||||
|
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_customMem */
|
||||||
|
#include "../zstd.h"
|
||||||
|
|
||||||
|
typedef struct POOL_ctx_s POOL_ctx;
|
||||||
|
|
||||||
|
/*! POOL_create() :
|
||||||
|
* Create a thread pool with at most `numThreads` threads.
|
||||||
|
* `numThreads` must be at least 1.
|
||||||
|
* The maximum number of queued jobs before blocking is `queueSize`.
|
||||||
|
* @return : POOL_ctx pointer on success, else NULL.
|
||||||
|
*/
|
||||||
|
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize);
|
||||||
|
|
||||||
|
POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
|
||||||
|
ZSTD_customMem customMem);
|
||||||
|
|
||||||
|
/*! POOL_free() :
|
||||||
|
* Free a thread pool returned by POOL_create().
|
||||||
|
*/
|
||||||
|
void POOL_free(POOL_ctx* ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/*! POOL_joinJobs() :
|
||||||
|
* Waits for all queued jobs to finish executing.
|
||||||
|
*/
|
||||||
|
void POOL_joinJobs(POOL_ctx* ctx);
|
||||||
|
|
||||||
|
/*! POOL_resize() :
|
||||||
|
* Expands or shrinks pool's number of threads.
|
||||||
|
* This is more efficient than releasing + creating a new context,
|
||||||
|
* since it tries to preserve and re-use existing threads.
|
||||||
|
* `numThreads` must be at least 1.
|
||||||
|
* @return : 0 when resize was successful,
|
||||||
|
* !0 (typically 1) if there is an error.
|
||||||
|
* note : only numThreads can be resized, queueSize remains unchanged.
|
||||||
|
*/
|
||||||
|
int POOL_resize(POOL_ctx* ctx, size_t numThreads);
|
||||||
|
|
||||||
|
/*! POOL_sizeof() :
|
||||||
|
* @return threadpool memory usage
|
||||||
|
* note : compatible with NULL (returns 0 in this case)
|
||||||
|
*/
|
||||||
|
size_t POOL_sizeof(const POOL_ctx* ctx);
|
||||||
|
|
||||||
|
/*! POOL_function :
|
||||||
|
* The function type that can be added to a thread pool.
|
||||||
|
*/
|
||||||
|
typedef void (*POOL_function)(void*);
|
||||||
|
|
||||||
|
/*! POOL_add() :
|
||||||
|
* Add the job `function(opaque)` to the thread pool. `ctx` must be valid.
|
||||||
|
* Possibly blocks until there is room in the queue.
|
||||||
|
* Note : The function may be executed asynchronously,
|
||||||
|
* therefore, `opaque` must live until function has been completed.
|
||||||
|
*/
|
||||||
|
void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque);
|
||||||
|
|
||||||
|
|
||||||
|
/*! POOL_tryAdd() :
|
||||||
|
* Add the job `function(opaque)` to thread pool _if_ a queue slot is available.
|
||||||
|
* Returns immediately even if not (does not block).
|
||||||
|
* @return : 1 if successful, 0 if not.
|
||||||
|
*/
|
||||||
|
int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
148
external/zstd/common/portability_macros.h
vendored
Normal file
148
external/zstd/common/portability_macros.h
vendored
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZSTD_PORTABILITY_MACROS_H
|
||||||
|
#define ZSTD_PORTABILITY_MACROS_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This header file contains macro definitions to support portability.
|
||||||
|
* This header is shared between C and ASM code, so it MUST only
|
||||||
|
* contain macro definitions. It MUST not contain any C code.
|
||||||
|
*
|
||||||
|
* This header ONLY defines macros to detect platforms/feature support.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* compat. with non-clang compilers */
|
||||||
|
#ifndef __has_attribute
|
||||||
|
#define __has_attribute(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* compat. with non-clang compilers */
|
||||||
|
#ifndef __has_builtin
|
||||||
|
# define __has_builtin(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* compat. with non-clang compilers */
|
||||||
|
#ifndef __has_feature
|
||||||
|
# define __has_feature(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* detects whether we are being compiled under msan */
|
||||||
|
#ifndef ZSTD_MEMORY_SANITIZER
|
||||||
|
# if __has_feature(memory_sanitizer)
|
||||||
|
# define ZSTD_MEMORY_SANITIZER 1
|
||||||
|
# else
|
||||||
|
# define ZSTD_MEMORY_SANITIZER 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* detects whether we are being compiled under asan */
|
||||||
|
#ifndef ZSTD_ADDRESS_SANITIZER
|
||||||
|
# if __has_feature(address_sanitizer)
|
||||||
|
# define ZSTD_ADDRESS_SANITIZER 1
|
||||||
|
# elif defined(__SANITIZE_ADDRESS__)
|
||||||
|
# define ZSTD_ADDRESS_SANITIZER 1
|
||||||
|
# else
|
||||||
|
# define ZSTD_ADDRESS_SANITIZER 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* detects whether we are being compiled under dfsan */
|
||||||
|
#ifndef ZSTD_DATAFLOW_SANITIZER
|
||||||
|
# if __has_feature(dataflow_sanitizer)
|
||||||
|
# define ZSTD_DATAFLOW_SANITIZER 1
|
||||||
|
# else
|
||||||
|
# define ZSTD_DATAFLOW_SANITIZER 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Mark the internal assembly functions as hidden */
|
||||||
|
#ifdef __ELF__
|
||||||
|
# define ZSTD_HIDE_ASM_FUNCTION(func) .hidden func
|
||||||
|
#else
|
||||||
|
# define ZSTD_HIDE_ASM_FUNCTION(func)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Enable runtime BMI2 dispatch based on the CPU.
|
||||||
|
* Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
|
||||||
|
*/
|
||||||
|
#ifndef DYNAMIC_BMI2
|
||||||
|
#if ((defined(__clang__) && __has_attribute(__target__)) \
|
||||||
|
|| (defined(__GNUC__) \
|
||||||
|
&& (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
|
||||||
|
&& (defined(__x86_64__) || defined(_M_X64)) \
|
||||||
|
&& !defined(__BMI2__)
|
||||||
|
# define DYNAMIC_BMI2 1
|
||||||
|
#else
|
||||||
|
# define DYNAMIC_BMI2 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only enable assembly for GNUC compatible compilers,
|
||||||
|
* because other platforms may not support GAS assembly syntax.
|
||||||
|
*
|
||||||
|
* Only enable assembly for Linux / MacOS, other platforms may
|
||||||
|
* work, but they haven't been tested. This could likely be
|
||||||
|
* extended to BSD systems.
|
||||||
|
*
|
||||||
|
* Disable assembly when MSAN is enabled, because MSAN requires
|
||||||
|
* 100% of code to be instrumented to work.
|
||||||
|
*/
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# if defined(__linux__) || defined(__linux) || defined(__APPLE__)
|
||||||
|
# if ZSTD_MEMORY_SANITIZER
|
||||||
|
# define ZSTD_ASM_SUPPORTED 0
|
||||||
|
# elif ZSTD_DATAFLOW_SANITIZER
|
||||||
|
# define ZSTD_ASM_SUPPORTED 0
|
||||||
|
# else
|
||||||
|
# define ZSTD_ASM_SUPPORTED 1
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define ZSTD_ASM_SUPPORTED 0
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define ZSTD_ASM_SUPPORTED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether we should enable assembly for x86-64
|
||||||
|
* with BMI2.
|
||||||
|
*
|
||||||
|
* Enable if all of the following conditions hold:
|
||||||
|
* - ASM hasn't been explicitly disabled by defining ZSTD_DISABLE_ASM
|
||||||
|
* - Assembly is supported
|
||||||
|
* - We are compiling for x86-64 and either:
|
||||||
|
* - DYNAMIC_BMI2 is enabled
|
||||||
|
* - BMI2 is supported at compile time
|
||||||
|
*/
|
||||||
|
#if !defined(ZSTD_DISABLE_ASM) && \
|
||||||
|
ZSTD_ASM_SUPPORTED && \
|
||||||
|
defined(__x86_64__) && \
|
||||||
|
(DYNAMIC_BMI2 || defined(__BMI2__))
|
||||||
|
# define ZSTD_ENABLE_ASM_X86_64_BMI2 1
|
||||||
|
#else
|
||||||
|
# define ZSTD_ENABLE_ASM_X86_64_BMI2 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For x86 ELF targets, add .note.gnu.property section for Intel CET in
|
||||||
|
* assembly sources when CET is enabled.
|
||||||
|
*/
|
||||||
|
#if defined(__ELF__) && (defined(__x86_64__) || defined(__i386__)) \
|
||||||
|
&& defined(__has_include)
|
||||||
|
# if __has_include(<cet.h>)
|
||||||
|
# include <cet.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZSTD_PORTABILITY_MACROS_H */
|
||||||
176
external/zstd/common/threading.c
vendored
Normal file
176
external/zstd/common/threading.c
vendored
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2016 Tino Reichardt
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* You can contact the author at:
|
||||||
|
* - zstdmt source repository: https://github.com/mcmilk/zstdmt
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file will hold wrapper for systems, which do not support pthreads
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "threading.h"
|
||||||
|
|
||||||
|
/* create fake symbol to avoid empty translation unit warning */
|
||||||
|
int g_ZSTD_threading_useless_symbol;
|
||||||
|
|
||||||
|
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Windows minimalist Pthread Wrapper
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* === Dependencies === */
|
||||||
|
#include <process.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* === Implementation === */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* (*start_routine)(void*);
|
||||||
|
void* arg;
|
||||||
|
int initialized;
|
||||||
|
ZSTD_pthread_cond_t initialized_cond;
|
||||||
|
ZSTD_pthread_mutex_t initialized_mutex;
|
||||||
|
} ZSTD_thread_params_t;
|
||||||
|
|
||||||
|
static unsigned __stdcall worker(void *arg)
|
||||||
|
{
|
||||||
|
void* (*start_routine)(void*);
|
||||||
|
void* thread_arg;
|
||||||
|
|
||||||
|
/* Inialized thread_arg and start_routine and signal main thread that we don't need it
|
||||||
|
* to wait any longer.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
ZSTD_thread_params_t* thread_param = (ZSTD_thread_params_t*)arg;
|
||||||
|
thread_arg = thread_param->arg;
|
||||||
|
start_routine = thread_param->start_routine;
|
||||||
|
|
||||||
|
/* Signal main thread that we are running and do not depend on its memory anymore */
|
||||||
|
ZSTD_pthread_mutex_lock(&thread_param->initialized_mutex);
|
||||||
|
thread_param->initialized = 1;
|
||||||
|
ZSTD_pthread_cond_signal(&thread_param->initialized_cond);
|
||||||
|
ZSTD_pthread_mutex_unlock(&thread_param->initialized_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
start_routine(thread_arg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
|
||||||
|
void* (*start_routine) (void*), void* arg)
|
||||||
|
{
|
||||||
|
ZSTD_thread_params_t thread_param;
|
||||||
|
(void)unused;
|
||||||
|
|
||||||
|
thread_param.start_routine = start_routine;
|
||||||
|
thread_param.arg = arg;
|
||||||
|
thread_param.initialized = 0;
|
||||||
|
*thread = NULL;
|
||||||
|
|
||||||
|
/* Setup thread initialization synchronization */
|
||||||
|
if(ZSTD_pthread_cond_init(&thread_param.initialized_cond, NULL)) {
|
||||||
|
/* Should never happen on Windows */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(ZSTD_pthread_mutex_init(&thread_param.initialized_mutex, NULL)) {
|
||||||
|
/* Should never happen on Windows */
|
||||||
|
ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spawn thread */
|
||||||
|
*thread = (HANDLE)_beginthreadex(NULL, 0, worker, &thread_param, 0, NULL);
|
||||||
|
if (!thread) {
|
||||||
|
ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);
|
||||||
|
ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for thread to be initialized */
|
||||||
|
ZSTD_pthread_mutex_lock(&thread_param.initialized_mutex);
|
||||||
|
while(!thread_param.initialized) {
|
||||||
|
ZSTD_pthread_cond_wait(&thread_param.initialized_cond, &thread_param.initialized_mutex);
|
||||||
|
}
|
||||||
|
ZSTD_pthread_mutex_unlock(&thread_param.initialized_mutex);
|
||||||
|
ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);
|
||||||
|
ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZSTD_pthread_join(ZSTD_pthread_t thread)
|
||||||
|
{
|
||||||
|
DWORD result;
|
||||||
|
|
||||||
|
if (!thread) return 0;
|
||||||
|
|
||||||
|
result = WaitForSingleObject(thread, INFINITE);
|
||||||
|
CloseHandle(thread);
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
return 0;
|
||||||
|
case WAIT_ABANDONED:
|
||||||
|
return EINVAL;
|
||||||
|
default:
|
||||||
|
return GetLastError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ZSTD_MULTITHREAD */
|
||||||
|
|
||||||
|
#if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32)
|
||||||
|
|
||||||
|
#define ZSTD_DEPS_NEED_MALLOC
|
||||||
|
#include "zstd_deps.h"
|
||||||
|
|
||||||
|
int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr)
|
||||||
|
{
|
||||||
|
*mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t));
|
||||||
|
if (!*mutex)
|
||||||
|
return 1;
|
||||||
|
return pthread_mutex_init(*mutex, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex)
|
||||||
|
{
|
||||||
|
if (!*mutex)
|
||||||
|
return 0;
|
||||||
|
{
|
||||||
|
int const ret = pthread_mutex_destroy(*mutex);
|
||||||
|
ZSTD_free(*mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr)
|
||||||
|
{
|
||||||
|
*cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t));
|
||||||
|
if (!*cond)
|
||||||
|
return 1;
|
||||||
|
return pthread_cond_init(*cond, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond)
|
||||||
|
{
|
||||||
|
if (!*cond)
|
||||||
|
return 0;
|
||||||
|
{
|
||||||
|
int const ret = pthread_cond_destroy(*cond);
|
||||||
|
ZSTD_free(*cond);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
150
external/zstd/common/threading.h
vendored
Normal file
150
external/zstd/common/threading.h
vendored
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2016 Tino Reichardt
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* You can contact the author at:
|
||||||
|
* - zstdmt source repository: https://github.com/mcmilk/zstdmt
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef THREADING_H_938743
|
||||||
|
#define THREADING_H_938743
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Windows minimalist Pthread Wrapper
|
||||||
|
*/
|
||||||
|
#ifdef WINVER
|
||||||
|
# undef WINVER
|
||||||
|
#endif
|
||||||
|
#define WINVER 0x0600
|
||||||
|
|
||||||
|
#ifdef _WIN32_WINNT
|
||||||
|
# undef _WIN32_WINNT
|
||||||
|
#endif
|
||||||
|
#define _WIN32_WINNT 0x0600
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */
|
||||||
|
#include <windows.h>
|
||||||
|
#undef ERROR
|
||||||
|
#define ERROR(name) ZSTD_ERROR(name)
|
||||||
|
|
||||||
|
|
||||||
|
/* mutex */
|
||||||
|
#define ZSTD_pthread_mutex_t CRITICAL_SECTION
|
||||||
|
#define ZSTD_pthread_mutex_init(a, b) ((void)(b), InitializeCriticalSection((a)), 0)
|
||||||
|
#define ZSTD_pthread_mutex_destroy(a) DeleteCriticalSection((a))
|
||||||
|
#define ZSTD_pthread_mutex_lock(a) EnterCriticalSection((a))
|
||||||
|
#define ZSTD_pthread_mutex_unlock(a) LeaveCriticalSection((a))
|
||||||
|
|
||||||
|
/* condition variable */
|
||||||
|
#define ZSTD_pthread_cond_t CONDITION_VARIABLE
|
||||||
|
#define ZSTD_pthread_cond_init(a, b) ((void)(b), InitializeConditionVariable((a)), 0)
|
||||||
|
#define ZSTD_pthread_cond_destroy(a) ((void)(a))
|
||||||
|
#define ZSTD_pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE)
|
||||||
|
#define ZSTD_pthread_cond_signal(a) WakeConditionVariable((a))
|
||||||
|
#define ZSTD_pthread_cond_broadcast(a) WakeAllConditionVariable((a))
|
||||||
|
|
||||||
|
/* ZSTD_pthread_create() and ZSTD_pthread_join() */
|
||||||
|
typedef HANDLE ZSTD_pthread_t;
|
||||||
|
|
||||||
|
int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
|
||||||
|
void* (*start_routine) (void*), void* arg);
|
||||||
|
|
||||||
|
int ZSTD_pthread_join(ZSTD_pthread_t thread);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add here more wrappers as required
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(ZSTD_MULTITHREAD) /* posix assumed ; need a better detection method */
|
||||||
|
/* === POSIX Systems === */
|
||||||
|
# include <pthread.h>
|
||||||
|
|
||||||
|
#if DEBUGLEVEL < 1
|
||||||
|
|
||||||
|
#define ZSTD_pthread_mutex_t pthread_mutex_t
|
||||||
|
#define ZSTD_pthread_mutex_init(a, b) pthread_mutex_init((a), (b))
|
||||||
|
#define ZSTD_pthread_mutex_destroy(a) pthread_mutex_destroy((a))
|
||||||
|
#define ZSTD_pthread_mutex_lock(a) pthread_mutex_lock((a))
|
||||||
|
#define ZSTD_pthread_mutex_unlock(a) pthread_mutex_unlock((a))
|
||||||
|
|
||||||
|
#define ZSTD_pthread_cond_t pthread_cond_t
|
||||||
|
#define ZSTD_pthread_cond_init(a, b) pthread_cond_init((a), (b))
|
||||||
|
#define ZSTD_pthread_cond_destroy(a) pthread_cond_destroy((a))
|
||||||
|
#define ZSTD_pthread_cond_wait(a, b) pthread_cond_wait((a), (b))
|
||||||
|
#define ZSTD_pthread_cond_signal(a) pthread_cond_signal((a))
|
||||||
|
#define ZSTD_pthread_cond_broadcast(a) pthread_cond_broadcast((a))
|
||||||
|
|
||||||
|
#define ZSTD_pthread_t pthread_t
|
||||||
|
#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))
|
||||||
|
#define ZSTD_pthread_join(a) pthread_join((a),NULL)
|
||||||
|
|
||||||
|
#else /* DEBUGLEVEL >= 1 */
|
||||||
|
|
||||||
|
/* Debug implementation of threading.
|
||||||
|
* In this implementation we use pointers for mutexes and condition variables.
|
||||||
|
* This way, if we forget to init/destroy them the program will crash or ASAN
|
||||||
|
* will report leaks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ZSTD_pthread_mutex_t pthread_mutex_t*
|
||||||
|
int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr);
|
||||||
|
int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex);
|
||||||
|
#define ZSTD_pthread_mutex_lock(a) pthread_mutex_lock(*(a))
|
||||||
|
#define ZSTD_pthread_mutex_unlock(a) pthread_mutex_unlock(*(a))
|
||||||
|
|
||||||
|
#define ZSTD_pthread_cond_t pthread_cond_t*
|
||||||
|
int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr);
|
||||||
|
int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond);
|
||||||
|
#define ZSTD_pthread_cond_wait(a, b) pthread_cond_wait(*(a), *(b))
|
||||||
|
#define ZSTD_pthread_cond_signal(a) pthread_cond_signal(*(a))
|
||||||
|
#define ZSTD_pthread_cond_broadcast(a) pthread_cond_broadcast(*(a))
|
||||||
|
|
||||||
|
#define ZSTD_pthread_t pthread_t
|
||||||
|
#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))
|
||||||
|
#define ZSTD_pthread_join(a) pthread_join((a),NULL)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* ZSTD_MULTITHREAD not defined */
|
||||||
|
/* No multithreading support */
|
||||||
|
|
||||||
|
typedef int ZSTD_pthread_mutex_t;
|
||||||
|
#define ZSTD_pthread_mutex_init(a, b) ((void)(a), (void)(b), 0)
|
||||||
|
#define ZSTD_pthread_mutex_destroy(a) ((void)(a))
|
||||||
|
#define ZSTD_pthread_mutex_lock(a) ((void)(a))
|
||||||
|
#define ZSTD_pthread_mutex_unlock(a) ((void)(a))
|
||||||
|
|
||||||
|
typedef int ZSTD_pthread_cond_t;
|
||||||
|
#define ZSTD_pthread_cond_init(a, b) ((void)(a), (void)(b), 0)
|
||||||
|
#define ZSTD_pthread_cond_destroy(a) ((void)(a))
|
||||||
|
#define ZSTD_pthread_cond_wait(a, b) ((void)(a), (void)(b))
|
||||||
|
#define ZSTD_pthread_cond_signal(a) ((void)(a))
|
||||||
|
#define ZSTD_pthread_cond_broadcast(a) ((void)(a))
|
||||||
|
|
||||||
|
/* do not use ZSTD_pthread_t */
|
||||||
|
|
||||||
|
#endif /* ZSTD_MULTITHREAD */
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* THREADING_H_938743 */
|
||||||
24
external/zstd/common/xxhash.c
vendored
Normal file
24
external/zstd/common/xxhash.c
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* xxHash - Fast Hash algorithm
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* You can contact the author at :
|
||||||
|
* - xxHash homepage: https://cyan4973.github.io/xxHash/
|
||||||
|
* - xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* xxhash.c instantiates functions defined in xxhash.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
|
||||||
|
#define XXH_IMPLEMENTATION /* access definitions */
|
||||||
|
|
||||||
|
#include "xxhash.h"
|
||||||
5686
external/zstd/common/xxhash.h
vendored
Normal file
5686
external/zstd/common/xxhash.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user