mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 17:29:21 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8373ac6746 | ||
|
|
73342af8b6 | ||
|
|
d972f66faa | ||
|
|
dadf49764b | ||
|
|
1071c93c82 | ||
|
|
773c7ed5ee | ||
|
|
a65a5c675a | ||
|
|
0ffd876115 | ||
|
|
fdee0f4e7e | ||
|
|
7f411db808 | ||
|
|
218286aa99 | ||
|
|
d4d9129ad4 | ||
|
|
be89054d07 | ||
|
|
28043d88b0 | ||
|
|
60c32fe494 | ||
|
|
20e70f9caa | ||
|
|
4621ed7dcc | ||
|
|
646cadba8c | ||
|
|
edd9ed3619 | ||
|
|
53a35e87c3 | ||
|
|
e9a5625445 | ||
|
|
8038d899d6 | ||
|
|
e306dd8eeb | ||
|
|
8db304328c | ||
|
|
af88aaee77 | ||
|
|
ea18d4ffcb | ||
|
|
27b02d66aa | ||
|
|
8bde566019 | ||
|
|
7cb5857ed3 | ||
|
|
48830e72df | ||
|
|
fcefefaeab | ||
|
|
21cf6b89a8 | ||
|
|
c007a81103 | ||
|
|
80fc5062c1 | ||
|
|
e43f07b85b | ||
|
|
a3be19214e | ||
|
|
90040117af | ||
|
|
5887016db3 | ||
|
|
e5553bde4e | ||
|
|
a35323ace9 | ||
|
|
6521bfcdc1 | ||
|
|
e5bbd9488f | ||
|
|
6b65daf07d | ||
|
|
03f2d2376e | ||
|
|
214a80b338 | ||
|
|
d1c03b22e3 | ||
|
|
260352aa9e | ||
|
|
2ea76c6188 | ||
|
|
9e100b752e | ||
|
|
23b8652656 | ||
|
|
c88226188f | ||
|
|
c3fee95273 | ||
|
|
7900ba604f | ||
|
|
21228cfbd4 | ||
|
|
0437659490 | ||
|
|
d8f780848a | ||
|
|
14580e5f6f | ||
|
|
0ad936f600 | ||
|
|
607711d3f9 | ||
|
|
7439f4d6d0 | ||
|
|
137f18bed1 | ||
|
|
7af4f6e84d | ||
|
|
b644a37622 | ||
|
|
e1daabde65 | ||
|
|
ec685d051e | ||
|
|
f6aeb717ba | ||
|
|
54706bec8a | ||
|
|
eb259174b8 | ||
|
|
3bc06b0d57 | ||
|
|
7f4f1d82bb | ||
|
|
b5c5508e62 | ||
|
|
7a3d78b1c0 | ||
|
|
89b46bc246 | ||
|
|
32ed7ed1d7 | ||
|
|
e4fd172892 | ||
|
|
57c52e4fc7 | ||
|
|
bd04a6412d | ||
|
|
902949ea94 | ||
|
|
0570ed4ca3 | ||
|
|
b3c929499e | ||
|
|
0d46eb9066 | ||
|
|
acf5c2e992 | ||
|
|
7b55b03c96 | ||
|
|
0216aab022 | ||
|
|
c10bac6558 | ||
|
|
d4fb27a7a9 | ||
|
|
4803100dc4 | ||
|
|
ed3412c004 | ||
|
|
63acb6173a | ||
|
|
375eb4b852 | ||
|
|
7dba607d76 | ||
|
|
7d9d57dc50 | ||
|
|
27fbb3f971 | ||
|
|
9188c4a7f0 | ||
|
|
ea7e9aaa61 | ||
|
|
9e85eec4a7 | ||
|
|
197203d09b | ||
|
|
d14c4d2883 | ||
|
|
4954af9dc7 | ||
|
|
b17dd28ff2 | ||
|
|
6e61eb084a | ||
|
|
d0212ec5aa | ||
|
|
523d7d6ee8 | ||
|
|
647e39afaa | ||
|
|
7b46cca917 | ||
|
|
f93499181c | ||
|
|
c31e0ba9b9 | ||
|
|
4a6dc36b1c | ||
|
|
c6967f56bd | ||
|
|
0e654c8e9e | ||
|
|
e1270742b9 | ||
|
|
1c87853496 | ||
|
|
119788593c | ||
|
|
fb2b3695d9 | ||
|
|
aacf2bed34 | ||
|
|
badd588652 | ||
|
|
a40c3767bb | ||
|
|
b0831bf1a0 | ||
|
|
d1f7d8af0d | ||
|
|
f7f007519c | ||
|
|
92a098ee02 | ||
|
|
d00c2a6407 | ||
|
|
991b43d4ee | ||
|
|
ac8a977492 | ||
|
|
1bc588acbd | ||
|
|
eafeb83d0b | ||
|
|
2e215bda5b | ||
|
|
0a5fd837a2 | ||
|
|
edf10b576f | ||
|
|
46dcf1204e | ||
|
|
5feeb362b1 | ||
|
|
d6a1c21fe1 | ||
|
|
67358fb145 | ||
|
|
41fbbda8e8 | ||
|
|
b1b5148090 | ||
|
|
bd1d39d7fb | ||
|
|
b2c7fae912 | ||
|
|
13e88ebe74 | ||
|
|
d5d6b1d91e | ||
|
|
8915d82fd6 | ||
|
|
0785d4aa72 | ||
|
|
0744683c2b | ||
|
|
b483f233d2 | ||
|
|
55afe18872 | ||
|
|
f83e614b4e | ||
|
|
5dc070f041 | ||
|
|
585af66b5c | ||
|
|
c8241f3f21 | ||
|
|
3a82cf980d | ||
|
|
7b47f5f49a | ||
|
|
94e4b1883a | ||
|
|
c73592d379 | ||
|
|
4ba0ba4c70 | ||
|
|
11dba60ea7 | ||
|
|
97ad8cbfd2 | ||
|
|
b5be2006f2 | ||
|
|
8ec39ca7ec | ||
|
|
bd937eb49f | ||
|
|
23b810b820 | ||
|
|
322aeb4e46 | ||
|
|
ed2d6b1730 | ||
|
|
9afa30af5e | ||
|
|
5d3719df44 | ||
|
|
3f00d2f041 | ||
|
|
a30a86a09c | ||
|
|
bd10e5bdc3 | ||
|
|
0e1d5ba30e | ||
|
|
10f42d7034 | ||
|
|
6986caed5b | ||
|
|
c802a549f6 | ||
|
|
0a75b51b29 | ||
|
|
0c64ac0bde | ||
|
|
15b0f5478f | ||
|
|
a6b0199204 | ||
|
|
973f5cda6d | ||
|
|
46a318db45 | ||
|
|
7949a9c8ad | ||
|
|
2ae11b7222 | ||
|
|
f05c124c98 | ||
|
|
5f182fa564 | ||
|
|
c2d5003f80 | ||
|
|
6e2709d62a | ||
|
|
eef86d5f72 | ||
|
|
863aaa5b9d | ||
|
|
54eed63418 | ||
|
|
7695298dfc | ||
|
|
917fb1f796 | ||
|
|
81075aa5fa | ||
|
|
ff7982fbcd | ||
|
|
7915b040a9 | ||
|
|
a129764f0d | ||
|
|
aeddcb54e0 | ||
|
|
10f0073778 | ||
|
|
8b6e58eebd | ||
|
|
49bd8d2d27 | ||
|
|
946d87cf89 | ||
|
|
138d5b3a4e | ||
|
|
cdba9accdf | ||
|
|
963350a0f2 | ||
|
|
dd48b65687 | ||
|
|
642d6c9fb8 | ||
|
|
6738fa57aa | ||
|
|
d40d7c389b | ||
|
|
3c2e3f1ce9 | ||
|
|
766c59d469 | ||
|
|
7492f5d60c | ||
|
|
bd9c35d379 | ||
|
|
5d4069cf8f | ||
|
|
0caeed6e1d | ||
|
|
98194ce135 | ||
|
|
4dcda032d0 | ||
|
|
f74fddf3fd | ||
|
|
08481e2a68 | ||
|
|
dc50ff584e | ||
|
|
98be8f0c22 | ||
|
|
3647bdef0f | ||
|
|
75fcd63b4a | ||
|
|
27cacffe54 | ||
|
|
74d85e3269 | ||
|
|
9d92888846 | ||
|
|
adfabcb742 | ||
|
|
620302ddaa | ||
|
|
da9f87c63f | ||
|
|
fe2fd18aad | ||
|
|
1c61068291 | ||
|
|
681983d1b2 | ||
|
|
ec627a9c00 | ||
|
|
462cedb654 | ||
|
|
f1347829c2 | ||
|
|
b08169255d | ||
|
|
610b0b7095 | ||
|
|
caf3f3dadd | ||
|
|
04962e1741 | ||
|
|
44e2530fbb | ||
|
|
52b827155f | ||
|
|
3eecf92f8f | ||
|
|
9184a9d04c | ||
|
|
5534fd7275 | ||
|
|
8e06aa2417 | ||
|
|
f57fcd4048 | ||
|
|
4b4576ed62 | ||
|
|
9f8092dc27 | ||
|
|
e40f0d308b | ||
|
|
2259e9b38e | ||
|
|
e44f0749a1 | ||
|
|
3fe52bb7fb | ||
|
|
2edc6d6e6a | ||
|
|
fce9da5e76 | ||
|
|
4b2f27eff8 | ||
|
|
7919a87b97 | ||
|
|
8584b122e1 | ||
|
|
ec7e528094 | ||
|
|
f0c9c542a2 | ||
|
|
4ed88ec68a | ||
|
|
140b8f5e0a | ||
|
|
b5df2b883a | ||
|
|
4fab84ca9e | ||
|
|
d8a5505204 | ||
|
|
1218aebfbf | ||
|
|
b81ec7d631 | ||
|
|
f8479c2b5a | ||
|
|
69f3dda90a | ||
|
|
a06b303879 | ||
|
|
ef9beea9f8 | ||
|
|
cd8f6ede4e | ||
|
|
e76265e1aa | ||
|
|
6443d6f019 | ||
|
|
293e797146 | ||
|
|
55c855267e | ||
|
|
73a5ec9f42 | ||
|
|
86f8670d0b | ||
|
|
6772b89872 | ||
|
|
d95e46c2bd | ||
|
|
74d9f976a8 | ||
|
|
b1a3ea72c9 | ||
|
|
ab888629a5 | ||
|
|
935c7d0e2c | ||
|
|
a8028d5e8e | ||
|
|
cc1e080dfe | ||
|
|
35f7ef3cc2 | ||
|
|
c226bd87f4 | ||
|
|
c0b7c34264 | ||
|
|
5cf7b57064 | ||
|
|
adf6a7ff20 | ||
|
|
5a7cebf7da | ||
|
|
4a8fdaed84 | ||
|
|
4441219df9 | ||
|
|
750ad9aa7b | ||
|
|
0d7a028ce3 | ||
|
|
84975d71ea | ||
|
|
45c0dc4486 | ||
|
|
2c21e3df8b | ||
|
|
138f41160f | ||
|
|
194de13afb | ||
|
|
2c7c8def4c | ||
|
|
ff3928224e | ||
|
|
a39c38f267 | ||
|
|
8e54b4cec9 | ||
|
|
0dfb2b57fb | ||
|
|
a84c9022af | ||
|
|
0a5d4288f5 | ||
|
|
3c6ac487d0 | ||
|
|
466bd3be7f | ||
|
|
5dc7b7f7c7 | ||
|
|
3e814bc4b6 | ||
|
|
f70b6fbf58 | ||
|
|
30a90adc47 | ||
|
|
621a0b61f6 | ||
|
|
244a2ad052 | ||
|
|
bb04b0b9d3 | ||
|
|
e616b41b62 | ||
|
|
fb8c73508b | ||
|
|
f2a73d1b14 | ||
|
|
2b4f2525d0 | ||
|
|
75175ddbce | ||
|
|
4dcbd3e383 | ||
|
|
b48ab663b0 | ||
|
|
364d518726 | ||
|
|
d1c7d97b10 | ||
|
|
f8b6443b91 | ||
|
|
8344ed9db5 | ||
|
|
76f3d0c1b7 | ||
|
|
52af69e6cd | ||
|
|
d6b1836919 | ||
|
|
7c483340fc | ||
|
|
33de17548b | ||
|
|
9cd19d4944 | ||
|
|
89e4cac3f1 | ||
|
|
29e9027ec0 | ||
|
|
68c377cd55 | ||
|
|
706ab17b2c | ||
|
|
fede9eee4b | ||
|
|
d84a2ef700 | ||
|
|
4ba92b1643 | ||
|
|
57a728fd41 | ||
|
|
bc8f98358b | ||
|
|
3887db349e | ||
|
|
98448960f5 | ||
|
|
22a2b5ac1c | ||
|
|
6e4620cebc | ||
|
|
458d636861 | ||
|
|
64c01e620d | ||
|
|
57c4802ab4 | ||
|
|
74f1bf59b9 | ||
|
|
cacbd451dc | ||
|
|
7174563f7d | ||
|
|
d5f862ee07 | ||
|
|
f66d4ea33c | ||
|
|
0797fd957a | ||
|
|
b45acf2223 | ||
|
|
30143f15f2 | ||
|
|
24389bbcd5 | ||
|
|
2e50b57643 | ||
|
|
5b995dec26 | ||
|
|
5ae4524176 | ||
|
|
87a7795331 | ||
|
|
44fc3666ed | ||
|
|
cea6b17391 | ||
|
|
334a43a7c5 | ||
|
|
29475a904f | ||
|
|
159602d697 | ||
|
|
de88edf56c | ||
|
|
4fb6bc9f33 | ||
|
|
b82a20ea0c | ||
|
|
8291b18771 | ||
|
|
181824eb00 | ||
|
|
7a2115670a | ||
|
|
951999e5ce | ||
|
|
23acacf436 | ||
|
|
925c459aed | ||
|
|
0482892a9c | ||
|
|
dd922bfc2c | ||
|
|
35543ecd91 | ||
|
|
e08290acb0 | ||
|
|
e34c84d791 | ||
|
|
2e4b734159 | ||
|
|
3b64752f4f | ||
|
|
9829051841 | ||
|
|
fc2a011a5c | ||
|
|
0e7ff6ea4e | ||
|
|
e784cc1aaf | ||
|
|
e4a8f42ad1 | ||
|
|
a04fe66032 | ||
|
|
9669cff16b | ||
|
|
09439332f3 | ||
|
|
216deda910 | ||
|
|
7bbdd6d18a | ||
|
|
b037da7264 | ||
|
|
ef35adc9d6 | ||
|
|
f6a8480f21 | ||
|
|
d3b3b40ea7 | ||
|
|
6972cc2bc6 | ||
|
|
74cef32c1d | ||
|
|
d50be7a0ab | ||
|
|
d228e5f759 | ||
|
|
10546594de | ||
|
|
e9b5f009cc | ||
|
|
d6ec36c707 | ||
|
|
be84700d0a | ||
|
|
ad5b2d614a | ||
|
|
9e87040c02 | ||
|
|
90abd49892 | ||
|
|
654aae58d6 | ||
|
|
e6adca7679 | ||
|
|
095f6d4377 | ||
|
|
b946b146f3 | ||
|
|
4e0f8bf621 | ||
|
|
de4343caeb | ||
|
|
a9426925cf | ||
|
|
aebdc8b747 | ||
|
|
c9d4775ffc | ||
|
|
3b8bd1a6e8 | ||
|
|
734401440d | ||
|
|
9fbf3b9732 | ||
|
|
67b180d63d | ||
|
|
c378665af5 | ||
|
|
3187c87451 | ||
|
|
122be0cc64 | ||
|
|
6b13e3f050 | ||
|
|
87e248f4eb | ||
|
|
2be7106055 | ||
|
|
0a24f5f38a | ||
|
|
6189fd3f42 | ||
|
|
29d5a692d0 | ||
|
|
358cafa978 | ||
|
|
b3eebbd5ec | ||
|
|
cc5b491e21 | ||
|
|
bf0b9f536a | ||
|
|
6f471e0660 | ||
|
|
484c4ad51e | ||
|
|
66c77af4a6 | ||
|
|
667568b0b8 | ||
|
|
f3ff36ac34 | ||
|
|
feaefbef04 | ||
|
|
a16aba2138 | ||
|
|
50d27fada9 | ||
|
|
a6d92de0b2 | ||
|
|
89391ccf9a | ||
|
|
e430f832cc | ||
|
|
9280340fe0 | ||
|
|
85466225de | ||
|
|
c9aaf598bb | ||
|
|
92e795aa28 | ||
|
|
fa2c789c3f | ||
|
|
475213aa0a | ||
|
|
32d6eeaf07 | ||
|
|
6f95e7819a | ||
|
|
f24f827c4c | ||
|
|
53a266728b | ||
|
|
215ed2ccf6 | ||
|
|
a671b6394c | ||
|
|
dec1fd097c | ||
|
|
a0f0d7bed2 | ||
|
|
6a21eca5df | ||
|
|
c37f540b72 | ||
|
|
5aba614b60 | ||
|
|
0680505ebf | ||
|
|
528af55abd | ||
|
|
1167dde73a | ||
|
|
b3abdefb9a | ||
|
|
1b0ae7a0b2 | ||
|
|
f3daf070e1 | ||
|
|
6241909a08 | ||
|
|
7fbb7a8007 | ||
|
|
e96cbcac04 | ||
|
|
0706cdea4c | ||
|
|
07099797bd | ||
|
|
77967f0148 | ||
|
|
56e40e8204 | ||
|
|
218c6f30b9 | ||
|
|
b2c20e8ce0 | ||
|
|
76eeee2c9a | ||
|
|
3b7e0a8db1 | ||
|
|
c5e5cf28af | ||
|
|
8ff0430370 | ||
|
|
0a83817f25 | ||
|
|
f8b4289811 |
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
# EditorConfig: http://EditorConfig.org
|
||||
# EditorConfig: https://EditorConfig.org
|
||||
|
||||
# Top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
+2
-2
@@ -9,6 +9,8 @@
|
||||
*.map
|
||||
*.swp
|
||||
*.cache
|
||||
*.gcda
|
||||
*.gcno
|
||||
.tmp
|
||||
.tmp.c
|
||||
.tmp.cxx
|
||||
@@ -92,7 +94,6 @@ database
|
||||
overlays
|
||||
playlists
|
||||
states
|
||||
system
|
||||
shaders/shaders_cg
|
||||
shaders/shaders_glsl
|
||||
shaders/shaders_slang
|
||||
@@ -218,7 +219,6 @@ libretro-common/samples/streams/rzip/rzip
|
||||
|
||||
#VITA
|
||||
param.sfo
|
||||
*.S
|
||||
*.wo
|
||||
*.elf
|
||||
*.self
|
||||
|
||||
@@ -426,6 +426,28 @@ build-retroarch-dingux-odbeta-mips32:
|
||||
- "cp -f libretro-common/audio/dsp_filters/*.dsp ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/audio"
|
||||
- "cp -f gfx/video_filters/*.filt ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/video"
|
||||
|
||||
build-retroarch-rs90-odbeta-mips32:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-dingux:odbeta
|
||||
stage: build
|
||||
variables:
|
||||
MEDIA_PATH: .media
|
||||
STRIP_BIN: 1
|
||||
before_script:
|
||||
- export NUMPROC=$(($(nproc)/3))
|
||||
artifacts:
|
||||
paths:
|
||||
- retroarch
|
||||
- retroarch_rs90_odbeta.opk
|
||||
- ${MEDIA_PATH}
|
||||
expire_in: 10 min
|
||||
dependencies: []
|
||||
script:
|
||||
- "make -j$NUMPROC -f Makefile.rs90"
|
||||
- "mkdir -p ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/audio"
|
||||
- "mkdir -p ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/video"
|
||||
- "cp -f libretro-common/audio/dsp_filters/*.dsp ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/audio"
|
||||
- "cp -f gfx/video_filters/*.filt ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/video"
|
||||
|
||||
build-retroarch-android-normal:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-android:latest
|
||||
stage: build
|
||||
|
||||
+157
@@ -1,5 +1,162 @@
|
||||
# Future
|
||||
|
||||
# 1.9.7
|
||||
- 3DS: Add unique ID's
|
||||
- CRT/SWITCHRES: Fixed some Monitor index bugs ad updated to the latest SR2
|
||||
- CRT/SWITCHRES: Fixed monitor index corruption on Windows and added correct fractal scaling. Only used when required
|
||||
- CRT/SWITCHRES: Updated log defines to match SR upstream.
|
||||
- CRT/SWITCHRES: Added new SR_CONFIG_PATHS for non Windows and Linux systems.
|
||||
Not that SR works on them but to fix RA compile issues
|
||||
- CRT/SWITCHRES: Updated SR2 code base to latest. Added supprt for windows monitor indexing. Fixed monitor index bug where index 1 was not being used correctly and "auto" was not being sent.
|
||||
- CRT/SWITCHRES: Updated swithres for x86 windows fix
|
||||
- CRT/SWITCHRES: fixed SR2 auto issue
|
||||
- CRT/SWITCHRES: Fixed auto monitor bug
|
||||
- CRT/SWITCHRES: Fixed monitor index corruption on Windows
|
||||
- CRT/SWITCHRES: Fixed buffer size bug
|
||||
- CRT/SWITCHRES: Added correct fractal scalling. only used when required.
|
||||
- CORE INFO: Automatically disable core info cache when core info directory is read-only
|
||||
- EMSCRIPTEN: add MAME2003 / MAME2003-plus to web.libretro
|
||||
- INPUT/UDEV: udev fixes add pointer pressed to pointer device to allow udev users to access this device
|
||||
- LIBNX/SWITCH: Enable 7zip support
|
||||
- LINUX/XDG: Prevent xdg-screensaver's "Protocol error" messages
|
||||
- LOCALIZATION: Fetch translations from Crowdin
|
||||
- LOCALIZATION: Add missing languages for the first startup
|
||||
- MENU/XMB/WIDGETS: Add workaround for FPU bug that breaks scale factor comparisons on certain platforms (fixes XMB thumbnails on 32bit Linux/Windows)
|
||||
- MENU/RGUI: Enable fullscreen thumbnail toggle using RetroPad 'start' button
|
||||
- MENU/RGUI: Fix sublabel length when menu clock is disabled
|
||||
- NETWORK/HTTP: Fix HTTP progress indication for large files on 32-bit systems
|
||||
- NETWORK/NATT: implement natt fix from void()
|
||||
- OPENDINGUX: Fix display when cores 'drop' frames
|
||||
- OPENDINGUX BETA: Use ALSA audio driver by default
|
||||
- OPENDINGUX BETA: Fix IPU scaling when running 256x224 (SNES/Genesis) content
|
||||
- PATHS: Fix garbled path string
|
||||
- PS2: Implement proper ps2_font driver instead of using the font driver from gskit
|
||||
- PS2: Use BDM for increasing up USB stability
|
||||
- PS3: First basic RSX driver for PSL1GHT
|
||||
- RS90: Initial port
|
||||
- RS90: Fix offset of OSD text
|
||||
- RS90: Disable menu clock by default
|
||||
- RS90: Hide 'Bilinear Filtering' video option
|
||||
- RS90: Move appdata (retroarch) base directory to external microsd card
|
||||
- RS90: Add optional approximate 'semi-linear' scaling filter
|
||||
- SHADERS: Max Shader Parameters increased to 1024
|
||||
- VIDEO: Add 'Integer Scale Overlay' - Force integer scaling to round up to the next larger integer instead of rounding down
|
||||
- VIDEO: New 'Full' aspect ratio added. This aspect ratio is useful when used with a shader which has a border in it. The aspect ratio is set to the full window area, so that the viewport spans the whole viewport. When using a border type shader like the Mega Bezel this allows the graphics to span the whole window regardless of the user's monitor aspect ratio
|
||||
- VITA: Wrong flags for not piglet version
|
||||
- UNIX: Correct backlight max_brightness path
|
||||
- UWP/XBOX: Default to Direct3D11 driver on UWP builds
|
||||
- UWP/XBOX: Do not use windowed mode on UWP/Xbox by default, set default resolution to 1920x1080 by default. Should fix display issues with Dolphin/PCSX2 on Xbox
|
||||
- WIIU: Fix inputs breaking when connecting/disconnecting remotes
|
||||
- WIIU: Input - ignore some bogus KPAD results
|
||||
- WIIU: Font rendering fixes - render font lines with correct spacing, and only sample alpha channel when rendering fonts
|
||||
- WIIU/NETWORK: Network speed optimisations - WINSCALE, TCP sACK, large buffers
|
||||
- WIIU/LIBFAT: Increase cache size on WiiU
|
||||
- WIIU/FILE IO: Filesystem optimisations - add fast path for already aligned buffers
|
||||
- WIIU/FILE IO: Use 128K vbufs for WiiU - we have loads of RAM and large vbufs are very beneficial
|
||||
- WIIU/MENU/OZONE: Fix Ozone rendering error (scissor fix)
|
||||
- WIIU/MENU/OZONE: Use Ozone icons instead of XMB Monochrome
|
||||
|
||||
# 1.9.6
|
||||
- ARCHIVE: Fix archive delimiter detection when file path contains no slashes
|
||||
- ANDROID: Do not duplicate port 0 mouse and gun inputs to other ports
|
||||
- AUDIO/XAUDIO2: Fail instead of crashing when disconnecting an audio device
|
||||
- CHEEVOS: Reset cached progress each time menu is opened
|
||||
- CRT/SWITCHRES: Add support for switchres.ini core and directory overrides
|
||||
- D3D11: Don't use allow tearing flag with blit swap chains. Also disables the flip model if the allow tearing flag is not supported.
|
||||
- D3D11: Disable DXGI's ALT+ENTER handling
|
||||
- D3D11: Don't pass ALLOW_TEARING when unsupported
|
||||
- D3D11: Fix non-vsynced output without flip, black screens in fullscreen
|
||||
- D3D12: Relocated 'd3d12_gfx_sync'
|
||||
- D3D12: Fixed swap interval option
|
||||
- GFX: Fix uninitialized variables in gfx_display_draw_cursor
|
||||
- HISTORY: Hide 'Add to Favorites' when viewing an entry of the favorites playlist
|
||||
- INPUT: 'Analog to Digital Type' usability improvements
|
||||
- INPUT: Add support for mapping multiple controllers to a single input device
|
||||
- INPUT/REMAPPING: Add support for mapping multiple controllers to a single input device
|
||||
- INPUT/LIGHTGUN: Bind lightgun trigger to first mouse button by default
|
||||
- INPUT/WINDOWS/RAWINPUT: Mouse access violation fix
|
||||
- INPUT/UDEV: Only add mouse if it has buttons and add vebose device friendly names
|
||||
- INPUT/UDEV: Skip mouse with no button errors and keep the rest
|
||||
- INPUT/UDEV: Fix Game Focus mode
|
||||
- INPUT/UDEV/X11: Change udev driver for dual lightgun support in X11
|
||||
- LIBNX/SWITCH: Update to libnx 4.0.0
|
||||
- LOCALIZATION: Fetch translations from Crowdin
|
||||
- LOCALIZATION: Fix Switchres menu texts
|
||||
- MENU/OZONE: Ensure sidebar display status is updated correctly when performing rapid menu navigation
|
||||
- MENU/XMB: Dynamic wallpaper fix
|
||||
- MENU/XMB: Icon opacity fix
|
||||
- MENU/QT/WIMP: Fix default core detection when playlist file name does not match 'db_name'
|
||||
- PLAYLISTS: Optimise scanning of large rom sets
|
||||
- SECURITY: Plug so-called high-risk vulnerability related to Powershell - avoid injection - don't send speech input as commandline argument
|
||||
- UWP/XBOX: Add expanded resources Rescap to increase performance of UWP version in app mode on Xbox
|
||||
- WINDOWS/INSTALLER: Add smarter isEmptyDir reference implementation that looks for subdirectories from NSIS documentation
|
||||
- WINDOWS/INSTALLER: Register new function DirectorySet that is called when pressing the "Next" button on the MUI_PAGE_DIRECTORY, aka the install folder selection GUI. DirectorySet contains the criteria for an acceptable folder, which are:
|
||||
- `IfFileExists "$INSTDIR\retroarch.exe"` returns 1
|
||||
- `IfFileExists "$INSTDIR\*.*` returns 0, there is no existing folder
|
||||
- `IfFileExists "$INSTDIR\*.*"` returns 1, there is a folder, and `isEmptyDir` returns 1, therefore the folder is empty, including of subdirectories
|
||||
- X11: Fix threaded video segfault
|
||||
|
||||
# 1.9.5
|
||||
- ALSATHREAD: Make alsathread default for all ALSA devices with threads
|
||||
- ARCHIVE: Fix loading of archived content with file names containing '#' characters
|
||||
- CHEEVOS: Upgrade to rcheevos 10.1
|
||||
- CHEEVOS: Challenge indicators
|
||||
- CHEEVOS: Group achievements by category in quick menu
|
||||
- CHEEVOS: Relabel 'Start Active' with 'Encore Mode'
|
||||
- D3D10: Window title should now update
|
||||
- D3D11: Window title should now update
|
||||
- D3D11: Allow fastforward in fullscreen
|
||||
- D3D12: Window title should now update
|
||||
- D3D12: Allow fastforward in fullscreen
|
||||
- CRT/SWITCHRES: New implementation
|
||||
- FONTS: Improve message wrapping with CJK languages
|
||||
- FONTS: Fix garbled characters when converting encodings
|
||||
- INPUT: Allow the 8 analog stick directions to be used as keys for core keyboard mappings
|
||||
- LIBRETRO: Add API extension for setting 'need_fullpath' based on content file extension and to request persistent frontend content data buffers
|
||||
- MENU/SEARCH: Add enhanced search functionality to the 'Manage Cores' menu
|
||||
- OPENDINGUX: Fix black screens when triggering gfx driver initialisation via menu actions
|
||||
- UNIX: Get better battery stats on sysfs nodes
|
||||
- VIDEO: Extend Frame Delay range to 19 to accommodate PAL land too
|
||||
- WIFI/LAKKA: Add nmcli to wifi drivers
|
||||
- WIFI/LAKKA: Add wifi configuration menu
|
||||
- X11: fix fullscreen when swapping monitors/resolution
|
||||
|
||||
# 1.9.4
|
||||
- CHEEVOS: update rcheevos to v10.0.0
|
||||
- CONTENT LOADING/FILE IO: Prevent unnecessary extraction (to disk) of compressed content files when need_fullpath is false
|
||||
- CORE INFO/FILE IO: Enable core info cache by default now for all platforms
|
||||
- CORE INFO/REGRESSION FIX: Fix regression caused by core info file caching - Downloads was no longer showing up in Load Content
|
||||
- FILE IO/COMPRESSED: Ability to load content inside ZIP files directly into RAM
|
||||
- INPUT/OVERLAYS: Add option to select between 'touched' elements and physical controller inputs when showing inputs on overlays
|
||||
- INPUT REMAPPING/OVERLAYS: Prevent duplicate inputs when using remaps with input overlays
|
||||
- LAKKA: Add brightness restore hook
|
||||
- LOCALIZATION: Fetch translations from Crowdin
|
||||
- MENU/OZONE: Added simple playlist entry enumeration
|
||||
- MENU/XMB: Fix display of 'Maximum Users' menu entry dropdown list
|
||||
- PS3/PSL1GHT: Joypad driver works again
|
||||
- PSTV: Fix Vita input driver for PSTV
|
||||
- PSTV: Support for 720p on PSTV when using 'Unlock framebuffer' in Sharpscale plugin
|
||||
- PSTV: Fix scaling on PSTV when not using 720p
|
||||
- RPNG: Fix some memory corruption if processing broken input PNG file
|
||||
- SECURITY: Fix CVE-2021-28927
|
||||
|
||||
# 1.9.3
|
||||
- 3DS: Disable menu screensaver animations in XMB/GLUI
|
||||
- COMMAND: Initialize netcmd->cmd_source_len before recvfrom()
|
||||
- CONTENT LOADING/STATICALLY LINKED: Ensure 'Always Reload Core on Run Content' setting is applied when loading content via the file browser
|
||||
- CONTENT LOADING/EMSCRIPTEN: Fix content loading via file browser on platforms with 'broken' core handling (i.e. emscripten)
|
||||
- CORE INFO: Skip whitespace when writing compressed core info cache files
|
||||
- CORE INFO/FILE IO: Core Info cache; significant file I/O performance improvements on systems with slow disk file I/O
|
||||
- CORE INFO/FILE IO: Enable core info cache by default on all 'console' platforms
|
||||
- FREEBSD: FreeBSD build fix
|
||||
- LAKKA: Support for tweaking CPU governors/scaling policies
|
||||
- LAKKA: This adds managed policies and settings to store them and reload them at startup
|
||||
- LIBRETRO API: Add API extension for cores to override frontend fast-forward state
|
||||
- MENU/RGUI: Fix saving of config files/overrides when 'Lock Menu Aspect Ratio' is enabled
|
||||
- SHADERS: Fix 'Auto-Shader Delay' functionality
|
||||
- UWP/D3D11: Disable mipmap generation
|
||||
- UWP/XBOX: Add 'Force 4K resolution' option (Force the resolution to the fullscreen size on Xbox, if set to 0, a fixed value of 3840 x 2160 will be used)
|
||||
|
||||
# 1.9.2
|
||||
- 3DS: Enable graphics widgets / overlays
|
||||
- 3DS: Load texture images as BGR colors
|
||||
|
||||
+65
-15
@@ -275,6 +275,10 @@ OBJ += \
|
||||
$(LIBRETRO_COMM_DIR)/memmap/memalign.o \
|
||||
$(LIBRETRO_COMM_DIR)/file/nbio/nbio_stdio.o
|
||||
|
||||
OBJ += \
|
||||
$(LIBRETRO_COMM_DIR)/lists/linked_list.o \
|
||||
$(LIBRETRO_COMM_DIR)/queues/generic_queue.o
|
||||
|
||||
ifneq ($(findstring Linux,$(OS)),)
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/file/nbio/nbio_linux.o
|
||||
endif
|
||||
@@ -300,7 +304,6 @@ OBJ += \
|
||||
input/common/input_hid_common.o \
|
||||
led/led_driver.o \
|
||||
gfx/video_coord_array.o \
|
||||
gfx/video_crt_switch.o \
|
||||
gfx/gfx_display.o \
|
||||
gfx/gfx_animation.o \
|
||||
gfx/gfx_thumbnail_path.o \
|
||||
@@ -665,7 +668,7 @@ else ifeq ($(HAVE_BUILTINMBEDTLS), 1)
|
||||
DEFINES += -DMBEDTLS_SSL_DEBUG_ALL
|
||||
endif
|
||||
|
||||
# MinGW requires this for some reason,
|
||||
# MinGW requires this for some reason,
|
||||
# even though the include paths are relative to the source
|
||||
INCLUDE_DIRS += -Ideps/mbedtls
|
||||
|
||||
@@ -764,6 +767,12 @@ endif
|
||||
|
||||
ifeq ($(HAVE_LAKKA), 1)
|
||||
OBJ += wifi/drivers/connmanctl.o
|
||||
OBJ += misc/cpufreq/cpufreq.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_WIFI), 1)
|
||||
OBJ += wifi/drivers/nmcli.o
|
||||
DEFINES += -DHAVE_WIFI
|
||||
endif
|
||||
|
||||
# Audio
|
||||
@@ -820,7 +829,9 @@ ifeq ($(HAVE_ALSA), 1)
|
||||
|
||||
ifneq ($(HAVE_HAKCHI), 1)
|
||||
ifneq ($(HAVE_SEGAM), 1)
|
||||
OBJ += midi/drivers/alsa_midi.o
|
||||
ifneq ($(DINGUX), 1)
|
||||
OBJ += midi/drivers/alsa_midi.o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -1565,8 +1576,14 @@ else ifeq ($(HAVE_SDL), 1)
|
||||
else ifeq ($(HAVE_SDL_DINGUX), 1)
|
||||
HAVE_SDL_COMMON = 1
|
||||
DEF_FLAGS += -DHAVE_SDL -DHAVE_SDL_DINGUX
|
||||
OBJ += gfx/drivers/sdl_dingux_gfx.o \
|
||||
input/drivers/sdl_dingux_input.o \
|
||||
|
||||
ifeq ($(RS90), 1)
|
||||
OBJ += gfx/drivers/sdl_rs90_gfx.o
|
||||
else
|
||||
OBJ += gfx/drivers/sdl_dingux_gfx.o
|
||||
endif
|
||||
|
||||
OBJ += input/drivers/sdl_dingux_input.o \
|
||||
input/drivers_joypad/sdl_dingux_joypad.o
|
||||
DEF_FLAGS += $(SDL_DINGUX_CFLAGS)
|
||||
LIBS += $(SDL_DINGUX_LIBS)
|
||||
@@ -1985,7 +2002,8 @@ ifeq ($(HAVE_CDROM), 1)
|
||||
DEFINES += -DHAVE_CDROM
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/cdrom/cdrom.o \
|
||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation_cdrom.o \
|
||||
$(LIBRETRO_COMM_DIR)/media/media_detect_cd.o
|
||||
$(LIBRETRO_COMM_DIR)/media/media_detect_cd.o \
|
||||
tasks/task_content_disc.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RTGA), 1)
|
||||
@@ -2101,8 +2119,7 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
INCLUDE_DIRS += -Ideps/rcheevos/include
|
||||
|
||||
OBJ += cheevos/cheevos.o \
|
||||
cheevos/badges.o \
|
||||
cheevos/cheevos_memory.o \
|
||||
cheevos/cheevos_menu.o \
|
||||
cheevos/cheevos_parser.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/cdfs/cdfs.o \
|
||||
deps/rcheevos/src/rcheevos/alloc.o \
|
||||
@@ -2114,6 +2131,7 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
deps/rcheevos/src/rcheevos/lboard.o \
|
||||
deps/rcheevos/src/rcheevos/memref.o \
|
||||
deps/rcheevos/src/rcheevos/operand.o \
|
||||
deps/rcheevos/src/rcheevos/rc_libretro.o \
|
||||
deps/rcheevos/src/rcheevos/richpresence.o \
|
||||
deps/rcheevos/src/rcheevos/runtime.o \
|
||||
deps/rcheevos/src/rcheevos/runtime_progress.o \
|
||||
@@ -2263,6 +2281,39 @@ ifeq ($(HAVE_FFMPEG), 1)
|
||||
INCLUDE_DIRS += -Iffmpeg
|
||||
endif
|
||||
|
||||
# CRT mode switching
|
||||
ifeq ($(HAVE_CRTSWITCHRES), 1)
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/switchres
|
||||
OBJ += gfx/video_crt_switch.o \
|
||||
$(DEPS_DIR)/switchres/monitor.o \
|
||||
$(DEPS_DIR)/switchres/modeline.o \
|
||||
$(DEPS_DIR)/switchres/switchres.o \
|
||||
$(DEPS_DIR)/switchres/display.o \
|
||||
$(DEPS_DIR)/switchres/custom_video.o \
|
||||
$(DEPS_DIR)/switchres/log.o \
|
||||
$(DEPS_DIR)/switchres/switchres_wrapper.o \
|
||||
$(DEPS_DIR)/switchres/edid.o
|
||||
ifneq ($(findstring Win32,$(OS)),)
|
||||
OBJ += $(DEPS_DIR)/switchres/display_windows.o \
|
||||
$(DEPS_DIR)/switchres/custom_video_ati_family.o \
|
||||
$(DEPS_DIR)/switchres/custom_video_ati.o \
|
||||
$(DEPS_DIR)/switchres/custom_video_adl.o \
|
||||
$(DEPS_DIR)/switchres/custom_video_pstrip.o \
|
||||
$(DEPS_DIR)/switchres/resync_windows.o
|
||||
endif
|
||||
ifneq ($(findstring Linux,$(OS)),)
|
||||
OBJ += $(DEPS_DIR)/switchres/display_linux.o
|
||||
ifeq ($(HAVE_X11)$(HAVE_XRANDR), 11)
|
||||
OBJ += $(DEPS_DIR)/switchres/custom_video_xrandr.o
|
||||
DEFINES += -DSR_WITH_XRANDR
|
||||
endif
|
||||
endif
|
||||
ifneq ($(findstring Win32,$(OS)),)
|
||||
DEFINES += -DSR_WIN32_STATIC
|
||||
endif
|
||||
LIBS += -lstdc++
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_COMPRESSION), 1)
|
||||
DEFINES += -DHAVE_COMPRESSION
|
||||
OBJ += tasks/task_decompress.o
|
||||
@@ -2280,9 +2331,9 @@ ifeq ($(HAVE_COCOA_COMMON),1)
|
||||
OBJ += input/drivers/cocoa_input.o \
|
||||
ui/drivers/ui_cocoa.o \
|
||||
ui/drivers/cocoa/cocoa_common.o
|
||||
|
||||
|
||||
ifeq ($(HAVE_OPENGL), 1)
|
||||
DEFINES += -DGL_SILENCE_DEPRECATION
|
||||
DEFINES += -DGL_SILENCE_DEPRECATION
|
||||
OBJ += gfx/drivers_context/cocoa_gl_ctx.o
|
||||
endif
|
||||
ifeq ($(HAVE_VULKAN), 1)
|
||||
@@ -2326,10 +2377,10 @@ endif
|
||||
|
||||
ifeq ($(WANT_IOSUHAX), 1)
|
||||
DEFINES += -DHAVE_IOSUHAX
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/libiosuhax
|
||||
OBJ += $(DEPS_DIR)/libiosuhax/iosuhax.o \
|
||||
$(DEPS_DIR)/libiosuhax/iosuhax_devoptab.o \
|
||||
$(DEPS_DIR)/libiosuhax/iosuhax_disc_interface.o
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/libiosuhax/include
|
||||
OBJ += $(DEPS_DIR)/libiosuhax/source/iosuhax.o \
|
||||
$(DEPS_DIR)/libiosuhax/source/iosuhax_devoptab.o \
|
||||
$(DEPS_DIR)/libiosuhax/source/iosuhax_disc_interface.o
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_LIBFAT), 1)
|
||||
@@ -2437,4 +2488,3 @@ ifeq ($(HAVE_ODROIDGO2), 1)
|
||||
endif
|
||||
|
||||
##################################
|
||||
|
||||
+1
-1
@@ -490,7 +490,7 @@ else ifeq ($(platform), windows_msvc2005_x86)
|
||||
CXX = cl.exe
|
||||
LD = link.exe
|
||||
|
||||
PLATCFLAGS += -D_WIN32 -D_WIN32_WINNT=0x0410 -D__STDC_CONSTANT_MACROS -D_MBCS -D__SSE__
|
||||
PLATCFLAGS += -D_WIN32 -D_WIN32_WINNT=0x0410 -D__STDC_CONSTANT_MACROS -D_MBCS
|
||||
PLATCFLAGS += -DHAVE_OPENGL -DHAVE_OPENGL1 -DHAVE_GLSL -DHAVE_OZONE -DHAVE_GFX_WIDGETS -DHAVE_CC_RESAMPLER
|
||||
PLATCFLAGS += -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_CDROM
|
||||
PLATCFLAGS += -bigobj
|
||||
|
||||
@@ -32,6 +32,7 @@ HAVE_RTGA = 1
|
||||
HAVE_RPNG = 1
|
||||
HAVE_RJPEG = 1
|
||||
HAVE_RBMP = 1
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_ZLIB = 1
|
||||
HAVE_BUILTINZLIB = 1
|
||||
HAVE_LIBRETRODB = 1
|
||||
|
||||
+1
-2
@@ -24,7 +24,6 @@ endif
|
||||
|
||||
INCDIR = -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/ports/include
|
||||
INCDIR += -Ips2/include -Ilibretro-common/include -Ideps -Ideps/stb -Ideps/7zip
|
||||
INCDIR += -Ideps/pthreads -Ideps/pthreads/platform/ps2 -Ideps/pthreads/platform/helper
|
||||
CFLAGS = $(OPTIMIZE_LV) $(DISABLE_WARNINGS) -ffast-math -fsingle-precision-constant
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
@@ -50,7 +49,7 @@ CFLAGS += $(RARCH_DEFINES)
|
||||
# All the IRX objects
|
||||
EE_OBJS += $(IRX_DIR)/sio2man_irx.o $ $(IRX_DIR)/iomanX_irx.o $(IRX_DIR)/fileXio_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/usbhdfsd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/bdm_irx.o $(IRX_DIR)/bdmfs_vfat_irx.o $(IRX_DIR)/usbmass_bd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/libsd_irx.o $(IRX_DIR)/audsrv_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/cdfs_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mtapman_irx.o $(IRX_DIR)/padman_irx.o
|
||||
|
||||
@@ -61,7 +61,8 @@ EE_OBJS = frontend/frontend_salamander.o \
|
||||
|
||||
# Needed IRX objects
|
||||
EE_OBJS += $(IRX_DIR)/sio2man_irx.o $ $(IRX_DIR)/iomanX_irx.o $(IRX_DIR)/fileXio_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/usbhdfsd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/bdm_irx.o $(IRX_DIR)/bdmfs_vfat_irx.o $(IRX_DIR)/usbmass_bd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/cdfs_irx.o
|
||||
|
||||
EE_CFLAGS = $(CFLAGS)
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@ CORE_PATH = pkg/psl1ght/pkg/USRDIR/cores/CORE.SELF
|
||||
INCLUDE += -I. -Ips3/gcmgl/include/export -Ips3/include -Ideps -Ideps/stb -Ilibretro-common/include/compat/zlib -Ilibretro-common/include $(LIBPSL1GHT_INC) -Iinclude -Idefines
|
||||
LIBDIRS += -L.
|
||||
|
||||
MACHDEP := -D__PSL1GHT__ -mcpu=cell
|
||||
MACHDEP := -D__PSL1GHT__ -D__PS3__ -mcpu=cell
|
||||
CFLAGS += -Wall $(MACHDEP) $(INCLUDE)
|
||||
LDFLAGS := $(MACHDEP)
|
||||
LIBS := -lretro_psl1ght -laudio -lrsx -lgcm_sys -lnet -lio -lsysutil -lsysmodule -lm -ljpgdec -lpngdec -llv2 -lnet -lnetctl -lsysfs
|
||||
@@ -66,7 +66,7 @@ endif
|
||||
SHARED_FLAGS :=
|
||||
|
||||
SHARED_FLAGS += -DHAVE_VIDEO_LAYOUT
|
||||
SHARED_FLAGS += -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS -DRARCH_CONSOLE -DHAVE_OVERLAY -DHAVE_HEADSET -DHAVE_CG -DHAVE_CG_RUNTIME_COMPILER -DHAVE_GCMGL -DHAVE_SYSMODULES -DHAVE_SYSUTILS -DHAVE_RARCH_EXEC -DHAVE_MOUSE -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_GRIFFIN=1 -DHAVE_NETWORKING=1 -DHAVE_SOCKET_LEGACY=1 -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT) -Wno-char-subscripts -DHAVE_CC_RESAMPLER -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DHAVE_REWIND -DHAVE_MULTIMAN -DHAVE_RGUI
|
||||
SHARED_FLAGS += -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS -DRARCH_CONSOLE -DHAVE_OVERLAY -DHAVE_HEADSET -DHAVE_CG -DHAVE_CG_RUNTIME_COMPILER -DHAVE_SYSMODULES -DHAVE_SYSUTILS -DHAVE_RARCH_EXEC -DHAVE_MOUSE -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_GRIFFIN=1 -DHAVE_NETWORKING=1 -DHAVE_SOCKET_LEGACY=1 -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT) -Wno-char-subscripts -DHAVE_CC_RESAMPLER -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DHAVE_REWIND -DHAVE_MULTIMAN -DHAVE_RGUI
|
||||
CFLAGS += -std=gnu99 $(SHARED_FLAGS)
|
||||
CXXFLAGS += $(SHARED_FLAGS)
|
||||
|
||||
|
||||
@@ -27,13 +27,14 @@ ELF_TARGET := retroarch_psl1ght_salamander.elf
|
||||
ELF_TARGET_NONSTRIPPED := retroarch_psl1ght_salamander_nonstripped.elf
|
||||
EBOOT_PATH = pkg/psl1ght/pkg/USRDIR/EBOOT.BIN
|
||||
|
||||
INCLUDE += -I. -Ips3/gcmgl/include/export -Ips3/include -Ideps -Ideps/stb -Ilibretro-common/include/compat/zlib -Ilibretro-common/include $(LIBPSL1GHT_INC) -Iinclude
|
||||
INCLUDE += -I. -Ips3/gcmgl/include/export -Ips3/include -Ideps -Ideps/stb -Ilibretro-common/include/compat/zlib \
|
||||
-Ilibretro-common/include $(LIBPSL1GHT_INC) -Iinclude -Idefines
|
||||
LIBDIRS += -L.
|
||||
|
||||
MACHDEP := -D__PSL1GHT__ -mcpu=cell -mhard-float -fmodulo-sched -ffunction-sections -fdata-sections
|
||||
MACHDEP := -D__PS3__ -D__PSL1GHT__ -mcpu=cell -mhard-float -fmodulo-sched -ffunction-sections -fdata-sections
|
||||
CFLAGS += -Wall $(MACHDEP) $(INCLUDE)
|
||||
LDFLAGS := $(MACHDEP)
|
||||
LIBS := -lgcm_sys -lrsx -lsysutil -lio -lnet -lsysmodule -lrt -llv2 -lm
|
||||
LIBS := -lgcm_sys -lrsx -lsysutil -lio -lnet -lsysmodule -lrt -llv2 -lm -lsysfs
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ ifeq ($(WHOLE_ARCHIVE_LINK), 1)
|
||||
WHOLE_END := -Wl,--no-whole-archive
|
||||
endif
|
||||
|
||||
INCDIR = deps deps/stb deps/7zip deps/pthreads deps/pthreads/platform/psp deps/pthreads/platform/helper libretro-common/include libretro-common/include/compat/zlib
|
||||
INCDIR = deps deps/stb deps/7zip libretro-common/include libretro-common/include/compat/zlib
|
||||
CFLAGS = $(OPTIMIZE_LV) -G0 -std=gnu99 -ffast-math -fsingle-precision-constant
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
@@ -27,7 +27,7 @@ RARCH_DEFINES = -DPSP -D_MIPS_ARCH_ALLEGREX -DHAVE_LANGEXTRA -DHAVE_ZLIB -DHAVE_
|
||||
|
||||
LIBDIR =
|
||||
LDFLAGS =
|
||||
LIBS = $(WHOLE_START) -lretro_psp1 $(WHOLE_END) -lstdc++ -lpspgu -lpspgum -lm -lpspaudio -lpspfpu -lpsppower -lpsprtc
|
||||
LIBS = $(WHOLE_START) -lretro_psp1 $(WHOLE_END) -lstdc++ -lpspgu -lpspgum -lm -lpspaudio -lpspfpu -lpsppower -lpsprtc -lpthread-psp
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
RARCH_DEFINES += -DHAVE_THREADS
|
||||
|
||||
+3
-1
@@ -219,7 +219,9 @@ opk: $(TARGET)
|
||||
echo "$$DESKTOP_ENTRY" > default.gcw0.desktop
|
||||
rm -f $(OPK_NAME)
|
||||
cp media/ico_src/icon32.png retroarch.png
|
||||
if [ $$STRIP_BIN -eq 1 ]; then $(STRIP) --strip-unneeded retroarch; fi
|
||||
ifeq ($(STRIP_BIN),1)
|
||||
$(STRIP) --strip-unneeded retroarch
|
||||
endif
|
||||
$(GCW0_MK_SQUASH_FS) retroarch default.gcw0.desktop retroarch.png $(OPK_NAME) -all-root -no-xattrs -noappend -no-exports
|
||||
rm -f default.gcw0.desktop retroarch.png
|
||||
|
||||
|
||||
@@ -45,8 +45,7 @@ HAVE_SCREENSHOTS = 0
|
||||
HAVE_REWIND = 1
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_AL = 1
|
||||
# ALSA freezes when switching back from menu
|
||||
HAVE_ALSA = 0
|
||||
HAVE_ALSA = 1
|
||||
HAVE_DSP_FILTER = 1
|
||||
HAVE_VIDEO_FILTER = 1
|
||||
HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
@@ -121,6 +120,7 @@ DEF_FLAGS += -ffunction-sections -fdata-sections
|
||||
DEF_FLAGS += -I. -Ideps -Ideps/stb -DDINGUX=1 -DDINGUX_BETA=1 -MMD
|
||||
DEF_FLAGS += -Wall -Wno-unused-variable
|
||||
DEF_FLAGS += -std=gnu99 -D_GNU_SOURCE -flto
|
||||
DEF_FLAGS += -lasound
|
||||
LIBS := -ldl -lz -lrt -ludev -pthread
|
||||
CFLAGS :=
|
||||
CXXFLAGS := -fno-exceptions -fno-rtti -std=c++11 -D__STDC_CONSTANT_MACROS
|
||||
@@ -134,6 +134,7 @@ DEFINES += -DHAVE_GETOPT_LONG=1 -DHAVE_STRCASESTR=1 -DHAVE_DYNAMIC=1
|
||||
DEFINES += -DHAVE_AL=1
|
||||
DEFINES += -DHAVE_FILTERS_BUILTIN
|
||||
DEFINES += -DHAVE_UDEV=1
|
||||
DEFINES += -DHAVE_ALSA
|
||||
|
||||
SDL_DINGUX_CFLAGS := $(shell $(GCW0_SDL_CONFIG) --cflags)
|
||||
SDL_DINGUX_LIBS := $(shell $(GCW0_SDL_CONFIG) --libs)
|
||||
@@ -219,7 +220,9 @@ opk: $(TARGET)
|
||||
echo "$$DESKTOP_ENTRY" > default.gcw0.desktop
|
||||
rm -f $(OPK_NAME)
|
||||
cp media/ico_src/icon32.png retroarch.png
|
||||
if [ $$STRIP_BIN -eq 1 ]; then $(STRIP) --strip-unneeded retroarch; fi
|
||||
ifeq ($(STRIP_BIN),1)
|
||||
$(STRIP) --strip-unneeded retroarch
|
||||
endif
|
||||
$(GCW0_MK_SQUASH_FS) retroarch default.gcw0.desktop retroarch.png $(OPK_NAME) -all-root -no-xattrs -noappend -no-exports
|
||||
rm -f default.gcw0.desktop retroarch.png
|
||||
|
||||
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
#########################
|
||||
## Toolchain variables ##
|
||||
#########################
|
||||
|
||||
# Alpha toolchain
|
||||
TOOLCHAIN_DIR=/opt/rs90-toolchain
|
||||
|
||||
# All toolchain-related variables may be
|
||||
# overridden via the command line
|
||||
ifdef GCW0_CC
|
||||
CC = $(GCW0_CC)
|
||||
else
|
||||
CC = $(TOOLCHAIN_DIR)/usr/bin/mipsel-rs90-linux-musl-gcc
|
||||
endif
|
||||
|
||||
ifdef GCW0_CXX
|
||||
CXX = $(GCW0_CXX)
|
||||
else
|
||||
CXX = $(TOOLCHAIN_DIR)/usr/bin/mipsel-rs90-linux-musl-g++
|
||||
endif
|
||||
|
||||
ifdef GCW0_STRIP
|
||||
STRIP = $(GCW0_STRIP)
|
||||
else
|
||||
STRIP = $(TOOLCHAIN_DIR)/usr/bin/mipsel-rs90-linux-musl-strip
|
||||
endif
|
||||
|
||||
GCW0_SDL_CONFIG ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/bin/sdl-config
|
||||
GCW0_FREETYPE_CONFIG ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/bin/freetype-config
|
||||
GCW0_MK_SQUASH_FS ?= $(TOOLCHAIN_DIR)/usr/bin/mksquashfs
|
||||
|
||||
GCW0_INC_DIR ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/include
|
||||
GCW0_LIB_DIR ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/lib
|
||||
|
||||
#########################
|
||||
#########################
|
||||
|
||||
PACKAGE_NAME = retroarch
|
||||
|
||||
DEBUG ?= 0
|
||||
|
||||
RS90 = 1
|
||||
DINGUX = 1
|
||||
DINGUX_BETA = 1
|
||||
HAVE_SCREENSHOTS = 0
|
||||
HAVE_REWIND = 0
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_AL = 0
|
||||
HAVE_ALSA = 1
|
||||
HAVE_DSP_FILTER = 1
|
||||
HAVE_VIDEO_FILTER = 1
|
||||
HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
HAVE_STATIC_AUDIO_FILTERS = 1
|
||||
HAVE_FILTERS_BUILTIN = 1
|
||||
HAVE_BUILTINMBEDTLS = 0
|
||||
HAVE_BUILTINZLIB = 1
|
||||
HAVE_C99 = 1
|
||||
HAVE_CC = 1
|
||||
HAVE_CC_RESAMPLER = 1
|
||||
|
||||
HAVE_CHD = 0
|
||||
HAVE_COMMAND = 0
|
||||
HAVE_CXX = 1
|
||||
HAVE_DR_MP3 = 0
|
||||
HAVE_DYNAMIC = 1
|
||||
HAVE_EGL = 0
|
||||
HAVE_FREETYPE = 0
|
||||
HAVE_GDI = 0
|
||||
HAVE_GETADDRINFO = 0
|
||||
HAVE_GETOPT_LONG = 1
|
||||
HAVE_GLSL = 0
|
||||
HAVE_HID = 0
|
||||
HAVE_IBXM = 0
|
||||
HAVE_IMAGEVIEWER = 0
|
||||
HAVE_LANGEXTRA = 0
|
||||
HAVE_LIBRETRODB = 1
|
||||
HAVE_MENU = 1
|
||||
HAVE_MENU_COMMON = 1
|
||||
HAVE_GFX_WIDGETS = 0
|
||||
HAVE_MMAP = 1
|
||||
HAVE_OPENDINGUX_FBDEV = 0
|
||||
HAVE_OPENGL = 0
|
||||
HAVE_OPENGL1 = 0
|
||||
HAVE_OPENGLES = 0
|
||||
HAVE_OPENGLES3 = 0
|
||||
HAVE_OPENGL_CORE = 0
|
||||
HAVE_OPENSSL = 0
|
||||
HAVE_OVERLAY = 0
|
||||
HAVE_RBMP = 1
|
||||
HAVE_RJPEG = 1
|
||||
HAVE_RPILED = 0
|
||||
HAVE_RPNG = 1
|
||||
HAVE_RUNAHEAD = 0
|
||||
HAVE_SDL_DINGUX = 1
|
||||
HAVE_SHADERPIPELINE = 0
|
||||
HAVE_STB_FONT = 0
|
||||
HAVE_STB_IMAGE = 0
|
||||
HAVE_STB_VORBIS = 0
|
||||
HAVE_STDIN_CMD = 0
|
||||
HAVE_STRCASESTR = 1
|
||||
HAVE_THREADS = 1
|
||||
HAVE_UDEV = 1
|
||||
HAVE_RGUI = 1
|
||||
HAVE_MATERIALUI = 0
|
||||
HAVE_XMB = 0
|
||||
HAVE_OZONE = 0
|
||||
HAVE_ZLIB = 1
|
||||
HAVE_CONFIGFILE = 1
|
||||
HAVE_PATCH = 1
|
||||
HAVE_CHEATS = 1
|
||||
HAVE_CHEEVOS = 0
|
||||
HAVE_LIBSHAKE = 0
|
||||
HAVE_TINYALSA = 1
|
||||
HAVE_NEAREST_RESAMPLER = 1
|
||||
|
||||
OS = Linux
|
||||
TARGET = retroarch
|
||||
OPK_NAME = retroarch_rs90_odbeta.opk
|
||||
|
||||
OBJ :=
|
||||
LINK := $(CXX)
|
||||
DEF_FLAGS := -mplt -mno-shared
|
||||
DEF_FLAGS += -ffunction-sections -fdata-sections
|
||||
DEF_FLAGS += -I. -Ideps -Ideps/stb -DRS90=1 -DDINGUX=1 -DDINGUX_BETA=1 -MMD
|
||||
DEF_FLAGS += -Wall -Wno-unused-variable
|
||||
DEF_FLAGS += -std=gnu99 -D_GNU_SOURopendinguxCE -flto -lasound
|
||||
LIBS := -ldl -lz -lrt -ludev -pthread
|
||||
CFLAGS :=
|
||||
CXXFLAGS := -fno-exceptions -fno-rtti -std=c++11 -D__STDC_CONSTANT_MACROS
|
||||
ASFLAGS :=
|
||||
LDFLAGS := -Wl,--gc-sections
|
||||
INCLUDE_DIRS = -I$(GCW0_INC_DIR)
|
||||
LIBRARY_DIRS = -L$(GCW0_LIB_DIR)
|
||||
DEFINES := -DRARCH_INTERNAL -D_FILE_OFFSET_BITS=64 -UHAVE_STATIC_DUMMY
|
||||
DEFINES += -DHAVE_C99=1 -DHAVE_CXX=1
|
||||
DEFINES += -DHAVE_GETOPT_LONG=1 -DHAVE_STRCASESTR=1 -DHAVE_DYNAMIC=1
|
||||
DEFINES += -DHAVE_FILTERS_BUILTIN
|
||||
DEFINES += -DHAVE_UDEV=1
|
||||
DEFINES += -DHAVE_ALSA
|
||||
DEFINES += -DCC_RESAMPLER_PRECISION=0
|
||||
|
||||
SDL_DINGUX_CFLAGS := $(shell $(GCW0_SDL_CONFIG) --cflags)
|
||||
SDL_DINGUX_LIBS := $(shell $(GCW0_SDL_CONFIG) --libs)
|
||||
FREETYPE_CFLAGS := $(shell $(GCW0_FREETYPE_CONFIG) --cflags)
|
||||
FREETYPE_LIBS := $(shell $(GCW0_FREETYPE_CONFIG) --libs)
|
||||
MMAP_LIBS = -lc
|
||||
|
||||
OBJDIR_BASE := obj-unix
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
OBJDIR := $(OBJDIR_BASE)/debug
|
||||
DEF_FLAGS += -O0 -g -DDEBUG -D_DEBUG
|
||||
else
|
||||
OBJDIR := $(OBJDIR_BASE)/release
|
||||
DEF_FLAGS += -Ofast -DNDEBUG
|
||||
endif
|
||||
|
||||
include Makefile.common
|
||||
|
||||
DEF_FLAGS += $(INCLUDE_DIRS)
|
||||
LDFLAGS += $(CFLAGS) $(CXXFLAGS) $(DEF_FLAGS)
|
||||
CFLAGS += $(DEF_FLAGS)
|
||||
CXXFLAGS += $(DEF_FLAGS)
|
||||
|
||||
HEADERS = $(wildcard */*/*.h) $(wildcard */*.h) $(wildcard *.h)
|
||||
|
||||
Q := @
|
||||
|
||||
RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ))
|
||||
|
||||
define DESKTOP_ENTRY
|
||||
[Desktop Entry]
|
||||
Name=RetroArch
|
||||
Comment=Frontend for emulators, game engines
|
||||
Exec=retroarch
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Icon=retroarch
|
||||
Categories=emulators;
|
||||
X-OD-NeedsDownscaling=true
|
||||
endef
|
||||
export DESKTOP_ENTRY
|
||||
|
||||
all: $(TARGET) opk
|
||||
|
||||
-include $(RARCH_OBJ:.o=.d)
|
||||
|
||||
SYMBOL_MAP := -Wl,-Map=output.map
|
||||
|
||||
$(TARGET): $(RARCH_OBJ)
|
||||
@$(if $(Q), $(shell echo echo LD $@),)
|
||||
$(Q)$(LINK) -o $@ $(RARCH_OBJ) $(LIBS) $(LDFLAGS) $(LIBRARY_DIRS)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo CC $<),)
|
||||
$(Q)$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo CXX $<),)
|
||||
$(Q)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES) -MMD -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.m
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo OBJC $<),)
|
||||
$(Q)$(CXX) $(OBJCFLAGS) $(DEFINES) -MMD -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.S $(HEADERS)
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo AS $<),)
|
||||
$(Q)$(CC) $(CFLAGS) $(ASFLAGS) $(DEFINES) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR_BASE)
|
||||
rm -f $(TARGET)
|
||||
rm -f *.d
|
||||
rm -rf $(OPK_NAME)
|
||||
|
||||
opk: $(TARGET)
|
||||
echo "$$DESKTOP_ENTRY" > default.rs90.desktop
|
||||
rm -f $(OPK_NAME)
|
||||
cp media/ico_src/icon32.png retroarch.png
|
||||
ifeq ($STRIP_BIN, 1)
|
||||
$(STRIP) --strip-unneeded retroarch
|
||||
endif
|
||||
$(GCW0_MK_SQUASH_FS) retroarch default.rs90.desktop retroarch.png $(OPK_NAME) -all-root -no-xattrs -noappend -no-exports
|
||||
rm -f default.rs90.desktop retroarch.png
|
||||
|
||||
.PHONY: all clean opk
|
||||
|
||||
print-%:
|
||||
@echo '$*=$($*)'
|
||||
+11
-5
@@ -13,7 +13,7 @@ PC_DEVELOPMENT_UDP_PORT =
|
||||
OBJ :=
|
||||
|
||||
SCE_LIBC_SIZE := 4194304
|
||||
DEFINES := -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS
|
||||
DEFINES := -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_STB_VORBIS
|
||||
INCDIRS :=
|
||||
|
||||
ifeq ($(GRIFFIN_BUILD), 1)
|
||||
@@ -112,17 +112,23 @@ LD := $(CXX)
|
||||
|
||||
LIBDIRS := -L.
|
||||
|
||||
ARCHFLAGS := -march=armv7-a -mfpu=neon -mfloat-abi=hard -DVITA -DSCE_LIBC_SIZE=$(SCE_LIBC_SIZE)
|
||||
CFLAGS += $(ARCHFLAGS) -mword-relocations -fno-optimize-sibling-calls -O2
|
||||
ARCHFLAGS := -march=armv7-a -mfpu=neon -mfloat-abi=hard -DVITA
|
||||
ifeq ($(HAVE_VITAGLES), 1)
|
||||
ARCHFLAGS += -DSCE_LIBC_SIZE=$(SCE_LIBC_SIZE)
|
||||
endif
|
||||
|
||||
CFLAGS += $(ARCHFLAGS) -mword-relocations -fno-optimize-sibling-calls
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -g
|
||||
CFLAGS += -g -Og
|
||||
else
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
|
||||
ASFLAGS := $(CFLAGS)
|
||||
LDFLAGS := -Wl,-q
|
||||
|
||||
CFLAGS += -Wall -ffast-math -g
|
||||
CFLAGS += -Wall -ffast-math
|
||||
CFLAGS += -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DRARCH_CONSOLE
|
||||
CFLAGS += -DHAVE_DSP_FILTER
|
||||
CFLAGS += -DHAVE_VIDEO_FILTER
|
||||
|
||||
+1
-1
@@ -102,7 +102,7 @@ endif
|
||||
|
||||
INCDIRS += -Ilibretro-common/include/compat/zlib
|
||||
# for stb, libfat, iosuhax
|
||||
INCDIRS += -Ideps -Ideps/libfat/include -Ideps/libiosuhax
|
||||
INCDIRS += -Ideps -Ideps/libfat/include -Ideps/libiosuhax/include
|
||||
# pad_functions uses wiiu/input.h
|
||||
INCDIRS += -Iinput/include
|
||||
INCDIRS += -Ideps/SPIRV-Cross
|
||||
|
||||
@@ -546,7 +546,8 @@ static ssize_t dsound_write(void *data, const void *buf_, size_t size)
|
||||
break;
|
||||
|
||||
if (avail == 0)
|
||||
WaitForSingleObject(ds->event, INFINITE);
|
||||
if (!(WaitForSingleObject(ds->event, 50) == WAIT_OBJECT_0))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <retro_inline.h>
|
||||
|
||||
#include "../../retroarch.h"
|
||||
#include "../../defines/gx_defines.h"
|
||||
#include <defines/gx_defines.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "../../retroarch.h"
|
||||
|
||||
#include "../../defines/ps3_defines.h"
|
||||
#include <defines/ps3_defines.h>
|
||||
|
||||
#define AUDIO_BLOCKS 8
|
||||
#define AUDIO_CHANNELS 2
|
||||
|
||||
@@ -144,7 +144,7 @@ static void *libnx_audren_thread_audio_init(const char *device, unsigned rate, u
|
||||
int mpid;
|
||||
size_t mempool_size;
|
||||
unsigned real_latency;
|
||||
uint32_t thread_priority;
|
||||
int32_t thread_priority;
|
||||
|
||||
RARCH_LOG("[Audio]: Using libnx_audren_thread driver\n");
|
||||
|
||||
|
||||
@@ -371,7 +371,8 @@ static ssize_t xa_write(void *data, const void *buf, size_t size)
|
||||
XAUDIO2_BUFFER xa2buffer;
|
||||
|
||||
while (handle->buffers == MAX_BUFFERS - 1)
|
||||
WaitForSingleObject(handle->hEvent, INFINITE);
|
||||
if (!(WaitForSingleObject(handle->hEvent, 50) == WAIT_OBJECT_0))
|
||||
return -1;
|
||||
|
||||
xa2buffer.Flags = 0;
|
||||
xa2buffer.AudioBytes = handle->bufsize;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <errno.h>
|
||||
#include <reent.h>
|
||||
#include "../../defines/psp_defines.h"
|
||||
#include <defines/psp_defines.h>
|
||||
#include <psp2/kernel/sysmem.h>
|
||||
#include <psp2/kernel/threadmgr.h>
|
||||
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2016 - Andre Leiradella
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <file/file_path.h>
|
||||
|
||||
#include "../file_path_special.h"
|
||||
#include "../configuration.h"
|
||||
#include "../gfx/gfx_display.h"
|
||||
|
||||
#include "badges.h"
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
||||
#define CHEEVOS_MENU_BADGE_LIMIT 256
|
||||
/* TODO/FIXME - public global variables */
|
||||
static uintptr_t cheevos_badge_menu_texture_list[CHEEVOS_MENU_BADGE_LIMIT] = { 0 };
|
||||
|
||||
void cheevos_reset_menu_badges(void)
|
||||
{
|
||||
int index;
|
||||
for (index = 0; index < CHEEVOS_MENU_BADGE_LIMIT; ++index)
|
||||
{
|
||||
if (cheevos_badge_menu_texture_list[index])
|
||||
video_driver_texture_unload(&cheevos_badge_menu_texture_list[index]);
|
||||
}
|
||||
|
||||
memset(&cheevos_badge_menu_texture_list, 0,
|
||||
sizeof(cheevos_badge_menu_texture_list));
|
||||
}
|
||||
|
||||
void cheevos_set_menu_badge(int index, const char *badge, bool locked)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
if (index >= CHEEVOS_MENU_BADGE_LIMIT)
|
||||
return;
|
||||
|
||||
if (!settings || !settings->bools.cheevos_badges_enable)
|
||||
cheevos_badge_menu_texture_list[index] = 0;
|
||||
else
|
||||
cheevos_badge_menu_texture_list[index] =
|
||||
cheevos_get_badge_texture(badge, locked);
|
||||
}
|
||||
|
||||
uintptr_t cheevos_get_menu_badge_texture(int index)
|
||||
{
|
||||
if (index < CHEEVOS_MENU_BADGE_LIMIT)
|
||||
return cheevos_badge_menu_texture_list[index];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uintptr_t cheevos_get_badge_texture(const char *badge, bool locked)
|
||||
{
|
||||
char badge_file[24];
|
||||
char fullpath[PATH_MAX_LENGTH];
|
||||
uintptr_t tex = 0;
|
||||
|
||||
if (!badge)
|
||||
return 0;
|
||||
|
||||
fullpath[0] = badge_file[0] = '\0';
|
||||
|
||||
strlcpy(badge_file, badge, sizeof(badge_file));
|
||||
if (locked)
|
||||
strlcat(badge_file, "_lock", sizeof(badge_file));
|
||||
strlcat(badge_file, FILE_PATH_PNG_EXTENSION, sizeof(badge_file));
|
||||
|
||||
fill_pathname_application_special(fullpath, sizeof(fullpath),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES);
|
||||
|
||||
if (!gfx_display_reset_textures_list(badge_file, fullpath,
|
||||
&tex, TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL))
|
||||
tex = 0;
|
||||
|
||||
return tex;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_BADGE_H
|
||||
#define __RARCH_CHEEVOS_BADGE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <retro_common_api.h>
|
||||
#include <boolean.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
void cheevos_reset_menu_badges(void);
|
||||
void cheevos_set_menu_badge(int index, const char *badge, bool locked);
|
||||
uintptr_t cheevos_get_menu_badge_texture(int index);
|
||||
#endif
|
||||
|
||||
uintptr_t cheevos_get_badge_texture(const char* badge, bool locked);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
+329
-677
File diff suppressed because it is too large.
Load diff
+8
-33
@@ -21,64 +21,39 @@
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#include "../verbosity.h"
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct rcheevos_ctx_desc
|
||||
{
|
||||
unsigned idx;
|
||||
char *s;
|
||||
size_t len;
|
||||
} rcheevos_ctx_desc_t;
|
||||
|
||||
enum
|
||||
{
|
||||
RCHEEVOS_ACTIVE_SOFTCORE = 1 << 0,
|
||||
RCHEEVOS_ACTIVE_HARDCORE = 1 << 1,
|
||||
RCHEEVOS_ACTIVE_UNOFFICIAL = 1 << 2
|
||||
};
|
||||
|
||||
bool rcheevos_load(const void *data);
|
||||
size_t rcheevos_get_serialize_size(void);
|
||||
bool rcheevos_get_serialized_data(void* buffer);
|
||||
bool rcheevos_set_serialized_data(void* buffer);
|
||||
|
||||
void rcheevos_reset_game(bool widgets_ready);
|
||||
|
||||
void rcheevos_populate_menu(void* data);
|
||||
void rcheevos_populate_hardcore_pause_menu(void* data);
|
||||
void rcheevos_get_achievement_state(unsigned index, char* buffer, size_t buffer_size);
|
||||
|
||||
bool rcheevos_get_description(rcheevos_ctx_desc_t *desc);
|
||||
|
||||
void rcheevos_pause_hardcore(void);
|
||||
|
||||
bool rcheevos_unload(void);
|
||||
|
||||
void rcheevos_test(void);
|
||||
|
||||
void rcheevos_reset_game(bool widgets_ready);
|
||||
|
||||
void rcheevos_pause_hardcore(void);
|
||||
void rcheevos_hardcore_enabled_changed(void);
|
||||
void rcheevos_toggle_hardcore_paused(void);
|
||||
bool rcheevos_hardcore_active(void);
|
||||
|
||||
void rcheevos_validate_config_settings(void);
|
||||
|
||||
void rcheevos_leaderboards_enabled_changed(void);
|
||||
|
||||
void rcheevos_test(void);
|
||||
|
||||
void rcheevos_set_support_cheevos(bool state);
|
||||
|
||||
bool rcheevos_get_support_cheevos(void);
|
||||
|
||||
const char* rcheevos_get_hash(void);
|
||||
|
||||
const char *rcheevos_get_richpresence(void);
|
||||
int rcheevos_get_richpresence(char buffer[], int buffer_size);
|
||||
uintptr_t rcheevos_get_badge_texture(const char *badge, bool locked);
|
||||
|
||||
uint8_t* rcheevos_patch_address(unsigned address);
|
||||
|
||||
bool rcheevos_hardcore_active(void);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_CHEEVOS_H */
|
||||
@@ -0,0 +1,158 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
* Copyright (C) 2019-2021 - Brian Weiss
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_LOCALS_H
|
||||
#define __RARCH_CHEEVOS_LOCALS_H
|
||||
|
||||
#include "../deps/rcheevos/include/rc_runtime.h"
|
||||
|
||||
#include "../deps/rcheevos/src/rcheevos/rc_libretro.h"
|
||||
|
||||
#include <../command.h>
|
||||
#include <../verbosity.h>
|
||||
#include <boolean.h>
|
||||
#include <queues/task_queue.h>
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#include <rthreads/rthreads.h>
|
||||
#endif
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/************************************************************************
|
||||
* Logging *
|
||||
************************************************************************/
|
||||
|
||||
/* Define this macro to get extra-verbose log for cheevos. */
|
||||
#define CHEEVOS_VERBOSE
|
||||
|
||||
#define RCHEEVOS_TAG "[RCHEEVOS]: "
|
||||
#define CHEEVOS_FREE(p) do { void* q = (void*)p; if (q) free(q); } while (0)
|
||||
|
||||
#ifdef CHEEVOS_VERBOSE
|
||||
#define CHEEVOS_LOG RARCH_LOG
|
||||
#define CHEEVOS_ERR RARCH_ERR
|
||||
#else
|
||||
void rcheevos_log(const char *fmt, ...);
|
||||
#define CHEEVOS_LOG rcheevos_log
|
||||
#define CHEEVOS_ERR RARCH_ERR
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
* State *
|
||||
************************************************************************/
|
||||
|
||||
enum
|
||||
{
|
||||
RCHEEVOS_ACTIVE_SOFTCORE = 1 << 0,
|
||||
RCHEEVOS_ACTIVE_HARDCORE = 1 << 1,
|
||||
RCHEEVOS_ACTIVE_UNOFFICIAL = 1 << 2
|
||||
};
|
||||
|
||||
typedef struct rcheevos_racheevo_t
|
||||
{
|
||||
const char* title;
|
||||
const char* description;
|
||||
const char* badge;
|
||||
const char* memaddr;
|
||||
unsigned id;
|
||||
unsigned points;
|
||||
|
||||
retro_time_t unlock_time;
|
||||
uint8_t active;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
uint8_t menu_bucket;
|
||||
uint8_t menu_progress;
|
||||
uint8_t menu_badge_grayscale;
|
||||
uintptr_t menu_badge_texture;
|
||||
#endif
|
||||
|
||||
} rcheevos_racheevo_t;
|
||||
|
||||
typedef struct rcheevos_ralboard_t
|
||||
{
|
||||
const char* title;
|
||||
const char* description;
|
||||
const char* mem;
|
||||
unsigned id;
|
||||
unsigned format;
|
||||
} rcheevos_ralboard_t;
|
||||
|
||||
typedef struct rcheevos_rapatchdata_t
|
||||
{
|
||||
char* title;
|
||||
rcheevos_racheevo_t* core;
|
||||
rcheevos_racheevo_t* unofficial;
|
||||
rcheevos_ralboard_t* lboards;
|
||||
char* richpresence_script;
|
||||
|
||||
unsigned game_id;
|
||||
unsigned console_id;
|
||||
unsigned core_count;
|
||||
unsigned unofficial_count;
|
||||
unsigned lboard_count;
|
||||
} rcheevos_rapatchdata_t;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
||||
typedef struct rcheevos_menuitem_t
|
||||
{
|
||||
rcheevos_racheevo_t* cheevo;
|
||||
enum msg_hash_enums state_label_idx;
|
||||
} rcheevos_menuitem_t;
|
||||
|
||||
void rcheevos_menu_reset_badges(void);
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct rcheevos_locals_t
|
||||
{
|
||||
rc_runtime_t runtime; /* rcheevos runtime state */
|
||||
rcheevos_rapatchdata_t patchdata; /* achievement/leaderboard data from the server */
|
||||
rc_libretro_memory_regions_t memory;/* achievement addresses to core memory mappings */
|
||||
|
||||
retro_task_t* task; /* load task */
|
||||
#ifdef HAVE_THREADS
|
||||
slock_t* task_lock; /* mutex for starting/stopping load task */
|
||||
enum event_command queued_command; /* action queued by background thread to be run on main thread */
|
||||
#endif
|
||||
|
||||
char token[32]; /* user's session token */
|
||||
char hash[33]; /* retroachievements hash for current content */
|
||||
char user_agent_prefix[128]; /* RetroArch/OS version information */
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
rcheevos_menuitem_t* menuitems; /* array of items for the achievements quick menu */
|
||||
unsigned menuitem_capacity; /* maximum number of items in the menuitems array */
|
||||
unsigned menuitem_count; /* current number of items in the menuitems array */
|
||||
#endif
|
||||
|
||||
bool hardcore_active; /* hardcore functionality is active */
|
||||
bool loaded; /* load task has completed */
|
||||
bool core_supports; /* false if core explicitly disables achievements */
|
||||
bool leaderboards_enabled; /* leaderboards are enabled */
|
||||
bool leaderboard_notifications; /* leaderboard notifications are enabled */
|
||||
bool leaderboard_trackers; /* leaderboard trackers are enabled */
|
||||
} rcheevos_locals_t;
|
||||
|
||||
rcheevos_locals_t* get_rcheevos_locals(void);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_LOCALS_H */
|
||||
@@ -1,352 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2016 - Andre Leiradella
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cheevos_memory.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#include "../retroarch.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
#include "../deps/rcheevos/include/rcheevos.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
uint8_t* rcheevos_memory_find(
|
||||
const rcheevos_memory_regions_t* regions, unsigned address)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < regions->count; ++i)
|
||||
{
|
||||
const size_t size = regions->size[i];
|
||||
if (address < size)
|
||||
{
|
||||
if (regions->data[i] == NULL)
|
||||
break;
|
||||
|
||||
return ®ions->data[i][address];
|
||||
}
|
||||
|
||||
address -= size;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* rcheevos_memory_type(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case RC_MEMORY_TYPE_SAVE_RAM:
|
||||
return "SRAM";
|
||||
case RC_MEMORY_TYPE_VIDEO_RAM:
|
||||
return "VRAM";
|
||||
case RC_MEMORY_TYPE_UNUSED:
|
||||
return "UNUSED";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "SYSTEM RAM";
|
||||
}
|
||||
|
||||
static void rcheevos_memory_register_region(rcheevos_memory_regions_t* regions,
|
||||
int type, uint8_t* data, size_t size, const char* description)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
if (regions->count == MAX_MEMORY_REGIONS)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Too many memory memory regions to register\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data && regions->count > 0 && !regions->data[regions->count - 1])
|
||||
{
|
||||
/* extend null region */
|
||||
regions->size[regions->count - 1] += size;
|
||||
}
|
||||
else if (data && regions->count > 0 &&
|
||||
data == (regions->data[regions->count - 1] + regions->size[regions->count - 1]))
|
||||
{
|
||||
/* extend non-null region */
|
||||
regions->size[regions->count - 1] += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* create new region */
|
||||
regions->data[regions->count] = data;
|
||||
regions->size[regions->count] = size;
|
||||
++regions->count;
|
||||
}
|
||||
|
||||
regions->total_size += size;
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Registered 0x%04X bytes of %s at $%06X (%s)\n", (unsigned)size,
|
||||
rcheevos_memory_type(type), (unsigned)(regions->total_size - size), description);
|
||||
}
|
||||
|
||||
static void rcheevos_memory_init_without_regions(
|
||||
rcheevos_memory_regions_t* regions)
|
||||
{
|
||||
/* no regions specified, assume system RAM followed by save RAM */
|
||||
char description[64];
|
||||
retro_ctx_memory_info_t meminfo;
|
||||
|
||||
snprintf(description, sizeof(description), "offset 0x%06x", 0);
|
||||
|
||||
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
core_get_memory(&meminfo);
|
||||
rcheevos_memory_register_region(regions, RC_MEMORY_TYPE_SYSTEM_RAM, (uint8_t*)meminfo.data, meminfo.size, description);
|
||||
|
||||
meminfo.id = RETRO_MEMORY_SAVE_RAM;
|
||||
core_get_memory(&meminfo);
|
||||
rcheevos_memory_register_region(regions, RC_MEMORY_TYPE_SAVE_RAM, (uint8_t*)meminfo.data, meminfo.size, description);
|
||||
}
|
||||
|
||||
static const rarch_memory_descriptor_t* rcheevos_memory_get_descriptor(const rarch_memory_map_t* mmap, unsigned real_address)
|
||||
{
|
||||
const rarch_memory_descriptor_t* desc = mmap->descriptors;
|
||||
const rarch_memory_descriptor_t* end = desc + mmap->num_descriptors;
|
||||
|
||||
if (mmap->num_descriptors == 0)
|
||||
return NULL;
|
||||
|
||||
for (; desc < end; desc++)
|
||||
{
|
||||
if (desc->core.select == 0)
|
||||
{
|
||||
/* if select is 0, attempt to explcitly match the address */
|
||||
if (real_address >= desc->core.start && real_address < desc->core.start + desc->core.len)
|
||||
return desc;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise, attempt to match the address by matching the select bits */
|
||||
if (((desc->core.start ^ real_address) & desc->core.select) == 0)
|
||||
{
|
||||
/* sanity check - make sure the descriptor is large enough to hold the target address */
|
||||
if (real_address - desc->core.start < desc->core.len)
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rcheevos_memory_init_from_memory_map(rcheevos_memory_regions_t* regions, const rarch_memory_map_t* mmap, const rc_memory_regions_t* console_regions)
|
||||
{
|
||||
char description[64];
|
||||
unsigned i;
|
||||
uint8_t* region_start;
|
||||
uint8_t* desc_start;
|
||||
size_t desc_size;
|
||||
size_t offset;
|
||||
|
||||
for (i = 0; i < console_regions->num_regions; ++i)
|
||||
{
|
||||
const rc_memory_region_t* console_region = &console_regions->region[i];
|
||||
size_t console_region_size = console_region->end_address - console_region->start_address + 1;
|
||||
unsigned real_address = console_region->real_address;
|
||||
|
||||
while (console_region_size > 0)
|
||||
{
|
||||
const rarch_memory_descriptor_t* desc = rcheevos_memory_get_descriptor(mmap, real_address);
|
||||
if (!desc)
|
||||
{
|
||||
if (console_region->type != RC_MEMORY_TYPE_UNUSED)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Could not map region starting at $%06X\n",
|
||||
real_address - console_region->real_address + console_region->start_address);
|
||||
}
|
||||
|
||||
rcheevos_memory_register_region(regions, console_region->type, NULL, console_region_size, "null filler");
|
||||
break;
|
||||
}
|
||||
|
||||
offset = real_address - desc->core.start;
|
||||
snprintf(description, sizeof(description),
|
||||
"descriptor %u, offset 0x%06X",
|
||||
(int)(desc - mmap->descriptors) + 1, (int)offset);
|
||||
|
||||
if (desc->core.ptr)
|
||||
{
|
||||
desc_start = (uint8_t*)desc->core.ptr + desc->core.offset;
|
||||
region_start = desc_start + offset;
|
||||
}
|
||||
else
|
||||
region_start = NULL;
|
||||
|
||||
desc_size = desc->core.len - offset;
|
||||
|
||||
if (console_region_size > desc_size)
|
||||
{
|
||||
if (desc_size == 0)
|
||||
{
|
||||
if (console_region->type != RC_MEMORY_TYPE_UNUSED)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Could not map region starting at $%06X\n",
|
||||
real_address - console_region->real_address + console_region->start_address);
|
||||
}
|
||||
|
||||
rcheevos_memory_register_region(regions, console_region->type, NULL, console_region_size, "null filler");
|
||||
console_region_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rcheevos_memory_register_region(regions, console_region->type, region_start, desc_size, description);
|
||||
console_region_size -= desc_size;
|
||||
real_address += desc_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rcheevos_memory_register_region(regions, console_region->type, region_start, console_region_size, description);
|
||||
console_region_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned rcheevos_memory_console_region_to_ram_type(int region_type)
|
||||
{
|
||||
switch (region_type)
|
||||
{
|
||||
case RC_MEMORY_TYPE_SAVE_RAM:
|
||||
return RETRO_MEMORY_SAVE_RAM;
|
||||
case RC_MEMORY_TYPE_VIDEO_RAM:
|
||||
return RETRO_MEMORY_VIDEO_RAM;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return RETRO_MEMORY_SYSTEM_RAM;
|
||||
}
|
||||
|
||||
static void rcheevos_memory_init_from_unmapped_memory(rcheevos_memory_regions_t* regions, const rc_memory_regions_t* console_regions, int console)
|
||||
{
|
||||
char description[64];
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < console_regions->num_regions; ++i)
|
||||
{
|
||||
size_t offset;
|
||||
unsigned j;
|
||||
retro_ctx_memory_info_t meminfo;
|
||||
const rc_memory_region_t* console_region = &console_regions->region[i];
|
||||
const size_t console_region_size =
|
||||
console_region->end_address - console_region->start_address + 1;
|
||||
unsigned base_address = 0;
|
||||
|
||||
meminfo.id = rcheevos_memory_console_region_to_ram_type(console_region->type);
|
||||
|
||||
for (j = 0; j <= i; ++j)
|
||||
{
|
||||
const rc_memory_region_t* console_region2 = &console_regions->region[j];
|
||||
if (rcheevos_memory_console_region_to_ram_type(
|
||||
console_region2->type) == meminfo.id)
|
||||
{
|
||||
base_address = console_region2->start_address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
offset = console_region->start_address - base_address;
|
||||
|
||||
core_get_memory(&meminfo);
|
||||
|
||||
if (offset < meminfo.size)
|
||||
{
|
||||
meminfo.size -= offset;
|
||||
|
||||
if (meminfo.data)
|
||||
{
|
||||
snprintf(description, sizeof(description),
|
||||
"offset 0x%06X", (int)offset);
|
||||
meminfo.data = (uint8_t*)meminfo.data + offset;
|
||||
}
|
||||
else
|
||||
snprintf(description, sizeof(description), "null filler");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (console_region->type != RC_MEMORY_TYPE_UNUSED)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Could not map region starting at $%06X\n", console_region->start_address);
|
||||
}
|
||||
|
||||
meminfo.data = NULL;
|
||||
meminfo.size = 0;
|
||||
}
|
||||
|
||||
if (console_region_size > meminfo.size)
|
||||
{
|
||||
/* want more than what is available, take what we can and null fill the rest */
|
||||
rcheevos_memory_register_region(regions, console_region->type, (uint8_t*)meminfo.data, meminfo.size, description);
|
||||
rcheevos_memory_register_region(regions, console_region->type, NULL, console_region_size - meminfo.size, "null filler");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* only take as much as we need */
|
||||
rcheevos_memory_register_region(regions, console_region->type, (uint8_t*)meminfo.data, console_region_size, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rcheevos_memory_destroy(rcheevos_memory_regions_t* regions)
|
||||
{
|
||||
memset(regions, 0, sizeof(*regions));
|
||||
}
|
||||
|
||||
bool rcheevos_memory_init(rcheevos_memory_regions_t* regions, int console)
|
||||
{
|
||||
unsigned i;
|
||||
const rc_memory_regions_t* console_regions = rc_console_memory_regions(console);
|
||||
rcheevos_memory_regions_t new_regions;
|
||||
bool has_valid_region = false;
|
||||
|
||||
if (!regions)
|
||||
return false;
|
||||
|
||||
memset(&new_regions, 0, sizeof(new_regions));
|
||||
|
||||
if (console_regions == NULL || console_regions->num_regions == 0)
|
||||
{
|
||||
rcheevos_memory_init_without_regions(&new_regions);
|
||||
}
|
||||
else
|
||||
{
|
||||
rarch_system_info_t* system = runloop_get_system_info();
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
rcheevos_memory_init_from_memory_map(&new_regions, &system->mmaps, console_regions);
|
||||
else
|
||||
rcheevos_memory_init_from_unmapped_memory(&new_regions, console_regions, console);
|
||||
}
|
||||
|
||||
/* determine if any valid regions were found */
|
||||
for (i = 0; i < new_regions.count; i++)
|
||||
{
|
||||
if (new_regions.data[i])
|
||||
{
|
||||
has_valid_region = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(regions, &new_regions, sizeof(*regions));
|
||||
return has_valid_region;
|
||||
}
|
||||
@@ -0,0 +1,709 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2019-2021 - Brian Weiss
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cheevos_locals.h"
|
||||
|
||||
#include "../gfx/gfx_display.h"
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
||||
#include "cheevos.h"
|
||||
|
||||
#include "../deps/rcheevos/include/rc_runtime_types.h"
|
||||
|
||||
#include "../file_path_special.h"
|
||||
#include "../menu/menu_driver.h"
|
||||
#include "../menu/menu_entries.h"
|
||||
|
||||
#include <features/features_cpu.h>
|
||||
|
||||
enum rcheevos_menuitem_bucket
|
||||
{
|
||||
RCHEEVOS_MENUITEM_BUCKET_UNKNOWN = 0,
|
||||
RCHEEVOS_MENUITEM_BUCKET_LOCKED,
|
||||
RCHEEVOS_MENUITEM_BUCKET_UNLOCKED,
|
||||
RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED,
|
||||
RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED,
|
||||
RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE,
|
||||
RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE
|
||||
};
|
||||
|
||||
static void rcheevos_menu_update_bucket(rcheevos_racheevo_t* cheevo)
|
||||
{
|
||||
cheevo->menu_progress = 0;
|
||||
|
||||
if (!cheevo->memaddr)
|
||||
{
|
||||
/* non-active unsupported achievement */
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED;
|
||||
}
|
||||
else if (!(cheevo->active & RCHEEVOS_ACTIVE_HARDCORE))
|
||||
{
|
||||
/* non-active unlocked in hardcore achievement */
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_UNLOCKED;
|
||||
}
|
||||
else
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rc_trigger_t* trigger;
|
||||
|
||||
if (!rcheevos_locals->hardcore_active && !(cheevo->active & RCHEEVOS_ACTIVE_SOFTCORE))
|
||||
{
|
||||
/* non-active unlocked in softcore achievement in softcore mode */
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_UNLOCKED;
|
||||
return;
|
||||
}
|
||||
|
||||
/* active achievement */
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_LOCKED;
|
||||
|
||||
trigger = rc_runtime_get_achievement(&rcheevos_locals->runtime, cheevo->id);
|
||||
if (trigger)
|
||||
{
|
||||
if (trigger->measured_value && trigger->measured_target)
|
||||
{
|
||||
const unsigned long clamped_value = (unsigned long)
|
||||
MIN(trigger->measured_value, trigger->measured_target);
|
||||
cheevo->menu_progress =
|
||||
(uint8_t)((clamped_value * 100) / trigger->measured_target);
|
||||
}
|
||||
|
||||
if (trigger->state == RC_TRIGGER_STATE_PRIMED)
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE;
|
||||
else if (cheevo->menu_progress >= 80)
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rcheevos_menu_update_buckets(bool cheevos_test_unofficial)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rcheevos_racheevo_t* cheevo = rcheevos_locals->patchdata.core;
|
||||
rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->patchdata.core_count;
|
||||
|
||||
while (cheevo < stop)
|
||||
{
|
||||
rcheevos_menu_update_bucket(cheevo);
|
||||
++cheevo;
|
||||
}
|
||||
|
||||
if (cheevos_test_unofficial)
|
||||
{
|
||||
cheevo = rcheevos_locals->patchdata.unofficial;
|
||||
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
|
||||
|
||||
while (cheevo < stop)
|
||||
{
|
||||
rcheevos_menu_update_bucket(cheevo);
|
||||
++cheevo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool rcheevos_menu_get_state(unsigned menu_offset, char *buffer, size_t len)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
if (menu_offset < rcheevos_locals->menuitem_count)
|
||||
{
|
||||
const rcheevos_menuitem_t* menuitem = &rcheevos_locals->menuitems[menu_offset];
|
||||
const rcheevos_racheevo_t* cheevo = menuitem->cheevo;
|
||||
if (cheevo)
|
||||
{
|
||||
if (cheevo->menu_progress)
|
||||
{
|
||||
snprintf(buffer, len, "%s - %d%%",
|
||||
msg_hash_to_str(menuitem->state_label_idx),
|
||||
cheevo->menu_progress);
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(buffer, msg_hash_to_str(menuitem->state_label_idx), len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
buffer[0] = '\0';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rcheevos_menu_get_sublabel(unsigned menu_offset, char *buffer, size_t len)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
if (menu_offset < rcheevos_locals->menuitem_count)
|
||||
{
|
||||
const rcheevos_racheevo_t* cheevo = rcheevos_locals->menuitems[menu_offset].cheevo;
|
||||
if (cheevo && buffer)
|
||||
{
|
||||
strlcpy(buffer, cheevo->description, len);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
buffer[0] = '\0';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void rcheevos_menu_reset_badges(void)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rcheevos_racheevo_t* cheevo = rcheevos_locals->patchdata.core;
|
||||
rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->patchdata.core_count;
|
||||
|
||||
while (cheevo < stop)
|
||||
{
|
||||
if (cheevo->menu_badge_texture)
|
||||
video_driver_texture_unload(&cheevo->menu_badge_texture);
|
||||
++cheevo;
|
||||
}
|
||||
|
||||
cheevo = rcheevos_locals->patchdata.unofficial;
|
||||
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
|
||||
|
||||
while (cheevo < stop)
|
||||
{
|
||||
if (cheevo->menu_badge_texture)
|
||||
video_driver_texture_unload(&cheevo->menu_badge_texture);
|
||||
++cheevo;
|
||||
}
|
||||
}
|
||||
|
||||
static rcheevos_menuitem_t* rcheevos_menu_allocate(
|
||||
rcheevos_locals_t* rcheevos_locals, rcheevos_racheevo_t* cheevo)
|
||||
{
|
||||
rcheevos_menuitem_t* menuitem;
|
||||
|
||||
if (rcheevos_locals->menuitem_count == rcheevos_locals->menuitem_capacity)
|
||||
{
|
||||
if (rcheevos_locals->menuitems)
|
||||
{
|
||||
rcheevos_menuitem_t* new_menuitems;
|
||||
rcheevos_locals->menuitem_capacity += 32;
|
||||
new_menuitems = (rcheevos_menuitem_t*)realloc(rcheevos_locals->menuitems,
|
||||
rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t));
|
||||
|
||||
if (new_menuitems)
|
||||
{
|
||||
rcheevos_locals->menuitems = new_menuitems;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* realloc failed */
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG " could not allocate space for %u menu items\n",
|
||||
rcheevos_locals->menuitem_capacity);
|
||||
rcheevos_locals->menuitem_capacity -= 32;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rcheevos_locals->menuitem_capacity = 64;
|
||||
rcheevos_locals->menuitems = (rcheevos_menuitem_t*)
|
||||
malloc(rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t));
|
||||
|
||||
if (!rcheevos_locals->menuitems)
|
||||
{
|
||||
/* malloc failed */
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG " could not allocate space for %u menu items\n",
|
||||
rcheevos_locals->menuitem_capacity);
|
||||
rcheevos_locals->menuitem_capacity = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menuitem = &rcheevos_locals->menuitems[rcheevos_locals->menuitem_count++];
|
||||
menuitem->cheevo = cheevo;
|
||||
menuitem->state_label_idx = MSG_UNKNOWN;
|
||||
return menuitem;
|
||||
}
|
||||
|
||||
static void rcheevos_menu_append_header(rcheevos_locals_t* rcheevos_locals,
|
||||
enum msg_hash_enums label)
|
||||
{
|
||||
rcheevos_menuitem_t* menuitem = rcheevos_menu_allocate(rcheevos_locals, NULL);
|
||||
if (menuitem)
|
||||
menuitem->state_label_idx = label;
|
||||
}
|
||||
|
||||
static void rcheevos_menu_update_badge(rcheevos_racheevo_t* cheevo)
|
||||
{
|
||||
bool badge_grayscale = false;
|
||||
switch (cheevo->menu_bucket)
|
||||
{
|
||||
case RCHEEVOS_MENUITEM_BUCKET_LOCKED:
|
||||
case RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED:
|
||||
case RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE:
|
||||
case RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE:
|
||||
badge_grayscale = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
badge_grayscale = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cheevo->menu_badge_texture || cheevo->menu_badge_grayscale != badge_grayscale)
|
||||
{
|
||||
uintptr_t new_badge_texture =
|
||||
rcheevos_get_badge_texture(cheevo->badge, badge_grayscale);
|
||||
|
||||
if (new_badge_texture)
|
||||
{
|
||||
if (cheevo->menu_badge_texture)
|
||||
video_driver_texture_unload(&cheevo->menu_badge_texture);
|
||||
|
||||
cheevo->menu_badge_texture = new_badge_texture;
|
||||
cheevo->menu_badge_grayscale = badge_grayscale;
|
||||
}
|
||||
/* menu_badge_grayscale is overloaded such that any value greater than 1 indicates
|
||||
* the server default image is being used */
|
||||
else if (cheevo->menu_badge_grayscale < 2)
|
||||
{
|
||||
if (cheevo->menu_badge_texture)
|
||||
video_driver_texture_unload(&cheevo->menu_badge_texture);
|
||||
|
||||
/* requested badge is not available, check for server default */
|
||||
cheevo->menu_badge_texture =
|
||||
rcheevos_get_badge_texture("00000", false);
|
||||
|
||||
if (cheevo->menu_badge_texture)
|
||||
cheevo->menu_badge_grayscale = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rcheevos_menu_append_items(rcheevos_locals_t* rcheevos_locals,
|
||||
bool cheevos_test_unofficial, enum rcheevos_menuitem_bucket bucket)
|
||||
{
|
||||
const settings_t *settings = config_get_ptr();
|
||||
rcheevos_racheevo_t* cheevo = rcheevos_locals->patchdata.core;
|
||||
rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->patchdata.core_count;
|
||||
bool processing_unofficial = false;
|
||||
const unsigned first_index = rcheevos_locals->menuitem_count;
|
||||
|
||||
do
|
||||
{
|
||||
if (cheevo == stop)
|
||||
{
|
||||
if (!cheevos_test_unofficial || processing_unofficial)
|
||||
break;
|
||||
|
||||
processing_unofficial = true;
|
||||
cheevo = rcheevos_locals->patchdata.unofficial;
|
||||
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cheevo->menu_bucket == bucket)
|
||||
{
|
||||
rcheevos_menuitem_t* menuitem = rcheevos_menu_allocate(rcheevos_locals, cheevo);
|
||||
if (!menuitem)
|
||||
return;
|
||||
|
||||
switch (cheevo->menu_bucket)
|
||||
{
|
||||
case RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED:
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNSUPPORTED_ENTRY;
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED:
|
||||
{
|
||||
/* insert the item such that the unlock times are descending */
|
||||
unsigned entry_index = rcheevos_locals->menuitem_count - 1;
|
||||
while (entry_index > first_index)
|
||||
{
|
||||
rcheevos_menuitem_t* prev_menuitem = menuitem - 1;
|
||||
if (prev_menuitem->cheevo->unlock_time >= cheevo->unlock_time)
|
||||
break;
|
||||
|
||||
memcpy(menuitem, prev_menuitem, sizeof(rcheevos_menuitem_t));
|
||||
menuitem = prev_menuitem;
|
||||
--entry_index;
|
||||
}
|
||||
|
||||
menuitem->cheevo = cheevo;
|
||||
}
|
||||
/* fallthrough to RCHEEVOS_MENUITEM_BUCKET_UNLOCKED */
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_UNLOCKED:
|
||||
if (!(cheevo->active & RCHEEVOS_ACTIVE_HARDCORE))
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY_HARDCORE;
|
||||
else
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY;
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE:
|
||||
{
|
||||
/* insert the item such that the progresses are descending */
|
||||
unsigned entry_index = rcheevos_locals->menuitem_count - 1;
|
||||
while (entry_index > first_index)
|
||||
{
|
||||
rcheevos_menuitem_t* prev_menuitem = menuitem - 1;
|
||||
if (prev_menuitem->cheevo->menu_progress >= cheevo->menu_progress)
|
||||
break;
|
||||
|
||||
memcpy(menuitem, prev_menuitem, sizeof(rcheevos_menuitem_t));
|
||||
menuitem = prev_menuitem;
|
||||
--entry_index;
|
||||
}
|
||||
|
||||
menuitem->cheevo = cheevo;
|
||||
}
|
||||
/* fallthrough to default */
|
||||
|
||||
default:
|
||||
if (processing_unofficial)
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNOFFICIAL_ENTRY;
|
||||
else if (!(cheevo->active & RCHEEVOS_ACTIVE_SOFTCORE))
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY;
|
||||
else
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ENTRY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cheevo->badge && cheevo->badge[0] && settings &&
|
||||
settings->bools.cheevos_badges_enable)
|
||||
{
|
||||
rcheevos_menu_update_badge(cheevo);
|
||||
}
|
||||
}
|
||||
|
||||
++cheevo;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
uintptr_t rcheevos_menu_get_badge_texture(unsigned menu_offset)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
if (menu_offset < rcheevos_locals->menuitem_count)
|
||||
{
|
||||
rcheevos_racheevo_t* cheevo = rcheevos_locals->menuitems[menu_offset].cheevo;
|
||||
if (cheevo)
|
||||
{
|
||||
/* if we're using the placeholder badge, check to see if the real badge
|
||||
* has become available (do this roughly once a second) */
|
||||
if (cheevo->menu_badge_grayscale >= 2)
|
||||
{
|
||||
if (++cheevo->menu_badge_grayscale == 64)
|
||||
{
|
||||
cheevo->menu_badge_grayscale = 2;
|
||||
rcheevos_menu_update_badge(cheevo);
|
||||
}
|
||||
}
|
||||
|
||||
return cheevo->menu_badge_texture;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rcheevos_menu_populate_hardcore_pause_submenu(void* data)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
menu_displaylist_info_t* info = (menu_displaylist_info_t*)data;
|
||||
const settings_t* settings = config_get_ptr();
|
||||
const bool cheevos_hardcore_mode_enable = settings->bools.cheevos_hardcore_mode_enable;
|
||||
|
||||
if (cheevos_hardcore_mode_enable && rcheevos_locals->loaded)
|
||||
{
|
||||
if (rcheevos_locals->hardcore_active)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_CANCEL),
|
||||
msg_hash_to_str(MENU_ENUM_SUBLABEL_ACHIEVEMENT_PAUSE_CANCEL),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_CANCEL,
|
||||
MENU_SETTING_ACTION_CLOSE, 0, 0);
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE,
|
||||
MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME_CANCEL),
|
||||
msg_hash_to_str(MENU_ENUM_SUBLABEL_ACHIEVEMENT_RESUME_CANCEL),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_RESUME_CANCEL,
|
||||
MENU_SETTING_ACTION_CLOSE, 0, 0);
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_RESUME),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_RESUME,
|
||||
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rcheevos_menu_populate(void* data)
|
||||
{
|
||||
menu_displaylist_info_t* info = (menu_displaylist_info_t*)data;
|
||||
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
const settings_t* settings = config_get_ptr();
|
||||
const bool cheevos_test_unofficial = settings->bools.cheevos_test_unofficial;
|
||||
unsigned num_locked = 0;
|
||||
unsigned num_unlocked = 0;
|
||||
unsigned num_recently_unlocked = 0;
|
||||
unsigned num_unsupported = 0;
|
||||
unsigned num_active_challenges = 0;
|
||||
unsigned num_almost_there = 0;
|
||||
|
||||
if (rcheevos_locals->loaded)
|
||||
{
|
||||
const retro_time_t now = cpu_features_get_time_usec();
|
||||
const retro_time_t recent_unlock_time = now - (10 * 60 * 1000000); /* 10 minutes ago */
|
||||
bool processing_unofficial = false;
|
||||
rcheevos_racheevo_t* cheevo = NULL;
|
||||
rcheevos_racheevo_t* stop = NULL;
|
||||
|
||||
/* first menu item is the Pause/Resume Hardcore option (unless hardcore is disabled) */
|
||||
if (settings->bools.cheevos_enable && settings->bools.cheevos_hardcore_mode_enable)
|
||||
{
|
||||
if (rcheevos_locals->hardcore_active)
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_MENU),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
|
||||
MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS, 0, 0);
|
||||
else
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_MENU),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
|
||||
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, 0, 0);
|
||||
}
|
||||
|
||||
/* update the bucket for each achievement */
|
||||
rcheevos_menu_update_buckets(cheevos_test_unofficial);
|
||||
|
||||
/* count items in each bucket */
|
||||
cheevo = rcheevos_locals->patchdata.core;
|
||||
stop = cheevo + rcheevos_locals->patchdata.core_count;
|
||||
|
||||
do
|
||||
{
|
||||
if (cheevo == stop)
|
||||
{
|
||||
if (!cheevos_test_unofficial || processing_unofficial)
|
||||
break;
|
||||
|
||||
processing_unofficial = true;
|
||||
cheevo = rcheevos_locals->patchdata.unofficial;
|
||||
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (cheevo->menu_bucket)
|
||||
{
|
||||
case RCHEEVOS_MENUITEM_BUCKET_UNLOCKED:
|
||||
if (cheevo->unlock_time && cheevo->unlock_time >= recent_unlock_time)
|
||||
{
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED;
|
||||
++num_recently_unlocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_unlocked;
|
||||
}
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_LOCKED:
|
||||
++num_locked;
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED:
|
||||
++num_unsupported;
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE:
|
||||
++num_active_challenges;
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE:
|
||||
++num_almost_there;
|
||||
break;
|
||||
}
|
||||
|
||||
++cheevo;
|
||||
} while(true);
|
||||
|
||||
if (!rcheevos_locals->menuitems)
|
||||
{
|
||||
/* reserve space for all achievements and up to 6 headers before we need to realloc */
|
||||
rcheevos_locals->menuitem_capacity = rcheevos_locals->patchdata.core_count + 6;
|
||||
if (cheevos_test_unofficial)
|
||||
rcheevos_locals->menuitem_capacity += rcheevos_locals->patchdata.unofficial_count;
|
||||
|
||||
rcheevos_locals->menuitems = (rcheevos_menuitem_t*)
|
||||
malloc(rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t));
|
||||
if (!rcheevos_locals->menuitems)
|
||||
rcheevos_locals->menuitem_capacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset menu */
|
||||
rcheevos_locals->menuitem_count = 0;
|
||||
|
||||
/* active challenges */
|
||||
if (num_active_challenges)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_ACTIVE_CHALLENGES_ENTRY);
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial,
|
||||
RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE);
|
||||
}
|
||||
|
||||
/* recently unlocked */
|
||||
if (num_recently_unlocked)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_RECENTLY_UNLOCKED_ENTRY);
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial,
|
||||
RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED);
|
||||
}
|
||||
|
||||
/* almost there */
|
||||
if (num_almost_there)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_ALMOST_THERE_ENTRY);
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial,
|
||||
RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE);
|
||||
}
|
||||
|
||||
/* locked */
|
||||
if (num_locked)
|
||||
{
|
||||
if (rcheevos_locals->menuitem_count > 0)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ENTRY);
|
||||
}
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial,
|
||||
RCHEEVOS_MENUITEM_BUCKET_LOCKED);
|
||||
}
|
||||
|
||||
/* unlocked */
|
||||
if (num_unlocked)
|
||||
{
|
||||
if (rcheevos_locals->menuitem_count > 0)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY);
|
||||
}
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial,
|
||||
RCHEEVOS_MENUITEM_BUCKET_UNLOCKED);
|
||||
}
|
||||
|
||||
if (rcheevos_locals->menuitem_count > 0)
|
||||
{
|
||||
/* convert to menu entries */
|
||||
rcheevos_menuitem_t* menuitem = rcheevos_locals->menuitems;
|
||||
rcheevos_menuitem_t* stop = menuitem + rcheevos_locals->menuitem_count;
|
||||
char buffer[128];
|
||||
unsigned idx = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (menuitem->cheevo)
|
||||
{
|
||||
menu_entries_append_enum(info->list, menuitem->cheevo->title,
|
||||
menuitem->cheevo->description,
|
||||
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
|
||||
MENU_SETTINGS_CHEEVOS_START + idx, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer), "----- %s -----",
|
||||
msg_hash_to_str(menuitem->state_label_idx));
|
||||
|
||||
menu_entries_append_enum(info->list, buffer, "",
|
||||
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
|
||||
MENU_SETTINGS_CHEEVOS_START + idx, 0, 0);
|
||||
}
|
||||
|
||||
++idx;
|
||||
++menuitem;
|
||||
} while (menuitem != stop);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no achievements found */
|
||||
if (!rcheevos_locals->core_supports)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE),
|
||||
MENU_ENUM_LABEL_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
else if (!rcheevos_locals->token[0])
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_LOGGED_IN),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NOT_LOGGED_IN),
|
||||
MENU_ENUM_LABEL_NOT_LOGGED_IN,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ACHIEVEMENTS_TO_DISPLAY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NO_ACHIEVEMENTS_TO_DISPLAY),
|
||||
MENU_ENUM_LABEL_NO_ACHIEVEMENTS_TO_DISPLAY,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_MENU */
|
||||
|
||||
uintptr_t rcheevos_get_badge_texture(const char *badge, bool locked)
|
||||
{
|
||||
char badge_file[24];
|
||||
char fullpath[PATH_MAX_LENGTH];
|
||||
uintptr_t tex = 0;
|
||||
|
||||
if (!badge)
|
||||
return 0;
|
||||
|
||||
snprintf(badge_file, sizeof(badge_file), "%s%s%s", badge,
|
||||
locked ? "_lock" : "", FILE_PATH_PNG_EXTENSION);
|
||||
|
||||
fill_pathname_application_special(fullpath, sizeof(fullpath),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES);
|
||||
|
||||
if (!gfx_display_reset_textures_list(badge_file, fullpath,
|
||||
&tex, TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL))
|
||||
{
|
||||
tex = 0;
|
||||
}
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
* Copyright (C) 2019-2021 - Brian Weiss
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
@@ -12,33 +13,29 @@
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __RARCH_CHEEVOS_MEMORY_H
|
||||
#define __RARCH_CHEEVOS_MEMORY_H
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_MENU_H
|
||||
#define __RARCH_CHEEVOS_MENU_H
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#define MAX_MEMORY_REGIONS 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t* data[MAX_MEMORY_REGIONS];
|
||||
size_t size[MAX_MEMORY_REGIONS];
|
||||
size_t total_size;
|
||||
unsigned count;
|
||||
} rcheevos_memory_regions_t;
|
||||
|
||||
bool rcheevos_memory_init(rcheevos_memory_regions_t* regions, int console);
|
||||
void rcheevos_memory_destroy(rcheevos_memory_regions_t* regions);
|
||||
|
||||
uint8_t* rcheevos_memory_find(const rcheevos_memory_regions_t* regions,
|
||||
unsigned address);
|
||||
void rcheevos_menu_populate(void* data);
|
||||
void rcheevos_menu_populate_hardcore_pause_submenu(void* data);
|
||||
bool rcheevos_menu_get_state(unsigned menu_offset, char* buffer, size_t buffer_size);
|
||||
bool rcheevos_menu_get_sublabel(unsigned menu_offset, char* buffer, size_t buffer_size);
|
||||
uintptr_t rcheevos_menu_get_badge_texture(unsigned menu_offset);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
#endif /* HAVE_MENU */
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_MENU_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "cheevos_parser.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "cheevos_locals.h"
|
||||
|
||||
#include <encodings/utf.h>
|
||||
#include <formats/rjson.h>
|
||||
|
||||
@@ -16,49 +16,10 @@
|
||||
#ifndef __RARCH_CHEEVOS_PARSER_H
|
||||
#define __RARCH_CHEEVOS_PARSER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <boolean.h>
|
||||
|
||||
#include <retro_common_api.h>
|
||||
#include "cheevos_locals.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* title;
|
||||
const char* description;
|
||||
const char* badge;
|
||||
const char* memaddr;
|
||||
unsigned points;
|
||||
unsigned id;
|
||||
unsigned active;
|
||||
} rcheevos_racheevo_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* title;
|
||||
const char* description;
|
||||
const char* mem;
|
||||
unsigned id;
|
||||
unsigned format;
|
||||
} rcheevos_ralboard_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* title;
|
||||
rcheevos_racheevo_t* core;
|
||||
rcheevos_racheevo_t* unofficial;
|
||||
rcheevos_ralboard_t* lboards;
|
||||
char* richpresence_script;
|
||||
|
||||
unsigned game_id;
|
||||
unsigned console_id;
|
||||
unsigned core_count;
|
||||
unsigned unofficial_count;
|
||||
unsigned lboard_count;
|
||||
} rcheevos_rapatchdata_t;
|
||||
|
||||
typedef void (*rcheevos_unlock_cb_t)(unsigned id, void* userdata);
|
||||
|
||||
int rcheevos_get_json_error(const char* json, char* token, size_t length);
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2016 - Andre Leiradella
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_UTIL_H
|
||||
#define __RARCH_CHEEVOS_UTIL_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/*****************************************************************************
|
||||
Setup - mainly for debugging
|
||||
*****************************************************************************/
|
||||
|
||||
/* Define this macro to get extra-verbose log for cheevos. */
|
||||
#define CHEEVOS_VERBOSE
|
||||
|
||||
/*****************************************************************************
|
||||
End of setup
|
||||
*****************************************************************************/
|
||||
|
||||
#define RCHEEVOS_TAG "[RCHEEVOS]: "
|
||||
#define CHEEVOS_FREE(p) do { void* q = (void*)p; if (q) free(q); } while (0)
|
||||
|
||||
#ifdef CHEEVOS_VERBOSE
|
||||
|
||||
#define CHEEVOS_LOG RARCH_LOG
|
||||
#define CHEEVOS_ERR RARCH_ERR
|
||||
|
||||
#else
|
||||
|
||||
#define CHEEVOS_LOG rcheevos_log
|
||||
#define CHEEVOS_ERR RARCH_ERR
|
||||
|
||||
void rcheevos_log(const char *fmt, ...);
|
||||
|
||||
#endif
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_UTIL_H */
|
||||
@@ -166,6 +166,7 @@ static void command_network_poll(command_t *handle)
|
||||
char buf[1024];
|
||||
|
||||
buf[0] = '\0';
|
||||
netcmd->cmd_source_len = sizeof(struct sockaddr_storage);
|
||||
ret = recvfrom(netcmd->net_fd, buf, sizeof(buf) - 1, 0,
|
||||
(struct sockaddr*)&netcmd->cmd_source,
|
||||
&netcmd->cmd_source_len);
|
||||
|
||||
+61
-6
@@ -48,6 +48,11 @@
|
||||
#include "menu/menu_screensaver.h"
|
||||
#endif
|
||||
|
||||
/* Required for 'show inputs on overlay' setting */
|
||||
#if defined(HAVE_OVERLAY)
|
||||
#include "../input/input_overlay.h"
|
||||
#endif
|
||||
|
||||
#if defined(HW_RVL)
|
||||
#define MAX_GAMMA_SETTING 30
|
||||
#elif defined(GEKKO)
|
||||
@@ -152,6 +157,8 @@
|
||||
|
||||
#define DEFAULT_CRT_SWITCH_PORCH_ADJUST 0
|
||||
|
||||
#define DEFAULT_CRT_SWITCH_HIRES_MENU true
|
||||
|
||||
#define DEFAULT_HISTORY_LIST_ENABLE true
|
||||
|
||||
#define DEFAULT_PLAYLIST_ENTRY_RENAME true
|
||||
@@ -194,16 +201,21 @@
|
||||
|
||||
/* To start in Fullscreen, or not. */
|
||||
|
||||
#if defined(HAVE_STEAM) || defined(DINGUX)
|
||||
/* Start in fullscreen mode for Steam and
|
||||
* Dingux builds */
|
||||
#if defined(HAVE_STEAM) || defined(DINGUX) || defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
/* Start in fullscreen mode for Steam and Dingux
|
||||
* WinRT and Winapi Family builds */
|
||||
#define DEFAULT_FULLSCREEN true
|
||||
#else
|
||||
#define DEFAULT_FULLSCREEN false
|
||||
#endif
|
||||
|
||||
/* To use windowed mode or not when going fullscreen. */
|
||||
#define DEFAULT_WINDOWED_FULLSCREEN true
|
||||
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
/* Do not use windowed mode for WinRT and Winapi Family builds on the Xbox UWP with fixed resolution shrinks the image into the left top corner of the screen with some libretro cores */
|
||||
#define DEFAULT_WINDOWED_FULLSCREEN false
|
||||
#else
|
||||
#define DEFAULT_WINDOWED_FULLSCREEN true
|
||||
#endif
|
||||
|
||||
/* Which monitor to prefer. 0 is any monitor, 1 and up selects
|
||||
* specific monitors, 1 being the first monitor. */
|
||||
@@ -220,11 +232,17 @@
|
||||
#if defined(DINGUX)
|
||||
#define DEFAULT_FULLSCREEN_X 320
|
||||
#define DEFAULT_FULLSCREEN_Y 240
|
||||
#elif defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
#define DEFAULT_FULLSCREEN_X 1920
|
||||
#define DEFAULT_FULLSCREEN_Y 1080
|
||||
#else
|
||||
#define DEFAULT_FULLSCREEN_X 0
|
||||
#define DEFAULT_FULLSCREEN_Y 0
|
||||
#endif
|
||||
|
||||
/* Force 4k resolution */
|
||||
#define DEFAULT_FORCE_RESOLUTION false
|
||||
|
||||
/* Number of threads to use for video recording */
|
||||
#define DEFAULT_VIDEO_RECORD_THREADS 2
|
||||
|
||||
@@ -243,6 +261,11 @@
|
||||
#endif
|
||||
#define DEFAULT_CHECK_FIRMWARE_BEFORE_LOADING false
|
||||
|
||||
/* Specifies whether to cache core info
|
||||
* into a single (compressed) file for improved
|
||||
* load times on platforms with slow IO */
|
||||
#define DEFAULT_CORE_INFO_CACHE_ENABLE true
|
||||
|
||||
/* Specifies whether to 'reload' (fork and quit)
|
||||
* RetroArch when launching content with the
|
||||
* currently loaded core
|
||||
@@ -281,6 +304,7 @@
|
||||
* Can reduce latency at cost of higher risk of stuttering.
|
||||
*/
|
||||
#define DEFAULT_FRAME_DELAY 0
|
||||
#define MAXIMUM_FRAME_DELAY 19
|
||||
|
||||
/* Inserts black frame(s) inbetween frames.
|
||||
* Useful for Higher Hz monitors (set to multiples of 60 Hz) who want to play 60 Hz
|
||||
@@ -364,8 +388,10 @@
|
||||
/* Only scale in integer steps.
|
||||
* The base size depends on system-reported geometry and aspect ratio.
|
||||
* If video_force_aspect is not set, X/Y will be integer scaled independently.
|
||||
* Overscale rounds up instead of down, default is downscale.
|
||||
*/
|
||||
#define DEFAULT_SCALE_INTEGER false
|
||||
#define DEFAULT_SCALE_INTEGER_OVERSCALE false
|
||||
|
||||
/* Controls aspect ratio handling. */
|
||||
|
||||
@@ -394,6 +420,11 @@
|
||||
* in Dingux devices */
|
||||
#define DEFAULT_DINGUX_REFRESH_RATE DINGUX_REFRESH_RATE_60HZ
|
||||
#endif
|
||||
#if defined(RS90)
|
||||
/* Sets image filtering method on the RS90
|
||||
* when integer scaling is disabled */
|
||||
#define DEFAULT_DINGUX_RS90_SOFTFILTER_TYPE DINGUX_RS90_SOFTFILTER_POINT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Save configuration file on exit. */
|
||||
@@ -713,7 +744,9 @@ static const bool default_savefiles_in_content_dir = false;
|
||||
static const bool default_systemfiles_in_content_dir = false;
|
||||
static const bool default_screenshots_in_content_dir = false;
|
||||
|
||||
#if defined(_XBOX1) || defined(__PS3__) || defined(_XBOX360) || defined(DINGUX)
|
||||
#if defined(RS90)
|
||||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_START_SELECT
|
||||
#elif defined(_XBOX1) || defined(__PS3__) || defined(_XBOX360) || defined(DINGUX)
|
||||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_L3_R3
|
||||
#elif defined(PS2) || defined(PSP)
|
||||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_HOLD_START
|
||||
@@ -734,7 +767,15 @@ static const unsigned input_backtouch_toggle = false;
|
||||
|
||||
#define DEFAULT_OVERLAY_ENABLE_AUTOPREFERRED true
|
||||
|
||||
#define DEFAULT_SHOW_PHYSICAL_INPUTS true
|
||||
#if defined(HAVE_OVERLAY)
|
||||
#if defined(RARCH_MOBILE)
|
||||
#define DEFAULT_OVERLAY_SHOW_INPUTS OVERLAY_SHOW_INPUT_TOUCHED
|
||||
#else
|
||||
#define DEFAULT_OVERLAY_SHOW_INPUTS OVERLAY_SHOW_INPUT_PHYSICAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DEFAULT_OVERLAY_SHOW_INPUTS_PORT 0
|
||||
|
||||
#define DEFAULT_ALL_USERS_CONTROL_MENU false
|
||||
|
||||
@@ -756,6 +797,8 @@ static const unsigned input_backtouch_toggle = false;
|
||||
/* Font size for on-screen messages. */
|
||||
#if defined(DINGUX)
|
||||
#define DEFAULT_FONT_SIZE 12
|
||||
#elif defined(PS2)
|
||||
#define DEFAULT_FONT_SIZE 16
|
||||
#else
|
||||
#define DEFAULT_FONT_SIZE 32
|
||||
#endif
|
||||
@@ -1185,6 +1228,10 @@ static const int default_content_favorites_size = 200;
|
||||
#define DEFAULT_PLAYLIST_SHOW_SUBLABELS true
|
||||
#endif
|
||||
|
||||
/* Show the indices of playlist entries in
|
||||
* a menu-driver-specific fashion */
|
||||
#define DEFAULT_PLAYLIST_SHOW_ENTRY_IDX true
|
||||
|
||||
#define DEFAULT_PLAYLIST_FUZZY_ARCHIVE_MATCH false
|
||||
|
||||
#define DEFAULT_PLAYLIST_PORTABLE_PATHS false
|
||||
@@ -1284,6 +1331,14 @@ static const unsigned menu_left_thumbnails_default = 0;
|
||||
static const unsigned gfx_thumbnail_upscale_threshold = 0;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
#if defined(RS90)
|
||||
/* The RS-90 has a hardware clock that is neither
|
||||
* configurable nor persistent, rendering it useless.
|
||||
* We therefore hide it in the menu by default. */
|
||||
#define DEFAULT_MENU_TIMEDATE_ENABLE false
|
||||
#else
|
||||
#define DEFAULT_MENU_TIMEDATE_ENABLE true
|
||||
#endif
|
||||
#define DEFAULT_MENU_TIMEDATE_STYLE MENU_TIMEDATE_STYLE_DDMM_HM
|
||||
#define DEFAULT_MENU_TIMEDATE_DATE_SEPARATOR MENU_TIMEDATE_DATE_SEPARATOR_HYPHEN
|
||||
#endif
|
||||
|
||||
@@ -195,7 +195,7 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, RETROK_UNKNOWN,
|
||||
RARCH_LIGHTGUN_TRIGGER, NO_BTN, NO_BTN, 0,
|
||||
RARCH_LIGHTGUN_TRIGGER, RETRO_DEVICE_ID_MOUSE_LEFT, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
@@ -750,7 +750,7 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, RETROK_UNKNOWN,
|
||||
RARCH_LIGHTGUN_TRIGGER, NO_BTN, NO_BTN, 0,
|
||||
RARCH_LIGHTGUN_TRIGGER, RETRO_DEVICE_ID_MOUSE_LEFT, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
@@ -1304,7 +1304,7 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, RETROK_UNKNOWN,
|
||||
RARCH_LIGHTGUN_TRIGGER, NO_BTN, NO_BTN, 0,
|
||||
RARCH_LIGHTGUN_TRIGGER, RETRO_DEVICE_ID_MOUSE_LEFT, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
@@ -1872,7 +1872,7 @@ static const struct retro_keybind retro_keybinds_rest[] = {
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, RETROK_UNKNOWN,
|
||||
RARCH_LIGHTGUN_TRIGGER, NO_BTN, NO_BTN, 0,
|
||||
RARCH_LIGHTGUN_TRIGGER, RETRO_DEVICE_ID_MOUSE_LEFT, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
|
||||
@@ -350,6 +350,12 @@
|
||||
#define SUPPORTS_CORETEXT false
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK
|
||||
#define SUPPORTS_CHECK true
|
||||
#else
|
||||
#define SUPPORTS_CHECK false
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && !defined(GLOBAL_CONFIG_DIR)
|
||||
#if defined(__HAIKU__)
|
||||
#define GLOBAL_CONFIG_DIR "/system/settings"
|
||||
|
||||
+147
-38
@@ -70,6 +70,7 @@ enum video_driver_enum
|
||||
VIDEO_SDL,
|
||||
VIDEO_SDL2,
|
||||
VIDEO_SDL_DINGUX,
|
||||
VIDEO_SDL_RS90,
|
||||
VIDEO_EXT,
|
||||
VIDEO_WII,
|
||||
VIDEO_WIIU,
|
||||
@@ -93,6 +94,7 @@ enum video_driver_enum
|
||||
VIDEO_GDI,
|
||||
VIDEO_VGA,
|
||||
VIDEO_FPGA,
|
||||
VIDEO_RSX,
|
||||
VIDEO_NULL
|
||||
};
|
||||
|
||||
@@ -212,6 +214,7 @@ enum bluetooth_driver_enum
|
||||
enum wifi_driver_enum
|
||||
{
|
||||
WIFI_CONNMANCTL = BLUETOOTH_NULL + 1,
|
||||
WIFI_NMCLI,
|
||||
WIFI_NULL
|
||||
};
|
||||
|
||||
@@ -258,6 +261,9 @@ static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL;
|
||||
#else
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_METAL;
|
||||
#endif
|
||||
#elif defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
/* Lets default to D3D11 in UWP, even when its compiled with ANGLE, since ANGLE is just calling D3D anyway.*/
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D11;
|
||||
#elif defined(HAVE_OPENGL1) && defined(_MSC_VER) && (_MSC_VER <= 1600)
|
||||
/* On Windows XP and earlier, use gl1 by default
|
||||
* (regular opengl has compatibility issues with
|
||||
@@ -306,7 +312,11 @@ static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL;
|
||||
#elif defined(HAVE_SDL2)
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL2;
|
||||
#elif defined(HAVE_SDL_DINGUX)
|
||||
#if defined(RS90)
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL_RS90;
|
||||
#else
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL_DINGUX;
|
||||
#endif
|
||||
#elif defined(_WIN32) && !defined(_XBOX)
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GDI;
|
||||
#elif defined(DJGPP)
|
||||
@@ -315,6 +325,8 @@ static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VGA;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_FPGA;
|
||||
#elif defined(HAVE_DYLIB) && !defined(ANDROID)
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_EXT;
|
||||
#elif defined(__PSL1GHT__)
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_RSX;
|
||||
#else
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_NULL;
|
||||
#endif
|
||||
@@ -335,9 +347,13 @@ static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PS3;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_CTR;
|
||||
#elif defined(SWITCH)
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SWITCH;
|
||||
#elif defined(DINGUX_BETA) && defined(HAVE_ALSA)
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ALSA;
|
||||
#elif defined(DINGUX) && defined(HAVE_AL)
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_AL;
|
||||
#elif defined(HAVE_PULSE)
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PULSE;
|
||||
#elif defined(HAVE_ALSA) && defined(HAVE_VIDEOCORE)
|
||||
#elif defined(HAVE_ALSA) && defined(HAVE_THREADS)
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ALSATHREAD;
|
||||
#elif defined(HAVE_ALSA)
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ALSA;
|
||||
@@ -379,7 +395,9 @@ static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_EXT;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_NULL;
|
||||
#endif
|
||||
|
||||
#if defined(PSP) || defined(EMSCRIPTEN)
|
||||
#if defined(RS90)
|
||||
static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_NEAREST;
|
||||
#elif defined(PSP) || defined(EMSCRIPTEN)
|
||||
static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_CC;
|
||||
#else
|
||||
static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_SINC;
|
||||
@@ -393,7 +411,7 @@ static const enum record_driver_enum RECORD_DEFAULT_DRIVER = RECORD_NULL;
|
||||
|
||||
#ifdef HAVE_WINMM
|
||||
static const enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_WINMM;
|
||||
#elif defined(HAVE_ALSA) && !defined(HAVE_HAKCHI) && !defined(HAVE_SEGAM)
|
||||
#elif defined(HAVE_ALSA) && !defined(HAVE_HAKCHI) && !defined(HAVE_SEGAM) && !defined(DINGUX)
|
||||
static const enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_ALSA;
|
||||
#else
|
||||
static const enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_NULL;
|
||||
@@ -465,7 +483,7 @@ static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_WIIU;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_XDK;
|
||||
#elif defined(PS2)
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS2;
|
||||
#elif defined(__PS3__) && !defined(__PSL1GHT__)
|
||||
#elif defined(__PS3__) || defined(__PSL1GHT__)
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS3;
|
||||
#elif defined(ORBIS)
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS4;
|
||||
@@ -843,6 +861,8 @@ const char *config_get_default_video(void)
|
||||
return "xvideo";
|
||||
case VIDEO_SDL_DINGUX:
|
||||
return "sdl_dingux";
|
||||
case VIDEO_SDL_RS90:
|
||||
return "sdl_rs90";
|
||||
case VIDEO_SDL:
|
||||
return "sdl";
|
||||
case VIDEO_SDL2:
|
||||
@@ -867,6 +887,8 @@ const char *config_get_default_video(void)
|
||||
return "vga";
|
||||
case VIDEO_FPGA:
|
||||
return "fpga";
|
||||
case VIDEO_RSX:
|
||||
return "rsx";
|
||||
case VIDEO_NULL:
|
||||
break;
|
||||
}
|
||||
@@ -1085,6 +1107,8 @@ const char *config_get_default_wifi(void)
|
||||
{
|
||||
case WIFI_CONNMANCTL:
|
||||
return "connmanctl";
|
||||
case WIFI_NMCLI:
|
||||
return "nmcli";
|
||||
case WIFI_NULL:
|
||||
break;
|
||||
}
|
||||
@@ -1279,6 +1303,10 @@ static struct config_array_setting *populate_settings_array(settings_t *settings
|
||||
SETTING_ARRAY("discord_app_id", settings->arrays.discord_app_id, true, DEFAULT_DISCORD_APP_ID, true);
|
||||
SETTING_ARRAY("ai_service_url", settings->arrays.ai_service_url, true, DEFAULT_AI_SERVICE_URL, true);
|
||||
SETTING_ARRAY("crt_switch_timings", settings->arrays.crt_switch_timings, false, NULL, true);
|
||||
#ifdef HAVE_LAKKA
|
||||
SETTING_ARRAY("cpu_main_gov", settings->arrays.cpu_main_gov, false, NULL, true);
|
||||
SETTING_ARRAY("cpu_menu_gov", settings->arrays.cpu_menu_gov, false, NULL, true);
|
||||
#endif
|
||||
|
||||
*size = count;
|
||||
|
||||
@@ -1448,6 +1476,7 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
SETTING_BOOL("frame_time_counter_reset_after_load_state", &settings->bools.frame_time_counter_reset_after_load_state, true, false, false);
|
||||
SETTING_BOOL("frame_time_counter_reset_after_save_state", &settings->bools.frame_time_counter_reset_after_save_state, true, false, false);
|
||||
SETTING_BOOL("crt_switch_resolution_use_custom_refresh_rate", &settings->bools.crt_switch_custom_refresh_enable, true, false, false);
|
||||
SETTING_BOOL("crt_switch_hires_menu", &settings->bools.crt_switch_hires_menu, true, false, true);
|
||||
SETTING_BOOL("ui_companion_start_on_boot", &settings->bools.ui_companion_start_on_boot, true, ui_companion_start_on_boot, false);
|
||||
SETTING_BOOL("ui_companion_enable", &settings->bools.ui_companion_enable, true, ui_companion_enable, false);
|
||||
SETTING_BOOL("ui_companion_toggle", &settings->bools.ui_companion_toggle, false, ui_companion_toggle, false);
|
||||
@@ -1485,6 +1514,7 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
SETTING_BOOL("input_descriptor_hide_unbound", &settings->bools.input_descriptor_hide_unbound, true, input_descriptor_hide_unbound, false);
|
||||
SETTING_BOOL("load_dummy_on_core_shutdown", &settings->bools.load_dummy_on_core_shutdown, true, DEFAULT_LOAD_DUMMY_ON_CORE_SHUTDOWN, false);
|
||||
SETTING_BOOL("check_firmware_before_loading", &settings->bools.check_firmware_before_loading, true, DEFAULT_CHECK_FIRMWARE_BEFORE_LOADING, false);
|
||||
SETTING_BOOL("core_info_cache_enable", &settings->bools.core_info_cache_enable, true, DEFAULT_CORE_INFO_CACHE_ENABLE, false);
|
||||
#ifndef HAVE_DYNAMIC
|
||||
SETTING_BOOL("always_reload_core_on_run_content", &settings->bools.always_reload_core_on_run_content, true, DEFAULT_ALWAYS_RELOAD_CORE_ON_RUN_CONTENT, false);
|
||||
#endif
|
||||
@@ -1516,6 +1546,7 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
SETTING_BOOL("video_windowed_fullscreen", &settings->bools.video_windowed_fullscreen, true, DEFAULT_WINDOWED_FULLSCREEN, false);
|
||||
SETTING_BOOL("video_crop_overscan", &settings->bools.video_crop_overscan, true, DEFAULT_CROP_OVERSCAN, false);
|
||||
SETTING_BOOL("video_scale_integer", &settings->bools.video_scale_integer, true, DEFAULT_SCALE_INTEGER, false);
|
||||
SETTING_BOOL("video_scale_integer_overscale", &settings->bools.video_scale_integer_overscale, true, DEFAULT_SCALE_INTEGER_OVERSCALE, false);
|
||||
SETTING_BOOL("video_smooth", &settings->bools.video_smooth, true, DEFAULT_VIDEO_SMOOTH, false);
|
||||
SETTING_BOOL("video_ctx_scaling", &settings->bools.video_ctx_scaling, true, DEFAULT_VIDEO_CTX_SCALING, false);
|
||||
SETTING_BOOL("video_force_aspect", &settings->bools.video_force_aspect, true, DEFAULT_FORCE_ASPECT, false);
|
||||
@@ -1527,6 +1558,9 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
SETTING_BOOL("auto_screenshot_filename", &settings->bools.auto_screenshot_filename, true, DEFAULT_AUTO_SCREENSHOT_FILENAME, false);
|
||||
SETTING_BOOL("video_force_srgb_disable", &settings->bools.video_force_srgb_disable, true, false, false);
|
||||
SETTING_BOOL("video_fullscreen", &settings->bools.video_fullscreen, true, DEFAULT_FULLSCREEN, false);
|
||||
#ifdef __WINRT__
|
||||
SETTING_BOOL("video_force_resolution", &settings->bools.video_force_resolution, true, DEFAULT_FORCE_RESOLUTION, false);
|
||||
#endif
|
||||
SETTING_BOOL("bundle_assets_extract_enable", &settings->bools.bundle_assets_extract_enable, true, DEFAULT_BUNDLE_ASSETS_EXTRACT_ENABLE, false);
|
||||
SETTING_BOOL("video_vsync", &settings->bools.video_vsync, true, DEFAULT_VSYNC, false);
|
||||
SETTING_BOOL("video_adaptive_vsync", &settings->bools.video_adaptive_vsync, true, DEFAULT_ADAPTIVE_VSYNC, false);
|
||||
@@ -1593,7 +1627,7 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
SETTING_BOOL("menu_insert_disk_resume", &settings->bools.menu_insert_disk_resume, true, DEFAULT_MENU_INSERT_DISK_RESUME, false);
|
||||
SETTING_BOOL("menu_mouse_enable", &settings->bools.menu_mouse_enable, true, DEFAULT_MOUSE_ENABLE, false);
|
||||
SETTING_BOOL("menu_pointer_enable", &settings->bools.menu_pointer_enable, true, DEFAULT_POINTER_ENABLE, false);
|
||||
SETTING_BOOL("menu_timedate_enable", &settings->bools.menu_timedate_enable, true, true, false);
|
||||
SETTING_BOOL("menu_timedate_enable", &settings->bools.menu_timedate_enable, true, DEFAULT_MENU_TIMEDATE_ENABLE, false);
|
||||
SETTING_BOOL("menu_battery_level_enable", &settings->bools.menu_battery_level_enable, true, true, false);
|
||||
SETTING_BOOL("menu_core_enable", &settings->bools.menu_core_enable, true, true, false);
|
||||
SETTING_BOOL("menu_show_sublabels", &settings->bools.menu_show_sublabels, true, menu_show_sublabels, false);
|
||||
@@ -1726,6 +1760,7 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
SETTING_BOOL("cheevos_enable", &settings->bools.cheevos_enable, true, DEFAULT_CHEEVOS_ENABLE, false);
|
||||
SETTING_BOOL("cheevos_test_unofficial", &settings->bools.cheevos_test_unofficial, true, false, false);
|
||||
SETTING_BOOL("cheevos_hardcore_mode_enable", &settings->bools.cheevos_hardcore_mode_enable, true, false, false);
|
||||
SETTING_BOOL("cheevos_challenge_indicators", &settings->bools.cheevos_challenge_indicators, true, true, false);
|
||||
SETTING_BOOL("cheevos_richpresence_enable", &settings->bools.cheevos_richpresence_enable, true, true, false);
|
||||
SETTING_BOOL("cheevos_unlock_sound_enable", &settings->bools.cheevos_unlock_sound_enable, true, false, false);
|
||||
SETTING_BOOL("cheevos_verbose_enable", &settings->bools.cheevos_verbose_enable, true, false, false);
|
||||
@@ -1736,7 +1771,6 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
#ifdef HAVE_OVERLAY
|
||||
SETTING_BOOL("input_overlay_enable", &settings->bools.input_overlay_enable, true, config_overlay_enable_default(), false);
|
||||
SETTING_BOOL("input_overlay_enable_autopreferred", &settings->bools.input_overlay_enable_autopreferred, true, DEFAULT_OVERLAY_ENABLE_AUTOPREFERRED, false);
|
||||
SETTING_BOOL("input_overlay_show_physical_inputs", &settings->bools.input_overlay_show_physical_inputs, true, DEFAULT_SHOW_PHYSICAL_INPUTS, false);
|
||||
SETTING_BOOL("input_overlay_hide_in_menu", &settings->bools.input_overlay_hide_in_menu, true, DEFAULT_OVERLAY_HIDE_IN_MENU, false);
|
||||
SETTING_BOOL("input_overlay_hide_when_gamepad_connected", &settings->bools.input_overlay_hide_when_gamepad_connected, true, DEFAULT_OVERLAY_HIDE_WHEN_GAMEPAD_CONNECTED, false);
|
||||
SETTING_BOOL("input_overlay_show_mouse_cursor", &settings->bools.input_overlay_show_mouse_cursor, true, DEFAULT_OVERLAY_SHOW_MOUSE_CURSOR, false);
|
||||
@@ -1810,6 +1844,7 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
SETTING_BOOL("content_runtime_log", &settings->bools.content_runtime_log, true, DEFAULT_CONTENT_RUNTIME_LOG, false);
|
||||
SETTING_BOOL("content_runtime_log_aggregate", &settings->bools.content_runtime_log_aggregate, true, DEFAULT_CONTENT_RUNTIME_LOG_AGGREGATE, false);
|
||||
SETTING_BOOL("playlist_show_sublabels", &settings->bools.playlist_show_sublabels, true, DEFAULT_PLAYLIST_SHOW_SUBLABELS, false);
|
||||
SETTING_BOOL("playlist_show_entry_idx", &settings->bools.playlist_show_entry_idx, true, DEFAULT_PLAYLIST_SHOW_ENTRY_IDX, false);
|
||||
SETTING_BOOL("playlist_sort_alphabetical", &settings->bools.playlist_sort_alphabetical, true, DEFAULT_PLAYLIST_SORT_ALPHABETICAL, false);
|
||||
SETTING_BOOL("playlist_fuzzy_archive_match", &settings->bools.playlist_fuzzy_archive_match, true, DEFAULT_PLAYLIST_FUZZY_ARCHIVE_MATCH, false);
|
||||
SETTING_BOOL("playlist_portable_paths", &settings->bools.playlist_portable_paths, true, DEFAULT_PLAYLIST_PORTABLE_PATHS, false);
|
||||
@@ -2023,7 +2058,7 @@ static struct config_uint_setting *populate_settings_uint(
|
||||
SETTING_UINT("ozone_menu_color_theme", &settings->uints.menu_ozone_color_theme, true, DEFAULT_OZONE_COLOR_THEME, false);
|
||||
#endif
|
||||
#endif
|
||||
SETTING_UINT("audio_out_rate", &settings->uints.audio_out_rate, true, DEFAULT_OUTPUT_RATE, false);
|
||||
SETTING_UINT("audio_out_rate", &settings->uints.audio_output_sample_rate, true, DEFAULT_OUTPUT_RATE, false);
|
||||
SETTING_UINT("custom_viewport_width", &settings->video_viewport_custom.width, false, 0 /* TODO */, false);
|
||||
SETTING_UINT("crt_switch_resolution_super", &settings->uints.crt_switch_resolution_super, true, DEFAULT_CRT_SWITCH_RESOLUTION_SUPER, false);
|
||||
SETTING_UINT("custom_viewport_height", &settings->video_viewport_custom.height, false, 0 /* TODO */, false);
|
||||
@@ -2060,7 +2095,12 @@ static struct config_uint_setting *populate_settings_uint(
|
||||
SETTING_UINT("bundle_assets_extract_version_current", &settings->uints.bundle_assets_extract_version_current, true, 0, false);
|
||||
#endif
|
||||
SETTING_UINT("bundle_assets_extract_last_version", &settings->uints.bundle_assets_extract_last_version, true, 0, false);
|
||||
SETTING_UINT("input_overlay_show_physical_inputs_port", &settings->uints.input_overlay_show_physical_inputs_port, true, 0, false);
|
||||
|
||||
#if defined(HAVE_OVERLAY)
|
||||
SETTING_UINT("input_overlay_show_inputs", &settings->uints.input_overlay_show_inputs, true, DEFAULT_OVERLAY_SHOW_INPUTS, false);
|
||||
SETTING_UINT("input_overlay_show_inputs_port", &settings->uints.input_overlay_show_inputs_port, true, DEFAULT_OVERLAY_SHOW_INPUTS_PORT, false);
|
||||
#endif
|
||||
|
||||
SETTING_UINT("video_msg_bgcolor_red", &settings->uints.video_msg_bgcolor_red, true, message_bgcolor_red, false);
|
||||
SETTING_UINT("video_msg_bgcolor_green", &settings->uints.video_msg_bgcolor_green, true, message_bgcolor_green, false);
|
||||
SETTING_UINT("video_msg_bgcolor_blue", &settings->uints.video_msg_bgcolor_blue, true, message_bgcolor_blue, false);
|
||||
@@ -2097,6 +2137,9 @@ static struct config_uint_setting *populate_settings_uint(
|
||||
#if defined(DINGUX_BETA)
|
||||
SETTING_UINT("video_dingux_refresh_rate", &settings->uints.video_dingux_refresh_rate, true, DEFAULT_DINGUX_REFRESH_RATE, false);
|
||||
#endif
|
||||
#if defined(RS90)
|
||||
SETTING_UINT("video_dingux_rs90_softfilter_type", &settings->uints.video_dingux_rs90_softfilter_type, true, DEFAULT_DINGUX_RS90_SOFTFILTER_TYPE, false);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
@@ -2112,6 +2155,12 @@ static struct config_uint_setting *populate_settings_uint(
|
||||
|
||||
SETTING_UINT("video_black_frame_insertion", &settings->uints.video_black_frame_insertion, true, DEFAULT_BLACK_FRAME_INSERTION, false);
|
||||
|
||||
#ifdef HAVE_LAKKA
|
||||
SETTING_UINT("cpu_scaling_mode", &settings->uints.cpu_scaling_mode, true, 0, false);
|
||||
SETTING_UINT("cpu_min_freq", &settings->uints.cpu_min_freq, true, 1, false);
|
||||
SETTING_UINT("cpu_max_freq", &settings->uints.cpu_max_freq, true, ~0U, false);
|
||||
#endif
|
||||
|
||||
*size = count;
|
||||
|
||||
return tmp;
|
||||
@@ -2406,10 +2455,8 @@ void config_set_defaults(void *data)
|
||||
#endif
|
||||
|
||||
input_config_reset();
|
||||
#ifdef HAVE_CONFIGFILE
|
||||
input_remapping_deinit();
|
||||
input_remapping_set_defaults();
|
||||
#endif
|
||||
input_remapping_set_defaults(false);
|
||||
|
||||
/* Verify that binds are in proper order. */
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
@@ -2432,7 +2479,7 @@ void config_set_defaults(void *data)
|
||||
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
{
|
||||
settings->uints.input_joypad_map[i] = i;
|
||||
settings->uints.input_joypad_index[i] = i;
|
||||
#ifdef SWITCH /* Switch prefered default dpad mode */
|
||||
settings->uints.input_analog_dpad_mode[i] = ANALOG_DPAD_LSTICK;
|
||||
#else
|
||||
@@ -3167,7 +3214,7 @@ static bool config_load_file(global_t *global,
|
||||
buf[0] = '\0';
|
||||
|
||||
snprintf(buf, sizeof(buf), "input_player%u_joypad_index", i + 1);
|
||||
CONFIG_GET_INT_BASE(conf, settings, uints.input_joypad_map[i], buf);
|
||||
CONFIG_GET_INT_BASE(conf, settings, uints.input_joypad_index[i], buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "input_player%u_analog_dpad_mode", i + 1);
|
||||
CONFIG_GET_INT_BASE(conf, settings, uints.input_analog_dpad_mode[i], buf);
|
||||
@@ -3251,8 +3298,8 @@ static bool config_load_file(global_t *global,
|
||||
if (settings->uints.video_hard_sync_frames > 3)
|
||||
settings->uints.video_hard_sync_frames = 3;
|
||||
|
||||
if (settings->uints.video_frame_delay > 15)
|
||||
settings->uints.video_frame_delay = 15;
|
||||
if (settings->uints.video_frame_delay > MAXIMUM_FRAME_DELAY)
|
||||
settings->uints.video_frame_delay = MAXIMUM_FRAME_DELAY;
|
||||
|
||||
settings->uints.video_swap_interval = MAX(settings->uints.video_swap_interval, 1);
|
||||
settings->uints.video_swap_interval = MIN(settings->uints.video_swap_interval, 4);
|
||||
@@ -3641,20 +3688,23 @@ bool config_load_override(void *data)
|
||||
{
|
||||
char temp_path[PATH_MAX_LENGTH];
|
||||
|
||||
temp_path[0] = '\0';
|
||||
|
||||
RARCH_LOG("[Overrides]: Content dir-specific overrides found at \"%s\".\n",
|
||||
content_path);
|
||||
|
||||
if (should_append)
|
||||
{
|
||||
RARCH_LOG("[Overrides]: Content dir-specific overrides stacking on top of previous overrides.\n");
|
||||
strlcpy(temp_path, path_get(RARCH_PATH_CONFIG_APPEND), sizeof(temp_path));
|
||||
strlcat(temp_path, "|", sizeof(temp_path));
|
||||
strlcat(temp_path, content_path, sizeof(temp_path));
|
||||
snprintf(temp_path, sizeof(temp_path),
|
||||
"%s|%s",
|
||||
path_get(RARCH_PATH_CONFIG_APPEND),
|
||||
content_path
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_path[0] = '\0';
|
||||
strlcpy(temp_path, content_path, sizeof(temp_path));
|
||||
}
|
||||
|
||||
path_set(RARCH_PATH_CONFIG_APPEND, temp_path);
|
||||
|
||||
@@ -3670,20 +3720,23 @@ bool config_load_override(void *data)
|
||||
{
|
||||
char temp_path[PATH_MAX_LENGTH];
|
||||
|
||||
temp_path[0] = '\0';
|
||||
|
||||
RARCH_LOG("[Overrides]: Game-specific overrides found at \"%s\".\n",
|
||||
game_path);
|
||||
|
||||
if (should_append)
|
||||
{
|
||||
RARCH_LOG("[Overrides]: Game-specific overrides stacking on top of previous overrides.\n");
|
||||
strlcpy(temp_path, path_get(RARCH_PATH_CONFIG_APPEND), sizeof(temp_path));
|
||||
strlcat(temp_path, "|", sizeof(temp_path));
|
||||
strlcat(temp_path, game_path, sizeof(temp_path));
|
||||
snprintf(temp_path, sizeof(temp_path),
|
||||
"%s|%s",
|
||||
path_get(RARCH_PATH_CONFIG_APPEND),
|
||||
game_path
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_path[0] = '\0';
|
||||
strlcpy(temp_path, game_path, sizeof(temp_path));
|
||||
}
|
||||
|
||||
path_set(RARCH_PATH_CONFIG_APPEND, temp_path);
|
||||
|
||||
@@ -3821,9 +3874,7 @@ bool config_load_remap(const char *directory_input_remapping,
|
||||
FILE_PATH_REMAP_EXTENSION,
|
||||
sizeof(game_path));
|
||||
|
||||
#ifdef HAVE_CONFIGFILE
|
||||
input_remapping_set_defaults();
|
||||
#endif
|
||||
input_remapping_set_defaults(false);
|
||||
|
||||
/* If a game remap file exists, load it. */
|
||||
if ((new_conf = config_file_new_from_path_to_string(game_path)))
|
||||
@@ -4194,7 +4245,7 @@ bool config_save_file(const char *path)
|
||||
snprintf(cfg, sizeof(cfg), "input_device_p%u", i + 1);
|
||||
config_set_int(conf, cfg, settings->uints.input_device[i]);
|
||||
snprintf(cfg, sizeof(cfg), "input_player%u_joypad_index", i + 1);
|
||||
config_set_int(conf, cfg, settings->uints.input_joypad_map[i]);
|
||||
config_set_int(conf, cfg, settings->uints.input_joypad_index[i]);
|
||||
snprintf(cfg, sizeof(cfg), "input_libretro_device_p%u", i + 1);
|
||||
config_set_int(conf, cfg, input_config_get_device(i));
|
||||
snprintf(cfg, sizeof(cfg), "input_player%u_analog_dpad_mode", i + 1);
|
||||
@@ -4457,11 +4508,11 @@ bool config_save_overrides(enum override_type type, void *data)
|
||||
config_set_int(conf, cfg, overrides->uints.input_device[i]);
|
||||
}
|
||||
|
||||
if (settings->uints.input_joypad_map[i]
|
||||
!= overrides->uints.input_joypad_map[i])
|
||||
if (settings->uints.input_joypad_index[i]
|
||||
!= overrides->uints.input_joypad_index[i])
|
||||
{
|
||||
snprintf(cfg, sizeof(cfg), "input_player%u_joypad_index", i + 1);
|
||||
config_set_int(conf, cfg, overrides->uints.input_joypad_map[i]);
|
||||
config_set_int(conf, cfg, overrides->uints.input_joypad_index[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4574,7 +4625,7 @@ bool input_remapping_load_file(void *data, const char *path)
|
||||
if (!string_is_empty(global->name.remapfile))
|
||||
{
|
||||
input_remapping_deinit();
|
||||
input_remapping_set_defaults();
|
||||
input_remapping_set_defaults(false);
|
||||
}
|
||||
global->name.remapfile = strdup(path);
|
||||
|
||||
@@ -4582,9 +4633,6 @@ bool input_remapping_load_file(void *data, const char *path)
|
||||
{
|
||||
char s1[32], s2[32], s3[32];
|
||||
|
||||
global->old_analog_dpad_mode[i] = settings->uints.input_analog_dpad_mode[i];
|
||||
global->old_libretro_device[i] = settings->uints.input_libretro_device[i];
|
||||
|
||||
s1[0] = '\0';
|
||||
s2[0] = '\0';
|
||||
s3[0] = '\0';
|
||||
@@ -4629,9 +4677,12 @@ bool input_remapping_load_file(void *data, const char *path)
|
||||
else
|
||||
{
|
||||
char stk_ident[128];
|
||||
char key_ident[128];
|
||||
int stk_remap = -1;
|
||||
int key_remap = -1;
|
||||
|
||||
stk_ident[0] = '\0';
|
||||
key_ident[0] = '\0';
|
||||
|
||||
fill_pathname_join_delim(stk_ident, s3,
|
||||
key_string, '$', sizeof(stk_ident));
|
||||
@@ -4650,6 +4701,15 @@ bool input_remapping_load_file(void *data, const char *path)
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.input_remap_ids[i][j], stk_remap);
|
||||
}
|
||||
|
||||
fill_pathname_join_delim(key_ident, s2,
|
||||
key_string, '_', sizeof(key_ident));
|
||||
|
||||
if (!config_get_int(conf, key_ident, &key_remap))
|
||||
key_remap = RETROK_UNKNOWN;
|
||||
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.input_keymapper_ids[i][j], key_remap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4658,8 +4718,18 @@ bool input_remapping_load_file(void *data, const char *path)
|
||||
|
||||
snprintf(s1, sizeof(s1), "input_libretro_device_p%u", i + 1);
|
||||
CONFIG_GET_INT_BASE(conf, settings, uints.input_libretro_device[i], s1);
|
||||
|
||||
snprintf(s1, sizeof(s1), "input_remap_port_p%u", i + 1);
|
||||
CONFIG_GET_INT_BASE(conf, settings, uints.input_remap_ports[i], s1);
|
||||
}
|
||||
|
||||
input_remapping_update_port_map();
|
||||
|
||||
/* Whenever a remap file is loaded, subsequent
|
||||
* changes to global remap-related parameters
|
||||
* must be reset at the next core deinitialisation */
|
||||
input_remapping_enable_global_config_restore();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4698,14 +4768,38 @@ bool input_remapping_save_file(const char *path)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < max_users; i++)
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
{
|
||||
char s1[32], s2[32], s3[32];
|
||||
bool skip_port = true;
|
||||
char s1[32];
|
||||
char s2[32];
|
||||
char s3[32];
|
||||
|
||||
s1[0] = '\0';
|
||||
s2[0] = '\0';
|
||||
s3[0] = '\0';
|
||||
|
||||
/* We must include all mapped ports + all those
|
||||
* with an index less than max_users */
|
||||
if (i < max_users)
|
||||
skip_port = false;
|
||||
else
|
||||
{
|
||||
/* Check whether current port is mapped
|
||||
* to an input device */
|
||||
for (j = 0; j < max_users; j++)
|
||||
{
|
||||
if (i == settings->uints.input_remap_ports[j])
|
||||
{
|
||||
skip_port = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_port)
|
||||
continue;
|
||||
|
||||
snprintf(s1, sizeof(s1), "input_player%u_btn", i + 1);
|
||||
snprintf(s2, sizeof(s2), "input_player%u_key", i + 1);
|
||||
snprintf(s3, sizeof(s3), "input_player%u_stk", i + 1);
|
||||
@@ -4747,6 +4841,7 @@ bool input_remapping_save_file(const char *path)
|
||||
{
|
||||
char stk_ident[128];
|
||||
unsigned remap_id = settings->uints.input_remap_ids[i][j];
|
||||
unsigned keymap_id = settings->uints.input_keymapper_ids[i][j];
|
||||
const char *key_string = key_strings[j];
|
||||
stk_ident[0] = '\0';
|
||||
fill_pathname_join_delim(stk_ident, s3,
|
||||
@@ -4763,12 +4858,26 @@ bool input_remapping_save_file(const char *path)
|
||||
config_set_int(conf, stk_ident,
|
||||
settings->uints.input_remap_ids[i][j]);
|
||||
}
|
||||
|
||||
if (keymap_id != RETROK_UNKNOWN)
|
||||
{
|
||||
char key_ident[128];
|
||||
key_ident[0] = '\0';
|
||||
fill_pathname_join_delim(key_ident, s2,
|
||||
key_string, '_', sizeof(key_ident));
|
||||
config_set_int(conf, key_ident,
|
||||
settings->uints.input_keymapper_ids[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(s1, sizeof(s1), "input_libretro_device_p%u", i + 1);
|
||||
config_set_int(conf, s1, input_config_get_device(i));
|
||||
|
||||
snprintf(s1, sizeof(s1), "input_player%u_analog_dpad_mode", i + 1);
|
||||
config_set_int(conf, s1, settings->uints.input_analog_dpad_mode[i]);
|
||||
|
||||
snprintf(s1, sizeof(s1), "input_remap_port_p%u", i + 1);
|
||||
config_set_int(conf, s1, settings->uints.input_remap_ports[i]);
|
||||
}
|
||||
|
||||
ret = config_file_write(conf, remap_file, true);
|
||||
|
||||
+25
-7
@@ -67,7 +67,9 @@ enum crt_switch_type
|
||||
{
|
||||
CRT_SWITCH_NONE = 0,
|
||||
CRT_SWITCH_15KHZ,
|
||||
CRT_SWITCH_31KHZ
|
||||
CRT_SWITCH_31KHZ,
|
||||
CRT_SWITCH_32_120,
|
||||
CRT_SWITCH_INI
|
||||
};
|
||||
|
||||
enum override_type
|
||||
@@ -120,7 +122,7 @@ typedef struct settings
|
||||
unsigned placeholder;
|
||||
|
||||
unsigned input_split_joycon[MAX_USERS];
|
||||
unsigned input_joypad_map[MAX_USERS];
|
||||
unsigned input_joypad_index[MAX_USERS];
|
||||
unsigned input_device[MAX_USERS];
|
||||
unsigned input_mouse_index[MAX_USERS];
|
||||
/* Set by autoconfiguration in joypad_autoconfig_dir.
|
||||
@@ -128,13 +130,14 @@ typedef struct settings
|
||||
unsigned input_libretro_device[MAX_USERS];
|
||||
unsigned input_analog_dpad_mode[MAX_USERS];
|
||||
|
||||
unsigned input_keymapper_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END];
|
||||
|
||||
unsigned input_remap_ports[MAX_USERS];
|
||||
unsigned input_remap_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END];
|
||||
unsigned input_keymapper_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END];
|
||||
unsigned input_remap_port_map[MAX_USERS][MAX_USERS + 1];
|
||||
|
||||
unsigned led_map[MAX_LEDS];
|
||||
|
||||
unsigned audio_out_rate;
|
||||
unsigned audio_output_sample_rate;
|
||||
unsigned audio_block_frames;
|
||||
unsigned audio_latency;
|
||||
|
||||
@@ -206,6 +209,7 @@ typedef struct settings
|
||||
unsigned video_3ds_display_mode;
|
||||
unsigned video_dingux_ipu_filter_type;
|
||||
unsigned video_dingux_refresh_rate;
|
||||
unsigned video_dingux_rs90_softfilter_type;
|
||||
#ifdef HAVE_VIDEO_LAYOUT
|
||||
unsigned video_layout_selected_view;
|
||||
#endif
|
||||
@@ -266,7 +270,8 @@ typedef struct settings
|
||||
unsigned camera_width;
|
||||
unsigned camera_height;
|
||||
|
||||
unsigned input_overlay_show_physical_inputs_port;
|
||||
unsigned input_overlay_show_inputs;
|
||||
unsigned input_overlay_show_inputs_port;
|
||||
|
||||
unsigned run_ahead_frames;
|
||||
|
||||
@@ -288,6 +293,12 @@ typedef struct settings
|
||||
unsigned core_updater_auto_backup_history_size;
|
||||
unsigned video_black_frame_insertion;
|
||||
unsigned quit_on_close_content;
|
||||
|
||||
#ifdef HAVE_LAKKA
|
||||
unsigned cpu_scaling_mode;
|
||||
unsigned cpu_min_freq;
|
||||
unsigned cpu_max_freq;
|
||||
#endif
|
||||
} uints;
|
||||
|
||||
struct
|
||||
@@ -387,6 +398,8 @@ typedef struct settings
|
||||
char crt_switch_timings[255];
|
||||
#ifdef HAVE_LAKKA
|
||||
char timezone[TIMEZONE_LENGTH];
|
||||
char cpu_main_gov[32];
|
||||
char cpu_menu_gov[32];
|
||||
#endif
|
||||
} arrays;
|
||||
|
||||
@@ -485,6 +498,7 @@ typedef struct settings
|
||||
bool video_aspect_ratio_auto;
|
||||
bool video_dingux_ipu_keep_aspect;
|
||||
bool video_scale_integer;
|
||||
bool video_scale_integer_overscale;
|
||||
bool video_shader_enable;
|
||||
bool video_shader_watch_files;
|
||||
bool video_shader_remember_last_dir;
|
||||
@@ -508,6 +522,7 @@ typedef struct settings
|
||||
#ifdef HAVE_VIDEO_LAYOUT
|
||||
bool video_layout_enable;
|
||||
#endif
|
||||
bool video_force_resolution;
|
||||
|
||||
/* Accessibility */
|
||||
bool accessibility_enable;
|
||||
@@ -533,7 +548,6 @@ typedef struct settings
|
||||
bool input_overlay_enable_autopreferred;
|
||||
bool input_overlay_hide_in_menu;
|
||||
bool input_overlay_hide_when_gamepad_connected;
|
||||
bool input_overlay_show_physical_inputs;
|
||||
bool input_overlay_show_mouse_cursor;
|
||||
bool input_overlay_auto_rotate;
|
||||
bool input_overlay_auto_scale;
|
||||
@@ -688,6 +702,7 @@ typedef struct settings
|
||||
bool kiosk_mode_enable;
|
||||
|
||||
bool crt_switch_custom_refresh_enable;
|
||||
bool crt_switch_hires_menu;
|
||||
|
||||
/* Netplay */
|
||||
bool netplay_public_announce;
|
||||
@@ -723,6 +738,7 @@ typedef struct settings
|
||||
bool cheevos_auto_screenshot;
|
||||
bool cheevos_start_active;
|
||||
bool cheevos_unlock_sound_enable;
|
||||
bool cheevos_challenge_indicators;
|
||||
|
||||
/* Camera */
|
||||
bool camera_allow;
|
||||
@@ -777,6 +793,7 @@ typedef struct settings
|
||||
bool network_remote_enable_user[MAX_USERS];
|
||||
bool load_dummy_on_core_shutdown;
|
||||
bool check_firmware_before_loading;
|
||||
bool core_info_cache_enable;
|
||||
#ifndef HAVE_DYNAMIC
|
||||
bool always_reload_core_on_run_content;
|
||||
#endif
|
||||
@@ -816,6 +833,7 @@ typedef struct settings
|
||||
|
||||
bool playlist_sort_alphabetical;
|
||||
bool playlist_show_sublabels;
|
||||
bool playlist_show_entry_idx;
|
||||
bool playlist_fuzzy_archive_match;
|
||||
bool playlist_portable_paths;
|
||||
|
||||
|
||||
@@ -124,6 +124,10 @@ bool content_set_subsystem_by_name(const char* subsystem_name);
|
||||
/* Get the current subsystem "friendly name" */
|
||||
void content_get_subsystem_friendly_name(const char* subsystem_name, char* subsystem_friendly_name, size_t len);
|
||||
|
||||
/* Sets overrides which modify frontend handling of
|
||||
* specific content file types */
|
||||
bool content_file_override_set(const struct retro_system_content_info_override *overrides);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
+3
-18
@@ -116,7 +116,6 @@ bool core_backup_get_backup_path(
|
||||
const char *core_path, uint32_t crc, enum core_backup_mode backup_mode,
|
||||
const char *dir_core_assets, char *backup_path, size_t len)
|
||||
{
|
||||
int n;
|
||||
time_t current_time;
|
||||
struct tm time_info;
|
||||
const char *core_filename = NULL;
|
||||
@@ -152,7 +151,7 @@ bool core_backup_get_backup_path(
|
||||
rtime_localtime(¤t_time, &time_info);
|
||||
|
||||
/* Generate backup filename */
|
||||
n = snprintf(backup_filename, sizeof(backup_filename),
|
||||
snprintf(backup_filename, sizeof(backup_filename),
|
||||
"%s.%04u%02u%02uT%02u%02u%02u.%08x.%u%s",
|
||||
core_filename,
|
||||
(unsigned)time_info.tm_year + 1900,
|
||||
@@ -165,10 +164,6 @@ bool core_backup_get_backup_path(
|
||||
(unsigned)backup_mode,
|
||||
FILE_PATH_CORE_BACKUP_EXTENSION);
|
||||
|
||||
if ((n < 0) || (n >= 128))
|
||||
n = 0; /* Silence GCC warnings... */
|
||||
|
||||
(void)n;
|
||||
/* Build final path */
|
||||
fill_pathname_join(backup_path, backup_dir,
|
||||
backup_filename, len);
|
||||
@@ -712,7 +707,6 @@ bool core_backup_list_get_entry_timestamp_str(
|
||||
enum core_backup_date_separator_type date_separator,
|
||||
char *timestamp, size_t len)
|
||||
{
|
||||
int n;
|
||||
const char *format_str = "";
|
||||
|
||||
if (!entry || (len < 20))
|
||||
@@ -732,7 +726,7 @@ bool core_backup_list_get_entry_timestamp_str(
|
||||
break;
|
||||
}
|
||||
|
||||
n = snprintf(timestamp, len,
|
||||
snprintf(timestamp, len,
|
||||
format_str,
|
||||
entry->date.year,
|
||||
entry->date.month,
|
||||
@@ -741,9 +735,6 @@ bool core_backup_list_get_entry_timestamp_str(
|
||||
entry->date.minute,
|
||||
entry->date.second);
|
||||
|
||||
if ((n < 0) || (n >= 32))
|
||||
n = 0; /* Silence GCC warnings... */
|
||||
(void)n;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -754,15 +745,9 @@ bool core_backup_list_get_entry_crc_str(
|
||||
const core_backup_list_entry_t *entry,
|
||||
char *crc, size_t len)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (!entry || (len < 9))
|
||||
return false;
|
||||
|
||||
n = snprintf(crc, len, "%08x", entry->crc);
|
||||
|
||||
if ((n < 0) || (n >= 32))
|
||||
n = 0; /* Silence GCC warnings... */
|
||||
(void)n;
|
||||
snprintf(crc, len, "%08x", entry->crc);
|
||||
return true;
|
||||
}
|
||||
+1466
-96
File diff suppressed because it is too large.
Load diff
+9
-1
@@ -89,6 +89,7 @@ typedef struct
|
||||
bool database_match_archive_member;
|
||||
bool is_experimental;
|
||||
bool is_locked;
|
||||
bool is_installed;
|
||||
} core_info_t;
|
||||
|
||||
/* A subset of core_info parameters required for
|
||||
@@ -156,7 +157,8 @@ bool core_info_get_current_core(core_info_t **core);
|
||||
void core_info_deinit_list(void);
|
||||
|
||||
bool core_info_init_list(const char *path_info, const char *dir_cores,
|
||||
const char *exts, bool show_hidden_files);
|
||||
const char *exts, bool show_hidden_files,
|
||||
bool enable_cache, bool *cache_supported);
|
||||
|
||||
bool core_info_get_list(core_info_list_t **core);
|
||||
|
||||
@@ -203,6 +205,12 @@ core_info_state_t *coreinfo_get_ptr(void);
|
||||
|
||||
bool core_info_core_file_id_is_equal(const char *core_path_a, const char *core_path_b);
|
||||
|
||||
/* When called, generates a temporary file
|
||||
* that will force an info cache refresh the
|
||||
* next time that core info is initialised with
|
||||
* caching enabled */
|
||||
bool core_info_cache_force_refresh(const char *path_info);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* CORE_INFO_H_ */
|
||||
Vendored
+2
@@ -8,8 +8,10 @@
|
||||
|
||||
#define CProb UInt16
|
||||
|
||||
#undef kTopValue
|
||||
#define kTopValue ((UInt32)1 << 24)
|
||||
#define kNumModelBits 11
|
||||
#undef kBitModelTotal
|
||||
#define kBitModelTotal (1 << kNumModelBits)
|
||||
#define kNumMoveBits 5
|
||||
|
||||
|
||||
Vendored
+4
-4
@@ -144,7 +144,7 @@ int x86cpuid_GetFirm(const Cx86cpuid *p)
|
||||
return -1;
|
||||
}
|
||||
|
||||
BoolInt CPU_Is_InOrder()
|
||||
BoolInt CPU_Is_InOrder(void)
|
||||
{
|
||||
Cx86cpuid p;
|
||||
int firm;
|
||||
@@ -175,7 +175,7 @@ BoolInt CPU_Is_InOrder()
|
||||
|
||||
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
|
||||
#include <windows.h>
|
||||
static BoolInt CPU_Sys_Is_SSE_Supported()
|
||||
static BoolInt CPU_Sys_Is_SSE_Supported(void)
|
||||
{
|
||||
OSVERSIONINFO vi;
|
||||
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||
@@ -188,7 +188,7 @@ static BoolInt CPU_Sys_Is_SSE_Supported()
|
||||
#define CHECK_SYS_SSE_SUPPORT
|
||||
#endif
|
||||
|
||||
BoolInt CPU_Is_Aes_Supported()
|
||||
BoolInt CPU_Is_Aes_Supported(void)
|
||||
{
|
||||
Cx86cpuid p;
|
||||
CHECK_SYS_SSE_SUPPORT
|
||||
@@ -197,7 +197,7 @@ BoolInt CPU_Is_Aes_Supported()
|
||||
return (p.c >> 25) & 1;
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_PageGB()
|
||||
BoolInt CPU_IsSupported_PageGB(void)
|
||||
{
|
||||
Cx86cpuid cpuid;
|
||||
if (!x86cpuid_CheckAndRead(&cpuid))
|
||||
|
||||
Vendored
+3
-3
@@ -325,9 +325,9 @@ int x86cpuid_GetFirm(const Cx86cpuid *p);
|
||||
#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
|
||||
#define x86cpuid_GetStepping(ver) (ver & 0xF)
|
||||
|
||||
BoolInt CPU_Is_InOrder();
|
||||
BoolInt CPU_Is_Aes_Supported();
|
||||
BoolInt CPU_IsSupported_PageGB();
|
||||
BoolInt CPU_Is_InOrder(void);
|
||||
BoolInt CPU_Is_Aes_Supported(void);
|
||||
BoolInt CPU_IsSupported_PageGB(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Vendored
+4
-1
@@ -205,6 +205,7 @@ typedef struct
|
||||
#define kEndPosModelIndex 14
|
||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
||||
|
||||
#ifndef __LZMA_DEC_H
|
||||
typedef
|
||||
#ifdef _LZMA_PROB32
|
||||
UInt32
|
||||
@@ -212,6 +213,7 @@ typedef
|
||||
UInt16
|
||||
#endif
|
||||
CLzmaProb;
|
||||
#endif
|
||||
|
||||
#define LZMA_PB_MAX 4
|
||||
#define LZMA_LC_MAX 8
|
||||
@@ -973,7 +975,8 @@ MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTables(
|
||||
printf("\n MovePos %u", num);
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
||||
#undef MOVE_POS
|
||||
#define MOVE_POS(p, num) { \
|
||||
p->additionalOffset += (num); \
|
||||
p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); }
|
||||
|
||||
Vendored
+2
-2
@@ -63,8 +63,8 @@
|
||||
|
||||
/* Platform specific options */
|
||||
#if defined (__wiiu__)
|
||||
#define DEFAULT_CACHE_PAGES 4
|
||||
#define DEFAULT_SECTORS_PAGE 64
|
||||
#define DEFAULT_CACHE_PAGES 512
|
||||
#define DEFAULT_SECTORS_PAGE 128
|
||||
#if 0
|
||||
#define USE_LWP_LOCK
|
||||
#define USE_RTC_TIME
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
name: Publish Docker Image
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Get release version
|
||||
id: get_release_tag
|
||||
run: |
|
||||
echo RELEASE_VERSION=$(echo $(date '+%Y%m%d')) >> $GITHUB_ENV
|
||||
echo REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//" | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
echo REPOSITORY_OWNER=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $1}' | sed 's/[^a-zA-Z0-9]//g' | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
- name: Publish to Registry
|
||||
uses: elgohr/Publish-Docker-Github-Action@master
|
||||
with:
|
||||
name: ${{ env.REPOSITORY_OWNER }}/${{ env.REPOSITORY_NAME }}
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
snapshot: true
|
||||
cache: true
|
||||
tags: "latest, ${{ env.RELEASE_VERSION }}"
|
||||
@@ -0,0 +1,5 @@
|
||||
/*.a
|
||||
/build
|
||||
*.bz2
|
||||
release/
|
||||
lib/
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
language: cpp
|
||||
|
||||
os: linux
|
||||
sudo: false
|
||||
dist: trusty
|
||||
|
||||
env:
|
||||
global:
|
||||
- DEVKITPRO=/opt/devkitpro
|
||||
- DEVKITPPC=/opt/devkitpro/devkitPPC
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- "$HOME/.local"
|
||||
- "$DEVKITPRO"
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- p7zip-full
|
||||
|
||||
before_install:
|
||||
- mkdir -p "${DEVKITPRO}"
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb -O /tmp/devkitpro-pacman.deb; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo dpkg -i /tmp/devkitpro-pacman.deb; fi
|
||||
- yes | sudo dkp-pacman -Syu devkitPPC --needed
|
||||
|
||||
script:
|
||||
- make && make install
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
FROM wiiuenv/devkitppc:20210101
|
||||
|
||||
WORKDIR tmp_build
|
||||
COPY . .
|
||||
RUN make clean && make && mkdir -p /artifacts/wut/usr && cp -r lib /artifacts/wut/usr && cp -r include /artifacts/wut/usr
|
||||
WORKDIR /artifacts
|
||||
|
||||
FROM scratch
|
||||
COPY --from=0 /artifacts /artifacts
|
||||
Vendored
+157
@@ -0,0 +1,157 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
include $(DEVKITPRO)/wut/share/wut_rules
|
||||
|
||||
export VER_MAJOR := 1
|
||||
export VER_MINOR := 0
|
||||
export VER_PATCH := 0
|
||||
|
||||
VERSION := $(VER_MAJOR).$(VER_MINOR).$(VER_PATCH)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#-------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := source \
|
||||
include \
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
CFLAGS := -Wall -Werror -save-temps \
|
||||
-ffunction-sections -fdata-sections \
|
||||
$(MACHDEP) \
|
||||
$(BUILD_CFLAGS)
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -std=gnu++17
|
||||
|
||||
ASFLAGS := $(MACHDEP)
|
||||
|
||||
LDFLAGS = $(ARCH) -Wl,--gc-sections
|
||||
|
||||
|
||||
LIBS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS) $(WUT_ROOT)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
DEFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.def)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_SRC := $(DEFFILES:.def=.o) $(SFILES:.s=.o) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I.
|
||||
|
||||
.PHONY: all dist-bin dist-src dist install clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: lib/libiosuhax.a
|
||||
|
||||
dist-bin: all
|
||||
@tar --exclude=*~ -cjf libiosuhax-$(VERSION).tar.bz2 include lib
|
||||
|
||||
dist-src:
|
||||
@tar --exclude=*~ -cjf libiosuhax-src-$(VERSION).tar.bz2 include source Makefile
|
||||
|
||||
dist: dist-src dist-bin
|
||||
|
||||
install: dist-bin
|
||||
mkdir -p $(DESTDIR)$(DEVKITPRO)/wut/usr
|
||||
bzip2 -cd libiosuhax-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/wut/usr
|
||||
|
||||
lib:
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
release:
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
lib/libiosuhax.a :$(SOURCES) $(INCLUDES) | lib release
|
||||
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
|
||||
BUILD_CFLAGS="-DNDEBUG=1 -O2 -s" \
|
||||
DEPSDIR=$(CURDIR)/release \
|
||||
--no-print-directory -C release \
|
||||
-f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -rf release lib
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT) : $(OFILES)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%_bin.h %.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
[](https://travis-ci.org/dimok789/libiosuhax)
|
||||
# libiosuhax
|
||||
A PPC library to access IOSUHAX from PPC and a devoptab for any device or path.
|
||||
It's only compatible to RPX-Files.
|
||||
|
||||
## Building
|
||||
Make you to have [wut](https://github.com/devkitPro/wut/) installed and use the following command for build:
|
||||
```
|
||||
make install
|
||||
```
|
||||
+112
-109
@@ -1,109 +1,112 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2016
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
***************************************************************************/
|
||||
#ifndef _LIB_IOSUHAX_H_
|
||||
#define _LIB_IOSUHAX_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define IOS_ERROR_UNKNOWN_VALUE 0xFFFFFFD6
|
||||
#define IOS_ERROR_INVALID_ARG 0xFFFFFFE3
|
||||
#define IOS_ERROR_INVALID_SIZE 0xFFFFFFE9
|
||||
#define IOS_ERROR_UNKNOWN 0xFFFFFFF7
|
||||
#define IOS_ERROR_NOEXISTS 0xFFFFFFFA
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flag;
|
||||
uint32_t permission;
|
||||
uint32_t owner_id;
|
||||
uint32_t group_id;
|
||||
uint32_t size; // size in bytes
|
||||
uint32_t physsize; // physical size on disk in bytes
|
||||
uint32_t unk[3];
|
||||
uint32_t id;
|
||||
uint32_t ctime;
|
||||
uint32_t mtime;
|
||||
uint32_t unk2[0x0D];
|
||||
}fileStat_s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fileStat_s stat;
|
||||
char name[0x100];
|
||||
}directoryEntry_s;
|
||||
|
||||
#define DIR_ENTRY_IS_DIRECTORY 0x80000000
|
||||
|
||||
#define FSA_MOUNTFLAGS_BINDMOUNT (1 << 0)
|
||||
#define FSA_MOUNTFLAGS_GLOBAL (1 << 1)
|
||||
|
||||
int IOSUHAX_Open(const char *dev); // if dev == NULL the default path /dev/iosuhax will be used
|
||||
int IOSUHAX_Close(void);
|
||||
|
||||
int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size); // IOSU external input
|
||||
int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size); // IOSU external output
|
||||
int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size); // IOSU internal memcpy only
|
||||
|
||||
int IOSUHAX_SVC(uint32_t svc_id, uint32_t * args, uint32_t arg_cnt);
|
||||
|
||||
int IOSUHAX_FSA_Open();
|
||||
int IOSUHAX_FSA_Close(int fsaFd);
|
||||
|
||||
int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len);
|
||||
int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags);
|
||||
int IOSUHAX_FSA_FlushVolume(int fsaFd, const char* volume_path);
|
||||
|
||||
int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data);
|
||||
|
||||
int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags);
|
||||
int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle);
|
||||
int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data);
|
||||
int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle);
|
||||
int IOSUHAX_FSA_CloseDir(int fsaFd, int handle);
|
||||
int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path);
|
||||
|
||||
int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle);
|
||||
int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags);
|
||||
int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags);
|
||||
int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data);
|
||||
int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle);
|
||||
int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position);
|
||||
int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data);
|
||||
int IOSUHAX_FSA_Remove(int fsaFd, const char *path);
|
||||
int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode);
|
||||
|
||||
int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle);
|
||||
int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle);
|
||||
int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle);
|
||||
int IOSUHAX_FSA_RawClose(int fsaFd, int device_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2016
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
***************************************************************************/
|
||||
#ifndef _LIB_IOSUHAX_H_
|
||||
#define _LIB_IOSUHAX_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define IOS_ERROR_UNKNOWN_VALUE 0xFFFFFFD6
|
||||
#define IOS_ERROR_INVALID_ARG 0xFFFFFFE3
|
||||
#define IOS_ERROR_INVALID_SIZE 0xFFFFFFE9
|
||||
#define IOS_ERROR_UNKNOWN 0xFFFFFFF7
|
||||
#define IOS_ERROR_NOEXISTS 0xFFFFFFFA
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flag;
|
||||
uint32_t permission;
|
||||
uint32_t owner_id;
|
||||
uint32_t group_id;
|
||||
uint32_t size; // size in bytes
|
||||
uint32_t physsize; // physical size on disk in bytes
|
||||
uint32_t unk[3];
|
||||
uint32_t id;
|
||||
uint32_t ctime;
|
||||
uint32_t mtime;
|
||||
uint32_t unk2[0x0D];
|
||||
}fileStat_s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fileStat_s stat;
|
||||
char name[0x100];
|
||||
}directoryEntry_s;
|
||||
|
||||
#define DIR_ENTRY_IS_DIRECTORY 0x80000000
|
||||
|
||||
#define FSA_MOUNTFLAGS_BINDMOUNT (1 << 0)
|
||||
#define FSA_MOUNTFLAGS_GLOBAL (1 << 1)
|
||||
|
||||
int IOSUHAX_Open(const char *dev); // if dev == NULL the default path /dev/iosuhax will be used
|
||||
int IOSUHAX_Close(void);
|
||||
|
||||
int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size); // IOSU external input
|
||||
int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size); // IOSU external output
|
||||
int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size); // IOSU internal memcpy only
|
||||
|
||||
int IOSUHAX_kern_write32(uint32_t address, uint32_t value);
|
||||
int IOSUHAX_kern_read32(uint32_t address, uint32_t* out_buffer, uint32_t count);
|
||||
|
||||
int IOSUHAX_SVC(uint32_t svc_id, uint32_t * args, uint32_t arg_cnt);
|
||||
|
||||
int IOSUHAX_FSA_Open();
|
||||
int IOSUHAX_FSA_Close(int fsaFd);
|
||||
|
||||
int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len);
|
||||
int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags);
|
||||
int IOSUHAX_FSA_FlushVolume(int fsaFd, const char* volume_path);
|
||||
|
||||
int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data);
|
||||
|
||||
int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags);
|
||||
int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle);
|
||||
int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data);
|
||||
int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle);
|
||||
int IOSUHAX_FSA_CloseDir(int fsaFd, int handle);
|
||||
int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path);
|
||||
|
||||
int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle);
|
||||
int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags);
|
||||
int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags);
|
||||
int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data);
|
||||
int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle);
|
||||
int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position);
|
||||
int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data);
|
||||
int IOSUHAX_FSA_Remove(int fsaFd, const char *path);
|
||||
int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode);
|
||||
|
||||
int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle);
|
||||
int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle);
|
||||
int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle);
|
||||
int IOSUHAX_FSA_RawClose(int fsaFd, int device_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+42
-42
@@ -1,42 +1,42 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2015
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
***************************************************************************/
|
||||
#ifndef __IOSUHAX_DEVOPTAB_H_
|
||||
#define __IOSUHAX_DEVOPTAB_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//! virtual name example: sd or odd (for sd:/ or odd:/ access)
|
||||
//! fsaFd: fd received by IOSUHAX_FSA_Open();
|
||||
//! dev_path: (optional) if a device should be mounted to the mount_path. If NULL no IOSUHAX_FSA_Mount is not executed.
|
||||
//! mount_path: path to map to virtual device name
|
||||
int mount_fs(const char *virt_name, int fsaFd, const char *dev_path, const char *mount_path);
|
||||
int unmount_fs(const char *virt_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __IOSUHAX_DEVOPTAB_H_
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2015
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
***************************************************************************/
|
||||
#ifndef __IOSUHAX_DEVOPTAB_H_
|
||||
#define __IOSUHAX_DEVOPTAB_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//! virtual name example: sd or odd (for sd:/ or odd:/ access)
|
||||
//! fsaFd: fd received by IOSUHAX_FSA_Open();
|
||||
//! dev_path: (optional) if a device should be mounted to the mount_path. If NULL no IOSUHAX_FSA_Mount is not executed.
|
||||
//! mount_path: path to map to virtual device name
|
||||
int mount_fs(const char *virt_name, int fsaFd, const char *dev_path, const char *mount_path);
|
||||
int unmount_fs(const char *virt_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __IOSUHAX_DEVOPTAB_H_
|
||||
Vendored
+73
-73
@@ -1,73 +1,73 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2016
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
***************************************************************************/
|
||||
#ifndef _IOSUHAX_DISC_INTERFACE_H_
|
||||
#define _IOSUHAX_DISC_INTERFACE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DEVICE_TYPE_WII_U_SD (('W'<<24)|('U'<<16)|('S'<<8)|'D')
|
||||
#define DEVICE_TYPE_WII_U_USB (('W'<<24)|('U'<<16)|('S'<<8)|'B')
|
||||
#define FEATURE_WII_U_SD 0x00001000
|
||||
#define FEATURE_WII_U_USB 0x00002000
|
||||
|
||||
#ifndef OGC_DISC_IO_INCLUDE
|
||||
typedef uint32_t sec_t;
|
||||
|
||||
#define FEATURE_MEDIUM_CANREAD 0x00000001
|
||||
#define FEATURE_MEDIUM_CANWRITE 0x00000002
|
||||
|
||||
typedef bool (* FN_MEDIUM_STARTUP)(void) ;
|
||||
typedef bool (* FN_MEDIUM_ISINSERTED)(void) ;
|
||||
typedef bool (* FN_MEDIUM_READSECTORS)(uint32_t sector, uint32_t numSectors, void* buffer) ;
|
||||
typedef bool (* FN_MEDIUM_WRITESECTORS)(uint32_t sector, uint32_t numSectors, const void* buffer) ;
|
||||
typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ;
|
||||
typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ;
|
||||
|
||||
struct DISC_INTERFACE_STRUCT {
|
||||
unsigned long ioType ;
|
||||
unsigned long features ;
|
||||
FN_MEDIUM_STARTUP startup ;
|
||||
FN_MEDIUM_ISINSERTED isInserted ;
|
||||
FN_MEDIUM_READSECTORS readSectors ;
|
||||
FN_MEDIUM_WRITESECTORS writeSectors ;
|
||||
FN_MEDIUM_CLEARSTATUS clearStatus ;
|
||||
FN_MEDIUM_SHUTDOWN shutdown ;
|
||||
} ;
|
||||
|
||||
typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE ;
|
||||
#endif
|
||||
|
||||
extern const DISC_INTERFACE IOSUHAX_sdio_disc_interface;
|
||||
extern const DISC_INTERFACE IOSUHAX_usb_disc_interface;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2016
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
***************************************************************************/
|
||||
#ifndef _IOSUHAX_DISC_INTERFACE_H_
|
||||
#define _IOSUHAX_DISC_INTERFACE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DEVICE_TYPE_WII_U_SD (('W'<<24)|('U'<<16)|('S'<<8)|'D')
|
||||
#define DEVICE_TYPE_WII_U_USB (('W'<<24)|('U'<<16)|('S'<<8)|'B')
|
||||
#define FEATURE_WII_U_SD 0x00001000
|
||||
#define FEATURE_WII_U_USB 0x00002000
|
||||
|
||||
#ifndef OGC_DISC_IO_INCLUDE
|
||||
typedef uint32_t sec_t;
|
||||
|
||||
#define FEATURE_MEDIUM_CANREAD 0x00000001
|
||||
#define FEATURE_MEDIUM_CANWRITE 0x00000002
|
||||
|
||||
typedef bool (* FN_MEDIUM_STARTUP)(void) ;
|
||||
typedef bool (* FN_MEDIUM_ISINSERTED)(void) ;
|
||||
typedef bool (* FN_MEDIUM_READSECTORS)(uint32_t sector, uint32_t numSectors, void* buffer) ;
|
||||
typedef bool (* FN_MEDIUM_WRITESECTORS)(uint32_t sector, uint32_t numSectors, const void* buffer) ;
|
||||
typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ;
|
||||
typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ;
|
||||
|
||||
struct DISC_INTERFACE_STRUCT {
|
||||
unsigned long ioType ;
|
||||
unsigned long features ;
|
||||
FN_MEDIUM_STARTUP startup ;
|
||||
FN_MEDIUM_ISINSERTED isInserted ;
|
||||
FN_MEDIUM_READSECTORS readSectors ;
|
||||
FN_MEDIUM_WRITESECTORS writeSectors ;
|
||||
FN_MEDIUM_CLEARSTATUS clearStatus ;
|
||||
FN_MEDIUM_SHUTDOWN shutdown ;
|
||||
} ;
|
||||
|
||||
typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE ;
|
||||
#endif
|
||||
|
||||
extern const DISC_INTERFACE IOSUHAX_sdio_disc_interface;
|
||||
extern const DISC_INTERFACE IOSUHAX_usb_disc_interface;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Vendored
-51
@@ -1,51 +0,0 @@
|
||||
#ifndef __OS_FUNCTIONS_H_
|
||||
#define __OS_FUNCTIONS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OS_MUTEX_SIZE 44
|
||||
|
||||
// RetroArch mod: use existing headers; prevents conflicts in griffin
|
||||
#include <wiiu/os.h>
|
||||
#include <wiiu/ios.h>
|
||||
#if 0
|
||||
|
||||
#ifndef __WUT__
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//! Mutex functions
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
extern void (* OSInitMutex)(void* mutex);
|
||||
extern void (* OSLockMutex)(void* mutex);
|
||||
extern void (* OSUnlockMutex)(void* mutex);
|
||||
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//! IOS function
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
extern int (*IOS_Ioctl)(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len);
|
||||
extern int (*IOS_Open)(char *path, unsigned int mode);
|
||||
extern int (*IOS_Close)(int fd);
|
||||
#else
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//! Mutex functions
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
extern void OSInitMutex(void* mutex);
|
||||
extern void OSLockMutex(void* mutex);
|
||||
extern void OSUnlockMutex(void* mutex);
|
||||
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//! IOS function
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
extern int IOS_Ioctl(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len);
|
||||
extern int IOS_Open(char *path, unsigned int mode);
|
||||
extern int IOS_Close(int fd);
|
||||
#endif // __WUT__
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // 0
|
||||
|
||||
#endif // __OS_FUNCTIONS_H_
|
||||
+956
-1029
File diff suppressed because it is too large.
Load diff
+993
-1134
File diff suppressed because it is too large.
Load diff
+262
-262
@@ -1,262 +1,262 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2016
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
***************************************************************************/
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include "iosuhax.h"
|
||||
#include "iosuhax_disc_interface.h"
|
||||
|
||||
#define FSA_REF_SD 0x01
|
||||
#define FSA_REF_USB 0x02
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
static int fsaFdSd = 0;
|
||||
static int fsaFdUsb = 0;
|
||||
static int sdioFd = 0;
|
||||
static int usbFd = 0;
|
||||
|
||||
static void IOSUHAX_disc_io_initialize(void)
|
||||
{
|
||||
if(initialized == 0)
|
||||
{
|
||||
initialized = 1;
|
||||
fsaFdSd = -1;
|
||||
fsaFdUsb = -1;
|
||||
sdioFd = -1;
|
||||
usbFd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IOSUHAX_disc_io_fsa_open(int fsaFd)
|
||||
{
|
||||
IOSUHAX_disc_io_initialize();
|
||||
|
||||
if(IOSUHAX_Open(NULL) < 0)
|
||||
return false;
|
||||
|
||||
if(fsaFd == FSA_REF_SD)
|
||||
{
|
||||
if(fsaFdSd < 0)
|
||||
{
|
||||
fsaFdSd = IOSUHAX_FSA_Open();
|
||||
}
|
||||
|
||||
if(fsaFdSd >= 0)
|
||||
return true;
|
||||
}
|
||||
else if(fsaFd == FSA_REF_USB)
|
||||
{
|
||||
if(fsaFdUsb < 0)
|
||||
{
|
||||
fsaFdUsb = IOSUHAX_FSA_Open();
|
||||
}
|
||||
|
||||
if(fsaFdUsb >= 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void IOSUHAX_disc_io_fsa_close(int fsaFd)
|
||||
{
|
||||
if(fsaFd == FSA_REF_SD)
|
||||
{
|
||||
if(fsaFdSd >= 0)
|
||||
{
|
||||
IOSUHAX_FSA_Close(fsaFdSd);
|
||||
fsaFdSd = -1;
|
||||
}
|
||||
}
|
||||
else if(fsaFd == FSA_REF_USB)
|
||||
{
|
||||
if(fsaFdUsb >= 0)
|
||||
{
|
||||
IOSUHAX_FSA_Close(fsaFdUsb);
|
||||
fsaFdUsb = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_startup(void)
|
||||
{
|
||||
if(!IOSUHAX_disc_io_fsa_open(FSA_REF_SD))
|
||||
return false;
|
||||
|
||||
if(sdioFd < 0)
|
||||
{
|
||||
int res = IOSUHAX_FSA_RawOpen(fsaFdSd, "/dev/sdcard01", &sdioFd);
|
||||
if(res < 0)
|
||||
{
|
||||
IOSUHAX_disc_io_fsa_close(FSA_REF_SD);
|
||||
sdioFd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (sdioFd >= 0);
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_isInserted(void)
|
||||
{
|
||||
//! TODO: check for SD card inserted with IOSUHAX_FSA_GetDeviceInfo()
|
||||
return initialized && (fsaFdSd >= 0) && (sdioFd >= 0);
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_clearStatus(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_shutdown(void)
|
||||
{
|
||||
if(!IOSUHAX_sdio_isInserted())
|
||||
return false;
|
||||
|
||||
IOSUHAX_FSA_RawClose(fsaFdSd, sdioFd);
|
||||
IOSUHAX_disc_io_fsa_close(FSA_REF_SD);
|
||||
sdioFd = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_readSectors(uint32_t sector, uint32_t numSectors, void* buffer)
|
||||
{
|
||||
if(!IOSUHAX_sdio_isInserted() || !buffer)
|
||||
return false;
|
||||
|
||||
int res = IOSUHAX_FSA_RawRead(fsaFdSd, buffer, 512, numSectors, sector, sdioFd);
|
||||
if(res < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer)
|
||||
{
|
||||
if(!IOSUHAX_sdio_isInserted() || !buffer)
|
||||
return false;
|
||||
|
||||
int res = IOSUHAX_FSA_RawWrite(fsaFdSd, buffer, 512, numSectors, sector, sdioFd);
|
||||
if(res < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const DISC_INTERFACE IOSUHAX_sdio_disc_interface =
|
||||
{
|
||||
DEVICE_TYPE_WII_U_SD,
|
||||
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_SD,
|
||||
IOSUHAX_sdio_startup,
|
||||
IOSUHAX_sdio_isInserted,
|
||||
IOSUHAX_sdio_readSectors,
|
||||
IOSUHAX_sdio_writeSectors,
|
||||
IOSUHAX_sdio_clearStatus,
|
||||
IOSUHAX_sdio_shutdown
|
||||
};
|
||||
|
||||
static bool IOSUHAX_usb_startup(void)
|
||||
{
|
||||
if(!IOSUHAX_disc_io_fsa_open(FSA_REF_USB))
|
||||
return false;
|
||||
|
||||
if(usbFd < 0)
|
||||
{
|
||||
int res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb01", &usbFd);
|
||||
if(res < 0)
|
||||
{
|
||||
res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb02", &usbFd);
|
||||
if(res < 0)
|
||||
{
|
||||
IOSUHAX_disc_io_fsa_close(FSA_REF_USB);
|
||||
usbFd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (usbFd >= 0);
|
||||
}
|
||||
|
||||
static bool IOSUHAX_usb_isInserted(void)
|
||||
{
|
||||
return initialized && (fsaFdUsb >= 0) && (usbFd >= 0);
|
||||
}
|
||||
|
||||
static bool IOSUHAX_usb_clearStatus(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_usb_shutdown(void)
|
||||
{
|
||||
if(!IOSUHAX_usb_isInserted())
|
||||
return false;
|
||||
|
||||
IOSUHAX_FSA_RawClose(fsaFdUsb, usbFd);
|
||||
IOSUHAX_disc_io_fsa_close(FSA_REF_USB);
|
||||
usbFd = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_usb_readSectors(uint32_t sector, uint32_t numSectors, void* buffer)
|
||||
{
|
||||
if(!IOSUHAX_usb_isInserted() || !buffer)
|
||||
return false;
|
||||
|
||||
int res = IOSUHAX_FSA_RawRead(fsaFdUsb, buffer, 512, numSectors, sector, usbFd);
|
||||
if(res < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_usb_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer)
|
||||
{
|
||||
if(!IOSUHAX_usb_isInserted() || !buffer)
|
||||
return false;
|
||||
|
||||
int res = IOSUHAX_FSA_RawWrite(fsaFdUsb, buffer, 512, numSectors, sector, usbFd);
|
||||
if(res < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const DISC_INTERFACE IOSUHAX_usb_disc_interface =
|
||||
{
|
||||
DEVICE_TYPE_WII_U_USB,
|
||||
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_USB,
|
||||
IOSUHAX_usb_startup,
|
||||
IOSUHAX_usb_isInserted,
|
||||
IOSUHAX_usb_readSectors,
|
||||
IOSUHAX_usb_writeSectors,
|
||||
IOSUHAX_usb_clearStatus,
|
||||
IOSUHAX_usb_shutdown
|
||||
};
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2016
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
***************************************************************************/
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include "iosuhax.h"
|
||||
#include "iosuhax_disc_interface.h"
|
||||
|
||||
#define FSA_REF_SD 0x01
|
||||
#define FSA_REF_USB 0x02
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
static int fsaFdSd = 0;
|
||||
static int fsaFdUsb = 0;
|
||||
static int sdioFd = 0;
|
||||
static int usbFd = 0;
|
||||
|
||||
static void IOSUHAX_disc_io_initialize(void)
|
||||
{
|
||||
if(initialized == 0)
|
||||
{
|
||||
initialized = 1;
|
||||
fsaFdSd = -1;
|
||||
fsaFdUsb = -1;
|
||||
sdioFd = -1;
|
||||
usbFd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IOSUHAX_disc_io_fsa_open(int fsaFd)
|
||||
{
|
||||
IOSUHAX_disc_io_initialize();
|
||||
|
||||
if(IOSUHAX_Open(NULL) < 0)
|
||||
return false;
|
||||
|
||||
if(fsaFd == FSA_REF_SD)
|
||||
{
|
||||
if(fsaFdSd < 0)
|
||||
{
|
||||
fsaFdSd = IOSUHAX_FSA_Open();
|
||||
}
|
||||
|
||||
if(fsaFdSd >= 0)
|
||||
return true;
|
||||
}
|
||||
else if(fsaFd == FSA_REF_USB)
|
||||
{
|
||||
if(fsaFdUsb < 0)
|
||||
{
|
||||
fsaFdUsb = IOSUHAX_FSA_Open();
|
||||
}
|
||||
|
||||
if(fsaFdUsb >= 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void IOSUHAX_disc_io_fsa_close(int fsaFd)
|
||||
{
|
||||
if(fsaFd == FSA_REF_SD)
|
||||
{
|
||||
if(fsaFdSd >= 0)
|
||||
{
|
||||
IOSUHAX_FSA_Close(fsaFdSd);
|
||||
fsaFdSd = -1;
|
||||
}
|
||||
}
|
||||
else if(fsaFd == FSA_REF_USB)
|
||||
{
|
||||
if(fsaFdUsb >= 0)
|
||||
{
|
||||
IOSUHAX_FSA_Close(fsaFdUsb);
|
||||
fsaFdUsb = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_startup(void)
|
||||
{
|
||||
if(!IOSUHAX_disc_io_fsa_open(FSA_REF_SD))
|
||||
return false;
|
||||
|
||||
if(sdioFd < 0)
|
||||
{
|
||||
int res = IOSUHAX_FSA_RawOpen(fsaFdSd, "/dev/sdcard01", &sdioFd);
|
||||
if(res < 0)
|
||||
{
|
||||
IOSUHAX_disc_io_fsa_close(FSA_REF_SD);
|
||||
sdioFd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (sdioFd >= 0);
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_isInserted(void)
|
||||
{
|
||||
//! TODO: check for SD card inserted with IOSUHAX_FSA_GetDeviceInfo()
|
||||
return initialized && (fsaFdSd >= 0) && (sdioFd >= 0);
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_clearStatus(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_shutdown(void)
|
||||
{
|
||||
if(!IOSUHAX_sdio_isInserted())
|
||||
return false;
|
||||
|
||||
IOSUHAX_FSA_RawClose(fsaFdSd, sdioFd);
|
||||
IOSUHAX_disc_io_fsa_close(FSA_REF_SD);
|
||||
sdioFd = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_readSectors(uint32_t sector, uint32_t numSectors, void* buffer)
|
||||
{
|
||||
if(!IOSUHAX_sdio_isInserted())
|
||||
return false;
|
||||
|
||||
int res = IOSUHAX_FSA_RawRead(fsaFdSd, buffer, 512, numSectors, sector, sdioFd);
|
||||
if(res < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_sdio_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer)
|
||||
{
|
||||
if(!IOSUHAX_sdio_isInserted())
|
||||
return false;
|
||||
|
||||
int res = IOSUHAX_FSA_RawWrite(fsaFdSd, buffer, 512, numSectors, sector, sdioFd);
|
||||
if(res < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const DISC_INTERFACE IOSUHAX_sdio_disc_interface =
|
||||
{
|
||||
DEVICE_TYPE_WII_U_SD,
|
||||
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_SD,
|
||||
IOSUHAX_sdio_startup,
|
||||
IOSUHAX_sdio_isInserted,
|
||||
IOSUHAX_sdio_readSectors,
|
||||
IOSUHAX_sdio_writeSectors,
|
||||
IOSUHAX_sdio_clearStatus,
|
||||
IOSUHAX_sdio_shutdown
|
||||
};
|
||||
|
||||
static bool IOSUHAX_usb_startup(void)
|
||||
{
|
||||
if(!IOSUHAX_disc_io_fsa_open(FSA_REF_USB))
|
||||
return false;
|
||||
|
||||
if(usbFd < 0)
|
||||
{
|
||||
int res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb01", &usbFd);
|
||||
if(res < 0)
|
||||
{
|
||||
res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb02", &usbFd);
|
||||
if(res < 0)
|
||||
{
|
||||
IOSUHAX_disc_io_fsa_close(FSA_REF_USB);
|
||||
usbFd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (usbFd >= 0);
|
||||
}
|
||||
|
||||
static bool IOSUHAX_usb_isInserted(void)
|
||||
{
|
||||
return initialized && (fsaFdUsb >= 0) && (usbFd >= 0);
|
||||
}
|
||||
|
||||
static bool IOSUHAX_usb_clearStatus(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_usb_shutdown(void)
|
||||
{
|
||||
if(!IOSUHAX_usb_isInserted())
|
||||
return false;
|
||||
|
||||
IOSUHAX_FSA_RawClose(fsaFdUsb, usbFd);
|
||||
IOSUHAX_disc_io_fsa_close(FSA_REF_USB);
|
||||
usbFd = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_usb_readSectors(uint32_t sector, uint32_t numSectors, void* buffer)
|
||||
{
|
||||
if(!IOSUHAX_usb_isInserted())
|
||||
return false;
|
||||
|
||||
int res = IOSUHAX_FSA_RawRead(fsaFdUsb, buffer, 512, numSectors, sector, usbFd);
|
||||
if(res < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IOSUHAX_usb_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer)
|
||||
{
|
||||
if(!IOSUHAX_usb_isInserted())
|
||||
return false;
|
||||
|
||||
int res = IOSUHAX_FSA_RawWrite(fsaFdUsb, buffer, 512, numSectors, sector, usbFd);
|
||||
if(res < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const DISC_INTERFACE IOSUHAX_usb_disc_interface =
|
||||
{
|
||||
DEVICE_TYPE_WII_U_USB,
|
||||
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_USB,
|
||||
IOSUHAX_usb_startup,
|
||||
IOSUHAX_usb_isInserted,
|
||||
IOSUHAX_usb_readSectors,
|
||||
IOSUHAX_usb_writeSectors,
|
||||
IOSUHAX_usb_clearStatus,
|
||||
IOSUHAX_usb_shutdown
|
||||
};
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
#ifndef __OS_FUNCTIONS_H_
|
||||
#define __OS_FUNCTIONS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OS_MUTEX_SIZE 44
|
||||
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//! Mutex functions
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
extern void OSInitMutex(void* mutex);
|
||||
extern void OSLockMutex(void* mutex);
|
||||
extern void OSUnlockMutex(void* mutex);
|
||||
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//! IOS function
|
||||
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
extern int IOS_Ioctl(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len);
|
||||
extern int IOS_Open(char *path, unsigned int mode);
|
||||
extern int IOS_Close(int fd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __OS_FUNCTIONS_H_
|
||||
Vendored
+15
-3
@@ -11,6 +11,18 @@ extern "C" {
|
||||
|
||||
#define RGBA8(r,g,b,a) ((((a)&0xFF)<<24) | (((b)&0xFF)<<16) | (((g)&0xFF)<<8) | (((r)&0xFF)<<0))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VITA2D_VIDEO_MODE_960x544 = 0,
|
||||
VITA2D_VIDEO_MODE_1280x720
|
||||
} vita2d_video_mode;
|
||||
|
||||
typedef struct vita2d_video_mode_data {
|
||||
int width;
|
||||
int height;
|
||||
int stride;
|
||||
} vita2d_video_mode_data;
|
||||
|
||||
typedef struct vita2d_clear_vertex {
|
||||
float x;
|
||||
float y;
|
||||
@@ -58,7 +70,7 @@ typedef struct vita2d_pgf vita2d_pgf;
|
||||
|
||||
int vita2d_init();
|
||||
int vita2d_init_advanced(unsigned int temp_pool_size);
|
||||
int vita2d_init_advanced_with_msaa(unsigned int temp_pool_size, SceGxmMultisampleMode msaa);
|
||||
int vita2d_init_advanced_with_msaa(unsigned int temp_pool_size, SceGxmMultisampleMode msaa, vita2d_video_mode video_mode);
|
||||
void vita2d_wait_rendering_done();
|
||||
int vita2d_fini();
|
||||
|
||||
@@ -74,8 +86,8 @@ int vita2d_common_dialog_update();
|
||||
void vita2d_set_clear_color(unsigned int color);
|
||||
unsigned int vita2d_get_clear_color();
|
||||
|
||||
void vita2d_set_clear_color(unsigned int color);
|
||||
unsigned int vita2d_get_clear_color();
|
||||
vita2d_video_mode_data vita2d_get_video_mode_data();
|
||||
|
||||
void vita2d_set_vblank_wait(int enable);
|
||||
void *vita2d_get_current_fb();
|
||||
SceGxmContext *vita2d_get_context();
|
||||
|
||||
Vendored
+144
-73
@@ -18,9 +18,6 @@
|
||||
|
||||
/* Defines */
|
||||
|
||||
#define DISPLAY_WIDTH 960
|
||||
#define DISPLAY_HEIGHT 544
|
||||
#define DISPLAY_STRIDE_IN_PIXELS 1024
|
||||
#define DISPLAY_COLOR_FORMAT SCE_GXM_COLOR_FORMAT_A8B8G8R8
|
||||
#define DISPLAY_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8
|
||||
#define DISPLAY_BUFFER_COUNT 3
|
||||
@@ -44,6 +41,10 @@ extern const SceGxmProgram texture_tint_f_gxp;
|
||||
|
||||
/* Static variables */
|
||||
|
||||
static vita2d_video_mode_data video_mode_data;
|
||||
static vita2d_video_mode video_mode_initial;
|
||||
static SceGxmMultisampleMode current_msaa = SCE_GXM_MULTISAMPLE_4X;
|
||||
|
||||
static int pgf_module_was_loaded = 0;
|
||||
|
||||
static const SceGxmProgram *const clearVertexProgramGxp = &clear_v_gxp;
|
||||
@@ -60,8 +61,8 @@ static float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
static unsigned int clear_color_u = 0xFF000000;
|
||||
static int clip_rect_x_min = 0;
|
||||
static int clip_rect_y_min = 0;
|
||||
static int clip_rect_x_max = DISPLAY_WIDTH;
|
||||
static int clip_rect_y_max = DISPLAY_HEIGHT;
|
||||
static int clip_rect_x_max = 0;
|
||||
static int clip_rect_y_max = 0;
|
||||
static int vblank_wait = 1;
|
||||
static int drawing = 0;
|
||||
static int clipping_enabled = 0;
|
||||
@@ -152,6 +153,101 @@ static void patcher_host_free(void *user_data, void *mem)
|
||||
free(mem);
|
||||
}
|
||||
|
||||
vita2d_video_mode_data vita2d_get_video_mode_data(){
|
||||
return video_mode_data;
|
||||
}
|
||||
|
||||
static int vita2d_switch_video_mode(vita2d_video_mode video_mode){
|
||||
int i,x,y,err;
|
||||
|
||||
if(video_mode > video_mode_initial)
|
||||
return -1;
|
||||
switch (video_mode)
|
||||
{
|
||||
case VITA2D_VIDEO_MODE_960x544:
|
||||
video_mode_data.width = 960;
|
||||
video_mode_data.height = 544;
|
||||
video_mode_data.stride = 960;
|
||||
break;
|
||||
|
||||
case VITA2D_VIDEO_MODE_1280x720:
|
||||
video_mode_data.width = 1280;
|
||||
video_mode_data.height = 720;
|
||||
video_mode_data.stride = 1280;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
clip_rect_x_max = video_mode_data.width;
|
||||
clip_rect_y_max = video_mode_data.height;
|
||||
|
||||
if(renderTarget != NULL){
|
||||
sceGxmDestroyRenderTarget(renderTarget);
|
||||
|
||||
for (i = 0; i < DISPLAY_BUFFER_COUNT; i++) {
|
||||
// clear the buffer then deallocate
|
||||
memset(displayBufferData[i], 0, video_mode_data.height*video_mode_data.stride*4);
|
||||
gpu_free(displayBufferUid[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// allocate memory and sync objects for display buffers
|
||||
for (i = 0; i < DISPLAY_BUFFER_COUNT; i++) {
|
||||
// allocate memory for display
|
||||
displayBufferData[i] = gpu_alloc(
|
||||
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
|
||||
4*video_mode_data.stride*video_mode_data.height,
|
||||
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
|
||||
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||
&displayBufferUid[i]);
|
||||
|
||||
// memset the buffer to black
|
||||
for (y = 0; y < video_mode_data.height; y++) {
|
||||
unsigned int *row = (unsigned int *)displayBufferData[i] + y*video_mode_data.stride;
|
||||
for (x = 0; x < video_mode_data.width; x++) {
|
||||
row[x] = 0xff000000;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize a color surface for this display buffer
|
||||
err = sceGxmColorSurfaceInit(
|
||||
&displaySurface[i],
|
||||
DISPLAY_COLOR_FORMAT,
|
||||
SCE_GXM_COLOR_SURFACE_LINEAR,
|
||||
(current_msaa == SCE_GXM_MULTISAMPLE_NONE) ? SCE_GXM_COLOR_SURFACE_SCALE_NONE : SCE_GXM_COLOR_SURFACE_SCALE_MSAA_DOWNSCALE,
|
||||
SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
|
||||
video_mode_data.width,
|
||||
video_mode_data.height,
|
||||
video_mode_data.stride,
|
||||
displayBufferData[i]);
|
||||
|
||||
}
|
||||
|
||||
// set up parameters
|
||||
SceGxmRenderTargetParams renderTargetParams;
|
||||
memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams));
|
||||
renderTargetParams.flags = 0;
|
||||
renderTargetParams.width = video_mode_data.width;
|
||||
renderTargetParams.height = video_mode_data.height;
|
||||
renderTargetParams.scenesPerFrame = 1;
|
||||
renderTargetParams.multisampleMode = current_msaa;
|
||||
renderTargetParams.multisampleLocations = 0;
|
||||
renderTargetParams.driverMemBlock = -1; // Invalid UID
|
||||
|
||||
// create the render target
|
||||
err = sceGxmCreateRenderTarget(&renderTargetParams, &renderTarget);
|
||||
VITA2D_DEBUG("sceGxmCreateRenderTarget(): 0x%08X\n", err);
|
||||
|
||||
|
||||
|
||||
matrix_init_orthographic(_vita2d_ortho_matrix, 0.0f, video_mode_data.width, video_mode_data.height, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void display_callback(const void *callback_data)
|
||||
{
|
||||
SceDisplayFrameBuf framebuf;
|
||||
@@ -160,11 +256,14 @@ static void display_callback(const void *callback_data)
|
||||
memset(&framebuf, 0x00, sizeof(SceDisplayFrameBuf));
|
||||
framebuf.size = sizeof(SceDisplayFrameBuf);
|
||||
framebuf.base = display_data->address;
|
||||
framebuf.pitch = DISPLAY_STRIDE_IN_PIXELS;
|
||||
framebuf.pitch = video_mode_data.stride;
|
||||
framebuf.pixelformat = DISPLAY_PIXEL_FORMAT;
|
||||
framebuf.width = DISPLAY_WIDTH;
|
||||
framebuf.height = DISPLAY_HEIGHT;
|
||||
sceDisplaySetFrameBuf(&framebuf, SCE_DISPLAY_SETBUF_NEXTFRAME);
|
||||
framebuf.width = video_mode_data.width;
|
||||
framebuf.height = video_mode_data.height;
|
||||
if(sceDisplaySetFrameBuf(&framebuf, SCE_DISPLAY_SETBUF_NEXTFRAME) == SCE_DISPLAY_ERROR_INVALID_RESOLUTION){
|
||||
if(video_mode_initial)
|
||||
vita2d_switch_video_mode(VITA2D_VIDEO_MODE_960x544);
|
||||
}
|
||||
|
||||
if (vblank_wait) {
|
||||
sceDisplayWaitVblankStart();
|
||||
@@ -218,10 +317,10 @@ static void _vita2d_make_fragment_programs(vita2d_fragment_programs *out,
|
||||
VITA2D_DEBUG("texture_tint sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err);
|
||||
}
|
||||
|
||||
static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMode msaa)
|
||||
static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMode msaa, vita2d_video_mode video_mode)
|
||||
{
|
||||
int err;
|
||||
unsigned int i, x, y;
|
||||
unsigned int i;
|
||||
UNUSED(err);
|
||||
|
||||
if (vita2d_initialized) {
|
||||
@@ -229,6 +328,9 @@ static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMo
|
||||
return 1;
|
||||
}
|
||||
|
||||
video_mode_initial = video_mode;
|
||||
current_msaa = msaa;
|
||||
|
||||
SceGxmInitializeParams initializeParams;
|
||||
memset(&initializeParams, 0, sizeof(SceGxmInitializeParams));
|
||||
initializeParams.flags = 0;
|
||||
@@ -284,65 +386,32 @@ static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMo
|
||||
err = sceGxmCreateContext(&contextParams, &_vita2d_context);
|
||||
VITA2D_DEBUG("sceGxmCreateContext(): 0x%08X\n", err);
|
||||
|
||||
// set up parameters
|
||||
SceGxmRenderTargetParams renderTargetParams;
|
||||
memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams));
|
||||
renderTargetParams.flags = 0;
|
||||
renderTargetParams.width = DISPLAY_WIDTH;
|
||||
renderTargetParams.height = DISPLAY_HEIGHT;
|
||||
renderTargetParams.scenesPerFrame = 1;
|
||||
renderTargetParams.multisampleMode = msaa;
|
||||
renderTargetParams.multisampleLocations = 0;
|
||||
renderTargetParams.driverMemBlock = -1; // Invalid UID
|
||||
err = vita2d_switch_video_mode(video_mode);
|
||||
if(err<0){
|
||||
VITA2D_DEBUG("vita2d_switch_video_mode(): 0x%08X\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// create the render target
|
||||
err = sceGxmCreateRenderTarget(&renderTargetParams, &renderTarget);
|
||||
VITA2D_DEBUG("sceGxmCreateRenderTarget(): 0x%08X\n", err);
|
||||
vita2d_display_data displayData;
|
||||
displayData.address = displayBufferData[0];
|
||||
display_callback(&displayData);
|
||||
|
||||
// allocate memory and sync objects for display buffers
|
||||
for (i = 0; i < DISPLAY_BUFFER_COUNT; i++) {
|
||||
// allocate memory for display
|
||||
displayBufferData[i] = gpu_alloc(
|
||||
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
|
||||
4*DISPLAY_STRIDE_IN_PIXELS*DISPLAY_HEIGHT,
|
||||
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
|
||||
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||
&displayBufferUid[i]);
|
||||
|
||||
// memset the buffer to black
|
||||
for (y = 0; y < DISPLAY_HEIGHT; y++) {
|
||||
unsigned int *row = (unsigned int *)displayBufferData[i] + y*DISPLAY_STRIDE_IN_PIXELS;
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
row[x] = 0xff000000;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize a color surface for this display buffer
|
||||
err = sceGxmColorSurfaceInit(
|
||||
&displaySurface[i],
|
||||
DISPLAY_COLOR_FORMAT,
|
||||
SCE_GXM_COLOR_SURFACE_LINEAR,
|
||||
(msaa == SCE_GXM_MULTISAMPLE_NONE) ? SCE_GXM_COLOR_SURFACE_SCALE_NONE : SCE_GXM_COLOR_SURFACE_SCALE_MSAA_DOWNSCALE,
|
||||
SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
|
||||
DISPLAY_WIDTH,
|
||||
DISPLAY_HEIGHT,
|
||||
DISPLAY_STRIDE_IN_PIXELS,
|
||||
displayBufferData[i]);
|
||||
|
||||
// create a sync object that we will associate with this buffer
|
||||
err = sceGxmSyncObjectCreate(&displayBufferSync[i]);
|
||||
}
|
||||
|
||||
// compute the memory footprint of the depth buffer
|
||||
const unsigned int alignedWidth = ALIGN(DISPLAY_WIDTH, SCE_GXM_TILE_SIZEX);
|
||||
const unsigned int alignedHeight = ALIGN(DISPLAY_HEIGHT, SCE_GXM_TILE_SIZEY);
|
||||
const unsigned int alignedWidth = ALIGN(video_mode_data.width, SCE_GXM_TILE_SIZEX);
|
||||
const unsigned int alignedHeight = ALIGN(video_mode_data.height, SCE_GXM_TILE_SIZEY);
|
||||
unsigned int sampleCount = alignedWidth*alignedHeight;
|
||||
unsigned int depthStrideInSamples = alignedWidth;
|
||||
if (msaa == SCE_GXM_MULTISAMPLE_4X) {
|
||||
if (current_msaa == SCE_GXM_MULTISAMPLE_4X) {
|
||||
// samples increase in X and Y
|
||||
sampleCount *= 4;
|
||||
depthStrideInSamples *= 2;
|
||||
} else if (msaa == SCE_GXM_MULTISAMPLE_2X) {
|
||||
} else if (current_msaa == SCE_GXM_MULTISAMPLE_2X) {
|
||||
// samples increase in Y only
|
||||
sampleCount *= 2;
|
||||
}
|
||||
@@ -527,7 +596,7 @@ static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMo
|
||||
shaderPatcher,
|
||||
clearFragmentProgramId,
|
||||
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
|
||||
msaa,
|
||||
current_msaa,
|
||||
NULL,
|
||||
clearVertexProgramGxp,
|
||||
&clearFragmentProgram);
|
||||
@@ -686,8 +755,8 @@ static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMo
|
||||
VITA2D_DEBUG("texture sceGxmShaderPatcherCreateVertexProgram(): 0x%08X\n", err);
|
||||
|
||||
// Create variations of the fragment program based on blending mode
|
||||
_vita2d_make_fragment_programs(&_vita2d_fragmentPrograms.blend_mode_normal, &blend_info, msaa);
|
||||
_vita2d_make_fragment_programs(&_vita2d_fragmentPrograms.blend_mode_add, &blend_info_add, msaa);
|
||||
_vita2d_make_fragment_programs(&_vita2d_fragmentPrograms.blend_mode_normal, &blend_info, current_msaa);
|
||||
_vita2d_make_fragment_programs(&_vita2d_fragmentPrograms.blend_mode_add, &blend_info_add, current_msaa);
|
||||
|
||||
// Default to "normal" blending mode (non-additive)
|
||||
vita2d_set_blend_mode_add(0);
|
||||
@@ -713,9 +782,9 @@ static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMo
|
||||
sizeof(void *),
|
||||
SCE_GXM_MEMORY_ATTRIB_READ,
|
||||
&poolUid);
|
||||
|
||||
|
||||
matrix_init_orthographic(_vita2d_ortho_matrix, 0.0f, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
matrix_init_orthographic(_vita2d_ortho_matrix, 0.0f, video_mode_data.width, video_mode_data.height, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
backBufferIndex = 0;
|
||||
frontBufferIndex = 0;
|
||||
@@ -731,22 +800,23 @@ static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMo
|
||||
|
||||
int vita2d_init()
|
||||
{
|
||||
return vita2d_init_internal(DEFAULT_TEMP_POOL_SIZE, SCE_GXM_MULTISAMPLE_NONE);
|
||||
return vita2d_init_internal(DEFAULT_TEMP_POOL_SIZE, SCE_GXM_MULTISAMPLE_NONE, VITA2D_VIDEO_MODE_960x544);
|
||||
}
|
||||
|
||||
int vita2d_init_advanced(unsigned int temp_pool_size)
|
||||
{
|
||||
return vita2d_init_internal(temp_pool_size, SCE_GXM_MULTISAMPLE_NONE);
|
||||
return vita2d_init_internal(temp_pool_size, SCE_GXM_MULTISAMPLE_NONE, VITA2D_VIDEO_MODE_960x544);
|
||||
}
|
||||
|
||||
int vita2d_init_advanced_with_msaa(unsigned int temp_pool_size, SceGxmMultisampleMode msaa)
|
||||
int vita2d_init_advanced_with_msaa(unsigned int temp_pool_size, SceGxmMultisampleMode msaa, vita2d_video_mode video_mode)
|
||||
{
|
||||
return vita2d_init_internal(temp_pool_size, msaa);
|
||||
return vita2d_init_internal(temp_pool_size, msaa, video_mode);
|
||||
}
|
||||
|
||||
void vita2d_wait_rendering_done()
|
||||
{
|
||||
sceGxmFinish(_vita2d_context);
|
||||
if(vita2d_initialized)
|
||||
sceGxmFinish(_vita2d_context);
|
||||
}
|
||||
|
||||
int vita2d_fini()
|
||||
@@ -780,7 +850,7 @@ int vita2d_fini()
|
||||
gpu_free(depthBufferUid);
|
||||
for (i = 0; i < DISPLAY_BUFFER_COUNT; i++) {
|
||||
// clear the buffer then deallocate
|
||||
memset(displayBufferData[i], 0, DISPLAY_HEIGHT*DISPLAY_STRIDE_IN_PIXELS*4);
|
||||
memset(displayBufferData[i], 0, video_mode_data.height*video_mode_data.stride*4);
|
||||
gpu_free(displayBufferUid[i]);
|
||||
|
||||
// destroy the sync object
|
||||
@@ -808,6 +878,7 @@ int vita2d_fini()
|
||||
|
||||
// destroy the render target
|
||||
sceGxmDestroyRenderTarget(renderTarget);
|
||||
renderTarget = NULL;
|
||||
|
||||
// destroy the _vita2d_context
|
||||
sceGxmDestroyContext(_vita2d_context);
|
||||
@@ -933,7 +1004,7 @@ int vita2d_get_clipping_enabled()
|
||||
|
||||
void vita2d_set_clip_rectangle(int x_min, int y_min, int x_max, int y_max)
|
||||
{
|
||||
vita2d_set_viewport(0,0,DISPLAY_WIDTH,DISPLAY_HEIGHT);
|
||||
vita2d_set_viewport(0,0,video_mode_data.width,video_mode_data.height);
|
||||
clipping_enabled = 1;
|
||||
clip_rect_x_min = x_min;
|
||||
clip_rect_y_min = y_min;
|
||||
@@ -952,7 +1023,7 @@ void vita2d_set_clip_rectangle(int x_min, int y_min, int x_max, int y_max)
|
||||
SCE_GXM_STENCIL_OP_ZERO,
|
||||
0xFF,
|
||||
0xFF);
|
||||
vita2d_draw_rectangle(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0);
|
||||
vita2d_draw_rectangle(0, 0, video_mode_data.width, video_mode_data.height, 0);
|
||||
// set the stencil to 1 in the desired region
|
||||
sceGxmSetFrontStencilFunc(
|
||||
_vita2d_context,
|
||||
@@ -1003,9 +1074,9 @@ int vita2d_common_dialog_update()
|
||||
|
||||
updateParam.renderTarget.colorFormat = DISPLAY_COLOR_FORMAT;
|
||||
updateParam.renderTarget.surfaceType = SCE_GXM_COLOR_SURFACE_LINEAR;
|
||||
updateParam.renderTarget.width = DISPLAY_WIDTH;
|
||||
updateParam.renderTarget.height = DISPLAY_HEIGHT;
|
||||
updateParam.renderTarget.strideInPixels = DISPLAY_STRIDE_IN_PIXELS;
|
||||
updateParam.renderTarget.width = video_mode_data.width;
|
||||
updateParam.renderTarget.height = video_mode_data.height;
|
||||
updateParam.renderTarget.strideInPixels = video_mode_data.stride;
|
||||
|
||||
updateParam.renderTarget.colorSurfaceData = displayBufferData[backBufferIndex];
|
||||
updateParam.renderTarget.depthSurfaceData = depthBufferData;
|
||||
@@ -1100,7 +1171,7 @@ void vita2d_set_blend_mode_add(int enable)
|
||||
}
|
||||
|
||||
void vita2d_set_viewport(int x, int y, int width, int height){
|
||||
static float vh = DISPLAY_HEIGHT;
|
||||
float vh = video_mode_data.height;
|
||||
float sw = width / 2.;
|
||||
float sh = height / 2.;
|
||||
float x_scale = sw;
|
||||
|
||||
Vendored
-476
@@ -1,476 +0,0 @@
|
||||
PTHREADS-WIN32 RELEASE 2.8.0 (2006-12-22)
|
||||
-----------------------------------------
|
||||
Web Site: http://sources.redhat.com/pthreads-win32/
|
||||
FTP Site: ftp://sources.redhat.com/pub/pthreads-win32
|
||||
Maintainer: Ross Johnson <[email protected]>
|
||||
|
||||
|
||||
We are pleased to announce the availability of a new release of
|
||||
Pthreads-win32, an Open Source Software implementation of the
|
||||
Threads component of the POSIX 1003.1 2001 Standard for Microsoft's
|
||||
Win32 environment. Some functions from other sections of POSIX
|
||||
1003.1 2001 are also supported including semaphores and scheduling
|
||||
functions.
|
||||
|
||||
Some common non-portable functions are also implemented for
|
||||
additional compatibility, as are a few functions specific
|
||||
to pthreads-win32 for easier integration with Win32 applications.
|
||||
|
||||
Pthreads-win32 is free software, distributed under the GNU Lesser
|
||||
General Public License (LGPL).
|
||||
|
||||
|
||||
Acknowledgements
|
||||
----------------
|
||||
This library is based originally on a Win32 pthreads
|
||||
implementation contributed by John Bossom <[email protected]>.
|
||||
|
||||
The implementation of Condition Variables uses algorithms developed
|
||||
by Alexander Terekhov and Louis Thomas.
|
||||
|
||||
The implementation of POSIX mutexes has been improved by Thomas Pfaff
|
||||
and later by Alexander Terekhov.
|
||||
|
||||
The implementation of Spinlocks and Barriers was contributed
|
||||
by Ross Johnson.
|
||||
|
||||
The implementation of read/write locks was contributed by
|
||||
Aurelio Medina and improved by Alexander Terekhov.
|
||||
|
||||
Many others have contributed significant time and effort to solve crutial
|
||||
problems in order to make the library workable, robust and reliable.
|
||||
|
||||
Thanks to Xavier Leroy for granting permission to use and modify his
|
||||
LinuxThreads manual pages.
|
||||
|
||||
Thanks to The Open Group for making the Single Unix Specification
|
||||
publicly available - many of the manual pages included in the package
|
||||
were extracted from it.
|
||||
|
||||
There is also a separate CONTRIBUTORS file. This file and others are
|
||||
on the web site:
|
||||
|
||||
http://sources.redhat.com/pthreads-win32
|
||||
|
||||
As much as possible, the ChangeLog file acknowledges contributions to the
|
||||
code base in more detail.
|
||||
|
||||
|
||||
Changes since the last release
|
||||
------------------------------
|
||||
These are now documented in the NEWS file.
|
||||
See the ChangeLog file also.
|
||||
|
||||
|
||||
Known Bugs
|
||||
----------
|
||||
These are now documented in the BUGS file.
|
||||
|
||||
|
||||
Level of standards conformance
|
||||
------------------------------
|
||||
|
||||
The following POSIX 1003.1 2001 options are defined and set to 200112L:
|
||||
|
||||
_POSIX_THREADS
|
||||
_POSIX_THREAD_SAFE_FUNCTIONS
|
||||
_POSIX_THREAD_ATTR_STACKSIZE
|
||||
_POSIX_THREAD_PRIORITY_SCHEDULING
|
||||
_POSIX_SEMAPHORES
|
||||
_POSIX_READER_WRITER_LOCKS
|
||||
_POSIX_SPIN_LOCKS
|
||||
_POSIX_BARRIERS
|
||||
|
||||
|
||||
The following POSIX 1003.1 2001 options are defined and set to -1:
|
||||
|
||||
_POSIX_THREAD_ATTR_STACKADDR
|
||||
_POSIX_THREAD_PRIO_INHERIT
|
||||
_POSIX_THREAD_PRIO_PROTECT
|
||||
_POSIX_THREAD_PROCESS_SHARED
|
||||
|
||||
|
||||
The following POSIX 1003.1 2001 limits are defined and set:
|
||||
|
||||
_POSIX_THREAD_THREADS_MAX
|
||||
_POSIX_SEM_VALUE_MAX
|
||||
_POSIX_SEM_NSEMS_MAX
|
||||
_POSIX_THREAD_KEYS_MAX
|
||||
_POSIX_THREAD_DESTRUCTOR_ITERATIONS
|
||||
PTHREAD_STACK_MIN
|
||||
PTHREAD_THREADS_MAX
|
||||
SEM_VALUE_MAX
|
||||
SEM_NSEMS_MAX
|
||||
PTHREAD_KEYS_MAX
|
||||
PTHREAD_DESTRUCTOR_ITERATIONS
|
||||
|
||||
|
||||
The following functions are implemented:
|
||||
|
||||
---------------------------
|
||||
PThreads
|
||||
---------------------------
|
||||
pthread_attr_init
|
||||
pthread_attr_destroy
|
||||
pthread_attr_getdetachstate
|
||||
pthread_attr_getstackaddr
|
||||
pthread_attr_getstacksize
|
||||
pthread_attr_setdetachstate
|
||||
pthread_attr_setstackaddr
|
||||
pthread_attr_setstacksize
|
||||
|
||||
pthread_create
|
||||
pthread_detach
|
||||
pthread_equal
|
||||
pthread_exit
|
||||
pthread_join
|
||||
pthread_once
|
||||
pthread_self
|
||||
|
||||
pthread_cancel
|
||||
pthread_cleanup_pop
|
||||
pthread_cleanup_push
|
||||
pthread_setcancelstate
|
||||
pthread_setcanceltype
|
||||
pthread_testcancel
|
||||
|
||||
---------------------------
|
||||
Thread Specific Data
|
||||
---------------------------
|
||||
pthread_key_create
|
||||
pthread_key_delete
|
||||
pthread_setspecific
|
||||
pthread_getspecific
|
||||
|
||||
---------------------------
|
||||
Mutexes
|
||||
---------------------------
|
||||
pthread_mutexattr_init
|
||||
pthread_mutexattr_destroy
|
||||
pthread_mutexattr_getpshared
|
||||
pthread_mutexattr_setpshared
|
||||
pthread_mutexattr_gettype
|
||||
pthread_mutexattr_settype (types: PTHREAD_MUTEX_DEFAULT
|
||||
PTHREAD_MUTEX_NORMAL
|
||||
PTHREAD_MUTEX_ERRORCHECK
|
||||
PTHREAD_MUTEX_RECURSIVE )
|
||||
pthread_mutex_init
|
||||
pthread_mutex_destroy
|
||||
pthread_mutex_lock
|
||||
pthread_mutex_trylock
|
||||
pthread_mutex_timedlock
|
||||
pthread_mutex_unlock
|
||||
|
||||
---------------------------
|
||||
Condition Variables
|
||||
---------------------------
|
||||
pthread_condattr_init
|
||||
pthread_condattr_destroy
|
||||
pthread_condattr_getpshared
|
||||
pthread_condattr_setpshared
|
||||
|
||||
pthread_cond_init
|
||||
pthread_cond_destroy
|
||||
pthread_cond_wait
|
||||
pthread_cond_timedwait
|
||||
pthread_cond_signal
|
||||
pthread_cond_broadcast
|
||||
|
||||
---------------------------
|
||||
Read/Write Locks
|
||||
---------------------------
|
||||
pthread_rwlock_init
|
||||
pthread_rwlock_destroy
|
||||
pthread_rwlock_tryrdlock
|
||||
pthread_rwlock_trywrlock
|
||||
pthread_rwlock_rdlock
|
||||
pthread_rwlock_timedrdlock
|
||||
pthread_rwlock_rwlock
|
||||
pthread_rwlock_timedwrlock
|
||||
pthread_rwlock_unlock
|
||||
pthread_rwlockattr_init
|
||||
pthread_rwlockattr_destroy
|
||||
pthread_rwlockattr_getpshared
|
||||
pthread_rwlockattr_setpshared
|
||||
|
||||
---------------------------
|
||||
Spin Locks
|
||||
---------------------------
|
||||
pthread_spin_init
|
||||
pthread_spin_destroy
|
||||
pthread_spin_lock
|
||||
pthread_spin_unlock
|
||||
pthread_spin_trylock
|
||||
|
||||
---------------------------
|
||||
Barriers
|
||||
---------------------------
|
||||
pthread_barrier_init
|
||||
pthread_barrier_destroy
|
||||
pthread_barrier_wait
|
||||
pthread_barrierattr_init
|
||||
pthread_barrierattr_destroy
|
||||
pthread_barrierattr_getpshared
|
||||
pthread_barrierattr_setpshared
|
||||
|
||||
---------------------------
|
||||
Semaphores
|
||||
---------------------------
|
||||
sem_init
|
||||
sem_destroy
|
||||
sem_post
|
||||
sem_wait
|
||||
sem_trywait
|
||||
sem_timedwait
|
||||
sem_getvalue (# free if +ve, # of waiters if -ve)
|
||||
sem_open (returns an error ENOSYS)
|
||||
sem_close (returns an error ENOSYS)
|
||||
sem_unlink (returns an error ENOSYS)
|
||||
|
||||
---------------------------
|
||||
RealTime Scheduling
|
||||
---------------------------
|
||||
pthread_attr_getschedparam
|
||||
pthread_attr_setschedparam
|
||||
pthread_attr_getinheritsched
|
||||
pthread_attr_setinheritsched
|
||||
pthread_attr_getschedpolicy (only supports SCHED_OTHER)
|
||||
pthread_attr_setschedpolicy (only supports SCHED_OTHER)
|
||||
pthread_getschedparam
|
||||
pthread_setschedparam
|
||||
pthread_getconcurrency
|
||||
pthread_setconcurrency
|
||||
pthread_attr_getscope
|
||||
pthread_attr_setscope (only supports PTHREAD_SCOPE_SYSTEM)
|
||||
sched_get_priority_max
|
||||
sched_get_priority_min
|
||||
sched_rr_get_interval (returns an error ENOTSUP)
|
||||
sched_setscheduler (only supports SCHED_OTHER)
|
||||
sched_getscheduler (only supports SCHED_OTHER)
|
||||
sched_yield
|
||||
|
||||
---------------------------
|
||||
Signals
|
||||
---------------------------
|
||||
pthread_sigmask
|
||||
pthread_kill (only supports zero sig value,
|
||||
for thread validity checking)
|
||||
|
||||
---------------------------
|
||||
Non-portable routines (see the README.NONPORTABLE file for usage)
|
||||
---------------------------
|
||||
pthread_getw32threadhandle_np
|
||||
pthread_timechange_handler_np
|
||||
pthread_delay_np
|
||||
pthread_mutexattr_getkind_np
|
||||
pthread_mutexattr_setkind_np (types: PTHREAD_MUTEX_FAST_NP,
|
||||
PTHREAD_MUTEX_ERRORCHECK_NP,
|
||||
PTHREAD_MUTEX_RECURSIVE_NP,
|
||||
PTHREAD_MUTEX_ADAPTIVE_NP,
|
||||
PTHREAD_MUTEX_TIMED_NP)
|
||||
pthread_num_processors_np
|
||||
pthread_win32_process_attach_np (Required when statically linking
|
||||
the library)
|
||||
pthread_win32_process_detach_np (Required when statically linking
|
||||
the library)
|
||||
pthread_win32_thread_attach_np (Required when statically linking
|
||||
the library)
|
||||
pthread_win32_thread_detach_np (Required when statically linking
|
||||
the library)
|
||||
|
||||
---------------------------
|
||||
Static Initializers
|
||||
---------------------------
|
||||
PTHREAD_ONCE_INIT
|
||||
PTHREAD_MUTEX_INITIALIZER
|
||||
PTHREAD_RECURSIVE_MUTEX_INITIALIZER
|
||||
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
|
||||
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
|
||||
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
|
||||
PTHREAD_COND_INITIALIZER
|
||||
PTHREAD_RWLOCK_INITIALIZER
|
||||
PTHREAD_SPINLOCK_INITIALIZER
|
||||
|
||||
---------------------------
|
||||
Thread-Safe C Runtime Library (macros)
|
||||
---------------------------
|
||||
strtok_r
|
||||
asctime_r
|
||||
ctime_r
|
||||
gmtime_r
|
||||
localtime_r
|
||||
rand_r
|
||||
|
||||
|
||||
The following functions are not implemented:
|
||||
|
||||
---------------------------
|
||||
RealTime Scheduling
|
||||
---------------------------
|
||||
pthread_mutex_getprioceiling
|
||||
pthread_mutex_setprioceiling
|
||||
pthread_mutex_attr_getprioceiling
|
||||
pthread_mutex_attr_getprotocol
|
||||
pthread_mutex_attr_setprioceiling
|
||||
pthread_mutex_attr_setprotocol
|
||||
|
||||
---------------------------
|
||||
Fork Handlers
|
||||
---------------------------
|
||||
pthread_atfork
|
||||
|
||||
---------------------------
|
||||
Stdio
|
||||
---------------------------
|
||||
flockfile
|
||||
ftrylockfile
|
||||
funlockfile
|
||||
getc_unlocked
|
||||
getchar_unlocked
|
||||
putc_unlocked
|
||||
putchar_unlocked
|
||||
|
||||
---------------------------
|
||||
Thread-Safe C Runtime Library
|
||||
---------------------------
|
||||
readdir_r
|
||||
getgrgid_r
|
||||
getgrnam_r
|
||||
getpwuid_r
|
||||
getpwnam_r
|
||||
|
||||
---------------------------
|
||||
Signals
|
||||
---------------------------
|
||||
sigtimedwait
|
||||
sigwait
|
||||
sigwaitinfo
|
||||
|
||||
---------------------------
|
||||
General
|
||||
---------------------------
|
||||
sysconf
|
||||
|
||||
The library includes two non-API functions for creating cancellation
|
||||
points in applications and libraries:
|
||||
|
||||
pthreadCancelableWait
|
||||
pthreadCancelableTimedWait
|
||||
|
||||
|
||||
Availability
|
||||
------------
|
||||
|
||||
The prebuilt DLL, export libs (for both MSVC and Mingw32), and the header
|
||||
files (pthread.h, semaphore.h, sched.h) are available along with the
|
||||
complete source code.
|
||||
|
||||
The source code can be found at:
|
||||
|
||||
ftp://sources.redhat.com/pub/pthreads-win32
|
||||
|
||||
and as individual source code files at
|
||||
|
||||
ftp://sources.redhat.com/pub/pthreads-win32/source
|
||||
|
||||
The pre-built DLL, export libraries and include files can be found at:
|
||||
|
||||
ftp://sources.redhat.com/pub/pthreads-win32/dll-latest
|
||||
|
||||
|
||||
|
||||
Mailing List
|
||||
------------
|
||||
|
||||
There is a mailing list for discussing pthreads on Win32. To join,
|
||||
send email to:
|
||||
|
||||
[email protected]
|
||||
|
||||
|
||||
Application Development Environments
|
||||
------------------------------------
|
||||
|
||||
See the README file for more information.
|
||||
|
||||
MSVC:
|
||||
MSVC using SEH works. Distribute pthreadVSE.dll with your application.
|
||||
MSVC using C++ EH works. Distribute pthreadVCE.dll with your application.
|
||||
MSVC using C setjmp/longjmp works. Distribute pthreadVC.dll with your application.
|
||||
|
||||
|
||||
Mingw32:
|
||||
See the FAQ, Questions 6 and 10.
|
||||
|
||||
Mingw using C++ EH works. Distribute pthreadGCE.dll with your application.
|
||||
Mingw using C setjmp/longjmp works. Distribute pthreadGC.dll with your application.
|
||||
|
||||
|
||||
Cygwin: (http://sourceware.cygnus.com/cygwin/)
|
||||
Developers using Cygwin will not need pthreads-win32 since it has POSIX threads
|
||||
support. Refer to its documentation for details and extent.
|
||||
|
||||
|
||||
UWIN:
|
||||
UWIN is a complete Unix-like environment for Windows from AT&T. Pthreads-win32
|
||||
doesn't currently support UWIN (and vice versa), but that may change in the
|
||||
future.
|
||||
|
||||
Generally:
|
||||
For convenience, the following pre-built files are available on the FTP site
|
||||
(see Availability above):
|
||||
|
||||
pthread.h - for POSIX 1c threads
|
||||
semaphore.h - for POSIX 1b semaphores
|
||||
sched.h - for POSIX 1b scheduling
|
||||
pthreadVCE.dll - built with MSVC++ compiler using C++ EH
|
||||
pthreadVCE.lib
|
||||
pthreadVC.dll - built with MSVC compiler using C setjmp/longjmp
|
||||
pthreadVC.lib
|
||||
pthreadVSE.dll - built with MSVC compiler using SEH
|
||||
pthreadVSE.lib
|
||||
pthreadGCE.dll - built with Mingw32 G++ 2.95.2-1
|
||||
pthreadGC.dll - built with Mingw32 GCC 2.95.2-1 using setjmp/longjmp
|
||||
libpthreadGCE.a - derived from pthreadGCE.dll
|
||||
libpthreadGC.a - derived from pthreadGC.dll
|
||||
gcc.dll - needed if distributing applications that use
|
||||
pthreadGCE.dll (but see the FAQ Q 10 for the latest
|
||||
related information)
|
||||
|
||||
These are the only files you need in order to build POSIX threads
|
||||
applications for Win32 using either MSVC or Mingw32.
|
||||
|
||||
See the FAQ file in the source tree for additional information.
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
For the authoritative reference, see the online POSIX
|
||||
standard reference at:
|
||||
|
||||
http://www.OpenGroup.org
|
||||
|
||||
For POSIX Thread API programming, several reference books are
|
||||
available:
|
||||
|
||||
Programming with POSIX Threads
|
||||
David R. Butenhof
|
||||
Addison-Wesley (pub)
|
||||
|
||||
Pthreads Programming
|
||||
By Bradford Nichols, Dick Buttlar & Jacqueline Proulx Farrell
|
||||
O'Reilly (pub)
|
||||
|
||||
On the web: see the links at the bottom of the pthreads-win32 site:
|
||||
|
||||
http://sources.redhat.com/pthreads-win32/
|
||||
|
||||
Currently, there is no documentation included in the package apart
|
||||
from the copious comments in the source code.
|
||||
|
||||
|
||||
|
||||
Enjoy!
|
||||
|
||||
Ross Johnson
|
||||
Vendored
-129
@@ -1,129 +0,0 @@
|
||||
Contributors (in approximate order of appearance)
|
||||
|
||||
[See also the ChangeLog file where individuals are
|
||||
attributed in log entries. Likewise in the FAQ file.]
|
||||
|
||||
Ben Elliston bje at cygnus dot com
|
||||
Initiated the project;
|
||||
setup the project infrastructure (CVS, web page, etc.);
|
||||
early prototype routines.
|
||||
Ross Johnson rpj at callisto dot canberra dot edu dot au
|
||||
early prototype routines;
|
||||
ongoing project coordination/maintenance;
|
||||
implementation of spin locks and barriers;
|
||||
various enhancements;
|
||||
bug fixes;
|
||||
documentation;
|
||||
testsuite.
|
||||
Robert Colquhoun rjc at trump dot net dot au
|
||||
Early bug fixes.
|
||||
John E. Bossom John dot Bossom at cognos dot com
|
||||
Contributed substantial original working implementation;
|
||||
bug fixes;
|
||||
ongoing guidance and standards interpretation.
|
||||
Anders Norlander anorland at hem2 dot passagen dot se
|
||||
Early enhancements and runtime checking for supported
|
||||
Win32 routines.
|
||||
Tor Lillqvist tml at iki dot fi
|
||||
General enhancements;
|
||||
early bug fixes to condition variables.
|
||||
Scott Lightner scott at curriculum dot com
|
||||
Bug fix.
|
||||
Kevin Ruland Kevin dot Ruland at anheuser-busch dot com
|
||||
Various bug fixes.
|
||||
Mike Russo miker at eai dot com
|
||||
Bug fix.
|
||||
Mark E. Armstrong avail at pacbell dot net
|
||||
Bug fixes.
|
||||
Lorin Hochstein lmh at xiphos dot ca
|
||||
general bug fixes; bug fixes to condition variables.
|
||||
Peter Slacik Peter dot Slacik at tatramed dot sk
|
||||
Bug fixes.
|
||||
Mumit Khan khan at xraylith dot wisc dot edu
|
||||
Fixes to work with Mingw32.
|
||||
Milan Gardian mg at tatramed dot sk
|
||||
Bug fixes and reports/analyses of obscure problems.
|
||||
Aurelio Medina aureliom at crt dot com
|
||||
First implementation of read-write locks.
|
||||
Graham Dumpleton Graham dot Dumpleton at ra dot pad dot otc dot telstra dot com dot au
|
||||
Bug fix in condition variables.
|
||||
Tristan Savatier tristan at mpegtv dot com
|
||||
WinCE port.
|
||||
Erik Hensema erik at hensema dot xs4all dot nl
|
||||
Bug fixes.
|
||||
Rich Peters rpeters at micro-magic dot com
|
||||
Todd Owen towen at lucidcalm dot dropbear dot id dot au
|
||||
Bug fixes to dll loading.
|
||||
Jason Nye jnye at nbnet dot nb dot ca
|
||||
Implementation of async cancelation.
|
||||
Fred Forester fforest at eticomm dot net
|
||||
Kevin D. Clark kclark at cabletron dot com
|
||||
David Baggett dmb at itasoftware dot com
|
||||
Bug fixes.
|
||||
Paul Redondo paul at matchvision dot com
|
||||
Scott McCaskill scott at 3dfx dot com
|
||||
Bug fixes.
|
||||
Jef Gearhart jgearhart at tpssys dot com
|
||||
Bug fix.
|
||||
Arthur Kantor akantor at bexusa dot com
|
||||
Mutex enhancements.
|
||||
Steven Reddie smr at essemer dot com dot au
|
||||
Bug fix.
|
||||
Alexander Terekhov TEREKHOV at de dot ibm dot com
|
||||
Re-implemented and improved read-write locks;
|
||||
(with Louis Thomas) re-implemented and improved
|
||||
condition variables;
|
||||
enhancements to semaphores;
|
||||
enhancements to mutexes;
|
||||
new mutex implementation in 'futex' style;
|
||||
suggested a robust implementation of pthread_once
|
||||
similar to that implemented by V.Kliathcko;
|
||||
system clock change handling re CV timeouts;
|
||||
bug fixes.
|
||||
Thomas Pfaff tpfaff at gmx dot net
|
||||
Changes to make C version usable with C++ applications;
|
||||
re-implemented mutex routines to avoid Win32 mutexes
|
||||
and TryEnterCriticalSection;
|
||||
procedure to fix Mingw32 thread-safety issues.
|
||||
Franco Bez franco dot bez at gmx dot de
|
||||
procedure to fix Mingw32 thread-safety issues.
|
||||
Louis Thomas lthomas at arbitrade dot com
|
||||
(with Alexander Terekhov) re-implemented and improved
|
||||
condition variables.
|
||||
David Korn dgk at research dot att dot com
|
||||
Ported to UWIN.
|
||||
Phil Frisbie, Jr. phil at hawksoft dot com
|
||||
Bug fix.
|
||||
Ralf Brese Ralf dot Brese at pdb4 dot siemens dot de
|
||||
Bug fix.
|
||||
prionx at juno dot com prionx at juno dot com
|
||||
Bug fixes.
|
||||
Max Woodbury mtew at cds dot duke dot edu
|
||||
POSIX versioning conditionals;
|
||||
reduced namespace pollution;
|
||||
idea to separate routines to reduce statically
|
||||
linked image sizes.
|
||||
Rob Fanner rfanner at stonethree dot com
|
||||
Bug fix.
|
||||
Michael Johnson michaelj at maine dot rr dot com
|
||||
Bug fix.
|
||||
Nicolas Barry boozai at yahoo dot com
|
||||
Bug fixes.
|
||||
Piet van Bruggen pietvb at newbridges dot nl
|
||||
Bug fix.
|
||||
Makoto Kato raven at oldskool dot jp
|
||||
AMD64 port.
|
||||
Panagiotis E. Hadjidoukas peh at hpclab dot ceid dot upatras dot gr
|
||||
Contributed the QueueUserAPCEx package which
|
||||
makes preemptive async cancelation possible.
|
||||
Will Bryant will dot bryant at ecosm dot com
|
||||
Borland compiler patch and makefile.
|
||||
Anuj Goyal anuj dot goyal at gmail dot com
|
||||
Port to Digital Mars compiler.
|
||||
Gottlob Frege gottlobfrege at gmail dot com
|
||||
re-implemented pthread_once (version 2)
|
||||
(pthread_once cancellation added by rpj).
|
||||
Vladimir Kliatchko vladimir at kliatchko dot com
|
||||
reimplemented pthread_once with the same form
|
||||
as described by A.Terekhov (later version 2);
|
||||
implementation of MCS (Mellor-Crummey/Scott) locks.
|
||||
Vendored
-150
@@ -1,150 +0,0 @@
|
||||
pthreads-win32 - a POSIX threads library for Microsoft Windows
|
||||
|
||||
|
||||
This file is Copyrighted
|
||||
------------------------
|
||||
|
||||
This file is covered under the following Copyright:
|
||||
|
||||
Copyright (C) 2001,2006 Ross P. Johnson
|
||||
All rights reserved.
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Pthreads-win32 is covered by the GNU Lesser General Public License
|
||||
------------------------------------------------------------------
|
||||
|
||||
Pthreads-win32 is open software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License
|
||||
as published by the Free Software Foundation version 2.1 of the
|
||||
License.
|
||||
|
||||
Pthreads-win32 is several binary link libraries, several modules,
|
||||
associated interface definition files and scripts used to control
|
||||
its compilation and installation.
|
||||
|
||||
Pthreads-win32 is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
A copy of the GNU Lesser General Public License is distributed with
|
||||
pthreads-win32 under the filename:
|
||||
|
||||
COPYING.LIB
|
||||
|
||||
You should have received a copy of the version 2.1 GNU Lesser General
|
||||
Public License with pthreads-win32; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place
|
||||
Suite 330
|
||||
Boston, MA 02111-1307
|
||||
USA
|
||||
|
||||
The contact addresses for pthreads-win32 is as follows:
|
||||
|
||||
Web: http://sources.redhat.com/pthreads-win32
|
||||
Email: Ross Johnson
|
||||
Please use: [email protected]
|
||||
|
||||
|
||||
|
||||
Pthreads-win32 copyrights and exception files
|
||||
---------------------------------------------
|
||||
|
||||
With the exception of the files listed below, Pthreads-win32
|
||||
is covered under the following GNU Lesser General Public License
|
||||
Copyrights:
|
||||
|
||||
Pthreads-win32 - POSIX Threads Library for Win32
|
||||
Copyright(C) 1998 John E. Bossom
|
||||
Copyright(C) 1999,2006 Pthreads-win32 contributors
|
||||
|
||||
The current list of contributors is contained
|
||||
in the file CONTRIBUTORS included with the source
|
||||
code distribution. The current list of CONTRIBUTORS
|
||||
can also be seen at the following WWW location:
|
||||
http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
|
||||
Contact Email: Ross Johnson
|
||||
Please use: [email protected]
|
||||
|
||||
These files are not covered under one of the Copyrights listed above:
|
||||
|
||||
COPYING
|
||||
COPYING.LIB
|
||||
tests/rwlock7.c
|
||||
|
||||
This file, COPYING, is distributed under the Copyright found at the
|
||||
top of this file. It is important to note that you may distribute
|
||||
verbatim copies of this file but you may not modify this file.
|
||||
|
||||
The file COPYING.LIB, which contains a copy of the version 2.1
|
||||
GNU Lesser General Public License, is itself copyrighted by the
|
||||
Free Software Foundation, Inc. Please note that the Free Software
|
||||
Foundation, Inc. does NOT have a copyright over Pthreads-win32,
|
||||
only the COPYING.LIB that is supplied with pthreads-win32.
|
||||
|
||||
The file tests/rwlock7.c is derived from code written by
|
||||
Dave Butenhof for his book 'Programming With POSIX(R) Threads'.
|
||||
The original code was obtained by free download from his website
|
||||
http://home.earthlink.net/~anneart/family/Threads/source.html
|
||||
and did not contain a copyright or author notice. It is assumed to
|
||||
be freely distributable.
|
||||
|
||||
In all cases one may use and distribute these exception files freely.
|
||||
And because one may freely distribute the LGPL covered files, the
|
||||
entire pthreads-win32 source may be freely used and distributed.
|
||||
|
||||
|
||||
|
||||
General Copyleft and License info
|
||||
---------------------------------
|
||||
|
||||
For general information on Copylefts, see:
|
||||
|
||||
http://www.gnu.org/copyleft/
|
||||
|
||||
For information on GNU Lesser General Public Licenses, see:
|
||||
|
||||
http://www.gnu.org/copyleft/lesser.html
|
||||
http://www.gnu.org/copyleft/lesser.txt
|
||||
|
||||
|
||||
Why pthreads-win32 did not use the GNU General Public License
|
||||
-------------------------------------------------------------
|
||||
|
||||
The goal of the pthreads-win32 project has been to
|
||||
provide a quality and complete implementation of the POSIX
|
||||
threads API for Microsoft Windows within the limits imposed
|
||||
by virtue of it being a stand-alone library and not
|
||||
linked directly to other POSIX compliant libraries. For
|
||||
example, some functions and features, such as those based
|
||||
on POSIX signals, are missing.
|
||||
|
||||
Pthreads-win32 is a library, available in several different
|
||||
versions depending on supported compilers, and may be used
|
||||
as a dynamically linked module or a statically linked set of
|
||||
binary modules. It is not an application on it's own.
|
||||
|
||||
It was fully intended that pthreads-win32 be usable with
|
||||
commercial software not covered by either the GPL or the LGPL
|
||||
licenses. Pthreads-win32 has many contributors to it's
|
||||
code base, many of whom have done so because they have
|
||||
used the library in commercial or proprietry software
|
||||
projects.
|
||||
|
||||
Releasing pthreads-win32 under the LGPL ensures that the
|
||||
library can be used widely, while at the same time ensures
|
||||
that bug fixes and improvements to the pthreads-win32 code
|
||||
itself is returned to benefit all current and future users
|
||||
of the library.
|
||||
|
||||
Although pthreads-win32 makes it possible for applications
|
||||
that use POSIX threads to be ported to Win32 platforms, the
|
||||
broader goal of the project is to encourage the use of open
|
||||
standards, and in particular, to make it just a little easier
|
||||
for developers writing Win32 applications to consider
|
||||
widening the potential market for their products.
|
||||
Vendored
-504
@@ -1,504 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
Vendored
-516
@@ -1,516 +0,0 @@
|
||||
/*
|
||||
* implement.h
|
||||
*
|
||||
* Definitions that don't need to be public.
|
||||
*
|
||||
* Keeps all the internals out of pthread.h
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _IMPLEMENT_H
|
||||
#define _IMPLEMENT_H
|
||||
|
||||
#include "pte_osal.h"
|
||||
|
||||
/* use local include files during development */
|
||||
#include "semaphore.h"
|
||||
#include "sched.h"
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/*
|
||||
* This enumeration represents the state of the thread;
|
||||
* The thread is still "alive" if the numeric value of the
|
||||
* state is greater or equal "PThreadStateRunning".
|
||||
*/
|
||||
PThreadStateInitial = 0, /* Thread not running */
|
||||
PThreadStateRunning, /* Thread alive & kicking */
|
||||
PThreadStateSuspended, /* Thread alive but suspended */
|
||||
PThreadStateCancelPending, /* Thread alive but is */
|
||||
/* has cancelation pending. */
|
||||
PThreadStateCanceling, /* Thread alive but is */
|
||||
/* in the process of terminating */
|
||||
/* due to a cancellation request */
|
||||
PThreadStateException, /* Thread alive but exiting */
|
||||
/* due to an exception */
|
||||
PThreadStateLast
|
||||
}
|
||||
PThreadState;
|
||||
|
||||
|
||||
typedef struct pte_thread_t_ pte_thread_t;
|
||||
|
||||
struct pte_thread_t_
|
||||
{
|
||||
pte_osThreadHandle threadId; /* OS specific thread handle */
|
||||
// pthread_t ptHandle; /* This thread's permanent pthread_t handle */
|
||||
pte_thread_t * prevReuse; /* Links threads on reuse stack */
|
||||
volatile PThreadState state;
|
||||
void *exitStatus;
|
||||
void *parms;
|
||||
int ptErrno;
|
||||
int detachState;
|
||||
pthread_mutex_t threadLock; /* Used for serialised access to public thread state */
|
||||
int sched_priority; /* As set, not as currently is */
|
||||
pthread_mutex_t cancelLock; /* Used for async-cancel safety */
|
||||
int cancelState;
|
||||
int cancelType;
|
||||
int cancelEvent;
|
||||
jmp_buf start_mark;
|
||||
int implicit:
|
||||
1;
|
||||
void *keys;
|
||||
void *nextAssoc;
|
||||
|
||||
unsigned int x; /* Extra information - reuse count etc */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Special value to mark attribute objects as valid.
|
||||
*/
|
||||
#define PTE_ATTR_VALID ((unsigned long) 0xC4C0FFEE)
|
||||
|
||||
struct pthread_attr_t_
|
||||
{
|
||||
unsigned long valid;
|
||||
void *stackaddr;
|
||||
size_t stacksize;
|
||||
int detachstate;
|
||||
struct sched_param param;
|
||||
int inheritsched;
|
||||
int contentionscope;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* ====================
|
||||
* Semaphores, Mutexes and Condition Variables
|
||||
* ====================
|
||||
* ====================
|
||||
*/
|
||||
|
||||
struct sem_t_
|
||||
{
|
||||
int value;
|
||||
pthread_mutex_t lock;
|
||||
pte_osSemaphoreHandle sem;
|
||||
};
|
||||
|
||||
#define PTE_OBJECT_AUTO_INIT ((void *) -1)
|
||||
#define PTE_OBJECT_INVALID 0
|
||||
|
||||
struct pthread_mutex_t_
|
||||
{
|
||||
pte_osSemaphoreHandle handle;
|
||||
int lock_idx;
|
||||
/* Provides exclusive access to mutex state
|
||||
via the Interlocked* mechanism.
|
||||
0: unlocked/free.
|
||||
1: locked - no other waiters.
|
||||
-1: locked - with possible other waiters.
|
||||
*/
|
||||
int recursive_count; /* Number of unlocks a thread needs to perform
|
||||
before the lock is released (recursive
|
||||
mutexes only). */
|
||||
int kind; /* Mutex type. */
|
||||
pthread_t ownerThread;
|
||||
};
|
||||
|
||||
struct pthread_mutexattr_t_
|
||||
{
|
||||
int pshared;
|
||||
int kind;
|
||||
};
|
||||
|
||||
/*
|
||||
* Possible values, other than PTE_OBJECT_INVALID,
|
||||
* for the "interlock" element in a spinlock.
|
||||
*
|
||||
* In this implementation, when a spinlock is initialised,
|
||||
* the number of cpus available to the process is checked.
|
||||
* If there is only one cpu then "interlock" is set equal to
|
||||
* PTE_SPIN_USE_MUTEX and u.mutex is a initialised mutex.
|
||||
* If the number of cpus is greater than 1 then "interlock"
|
||||
* is set equal to PTE_SPIN_UNLOCKED and the number is
|
||||
* stored in u.cpus. This arrangement allows the spinlock
|
||||
* routines to attempt an InterlockedCompareExchange on "interlock"
|
||||
* immediately and, if that fails, to try the inferior mutex.
|
||||
*
|
||||
* "u.cpus" isn't used for anything yet, but could be used at
|
||||
* some point to optimise spinlock behaviour.
|
||||
*/
|
||||
#define PTE_SPIN_UNLOCKED (1)
|
||||
#define PTE_SPIN_LOCKED (2)
|
||||
#define PTE_SPIN_USE_MUTEX (3)
|
||||
|
||||
struct pthread_spinlock_t_
|
||||
{
|
||||
int interlock; /* Locking element for multi-cpus. */
|
||||
union
|
||||
{
|
||||
int cpus; /* No. of cpus if multi cpus, or */
|
||||
pthread_mutex_t mutex; /* mutex if single cpu. */
|
||||
} u;
|
||||
};
|
||||
|
||||
struct pthread_barrier_t_
|
||||
{
|
||||
unsigned int nCurrentBarrierHeight;
|
||||
unsigned int nInitialBarrierHeight;
|
||||
int iStep;
|
||||
int pshared;
|
||||
sem_t semBarrierBreeched[2];
|
||||
};
|
||||
|
||||
struct pthread_barrierattr_t_
|
||||
{
|
||||
int pshared;
|
||||
};
|
||||
|
||||
struct pthread_key_t_
|
||||
{
|
||||
unsigned key;
|
||||
void (*destructor) (void *);
|
||||
pthread_mutex_t keyLock;
|
||||
void *threads;
|
||||
};
|
||||
|
||||
|
||||
typedef struct ThreadParms ThreadParms;
|
||||
typedef struct ThreadKeyAssoc ThreadKeyAssoc;
|
||||
|
||||
struct ThreadParms
|
||||
{
|
||||
pthread_t tid;
|
||||
void *(*start) (void *);
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct pthread_cond_t_
|
||||
{
|
||||
long nWaitersBlocked; /* Number of threads blocked */
|
||||
long nWaitersGone; /* Number of threads timed out */
|
||||
long nWaitersToUnblock; /* Number of threads to unblock */
|
||||
sem_t semBlockQueue; /* Queue up threads waiting for the */
|
||||
/* condition to become signalled */
|
||||
sem_t semBlockLock; /* Semaphore that guards access to */
|
||||
/* | waiters blocked count/block queue */
|
||||
/* +-> Mandatory Sync.LEVEL-1 */
|
||||
pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */
|
||||
/* | waiters (to)unblock(ed) counts */
|
||||
/* +-> Optional* Sync.LEVEL-2 */
|
||||
pthread_cond_t next; /* Doubly linked list */
|
||||
pthread_cond_t prev;
|
||||
};
|
||||
|
||||
|
||||
struct pthread_condattr_t_
|
||||
{
|
||||
int pshared;
|
||||
};
|
||||
|
||||
#define PTE_RWLOCK_MAGIC 0xfacade2
|
||||
|
||||
struct pthread_rwlock_t_
|
||||
{
|
||||
pthread_mutex_t mtxExclusiveAccess;
|
||||
pthread_mutex_t mtxSharedAccessCompleted;
|
||||
pthread_cond_t cndSharedAccessCompleted;
|
||||
int nSharedAccessCount;
|
||||
int nExclusiveAccessCount;
|
||||
int nCompletedSharedAccessCount;
|
||||
int nMagic;
|
||||
};
|
||||
|
||||
struct pthread_rwlockattr_t_
|
||||
{
|
||||
int pshared;
|
||||
};
|
||||
|
||||
/*
|
||||
* MCS lock queue node - see pte_MCS_lock.c
|
||||
*/
|
||||
struct pte_mcs_node_t_
|
||||
{
|
||||
struct pte_mcs_node_t_ **lock; /* ptr to tail of queue */
|
||||
struct pte_mcs_node_t_ *next; /* ptr to successor in queue */
|
||||
unsigned int readyFlag; /* set after lock is released by
|
||||
predecessor */
|
||||
unsigned int nextFlag; /* set after 'next' ptr is set by
|
||||
successor */
|
||||
};
|
||||
|
||||
typedef struct pte_mcs_node_t_ pte_mcs_local_node_t;
|
||||
typedef struct pte_mcs_node_t_ *pte_mcs_lock_t;
|
||||
|
||||
|
||||
struct ThreadKeyAssoc
|
||||
{
|
||||
/*
|
||||
* Purpose:
|
||||
* This structure creates an association between a thread and a key.
|
||||
* It is used to implement the implicit invocation of a user defined
|
||||
* destroy routine for thread specific data registered by a user upon
|
||||
* exiting a thread.
|
||||
*
|
||||
* Graphically, the arrangement is as follows, where:
|
||||
*
|
||||
* K - Key with destructor
|
||||
* (head of chain is key->threads)
|
||||
* T - Thread that has called pthread_setspecific(Kn)
|
||||
* (head of chain is thread->keys)
|
||||
* A - Association. Each association is a node at the
|
||||
* intersection of two doubly-linked lists.
|
||||
*
|
||||
* T1 T2 T3
|
||||
* | | |
|
||||
* | | |
|
||||
* K1 -----+-----A-----A----->
|
||||
* | | |
|
||||
* | | |
|
||||
* K2 -----A-----A-----+----->
|
||||
* | | |
|
||||
* | | |
|
||||
* K3 -----A-----+-----A----->
|
||||
* | | |
|
||||
* | | |
|
||||
* V V V
|
||||
*
|
||||
* Access to the association is guarded by two locks: the key's
|
||||
* general lock (guarding the row) and the thread's general
|
||||
* lock (guarding the column). This avoids the need for a
|
||||
* dedicated lock for each association, which not only consumes
|
||||
* more handles but requires that: before the lock handle can
|
||||
* be released - both the key must be deleted and the thread
|
||||
* must have called the destructor. The two-lock arrangement
|
||||
* allows the resources to be freed as soon as either thread or
|
||||
* key is concluded.
|
||||
*
|
||||
* To avoid deadlock: whenever both locks are required, the key
|
||||
* and thread locks are always acquired in the order: key lock
|
||||
* then thread lock. An exception to this exists when a thread
|
||||
* calls the destructors, however this is done carefully to
|
||||
* avoid deadlock.
|
||||
*
|
||||
* An association is created when a thread first calls
|
||||
* pthread_setspecific() on a key that has a specified
|
||||
* destructor.
|
||||
*
|
||||
* An association is destroyed either immediately after the
|
||||
* thread calls the key destructor function on thread exit, or
|
||||
* when the key is deleted.
|
||||
*
|
||||
* Attributes:
|
||||
* thread
|
||||
* reference to the thread that owns the
|
||||
* association. This is actually the pointer to the
|
||||
* thread struct itself. Since the association is
|
||||
* destroyed before the thread exits, this can never
|
||||
* point to a different logical thread to the one that
|
||||
* created the assoc, i.e. after thread struct reuse.
|
||||
*
|
||||
* key
|
||||
* reference to the key that owns the association.
|
||||
*
|
||||
* nextKey
|
||||
* The pthread_t->keys attribute is the head of a
|
||||
* chain of associations that runs through the nextKey
|
||||
* link. This chain provides the 1 to many relationship
|
||||
* between a pthread_t and all pthread_key_t on which
|
||||
* it called pthread_setspecific.
|
||||
*
|
||||
* prevKey
|
||||
* Similarly.
|
||||
*
|
||||
* nextThread
|
||||
* The pthread_key_t->threads attribute is the head of
|
||||
* a chain of assoctiations that runs through the
|
||||
* nextThreads link. This chain provides the 1 to many
|
||||
* relationship between a pthread_key_t and all the
|
||||
* PThreads that have called pthread_setspecific for
|
||||
* this pthread_key_t.
|
||||
*
|
||||
* prevThread
|
||||
* Similarly.
|
||||
*
|
||||
* Notes:
|
||||
* 1) As soon as either the key or the thread is no longer
|
||||
* referencing the association, it can be destroyed. The
|
||||
* association will be removed from both chains.
|
||||
*
|
||||
* 2) An association is only created by
|
||||
* pthread_setspecific if the user provided a
|
||||
* destroyRoutine when they created the key.
|
||||
*
|
||||
*
|
||||
*/
|
||||
pte_thread_t * thread;
|
||||
pthread_key_t key;
|
||||
ThreadKeyAssoc *nextKey;
|
||||
ThreadKeyAssoc *nextThread;
|
||||
ThreadKeyAssoc *prevKey;
|
||||
ThreadKeyAssoc *prevThread;
|
||||
};
|
||||
|
||||
/*
|
||||
* Services available through EXCEPTION_PTE_SERVICES
|
||||
* and also used [as parameters to pte_throw()] as
|
||||
* generic exception selectors.
|
||||
*/
|
||||
|
||||
#define PTE_EPS_EXIT (1)
|
||||
#define PTE_EPS_CANCEL (2)
|
||||
|
||||
|
||||
/* Useful macros */
|
||||
#define PTE_MAX(a,b) ((a)<(b)?(b):(a))
|
||||
#define PTE_MIN(a,b) ((a)>(b)?(b):(a))
|
||||
|
||||
|
||||
/* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */
|
||||
#define PTE_THREAD_REUSE_EMPTY ((pte_thread_t *) 1)
|
||||
|
||||
extern int pte_processInitialized;
|
||||
extern pte_thread_t * pte_threadReuseTop;
|
||||
extern pte_thread_t * pte_threadReuseBottom;
|
||||
extern pthread_key_t pte_selfThreadKey;
|
||||
extern pthread_key_t pte_cleanupKey;
|
||||
extern pthread_cond_t pte_cond_list_head;
|
||||
extern pthread_cond_t pte_cond_list_tail;
|
||||
|
||||
extern int pte_mutex_default_kind;
|
||||
|
||||
extern int pte_concurrency;
|
||||
|
||||
extern int pte_features;
|
||||
|
||||
extern pte_osMutexHandle pte_thread_reuse_lock;
|
||||
extern pte_osMutexHandle pte_mutex_test_init_lock;
|
||||
extern pte_osMutexHandle pte_cond_list_lock;
|
||||
extern pte_osMutexHandle pte_cond_test_init_lock;
|
||||
extern pte_osMutexHandle pte_rwlock_test_init_lock;
|
||||
extern pte_osMutexHandle pte_spinlock_test_init_lock;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*
|
||||
* =====================
|
||||
* =====================
|
||||
* Forward Declarations
|
||||
* =====================
|
||||
* =====================
|
||||
*/
|
||||
|
||||
int pte_is_attr (const pthread_attr_t * attr);
|
||||
|
||||
int pte_cond_check_need_init (pthread_cond_t * cond);
|
||||
int pte_mutex_check_need_init (pthread_mutex_t * mutex);
|
||||
int pte_rwlock_check_need_init (pthread_rwlock_t * rwlock);
|
||||
int pte_spinlock_check_need_init (pthread_spinlock_t * lock);
|
||||
|
||||
int pte_processInitialize (void);
|
||||
|
||||
void pte_processTerminate (void);
|
||||
|
||||
void pte_threadDestroy (pthread_t tid);
|
||||
void pte_threadExitAndDestroy (pthread_t tid);
|
||||
|
||||
void pte_pop_cleanup_all (int execute);
|
||||
|
||||
pthread_t pte_new (void);
|
||||
|
||||
pthread_t pte_threadReusePop (void);
|
||||
|
||||
void pte_threadReusePush (pthread_t thread);
|
||||
|
||||
int pte_getprocessors (int *count);
|
||||
|
||||
int pte_setthreadpriority (pthread_t thread, int policy, int priority);
|
||||
|
||||
void pte_rwlock_cancelwrwait (void *arg);
|
||||
|
||||
int pte_threadStart (void *vthreadParms);
|
||||
|
||||
void pte_callUserDestroyRoutines (pthread_t thread);
|
||||
|
||||
int pte_tkAssocCreate (pte_thread_t * thread, pthread_key_t key);
|
||||
|
||||
void pte_tkAssocDestroy (ThreadKeyAssoc * assoc);
|
||||
|
||||
int sem_wait_nocancel (sem_t * sem);
|
||||
|
||||
unsigned int pte_relmillisecs (const struct timespec * abstime);
|
||||
|
||||
void pte_mcs_lock_acquire (pte_mcs_lock_t * lock, pte_mcs_local_node_t * node);
|
||||
|
||||
void pte_mcs_lock_release (pte_mcs_local_node_t * node);
|
||||
|
||||
/* Declared in private.c */
|
||||
void pte_throw (unsigned int exception);
|
||||
|
||||
int pte_cancellable_wait (pte_osSemaphoreHandle semHandle, unsigned int* timeout);
|
||||
|
||||
#define PTE_ATOMIC_EXCHANGE pte_osAtomicExchange
|
||||
#define PTE_ATOMIC_EXCHANGE_ADD pte_osAtomicExchangeAdd
|
||||
#define PTE_ATOMIC_COMPARE_EXCHANGE pte_osAtomicCompareExchange
|
||||
#define PTE_ATOMIC_DECREMENT pte_osAtomicDecrement
|
||||
#define PTE_ATOMIC_INCREMENT pte_osAtomicIncrement
|
||||
|
||||
int pte_thread_detach_np();
|
||||
int pte_thread_detach_and_exit_np();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* _IMPLEMENT_H */
|
||||
Vendored
-90
@@ -1,90 +0,0 @@
|
||||
/***
|
||||
* errno.h - system wide error numbers (set by system calls)
|
||||
*
|
||||
* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* Purpose:
|
||||
* This file defines the system-wide error numbers (set by
|
||||
* system calls). Conforms to the XENIX standard. Extended
|
||||
* for compatibility with Uniforum standard.
|
||||
* [System V]
|
||||
*
|
||||
* [Public]
|
||||
*
|
||||
****/
|
||||
|
||||
#ifndef _INC_ERRNO
|
||||
#define _INC_ERRNO
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* declare reference to errno */
|
||||
|
||||
extern int errno;
|
||||
|
||||
/* Error Codes */
|
||||
|
||||
#define EPERM 1
|
||||
#define ENOENT 2
|
||||
#define ESRCH 3
|
||||
#define EINTR 4
|
||||
#define EIO 5
|
||||
#define ENXIO 6
|
||||
#define E2BIG 7
|
||||
#define ENOEXEC 8
|
||||
#define EBADF 9
|
||||
#define ECHILD 10
|
||||
#define EAGAIN 11
|
||||
#define ENOMEM 12
|
||||
#define EACCES 13
|
||||
#define EFAULT 14
|
||||
#define EBUSY 16
|
||||
#define EEXIST 17
|
||||
#define EXDEV 18
|
||||
#define ENODEV 19
|
||||
#define ENOTDIR 20
|
||||
#define EISDIR 21
|
||||
#define EINVAL 22
|
||||
#define ENFILE 23
|
||||
#define EMFILE 24
|
||||
#define ENOTTY 25
|
||||
#define EFBIG 27
|
||||
#define ENOSPC 28
|
||||
#define ESPIPE 29
|
||||
#define EROFS 30
|
||||
#define EMLINK 31
|
||||
#define EPIPE 32
|
||||
#define EDOM 33
|
||||
#define ERANGE 34
|
||||
#define EDEADLK 36
|
||||
|
||||
/* defined differently in winsock.h on WinCE */
|
||||
#ifndef ENAMETOOLONG
|
||||
#define ENAMETOOLONG 38
|
||||
#endif
|
||||
|
||||
#define ENOLCK 39
|
||||
#define ENOSYS 40
|
||||
|
||||
/* defined differently in winsock.h on WinCE */
|
||||
#ifndef ENOTEMPTY
|
||||
#define ENOTEMPTY 41
|
||||
#endif
|
||||
|
||||
#define EILSEQ 42
|
||||
|
||||
/*
|
||||
* Support EDEADLOCK for compatibiity with older MS-C versions.
|
||||
*/
|
||||
#define EDEADLOCK EDEADLK
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _INC_ERRNO */
|
||||
-163
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* tls-helper.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tls-helper.h"
|
||||
|
||||
static int *keysUsed;
|
||||
|
||||
/* We don't protect this - it's only written on startup */
|
||||
static int maxTlsValues;
|
||||
|
||||
pte_osMutexHandle globalTlsLock;
|
||||
|
||||
pte_osResult pteTlsGlobalInit(int maxEntries)
|
||||
{
|
||||
int i;
|
||||
pte_osResult result;
|
||||
|
||||
pte_osMutexCreate(&globalTlsLock);
|
||||
|
||||
keysUsed = (int *) malloc(maxEntries * sizeof(int));
|
||||
|
||||
if (keysUsed != NULL)
|
||||
{
|
||||
for (i=0;i<maxEntries;i++)
|
||||
keysUsed[i] = 0;
|
||||
|
||||
maxTlsValues = maxEntries;
|
||||
|
||||
result = PTE_OS_OK;
|
||||
}
|
||||
else
|
||||
result = PTE_OS_NO_RESOURCES;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void * pteTlsThreadInit(void)
|
||||
{
|
||||
int i;
|
||||
void **pTlsStruct = (void **) malloc(maxTlsValues * sizeof(void*));
|
||||
|
||||
/* PTE library assumes that keys are initialized to zero */
|
||||
for (i=0; i<maxTlsValues;i++)
|
||||
pTlsStruct[i] = 0;
|
||||
|
||||
return (void *) pTlsStruct;
|
||||
}
|
||||
|
||||
|
||||
pte_osResult pteTlsAlloc(unsigned int *pKey)
|
||||
{
|
||||
int i;
|
||||
pte_osResult result = PTE_OS_NO_RESOURCES;
|
||||
|
||||
pte_osMutexLock(globalTlsLock);
|
||||
|
||||
for (i=0;i<maxTlsValues;i++)
|
||||
{
|
||||
if (keysUsed[i] == 0)
|
||||
{
|
||||
keysUsed[i] = 1;
|
||||
|
||||
*pKey = i+1;
|
||||
result = PTE_OS_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pte_osMutexUnlock(globalTlsLock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void * pteTlsGetValue(void *pTlsThreadStruct, unsigned int index)
|
||||
{
|
||||
void **pTls = (void **) pTlsThreadStruct;
|
||||
|
||||
if (keysUsed[index-1])
|
||||
{
|
||||
if (pTls != NULL)
|
||||
return pTls[index-1];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
pte_osResult pteTlsSetValue(void *pTlsThreadStruct, unsigned int index, void * value)
|
||||
{
|
||||
pte_osResult result;
|
||||
void ** pTls = (void **) pTlsThreadStruct;
|
||||
|
||||
if (pTls != NULL)
|
||||
{
|
||||
pTls[index-1] = value;
|
||||
result = PTE_OS_OK;
|
||||
}
|
||||
else
|
||||
result = PTE_OS_INVALID_PARAM;
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
pte_osResult pteTlsFree(unsigned int index)
|
||||
{
|
||||
pte_osResult result;
|
||||
|
||||
if (keysUsed != NULL)
|
||||
{
|
||||
pte_osMutexLock(globalTlsLock);
|
||||
|
||||
keysUsed[index-1] = 0;
|
||||
|
||||
pte_osMutexUnlock(globalTlsLock);
|
||||
|
||||
result = PTE_OS_OK;
|
||||
}
|
||||
else
|
||||
result = PTE_OS_GENERAL_FAILURE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void pteTlsThreadDestroy(void * pTlsThreadStruct)
|
||||
{
|
||||
free(pTlsThreadStruct);
|
||||
}
|
||||
|
||||
void pteTlsGlobalDestroy(void)
|
||||
{
|
||||
pte_osMutexDelete(globalTlsLock);
|
||||
free(keysUsed);
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* tls-helper.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef _TLS_HELPER_H_
|
||||
#define _TLS_HELPER_H_
|
||||
|
||||
#include "../psp/pte_osal.h"
|
||||
|
||||
/* @todo document.. */
|
||||
|
||||
pte_osResult pteTlsGlobalInit(int maxEntries);
|
||||
void * pteTlsThreadInit(void);
|
||||
|
||||
pte_osResult pteTlsAlloc(unsigned int *pKey);
|
||||
void * pteTlsGetValue(void *pTlsThreadStruct, unsigned int index);
|
||||
pte_osResult pteTlsSetValue(void *pTlsThreadStruct, unsigned int index, void * value);
|
||||
pte_osResult pteTlsFree(unsigned int index);
|
||||
|
||||
void pteTlsThreadDestroy(void * pTlsThreadStruct);
|
||||
void pteTlsGlobalDestroy(void);
|
||||
|
||||
#endif // _TLS_HELPER_H_
|
||||
Vendored
-51
@@ -1,51 +0,0 @@
|
||||
VPATH = ../..:../helper
|
||||
|
||||
TARGET_LIB = libpthread-psp.a
|
||||
|
||||
MUTEX_OBJS = pthread_mutex.o
|
||||
|
||||
MUTEXATTR_OBJS = pthread_mutexattr.o
|
||||
|
||||
SUPPORT_OBJS = pte.o pthread.o
|
||||
|
||||
THREAD_OBJS = sched.o
|
||||
|
||||
TLS_OBJS = pthread_key.o
|
||||
|
||||
MISC_OBJS = pthread_get.o
|
||||
|
||||
SEM_OBJS = sem.o
|
||||
|
||||
BARRIER_OBJS = pthread_barrier.o pthread_barrierattr.o
|
||||
|
||||
SPIN_OBJS = pthread_spin.o
|
||||
|
||||
CONDVAR_OBJS = pthread_cond.o pthread_condattr.o
|
||||
|
||||
RWLOCK_OBJS = pthread_rwlock.o pthread_rwlockattr.o
|
||||
|
||||
CANCEL_OBJS = pthread.o pthread_set.o
|
||||
|
||||
OS_OBJS = psp_osal.o tls-helper.o
|
||||
|
||||
OBJS = $(MUTEX_OBJS) $(MUTEXATTR_OBJS) $(THREAD_OBJS) $(SUPPORT_OBJS) $(TLS_OBJS) $(MISC_OBJS) $(SEM_OBJS) $(BARRIER_OBJS) $(SPIN_OBJS) $(CONDVAR_OBJS) $(RWLOCK_OBJS) $(CANCEL_OBJS) $(OS_OBJS)
|
||||
|
||||
INCDIR =
|
||||
CFLAGS = $(GLOBAL_CFLAGS) -G0 -O2 -Wall -g -fno-strict-aliasing -I../.. -I../helper
|
||||
CXXFLAGS = $(CFLAGS) -fexceptions -fno-rtti -Werror
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
LDFLAGS =
|
||||
LIBS =
|
||||
|
||||
PSPSDK=$(shell psp-config --pspsdk-path)
|
||||
include $(PSPSDK)/lib/build.mak
|
||||
|
||||
test :
|
||||
make -C ../../tests test
|
||||
|
||||
install: $(TARGET_LIB)
|
||||
@cp -v $(TARGET_LIB) `psp-config --psp-prefix`/lib
|
||||
@cp -v *.h `psp-config --psp-prefix`/include
|
||||
@echo "Done."
|
||||
|
||||
-842
@@ -1,842 +0,0 @@
|
||||
/*
|
||||
* psp_osal.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* For ftime */
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/timeb.h>
|
||||
|
||||
#include <pspkerror.h>
|
||||
|
||||
#include "pte_osal.h"
|
||||
#include "../../pthread.h"
|
||||
#include "../helper/tls-helper.h"
|
||||
|
||||
#define MAX_PSP_UID 2048 /* SWAG */
|
||||
|
||||
#define DEFAULT_STACK_SIZE_BYTES 4096
|
||||
|
||||
#define PSP_MAX_TLS 32
|
||||
|
||||
#if 1
|
||||
#define PSP_DEBUG(x) printf(x)
|
||||
#else
|
||||
#define PSP_DEBUG(x)
|
||||
#endif
|
||||
|
||||
/* TLS key used to access pspThreadData struct for reach thread. */
|
||||
static unsigned int threadDataKey;
|
||||
|
||||
/*
|
||||
* Data stored on a per-thread basis - allocated in pte_osThreadCreate
|
||||
* and freed in pte_osThreadDelete.
|
||||
*/
|
||||
typedef struct pspThreadData
|
||||
{
|
||||
/* Entry point and parameters to thread's main function */
|
||||
pte_osThreadEntryPoint entryPoint;
|
||||
void * argv;
|
||||
|
||||
/* Semaphore used for cancellation. Posted to by pte_osThreadCancel,
|
||||
polled in pte_osSemaphoreCancellablePend */
|
||||
SceUID cancelSem;
|
||||
|
||||
} pspThreadData;
|
||||
|
||||
|
||||
/* Structure used to emulate TLS on non-POSIX threads.
|
||||
* This limits us to one non-POSIX thread that can
|
||||
* call pthread functions. */
|
||||
static void *globalTls;
|
||||
|
||||
/* Helper functions */
|
||||
static pspThreadData *getThreadData(SceUID threadHandle);
|
||||
static void *getTlsStructFromThread(SceUID thid);
|
||||
|
||||
/* A new thread's stub entry point. It retrieves the real entry point from the per thread control
|
||||
* data as well as any parameters to this function, and then calls the entry point.
|
||||
*/
|
||||
int pspStubThreadEntry (unsigned int argc, void *argv)
|
||||
{
|
||||
int result;
|
||||
pspThreadData *pThreadData;
|
||||
|
||||
pThreadData = getThreadData(sceKernelGetThreadId());
|
||||
|
||||
result = (*(pThreadData->entryPoint))(pThreadData->argv);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Initialization
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
pte_osResult pte_osInit(void)
|
||||
{
|
||||
pte_osResult result;
|
||||
pspThreadData *pThreadData;
|
||||
char cancelSemName[64];
|
||||
|
||||
/* Allocate and initialize TLS support */
|
||||
result = pteTlsGlobalInit(PSP_MAX_TLS);
|
||||
|
||||
if (result == PTE_OS_OK)
|
||||
{
|
||||
/* Allocate a key that we use to store control information (e.g. cancellation semaphore) per thread */
|
||||
result = pteTlsAlloc(&threadDataKey);
|
||||
|
||||
if (result == PTE_OS_OK)
|
||||
{
|
||||
|
||||
/* Initialize the structure used to emulate TLS for
|
||||
* non-POSIX threads
|
||||
*/
|
||||
globalTls = pteTlsThreadInit();
|
||||
|
||||
/* Also create a "thread data" structure for a single non-POSIX thread. */
|
||||
|
||||
/* Allocate some memory for our per-thread control data. We use this for:
|
||||
* 1. Entry point and parameters for the user thread's main function.
|
||||
* 2. Semaphore used for thread cancellation.
|
||||
*/
|
||||
pThreadData = (pspThreadData *) malloc(sizeof(pspThreadData));
|
||||
|
||||
if (pThreadData == NULL)
|
||||
{
|
||||
result = PTE_OS_NO_RESOURCES;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Save a pointer to our per-thread control data as a TLS value */
|
||||
pteTlsSetValue(globalTls, threadDataKey, pThreadData);
|
||||
|
||||
/* Create a semaphore used to cancel threads */
|
||||
snprintf(cancelSemName, sizeof(cancelSemName), "pthread_cancelSemGlobal");
|
||||
|
||||
pThreadData->cancelSem = sceKernelCreateSema(cancelSemName,
|
||||
0, /* attributes (default) */
|
||||
0, /* initial value */
|
||||
255, /* maximum value */
|
||||
0); /* options (default) */
|
||||
result = PTE_OS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Threads
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
pte_osResult pte_osThreadCreate(pte_osThreadEntryPoint entryPoint,
|
||||
int stackSize,
|
||||
int initialPriority,
|
||||
void *argv,
|
||||
pte_osThreadHandle* ppte_osThreadHandle)
|
||||
{
|
||||
char threadName[64];
|
||||
char cancelSemName[64];
|
||||
static int threadNum = 1;
|
||||
int pspAttr;
|
||||
void *pTls;
|
||||
SceUID threadId;
|
||||
pte_osResult result;
|
||||
pspThreadData *pThreadData;
|
||||
|
||||
if (threadNum++ > MAX_PSP_UID)
|
||||
threadNum = 0;
|
||||
|
||||
/* Make sure that the stack we're going to allocate is big enough */
|
||||
if (stackSize < DEFAULT_STACK_SIZE_BYTES)
|
||||
stackSize = DEFAULT_STACK_SIZE_BYTES;
|
||||
|
||||
/* Allocate TLS structure for this thread. */
|
||||
pTls = pteTlsThreadInit();
|
||||
if (pTls == NULL)
|
||||
{
|
||||
PSP_DEBUG("pteTlsThreadInit: PTE_OS_NO_RESOURCES\n");
|
||||
result = PTE_OS_NO_RESOURCES;
|
||||
goto FAIL0;
|
||||
}
|
||||
|
||||
/* Allocate some memory for our per-thread control data. We use this for:
|
||||
* 1. Entry point and parameters for the user thread's main function.
|
||||
* 2. Semaphore used for thread cancellation.
|
||||
*/
|
||||
pThreadData = (pspThreadData *) malloc(sizeof(pspThreadData));
|
||||
|
||||
if (pThreadData == NULL)
|
||||
{
|
||||
pteTlsThreadDestroy(pTls);
|
||||
|
||||
PSP_DEBUG("malloc(pspThreadData): PTE_OS_NO_RESOURCES\n");
|
||||
result = PTE_OS_NO_RESOURCES;
|
||||
goto FAIL0;
|
||||
}
|
||||
|
||||
/* Save a pointer to our per-thread control data as a TLS value */
|
||||
pteTlsSetValue(pTls, threadDataKey, pThreadData);
|
||||
|
||||
pThreadData->entryPoint = entryPoint;
|
||||
pThreadData->argv = argv;
|
||||
|
||||
/* Create a semaphore used to cancel threads */
|
||||
snprintf(cancelSemName, sizeof(cancelSemName), "pthread_cancelSem%04d", threadNum);
|
||||
|
||||
pThreadData->cancelSem = sceKernelCreateSema(cancelSemName,
|
||||
0, /* attributes (default) */
|
||||
0, /* initial value */
|
||||
255, /* maximum value */
|
||||
0); /* options (default) */
|
||||
|
||||
|
||||
/* In order to emulate TLS functionality, we append the address of the TLS structure that we
|
||||
* allocated above to the thread's name. To set or get TLS values for this thread, the user
|
||||
* needs to get the name of the thread from the OS and then parse the name to extract
|
||||
* a pointer to the TLS structure.
|
||||
*/
|
||||
snprintf(threadName, sizeof(threadName), "pthread%04d__%x", threadNum, (unsigned int) pTls);
|
||||
|
||||
pspAttr = 0;
|
||||
|
||||
#if 0
|
||||
printf("%s %p %d %d %d\n",threadName, pspStubThreadEntry, initialPriority, stackSize, pspAttr);
|
||||
#endif
|
||||
threadId = sceKernelCreateThread(threadName,
|
||||
pspStubThreadEntry,
|
||||
initialPriority,
|
||||
stackSize,
|
||||
pspAttr,
|
||||
NULL);
|
||||
|
||||
if (threadId == (SceUID) SCE_KERNEL_ERROR_NO_MEMORY)
|
||||
{
|
||||
free(pThreadData);
|
||||
pteTlsThreadDestroy(pTls);
|
||||
|
||||
PSP_DEBUG("sceKernelCreateThread: PTE_OS_NO_RESOURCES\n");
|
||||
result = PTE_OS_NO_RESOURCES;
|
||||
}
|
||||
else if (threadId < 0)
|
||||
{
|
||||
free(pThreadData);
|
||||
pteTlsThreadDestroy(pTls);
|
||||
|
||||
PSP_DEBUG("sceKernelCreateThread: PTE_OS_GENERAL_FAILURE\n");
|
||||
result = PTE_OS_GENERAL_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppte_osThreadHandle = threadId;
|
||||
result = PTE_OS_OK;
|
||||
}
|
||||
|
||||
FAIL0:
|
||||
return result;
|
||||
}
|
||||
|
||||
pte_osResult pte_osThreadStart(pte_osThreadHandle osThreadHandle)
|
||||
{
|
||||
sceKernelStartThread(osThreadHandle, 0, NULL);
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
|
||||
pte_osResult pte_osThreadDelete(pte_osThreadHandle handle)
|
||||
{
|
||||
void *pTls = getTlsStructFromThread(handle);
|
||||
pspThreadData *pThreadData = getThreadData(handle);
|
||||
|
||||
sceKernelDeleteSema(pThreadData->cancelSem);
|
||||
|
||||
free(pThreadData);
|
||||
|
||||
pteTlsThreadDestroy(pTls);
|
||||
|
||||
sceKernelDeleteThread(handle);
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
pte_osResult pte_osThreadExitAndDelete(pte_osThreadHandle handle)
|
||||
{
|
||||
pte_osThreadDelete(handle);
|
||||
|
||||
sceKernelExitDeleteThread(0);
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
void pte_osThreadExit(void)
|
||||
{
|
||||
sceKernelExitThread(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This has to be cancellable, so we can't just call sceKernelWaitThreadEnd.
|
||||
* Instead, poll on this in a loop, like we do for a cancellable semaphore.
|
||||
*/
|
||||
pte_osResult pte_osThreadWaitForEnd(pte_osThreadHandle threadHandle)
|
||||
{
|
||||
pte_osResult result;
|
||||
pspThreadData *pThreadData = getThreadData(sceKernelGetThreadId());
|
||||
|
||||
while (1)
|
||||
{
|
||||
SceKernelThreadRunStatus info;
|
||||
|
||||
/* Poll task to see if it has ended */
|
||||
memset(&info,0,sizeof(info));
|
||||
info.size = sizeof(info);
|
||||
sceKernelReferThreadRunStatus(threadHandle, &info);
|
||||
|
||||
if (info.status == PSP_THREAD_STOPPED)
|
||||
{
|
||||
/* Thread has ended */
|
||||
result = PTE_OS_OK;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
SceKernelSemaInfo semInfo;
|
||||
|
||||
if (pThreadData != NULL)
|
||||
{
|
||||
SceUID osResult;
|
||||
|
||||
osResult = sceKernelReferSemaStatus(pThreadData->cancelSem, &semInfo);
|
||||
|
||||
if (osResult == SCE_KERNEL_ERROR_OK)
|
||||
{
|
||||
if (semInfo.currentCount > 0)
|
||||
{
|
||||
result = PTE_OS_INTERRUPTED;
|
||||
break;
|
||||
}
|
||||
/* Nothing found and not timed out yet; let's yield so we're not
|
||||
* in busy loop.
|
||||
*/
|
||||
else
|
||||
sceKernelDelayThread(POLLING_DELAY_IN_us);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = PTE_OS_GENERAL_FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
pte_osThreadHandle pte_osThreadGetHandle(void)
|
||||
{
|
||||
return sceKernelGetThreadId();
|
||||
}
|
||||
|
||||
int pte_osThreadGetPriority(pte_osThreadHandle threadHandle)
|
||||
{
|
||||
SceKernelThreadInfo thinfo;
|
||||
|
||||
thinfo.size = sizeof(SceKernelThreadInfo);
|
||||
|
||||
sceKernelReferThreadStatus(threadHandle, &thinfo);
|
||||
|
||||
return thinfo.currentPriority;
|
||||
}
|
||||
|
||||
pte_osResult pte_osThreadSetPriority(pte_osThreadHandle threadHandle, int newPriority)
|
||||
{
|
||||
sceKernelChangeThreadPriority(threadHandle, newPriority);
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
pte_osResult pte_osThreadCancel(pte_osThreadHandle threadHandle)
|
||||
{
|
||||
pspThreadData *pThreadData = getThreadData(threadHandle);
|
||||
SceUID osResult = sceKernelSignalSema(pThreadData->cancelSem, 1);
|
||||
|
||||
if (osResult == SCE_KERNEL_ERROR_OK)
|
||||
return PTE_OS_OK;
|
||||
|
||||
return PTE_OS_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
pte_osResult pte_osThreadCheckCancel(pte_osThreadHandle threadHandle)
|
||||
{
|
||||
SceKernelSemaInfo semInfo;
|
||||
SceUID osResult;
|
||||
pte_osResult result;
|
||||
pspThreadData *pThreadData = getThreadData(threadHandle);
|
||||
|
||||
if (pThreadData != NULL)
|
||||
{
|
||||
osResult = sceKernelReferSemaStatus(pThreadData->cancelSem, &semInfo);
|
||||
|
||||
if (osResult == SCE_KERNEL_ERROR_OK)
|
||||
{
|
||||
if (semInfo.currentCount > 0)
|
||||
result = PTE_OS_INTERRUPTED;
|
||||
else
|
||||
result = PTE_OS_OK;
|
||||
}
|
||||
/* sceKernelReferSemaStatus returned an error */
|
||||
else
|
||||
result = PTE_OS_GENERAL_FAILURE;
|
||||
}
|
||||
/* For some reason, we couldn't get thread data */
|
||||
else
|
||||
result = PTE_OS_GENERAL_FAILURE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void pte_osThreadSleep(unsigned int msecs)
|
||||
{
|
||||
sceKernelDelayThread(msecs*1000);
|
||||
}
|
||||
|
||||
int pte_osThreadGetMinPriority(void)
|
||||
{
|
||||
return 17;
|
||||
}
|
||||
|
||||
int pte_osThreadGetMaxPriority(void)
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
int pte_osThreadGetDefaultPriority(void)
|
||||
{
|
||||
return 18;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Mutexes
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
pte_osResult pte_osMutexCreate(pte_osMutexHandle *pHandle)
|
||||
{
|
||||
static int mutexCtr = 0;
|
||||
char mutexName[32];
|
||||
pte_osMutexHandle handle;
|
||||
|
||||
if (mutexCtr++ > MAX_PSP_UID)
|
||||
mutexCtr = 0;
|
||||
|
||||
snprintf(mutexName,sizeof(mutexName),"mutex%d",mutexCtr);
|
||||
|
||||
handle = sceKernelCreateSema(mutexName,
|
||||
0, /* attributes (default) */
|
||||
1, /* initial value */
|
||||
1, /* maximum value */
|
||||
0); /* options (default) */
|
||||
|
||||
*pHandle = handle;
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
pte_osResult pte_osMutexDelete(pte_osMutexHandle handle)
|
||||
{
|
||||
sceKernelDeleteSema(handle);
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
pte_osResult pte_osMutexLock(pte_osMutexHandle handle)
|
||||
{
|
||||
sceKernelWaitSema(handle, 1, NULL);
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
pte_osResult pte_osMutexTimedLock(pte_osMutexHandle handle, unsigned int timeoutMsecs)
|
||||
{
|
||||
SceUInt timeoutUsecs = timeoutMsecs*1000;
|
||||
int status = sceKernelWaitSema(handle, 1, &timeoutUsecs);
|
||||
|
||||
/* Assume that any error from sceKernelWaitSema was due to a timeout */
|
||||
if (status < 0)
|
||||
return PTE_OS_TIMEOUT;
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
|
||||
pte_osResult pte_osMutexUnlock(pte_osMutexHandle handle)
|
||||
{
|
||||
sceKernelSignalSema(handle, 1);
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Semaphores
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
pte_osResult pte_osSemaphoreCreate(int initialValue, pte_osSemaphoreHandle *pHandle)
|
||||
{
|
||||
pte_osSemaphoreHandle handle;
|
||||
static int semCtr = 0;
|
||||
char semName[32];
|
||||
|
||||
if (semCtr++ > MAX_PSP_UID)
|
||||
semCtr = 0;
|
||||
|
||||
snprintf(semName,sizeof(semName),"pthread_sem%d",semCtr);
|
||||
|
||||
handle = sceKernelCreateSema(semName,
|
||||
0, /* attributes (default) */
|
||||
initialValue, /* initial value */
|
||||
SEM_VALUE_MAX, /* maximum value */
|
||||
0); /* options (default) */
|
||||
|
||||
*pHandle = handle;
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
pte_osResult pte_osSemaphoreDelete(pte_osSemaphoreHandle handle)
|
||||
{
|
||||
sceKernelDeleteSema(handle);
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
|
||||
pte_osResult pte_osSemaphorePost(pte_osSemaphoreHandle handle, int count)
|
||||
{
|
||||
sceKernelSignalSema(handle, count);
|
||||
|
||||
return PTE_OS_OK;
|
||||
}
|
||||
|
||||
pte_osResult pte_osSemaphorePend(pte_osSemaphoreHandle handle, unsigned int *pTimeoutMsecs)
|
||||
{
|
||||
unsigned int timeoutUsecs;
|
||||
unsigned int *pTimeoutUsecs;
|
||||
SceUInt result;
|
||||
pte_osResult osResult;
|
||||
|
||||
if (pTimeoutMsecs == NULL)
|
||||
pTimeoutUsecs = NULL;
|
||||
else
|
||||
{
|
||||
timeoutUsecs = *pTimeoutMsecs * 1000;
|
||||
pTimeoutUsecs = &timeoutUsecs;
|
||||
}
|
||||
|
||||
result = sceKernelWaitSema(handle, 1, pTimeoutUsecs);
|
||||
|
||||
if (result == SCE_KERNEL_ERROR_OK)
|
||||
return PTE_OS_OK;
|
||||
|
||||
if (result == SCE_KERNEL_ERROR_WAIT_TIMEOUT)
|
||||
return PTE_OS_TIMEOUT;
|
||||
|
||||
return PTE_OS_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Pend on a semaphore- and allow the pend to be cancelled.
|
||||
*
|
||||
* PSP OS provides no functionality to asynchronously interrupt a blocked call. We simulte
|
||||
* this by polling on the main semaphore and the cancellation semaphore and sleeping in a loop.
|
||||
*/
|
||||
pte_osResult pte_osSemaphoreCancellablePend(pte_osSemaphoreHandle semHandle, unsigned int *pTimeout)
|
||||
{
|
||||
pspThreadData *pThreadData;
|
||||
|
||||
pThreadData = getThreadData(sceKernelGetThreadId());
|
||||
|
||||
clock_t start_time;
|
||||
pte_osResult result = PTE_OS_OK;
|
||||
unsigned int timeout;
|
||||
unsigned char timeoutEnabled;
|
||||
|
||||
start_time = clock();
|
||||
|
||||
// clock() is in microseconds, timeout as passed in was in milliseconds
|
||||
if (pTimeout == NULL)
|
||||
{
|
||||
timeout = 0;
|
||||
timeoutEnabled = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeout = *pTimeout * 1000;
|
||||
timeoutEnabled = 1;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
SceUInt semTimeout;
|
||||
int status;
|
||||
|
||||
/* Poll semaphore */
|
||||
semTimeout = 0;
|
||||
status = sceKernelWaitSema(semHandle, 1, &semTimeout);
|
||||
|
||||
if (status == SCE_KERNEL_ERROR_OK)
|
||||
{
|
||||
/* User semaphore posted to */
|
||||
result = PTE_OS_OK;
|
||||
break;
|
||||
}
|
||||
else if ((timeoutEnabled) && ((clock() - start_time) > timeout))
|
||||
{
|
||||
/* Timeout expired */
|
||||
result = PTE_OS_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
SceKernelSemaInfo semInfo;
|
||||
|
||||
if (pThreadData != NULL)
|
||||
{
|
||||
SceUID osResult;
|
||||
|
||||
osResult = sceKernelReferSemaStatus(pThreadData->cancelSem, &semInfo);
|
||||
|
||||
if (osResult == SCE_KERNEL_ERROR_OK)
|
||||
{
|
||||
if (semInfo.currentCount > 0)
|
||||
{
|
||||
result = PTE_OS_INTERRUPTED;
|
||||
break;
|
||||
}
|
||||
/* Nothing found and not timed out yet; let's yield so we're not
|
||||
* in busy loop.
|
||||
*/
|
||||
else
|
||||
sceKernelDelayThread(POLLING_DELAY_IN_us);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = PTE_OS_GENERAL_FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Atomic Operations
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
int pte_osAtomicExchange(int *ptarg, int val)
|
||||
{
|
||||
int intc = pspSdkDisableInterrupts();
|
||||
int origVal = *ptarg;
|
||||
|
||||
*ptarg = val;
|
||||
|
||||
pspSdkEnableInterrupts(intc);
|
||||
|
||||
return origVal;
|
||||
|
||||
}
|
||||
|
||||
int pte_osAtomicCompareExchange(int *pdest, int exchange, int comp)
|
||||
{
|
||||
int intc = pspSdkDisableInterrupts();
|
||||
int origVal = *pdest;
|
||||
|
||||
if (*pdest == comp)
|
||||
*pdest = exchange;
|
||||
|
||||
pspSdkEnableInterrupts(intc);
|
||||
|
||||
return origVal;
|
||||
}
|
||||
|
||||
|
||||
int pte_osAtomicExchangeAdd(int volatile* pAddend, int value)
|
||||
{
|
||||
int intc = pspSdkDisableInterrupts();
|
||||
int origVal = *pAddend;
|
||||
|
||||
*pAddend += value;
|
||||
|
||||
pspSdkEnableInterrupts(intc);
|
||||
|
||||
return origVal;
|
||||
}
|
||||
|
||||
int pte_osAtomicDecrement(int *pdest)
|
||||
{
|
||||
int val;
|
||||
|
||||
int intc = pspSdkDisableInterrupts();
|
||||
|
||||
(*pdest)--;
|
||||
val = *pdest;
|
||||
|
||||
pspSdkEnableInterrupts(intc);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int pte_osAtomicIncrement(int *pdest)
|
||||
{
|
||||
int val;
|
||||
|
||||
int intc = pspSdkDisableInterrupts();
|
||||
|
||||
(*pdest)++;
|
||||
val = *pdest;
|
||||
|
||||
pspSdkEnableInterrupts(intc);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Helper functions
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
static pspThreadData *getThreadData(SceUID threadHandle)
|
||||
{
|
||||
void *pTls = getTlsStructFromThread(threadHandle);
|
||||
pspThreadData *pThreadData = (pspThreadData *)
|
||||
pteTlsGetValue(pTls, threadDataKey);
|
||||
|
||||
return pThreadData;
|
||||
}
|
||||
|
||||
static void *getTlsStructFromThread(SceUID thid)
|
||||
{
|
||||
SceKernelThreadInfo thinfo;
|
||||
unsigned int ptr;
|
||||
unsigned int thrNum;
|
||||
int numMatches;
|
||||
|
||||
thinfo.size = sizeof(SceKernelThreadInfo);
|
||||
|
||||
sceKernelReferThreadStatus(thid, &thinfo);
|
||||
|
||||
numMatches = sscanf(thinfo.name,"pthread%04d__%x", &thrNum, &ptr);
|
||||
|
||||
/* If we were called from a pthread, use the TLS allocated when the thread
|
||||
* was created. Otherwise, we were called from a non-pthread, so use the
|
||||
* "global". This is a pretty bad hack, but necessary due to lack of TLS on PSP.
|
||||
*/
|
||||
if (numMatches == 2)
|
||||
return (void *) ptr;
|
||||
|
||||
return globalTls;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Thread Local Storage
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
pte_osResult pte_osTlsSetValue(unsigned int key, void * value)
|
||||
{
|
||||
void *pTls = getTlsStructFromThread(sceKernelGetThreadId());
|
||||
|
||||
return pteTlsSetValue(pTls, key, value);
|
||||
}
|
||||
|
||||
void * pte_osTlsGetValue(unsigned int index)
|
||||
{
|
||||
void *pTls = getTlsStructFromThread(sceKernelGetThreadId());
|
||||
|
||||
return (void *) pteTlsGetValue(pTls, index);
|
||||
|
||||
}
|
||||
|
||||
|
||||
pte_osResult pte_osTlsAlloc(unsigned int *pKey)
|
||||
{
|
||||
void *pTls = getTlsStructFromThread(sceKernelGetThreadId());
|
||||
|
||||
return pteTlsAlloc(pKey);
|
||||
|
||||
}
|
||||
|
||||
pte_osResult pte_osTlsFree(unsigned int index)
|
||||
{
|
||||
return pteTlsFree(index);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Miscellaneous
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
int ftime(struct timeb *tb)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
gettimeofday(&tv, &tz);
|
||||
|
||||
tb->time = tv.tv_sec;
|
||||
tb->millitm = tv.tv_usec / 1000;
|
||||
tb->timezone = tz.tz_minuteswest;
|
||||
tb->dstflag = tz.tz_dsttime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* psp_osal.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <pspsdk.h>
|
||||
|
||||
typedef SceUID pte_osThreadHandle;
|
||||
|
||||
typedef SceUID pte_osSemaphoreHandle;
|
||||
|
||||
typedef SceUID pte_osMutexHandle;
|
||||
|
||||
|
||||
#define OS_IS_HANDLE_VALID(x) ((x) > 0)
|
||||
|
||||
#define OS_MAX_SIMUL_THREADS 10
|
||||
|
||||
#define OS_DEFAULT_PRIO 11
|
||||
|
||||
#define OS_MIN_PRIO 17
|
||||
#define OS_MAX_PRIO 32
|
||||
|
||||
#if 0
|
||||
#define HAVE_THREAD_SAFE_ERRNO
|
||||
#endif
|
||||
|
||||
#define POLLING_DELAY_IN_us 100
|
||||
|
||||
#define OS_MAX_SEM_VALUE 254
|
||||
|
||||
int PspInterlockedExchange(int *ptarg, int val);
|
||||
int PspInterlockedCompareExchange(int *pdest, int exchange, int comp);
|
||||
int PspInterlockedExchangeAdd(int volatile* pAddend, int value);
|
||||
int PspInterlockedDecrement(int *pdest);
|
||||
int PspInterlockedIncrement(int *pdest);
|
||||
|
||||
|
||||
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
#ifndef _OS_SUPPORT_H_
|
||||
#define _OS_SUPPORT_H_
|
||||
|
||||
/* Platform specific one must be included first */
|
||||
#include "psp_osal.h"
|
||||
|
||||
#include "pte_generic_osal.h"
|
||||
|
||||
#endif /* _OS_SUPPORT_H */
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
/* pte_types.h */
|
||||
|
||||
#ifndef PTE_TYPES_H
|
||||
#define PTE_TYPES_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/timeb.h>
|
||||
|
||||
typedef int pid_t;
|
||||
|
||||
#endif /* PTE_TYPES_H */
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pspkernel.h>
|
||||
#include <pspdebug.h>
|
||||
#include <pspsdk.h>
|
||||
#include <pspctrl.h>
|
||||
|
||||
PSP_MODULE_INFO("Pthread Test", 0, 1, 1);
|
||||
|
||||
extern void pte_test_main();
|
||||
|
||||
#ifdef JNS
|
||||
#define printf pspDebugScreenPrintf
|
||||
#endif
|
||||
|
||||
/* Exit callback */
|
||||
int exit_callback(int arg1, int arg2, void *common)
|
||||
{
|
||||
sceKernelExitGame();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback thread */
|
||||
int CallbackThread(SceSize args, void *argp)
|
||||
{
|
||||
int cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
|
||||
sceKernelRegisterExitCallback(cbid);
|
||||
|
||||
sceKernelSleepThreadCB();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets up the callback thread and returns its thread id */
|
||||
int SetupCallbacks(void)
|
||||
{
|
||||
int thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
|
||||
if (thid >= 0)
|
||||
sceKernelStartThread(thid, 0, 0);
|
||||
|
||||
return thid;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
SceCtrlData pad;
|
||||
|
||||
pspDebugScreenInit();
|
||||
SetupCallbacks();
|
||||
|
||||
pte_test_main();
|
||||
|
||||
while (1)
|
||||
{
|
||||
sceCtrlReadBufferPositive(&pad, 1);
|
||||
if (pad.Buttons & PSP_CTRL_UP)
|
||||
{
|
||||
printf("Exiting...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Vendored
-1059
File diff suppressed because it is too large.
Load diff
Vendored
-449
@@ -1,449 +0,0 @@
|
||||
/*
|
||||
* pte_cancellable_wait.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef _GENERIC_OS_SUPPORT_H_
|
||||
#define _GENERIC_OS_SUPPORT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
/** @name Misc */
|
||||
//@{
|
||||
typedef enum pte_osResult
|
||||
{
|
||||
|
||||
/** Operation completed successfully */
|
||||
PTE_OS_OK = 0,
|
||||
|
||||
/** Operation failed because there insufficient resources */
|
||||
PTE_OS_NO_RESOURCES,
|
||||
|
||||
/** Operation failed due to a general failure */
|
||||
PTE_OS_GENERAL_FAILURE,
|
||||
|
||||
/** Operation did not complete because a user specified timeout expired. */
|
||||
PTE_OS_TIMEOUT,
|
||||
|
||||
/** The operation was interrupted before it could complete. */
|
||||
PTE_OS_INTERRUPTED,
|
||||
|
||||
/** An invalid parameter was specified */
|
||||
PTE_OS_INVALID_PARAM
|
||||
|
||||
|
||||
} pte_osResult;
|
||||
|
||||
/**
|
||||
* Provides a hook for the OSAL to implement any OS specific initialization. This is guaranteed to be
|
||||
* called before any other OSAL function.
|
||||
*/
|
||||
pte_osResult pte_osInit(void);
|
||||
//@}
|
||||
|
||||
/** @name Mutexes */
|
||||
//@{
|
||||
|
||||
/**
|
||||
* Creates a mutex
|
||||
*
|
||||
* @param pHandle Set to the handle of the newly created mutex.
|
||||
*
|
||||
* @return PTE_OS_OK - Mutex successfully created
|
||||
* @return PTE_OS_NO_RESOURCESs - Insufficient resources to create mutex
|
||||
*/
|
||||
pte_osResult pte_osMutexCreate(pte_osMutexHandle *pHandle);
|
||||
|
||||
/**
|
||||
* Deletes a mutex and frees any associated resources.
|
||||
*
|
||||
* @param handle Handle of mutex to delete.
|
||||
*
|
||||
* @return PTE_OS_OK - Mutex successfully deleted.
|
||||
*/
|
||||
pte_osResult pte_osMutexDelete(pte_osMutexHandle handle);
|
||||
|
||||
/**
|
||||
* Locks the mutex
|
||||
*
|
||||
* @param handle Handle of mutex to lock.
|
||||
*
|
||||
* @return PTE_OS_OK - Mutex successfully locked.
|
||||
*/
|
||||
pte_osResult pte_osMutexLock(pte_osMutexHandle handle);
|
||||
|
||||
/**
|
||||
* Locks the mutex, returning after @p timeoutMsecs if the resources is not
|
||||
* available. Can be used for polling mutex by using @p timeoutMsecs of zero.
|
||||
*
|
||||
* @param handle Handle of mutex to lock.
|
||||
* @param timeoutMsecs Number of milliseconds to wait for resource before returning.
|
||||
*
|
||||
* @return PTE_OS_OK - Mutex successfully locked.
|
||||
* @return PTE_OS_TIMEOUT - Timeout expired before lock was obtained.
|
||||
*/
|
||||
pte_osResult pte_osMutexTimedLock(pte_osMutexHandle handle, unsigned int timeoutMsecs);
|
||||
|
||||
/**
|
||||
* Unlocks the mutex
|
||||
*
|
||||
* @param handle Handle of mutex to unlock
|
||||
*
|
||||
* @return PTE_OS_OK - Mutex successfully unlocked.
|
||||
*/
|
||||
pte_osResult pte_osMutexUnlock(pte_osMutexHandle handle);
|
||||
//@}
|
||||
|
||||
/** @name Threads */
|
||||
//@{
|
||||
typedef int (*pte_osThreadEntryPoint)(void *params);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new thread. The thread must be started in a suspended state - it will be
|
||||
* explicitly started when pte_osThreadStart() is called.
|
||||
*
|
||||
* @param entryPoint Entry point to the new thread.
|
||||
* @param stackSize The initial stack size, in bytes. Note that this can be considered a minimum -
|
||||
* for instance if the OS requires a larger stack space than what the caller specified.
|
||||
* @param initialPriority The priority that the new thread should be initially set to.
|
||||
* @param argv Parameter to pass to the new thread.
|
||||
* @param ppte_osThreadHandle set to the handle of the new thread.
|
||||
*
|
||||
* @return PTE_OS_OK - New thread successfully created.
|
||||
* @return PTE_OS_NO_RESOURCESs - Insufficient resources to create thread
|
||||
*/
|
||||
pte_osResult pte_osThreadCreate(pte_osThreadEntryPoint entryPoint,
|
||||
int stackSize,
|
||||
int initialPriority,
|
||||
void *argv,
|
||||
pte_osThreadHandle* ppte_osThreadHandle);
|
||||
|
||||
/**
|
||||
* Starts executing the specified thread.
|
||||
*
|
||||
* @param osThreadHandle handle of the thread to start.
|
||||
*
|
||||
* @return PTE_OS_OK - thread successfully started.
|
||||
*/
|
||||
pte_osResult pte_osThreadStart(pte_osThreadHandle osThreadHandle);
|
||||
|
||||
/**
|
||||
* Causes the current thread to stop executing.
|
||||
*
|
||||
* @return Never returns (thread terminated)
|
||||
*/
|
||||
void pte_osThreadExit();
|
||||
|
||||
/**
|
||||
* Waits for the specified thread to end. If the thread has already terminated, this returns
|
||||
* immediately.
|
||||
*
|
||||
* @param threadHandle Handle fo thread to wait for.
|
||||
*
|
||||
* @return PTE_OS_OK - specified thread terminated.
|
||||
*/
|
||||
pte_osResult pte_osThreadWaitForEnd(pte_osThreadHandle threadHandle);
|
||||
|
||||
/**
|
||||
* Returns the handle of the currently executing thread.
|
||||
*/
|
||||
pte_osThreadHandle pte_osThreadGetHandle(void);
|
||||
|
||||
/**
|
||||
* Returns the priority of the specified thread.
|
||||
*/
|
||||
int pte_osThreadGetPriority(pte_osThreadHandle threadHandle);
|
||||
|
||||
/**
|
||||
* Sets the priority of the specified thread.
|
||||
*
|
||||
* @return PTE_OS_OK - thread priority successfully set
|
||||
*/
|
||||
pte_osResult pte_osThreadSetPriority(pte_osThreadHandle threadHandle, int newPriority);
|
||||
|
||||
/**
|
||||
* Frees resources associated with the specified thread. This is called after the thread has terminated
|
||||
* and is no longer needed (e.g. after pthread_join returns). This call will always be made
|
||||
* from a different context than that of the target thread.
|
||||
*/
|
||||
pte_osResult pte_osThreadDelete(pte_osThreadHandle handle);
|
||||
|
||||
/**
|
||||
* Frees resources associated with the specified thread and then causes the thread to exit.
|
||||
* This is called after the thread has terminated and is no longer needed (e.g. after
|
||||
* pthread_join returns). This call will always be made from the context of the target thread.
|
||||
*/
|
||||
pte_osResult pte_osThreadExitAndDelete(pte_osThreadHandle handle);
|
||||
|
||||
/**
|
||||
* Cancels the specified thread. This should cause pte_osSemaphoreCancellablePend() and for pte_osThreadCheckCancel()
|
||||
* to return @p PTE_OS_INTERRUPTED.
|
||||
*
|
||||
* @param threadHandle handle to the thread to cancel.
|
||||
*
|
||||
* @return Thread successfully canceled.
|
||||
*/
|
||||
pte_osResult pte_osThreadCancel(pte_osThreadHandle threadHandle);
|
||||
|
||||
/**
|
||||
* Check if pte_osThreadCancel() has been called on the specified thread.
|
||||
*
|
||||
* @param threadHandle handle of thread to check the state of.
|
||||
*
|
||||
* @return PTE_OS_OK - Thread has not been cancelled
|
||||
* @return PTE_OS_INTERRUPTED - Thread has been cancelled.
|
||||
*/
|
||||
pte_osResult pte_osThreadCheckCancel(pte_osThreadHandle threadHandle);
|
||||
|
||||
/**
|
||||
* Causes the current thread to sleep for the specified number of milliseconds.
|
||||
*/
|
||||
void pte_osThreadSleep(unsigned int msecs);
|
||||
|
||||
/**
|
||||
* Returns the maximum allowable priority
|
||||
*/
|
||||
int pte_osThreadGetMaxPriority();
|
||||
|
||||
/**
|
||||
* Returns the minimum allowable priority
|
||||
*/
|
||||
int pte_osThreadGetMinPriority();
|
||||
|
||||
/**
|
||||
* Returns the priority that should be used if the caller to pthread_create doesn't
|
||||
* explicitly set one.
|
||||
*/
|
||||
int pte_osThreadGetDefaultPriority();
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/** @name Semaphores */
|
||||
//@{
|
||||
|
||||
/**
|
||||
* Creates a semaphore
|
||||
*
|
||||
* @param initialValue Initial value of the semaphore
|
||||
* @param pHandle Set to the handle of the newly created semaphore.
|
||||
*
|
||||
* @return PTE_OS_OK - Semaphore successfully created
|
||||
* @return PTE_OS_NO_RESOURCESs - Insufficient resources to create semaphore
|
||||
*/
|
||||
pte_osResult pte_osSemaphoreCreate(int initialValue, pte_osSemaphoreHandle *pHandle);
|
||||
|
||||
/**
|
||||
* Deletes a semaphore and frees any associated resources.
|
||||
*
|
||||
* @param handle Handle of semaphore to delete.
|
||||
*
|
||||
* @return PTE_OS_OK - Semaphore successfully deleted.
|
||||
*/
|
||||
pte_osResult pte_osSemaphoreDelete(pte_osSemaphoreHandle handle);
|
||||
|
||||
/**
|
||||
* Posts to the semaphore
|
||||
*
|
||||
* @param handle Semaphore to release
|
||||
* @param count Amount to increment the semaphore by.
|
||||
*
|
||||
* @return PTE_OS_OK - semaphore successfully released.
|
||||
*/
|
||||
pte_osResult pte_osSemaphorePost(pte_osSemaphoreHandle handle, int count);
|
||||
|
||||
/**
|
||||
* Acquire a semaphore, returning after @p timeoutMsecs if the semaphore is not
|
||||
* available. Can be used for polling a semaphore by using @p timeoutMsecs of zero.
|
||||
*
|
||||
* @param handle Handle of semaphore to acquire.
|
||||
* @param pTimeout Pointer to the number of milliseconds to wait to acquire the semaphore
|
||||
* before returning. If set to NULL, wait forever.
|
||||
*
|
||||
* @return PTE_OS_OK - Semaphore successfully acquired.
|
||||
* @return PTE_OS_TIMEOUT - Timeout expired before semaphore was obtained.
|
||||
*/
|
||||
pte_osResult pte_osSemaphorePend(pte_osSemaphoreHandle handle, unsigned int *pTimeout);
|
||||
|
||||
/**
|
||||
* Acquire a semaphore, returning after @p timeoutMsecs if the semaphore is not
|
||||
* available. Can be used for polling a semaphore by using @p timeoutMsecs of zero.
|
||||
* Call must return immediately if pte_osThreadCancel() is called on the thread waiting for
|
||||
* the semaphore.
|
||||
*
|
||||
* @param handle Handle of semaphore to acquire.
|
||||
* @param pTimeout Pointer to the number of milliseconds to wait to acquire the semaphore
|
||||
* before returning. If set to NULL, wait forever.
|
||||
*
|
||||
* @return PTE_OS_OK - Semaphore successfully acquired.
|
||||
* @return PTE_OS_TIMEOUT - Timeout expired before semaphore was obtained.
|
||||
*/
|
||||
pte_osResult pte_osSemaphoreCancellablePend(pte_osSemaphoreHandle handle, unsigned int *pTimeout);
|
||||
//@}
|
||||
|
||||
|
||||
/** @name Thread Local Storage */
|
||||
//@{
|
||||
/**
|
||||
* Sets the thread specific value for the specified key for the
|
||||
* currently executing thread.
|
||||
*
|
||||
* @param index The TLS key for the value.
|
||||
* @param value The value to save
|
||||
*/
|
||||
pte_osResult pte_osTlsSetValue(unsigned int key, void * value);
|
||||
|
||||
/**
|
||||
* Retrieves the thread specific value for the specified key for
|
||||
* the currently executing thread. If a value has not been set
|
||||
* for this key, NULL should be returned (i.e. TLS values default
|
||||
* to NULL).
|
||||
*
|
||||
* @param index The TLS key for the value.
|
||||
*
|
||||
* @return The value associated with @p key for the current thread.
|
||||
*/
|
||||
void * pte_osTlsGetValue(unsigned int key);
|
||||
|
||||
/**
|
||||
* Initializes the OS TLS support. This is called by the PTE library
|
||||
* prior to performing ANY TLS operation.
|
||||
*/
|
||||
void pte_osTlsInit(void);
|
||||
|
||||
/**
|
||||
* Allocates a new TLS key.
|
||||
*
|
||||
* @param pKey On success will be set to the newly allocated key.
|
||||
*
|
||||
* @return PTE_OS_OK - TLS key successfully allocated.
|
||||
* @return PTE_OS_NO_RESOURCESs - Insufficient resources to allocate key (e.g.
|
||||
* maximum number of keys reached).
|
||||
*/
|
||||
pte_osResult pte_osTlsAlloc(unsigned int *pKey);
|
||||
|
||||
/**
|
||||
* Frees the specified TLS key.
|
||||
*
|
||||
* @param index TLS key to free
|
||||
*
|
||||
* @return PTE_OS_OK - TLS key was successfully freed.
|
||||
*/
|
||||
pte_osResult pte_osTlsFree(unsigned int key);
|
||||
//@}
|
||||
|
||||
/** @name Atomic operations */
|
||||
//@{
|
||||
|
||||
/**
|
||||
* Sets the target to the specified value as an atomic operation.
|
||||
*
|
||||
* \code
|
||||
* origVal = *ptarg
|
||||
* *ptarg = val
|
||||
* return origVal
|
||||
* \endcode
|
||||
*
|
||||
* @param pTarg Pointer to the value to be exchanged.
|
||||
* @param val Value to be exchanged
|
||||
*
|
||||
* @return original value of destination
|
||||
*/
|
||||
int pte_osAtomicExchange(int *pTarg, int val);
|
||||
|
||||
/**
|
||||
* Performs an atomic compare-and-exchange oepration on the specified
|
||||
* value. That is:
|
||||
*
|
||||
* \code
|
||||
* origVal = *pdest
|
||||
* if (*pdest == comp)
|
||||
* then *pdest = exchange
|
||||
* return origVal
|
||||
* \endcode
|
||||
*
|
||||
* @param pdest Pointer to the destination value.
|
||||
* @param exchange Exchange value (value to set destination to if destination == comparand)
|
||||
* @param comp The value to compare to destination.
|
||||
*
|
||||
* @return Original value of destination
|
||||
*/
|
||||
int pte_osAtomicCompareExchange(int *pdest, int exchange, int comp);
|
||||
|
||||
/**
|
||||
* Adds the value to target as an atomic operation
|
||||
*
|
||||
* \code
|
||||
* origVal = *pdest
|
||||
* *pAddend += value
|
||||
* return origVal
|
||||
* \endcode
|
||||
*
|
||||
* @param pdest Pointer to the variable to be updated.
|
||||
* @param value Value to be added to the variable.
|
||||
*
|
||||
* @return Original value of destination
|
||||
*/
|
||||
int pte_osAtomicExchangeAdd(int volatile* pdest, int value);
|
||||
|
||||
/**
|
||||
* Decrements the destination.
|
||||
*
|
||||
* \code
|
||||
* origVal = *pdest
|
||||
* *pdest++
|
||||
* return origVal
|
||||
* \endcode
|
||||
*
|
||||
* @param pdest Destination value to decrement
|
||||
*
|
||||
* @return Original destination value
|
||||
*/
|
||||
int pte_osAtomicDecrement(int *pdest);
|
||||
|
||||
/**
|
||||
* Increments the destination value
|
||||
*
|
||||
* \code
|
||||
* origVal = *pdest;
|
||||
* *pdest++;
|
||||
* return origVal;
|
||||
*/
|
||||
int pte_osAtomicIncrement(int *pdest);
|
||||
//@}
|
||||
|
||||
struct timeb;
|
||||
|
||||
int ftime(struct timeb *tb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // _OS_SUPPORT_H_
|
||||
Vendored
-396
@@ -1,396 +0,0 @@
|
||||
/*
|
||||
* pte_main.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit instantiates data associated with the implementation
|
||||
* as a whole.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pte_osal.h"
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
|
||||
int pte_processInitialized = PTE_FALSE;
|
||||
pte_thread_t * pte_threadReuseTop = PTE_THREAD_REUSE_EMPTY;
|
||||
pte_thread_t * pte_threadReuseBottom = PTE_THREAD_REUSE_EMPTY;
|
||||
pthread_key_t pte_selfThreadKey = NULL;
|
||||
pthread_key_t pte_cleanupKey = NULL;
|
||||
pthread_cond_t pte_cond_list_head = NULL;
|
||||
pthread_cond_t pte_cond_list_tail = NULL;
|
||||
|
||||
int pte_concurrency = 0;
|
||||
|
||||
/* What features have been auto-detaected */
|
||||
int pte_features = 0;
|
||||
|
||||
unsigned char pte_smp_system = PTE_TRUE; /* Safer if assumed true initially. */
|
||||
|
||||
/*
|
||||
* Global lock for managing pthread_t struct reuse.
|
||||
*/
|
||||
pte_osMutexHandle pte_thread_reuse_lock;
|
||||
|
||||
/*
|
||||
* Global lock for testing internal state of statically declared mutexes.
|
||||
*/
|
||||
pte_osMutexHandle pte_mutex_test_init_lock;
|
||||
|
||||
/*
|
||||
* Global lock for testing internal state of PTHREAD_COND_INITIALIZER
|
||||
* created condition variables.
|
||||
*/
|
||||
pte_osMutexHandle pte_cond_test_init_lock;
|
||||
|
||||
/*
|
||||
* Global lock for testing internal state of PTHREAD_RWLOCK_INITIALIZER
|
||||
* created read/write locks.
|
||||
*/
|
||||
pte_osMutexHandle pte_rwlock_test_init_lock;
|
||||
|
||||
/*
|
||||
* Global lock for testing internal state of PTHREAD_SPINLOCK_INITIALIZER
|
||||
* created spin locks.
|
||||
*/
|
||||
pte_osMutexHandle pte_spinlock_test_init_lock;
|
||||
|
||||
/*
|
||||
* Global lock for condition variable linked list. The list exists
|
||||
* to wake up CVs when a WM_TIMECHANGE message arrives. See
|
||||
* w32_TimeChangeHandler.c.
|
||||
*/
|
||||
pte_osMutexHandle pte_cond_list_lock;
|
||||
|
||||
int pthread_create (pthread_t * tid,
|
||||
const pthread_attr_t * attr,
|
||||
void *(*start) (void *), void *arg)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function creates a thread running the start function,
|
||||
* passing it the parameter value, 'arg'. The 'attr'
|
||||
* argument specifies optional creation attributes.
|
||||
* The identity of the new thread is returned
|
||||
* via 'tid', which should not be NULL.
|
||||
*
|
||||
* PARAMETERS
|
||||
* tid
|
||||
* pointer to an instance of pthread_t
|
||||
*
|
||||
* attr
|
||||
* optional pointer to an instance of pthread_attr_t
|
||||
*
|
||||
* start
|
||||
* pointer to the starting routine for the new thread
|
||||
*
|
||||
* arg
|
||||
* optional parameter passed to 'start'
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function creates a thread running the start function,
|
||||
* passing it the parameter value, 'arg'. The 'attr'
|
||||
* argument specifies optional creation attributes.
|
||||
* The identity of the new thread is returned
|
||||
* via 'tid', which should not be the NULL pointer.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully created thread,
|
||||
* EINVAL attr invalid,
|
||||
* EAGAIN insufficient resources.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
pthread_t thread;
|
||||
pte_thread_t * tp;
|
||||
int result = EAGAIN;
|
||||
int run = PTE_TRUE;
|
||||
ThreadParms *parms = NULL;
|
||||
long stackSize;
|
||||
int priority = 0;
|
||||
pthread_t self;
|
||||
pte_osResult osResult;
|
||||
register pthread_attr_t a = NULL;
|
||||
|
||||
/*
|
||||
* Before doing anything, check that tid can be stored through
|
||||
* without invoking a memory protection error (segfault).
|
||||
* Make sure that the assignment below can't be optimised out by the compiler.
|
||||
* This is assured by conditionally assigning *tid again at the end.
|
||||
*/
|
||||
|
||||
if (attr != NULL)
|
||||
a = *attr;
|
||||
|
||||
if ((thread = pte_new ()) == NULL)
|
||||
goto FAIL0;
|
||||
|
||||
tp = (pte_thread_t *) thread;
|
||||
|
||||
priority = tp->sched_priority;
|
||||
|
||||
if ((parms = (ThreadParms *) malloc (sizeof (*parms))) == NULL)
|
||||
goto FAIL0;
|
||||
|
||||
parms->tid = thread;
|
||||
parms->start = start;
|
||||
parms->arg = arg;
|
||||
|
||||
if (a != NULL)
|
||||
{
|
||||
stackSize = a->stacksize;
|
||||
tp->detachState = a->detachstate;
|
||||
priority = a->param.sched_priority;
|
||||
|
||||
if ( (priority > pte_osThreadGetMaxPriority()) ||
|
||||
(priority < pte_osThreadGetMinPriority()) )
|
||||
{
|
||||
result = EINVAL;
|
||||
goto FAIL0;
|
||||
}
|
||||
|
||||
/* Everything else */
|
||||
|
||||
/*
|
||||
* Thread priority must be set to a valid system level
|
||||
* without altering the value set by pthread_attr_setschedparam().
|
||||
*/
|
||||
|
||||
if (PTHREAD_INHERIT_SCHED == a->inheritsched)
|
||||
{
|
||||
/*
|
||||
* If the thread that called pthread_create() is an OS thread
|
||||
* then the inherited priority could be the result of a temporary
|
||||
* system adjustment. This is not the case for POSIX threads.
|
||||
*/
|
||||
self = pthread_self ();
|
||||
priority = ((pte_thread_t *) self)->sched_priority;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Default stackSize
|
||||
*/
|
||||
stackSize = PTHREAD_STACK_MIN;
|
||||
|
||||
}
|
||||
|
||||
tp->state = run ? PThreadStateInitial : PThreadStateSuspended;
|
||||
|
||||
tp->keys = NULL;
|
||||
|
||||
/*
|
||||
* Threads must be started in suspended mode and resumed if necessary
|
||||
* after _beginthreadex returns us the handle. Otherwise we set up a
|
||||
* race condition between the creating and the created threads.
|
||||
* Note that we also retain a local copy of the handle for use
|
||||
* by us in case thread.p->threadH gets NULLed later but before we've
|
||||
* finished with it here.
|
||||
*/
|
||||
result = pthread_mutex_lock (&tp->threadLock);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
/*
|
||||
* Must record the thread's sched_priority as given,
|
||||
* not as finally adjusted.
|
||||
*/
|
||||
tp->sched_priority = priority;
|
||||
|
||||
(void) pthread_mutex_unlock (&tp->threadLock);
|
||||
}
|
||||
|
||||
osResult = pte_osThreadCreate(pte_threadStart,
|
||||
stackSize,
|
||||
priority,
|
||||
parms,
|
||||
&(tp->threadId));
|
||||
|
||||
if (osResult == PTE_OS_OK)
|
||||
{
|
||||
pte_osThreadStart(tp->threadId);
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tp->threadId = 0;
|
||||
result = EAGAIN;
|
||||
goto FAIL0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fall Through Intentionally
|
||||
*/
|
||||
|
||||
/*
|
||||
* ------------
|
||||
* Failure Code
|
||||
* ------------
|
||||
*/
|
||||
|
||||
FAIL0:
|
||||
if (result != 0)
|
||||
{
|
||||
|
||||
pte_threadDestroy (thread);
|
||||
tp = NULL;
|
||||
|
||||
if (parms != NULL)
|
||||
free (parms);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tid != NULL)
|
||||
*tid = thread;
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* The functions pte_pop_cleanup and pte_push_cleanup
|
||||
* are implemented here for applications written in C with no
|
||||
* C++ destructor support.
|
||||
*/
|
||||
|
||||
pte_cleanup_t *pte_pop_cleanup (int execute)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function pops the most recently pushed cleanup
|
||||
* handler. If execute is nonzero, then the cleanup handler
|
||||
* is executed if non-null.
|
||||
*
|
||||
* PARAMETERS
|
||||
* execute
|
||||
* if nonzero, execute the cleanup handler
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function pops the most recently pushed cleanup
|
||||
* handler. If execute is nonzero, then the cleanup handler
|
||||
* is executed if non-null.
|
||||
* NOTE: specify 'execute' as nonzero to avoid duplication
|
||||
* of common cleanup code.
|
||||
*
|
||||
* RESULTS
|
||||
* N/A
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
pte_cleanup_t *cleanup;
|
||||
|
||||
cleanup = (pte_cleanup_t *) pthread_getspecific (pte_cleanupKey);
|
||||
|
||||
if (cleanup != NULL)
|
||||
{
|
||||
if (execute && (cleanup->routine != NULL))
|
||||
{
|
||||
|
||||
(*cleanup->routine) (cleanup->arg);
|
||||
|
||||
}
|
||||
|
||||
pthread_setspecific (pte_cleanupKey, (void *) cleanup->prev);
|
||||
|
||||
}
|
||||
|
||||
return (cleanup);
|
||||
|
||||
} /* pte_pop_cleanup */
|
||||
|
||||
|
||||
void
|
||||
pte_push_cleanup (pte_cleanup_t * cleanup,
|
||||
pte_cleanup_callback_t routine, void *arg)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function pushes a new cleanup handler onto the thread's stack
|
||||
* of cleanup handlers. Each cleanup handler pushed onto the stack is
|
||||
* popped and invoked with the argument 'arg' when
|
||||
* a) the thread exits by calling 'pthread_exit',
|
||||
* b) when the thread acts on a cancellation request,
|
||||
* c) or when the thread calls pthread_cleanup_pop with a nonzero
|
||||
* 'execute' argument
|
||||
*
|
||||
* PARAMETERS
|
||||
* cleanup
|
||||
* a pointer to an instance of pthread_cleanup_t,
|
||||
*
|
||||
* routine
|
||||
* pointer to a cleanup handler,
|
||||
*
|
||||
* arg
|
||||
* parameter to be passed to the cleanup handler
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function pushes a new cleanup handler onto the thread's stack
|
||||
* of cleanup handlers. Each cleanup handler pushed onto the stack is
|
||||
* popped and invoked with the argument 'arg' when
|
||||
* a) the thread exits by calling 'pthread_exit',
|
||||
* b) when the thread acts on a cancellation request,
|
||||
* c) or when the thrad calls pthread_cleanup_pop with a nonzero
|
||||
* 'execute' argument
|
||||
* NOTE: pthread_push_cleanup, pte_pop_cleanup must be paired
|
||||
* in the same lexical scope.
|
||||
*
|
||||
* RESULTS
|
||||
* pthread_cleanup_t *
|
||||
* pointer to the previous cleanup
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
cleanup->routine = routine;
|
||||
cleanup->arg = arg;
|
||||
|
||||
cleanup->prev = (pte_cleanup_t *) pthread_getspecific (pte_cleanupKey);
|
||||
|
||||
pthread_setspecific (pte_cleanupKey, (void *) cleanup);
|
||||
}
|
||||
Vendored
-1017
File diff suppressed because it is too large.
Load diff
Vendored
-891
@@ -1,891 +0,0 @@
|
||||
/* This is an implementation of the threads API of POSIX 1003.1-2001.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined( PTHREAD_H )
|
||||
#define PTHREAD_H
|
||||
|
||||
#include <pte_types.h>
|
||||
|
||||
#include <sched.h>
|
||||
|
||||
#define PTE_VERSION 2,8,0,0
|
||||
#define PTE_VERSION_STRING "2, 8, 0, 0\0"
|
||||
|
||||
/* There are two implementations of cancel cleanup.
|
||||
* Note that pthread.h is included in both application
|
||||
* compilation units and also internally for the library.
|
||||
* The code here and within the library aims to work
|
||||
* for all reasonable combinations of environments.
|
||||
*
|
||||
* The two implementations are:
|
||||
*
|
||||
* C
|
||||
* C++
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define defaults for cleanup code.
|
||||
* Note: Unless the build explicitly defines one of the following, then
|
||||
* we default to standard C style cleanup. This style uses setjmp/longjmp
|
||||
* in the cancelation and thread exit implementations and therefore won't
|
||||
* do stack unwinding if linked to applications that have it (e.g.
|
||||
* C++ apps). This is currently consistent with most/all commercial Unix
|
||||
* POSIX threads implementations.
|
||||
*/
|
||||
|
||||
#undef PTE_LEVEL
|
||||
|
||||
#if defined(_POSIX_SOURCE)
|
||||
#define PTE_LEVEL 0
|
||||
/* Early POSIX */
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
|
||||
#undef PTE_LEVEL
|
||||
#define PTE_LEVEL 1
|
||||
/* Include 1b, 1c and 1d */
|
||||
#endif
|
||||
|
||||
#if defined(INCLUDE_NP)
|
||||
#undef PTE_LEVEL
|
||||
#define PTE_LEVEL 2
|
||||
/* Include Non-Portable extensions */
|
||||
#endif
|
||||
|
||||
#define PTE_LEVEL_MAX 3
|
||||
|
||||
#if !defined(PTE_LEVEL)
|
||||
#define PTE_LEVEL PTE_LEVEL_MAX
|
||||
/* Include everything */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------
|
||||
*
|
||||
*
|
||||
* Module: pthread.h
|
||||
*
|
||||
* Purpose:
|
||||
* Provides an implementation of PThreads based upon the
|
||||
* standard:
|
||||
*
|
||||
* POSIX 1003.1-2001
|
||||
* and
|
||||
* The Single Unix Specification version 3
|
||||
*
|
||||
* (these two are equivalent)
|
||||
*
|
||||
* in order to enhance code portability between Windows,
|
||||
* various commercial Unix implementations, and Linux.
|
||||
*
|
||||
* See the ANNOUNCE file for a full list of conforming
|
||||
* routines and defined constants, and a list of missing
|
||||
* routines and constants not defined in this implementation.
|
||||
*
|
||||
* Authors:
|
||||
* There have been many contributors to this library.
|
||||
* The initial implementation was contributed by
|
||||
* John Bossom, and several others have provided major
|
||||
* sections or revisions of parts of the implementation.
|
||||
* Often significant effort has been contributed to
|
||||
* find and fix important bugs and other problems to
|
||||
* improve the reliability of the library, which sometimes
|
||||
* is not reflected in the amount of code which changed as
|
||||
* result.
|
||||
* As much as possible, the contributors are acknowledged
|
||||
* in the ChangeLog file in the source code distribution
|
||||
* where their changes are noted in detail.
|
||||
*
|
||||
* Contributors are listed in the CONTRIBUTORS file.
|
||||
*
|
||||
* As usual, all bouquets go to the contributors, and all
|
||||
* brickbats go to the project maintainer.
|
||||
*
|
||||
* Maintainer:
|
||||
* The code base for this project is coordinated and
|
||||
* eventually pre-tested, packaged, and made available by
|
||||
*
|
||||
* Ross Johnson <rpj@callisto.canberra.edu.au>
|
||||
*
|
||||
* QA Testers:
|
||||
* Ultimately, the library is tested in the real world by
|
||||
* a host of competent and demanding scientists and
|
||||
* engineers who report bugs and/or provide solutions
|
||||
* which are then fixed or incorporated into subsequent
|
||||
* versions of the library. Each time a bug is fixed, a
|
||||
* test case is written to prove the fix and ensure
|
||||
* that later changes to the code don't reintroduce the
|
||||
* same error. The number of test cases is slowly growing
|
||||
* and therefore so is the code reliability.
|
||||
*
|
||||
* Compliance:
|
||||
* See the file ANNOUNCE for the list of implemented
|
||||
* and not-implemented routines and defined options.
|
||||
* Of course, these are all defined is this file as well.
|
||||
*
|
||||
* Web site:
|
||||
* The source code and other information about this library
|
||||
* are available from
|
||||
*
|
||||
* http://sources.redhat.com/pthreads-win32/
|
||||
*
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
* Boolean values to make us independent of system includes.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
PTE_FALSE = 0,
|
||||
PTE_TRUE = (! PTE_FALSE)
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------
|
||||
*
|
||||
* POSIX 1003.1-2001 Options
|
||||
* =========================
|
||||
*
|
||||
* Options are normally set in <unistd.h>, which is not provided
|
||||
* with pthreads-embedded.
|
||||
*
|
||||
* For conformance with the Single Unix Specification (version 3), all of the
|
||||
* options below are defined, and have a value of either -1 (not supported)
|
||||
* or 200112L (supported).
|
||||
*
|
||||
* These options can neither be left undefined nor have a value of 0, because
|
||||
* either indicates that sysconf(), which is not implemented, may be used at
|
||||
* runtime to check the status of the option.
|
||||
*
|
||||
* _POSIX_THREADS (== 200112L)
|
||||
* If == 200112L, you can use threads
|
||||
*
|
||||
* _POSIX_THREAD_ATTR_STACKSIZE (== 200112L)
|
||||
* If == 200112L, you can control the size of a thread's
|
||||
* stack
|
||||
* pthread_attr_getstacksize
|
||||
* pthread_attr_setstacksize
|
||||
*
|
||||
* _POSIX_THREAD_ATTR_STACKADDR (== -1)
|
||||
* If == 200112L, you can allocate and control a thread's
|
||||
* stack. If not supported, the following functions
|
||||
* will return ENOSYS, indicating they are not
|
||||
* supported:
|
||||
* pthread_attr_getstackaddr
|
||||
* pthread_attr_setstackaddr
|
||||
*
|
||||
* _POSIX_THREAD_PRIORITY_SCHEDULING (== -1)
|
||||
* If == 200112L, you can use realtime scheduling.
|
||||
* This option indicates that the behaviour of some
|
||||
* implemented functions conforms to the additional TPS
|
||||
* requirements in the standard. E.g. rwlocks favour
|
||||
* writers over readers when threads have equal priority.
|
||||
*
|
||||
* _POSIX_THREAD_PRIO_INHERIT (== -1)
|
||||
* If == 200112L, you can create priority inheritance
|
||||
* mutexes.
|
||||
* pthread_mutexattr_getprotocol +
|
||||
* pthread_mutexattr_setprotocol +
|
||||
*
|
||||
* _POSIX_THREAD_PRIO_PROTECT (== -1)
|
||||
* If == 200112L, you can create priority ceiling mutexes
|
||||
* Indicates the availability of:
|
||||
* pthread_mutex_getprioceiling
|
||||
* pthread_mutex_setprioceiling
|
||||
* pthread_mutexattr_getprioceiling
|
||||
* pthread_mutexattr_getprotocol +
|
||||
* pthread_mutexattr_setprioceiling
|
||||
* pthread_mutexattr_setprotocol +
|
||||
*
|
||||
* _POSIX_THREAD_PROCESS_SHARED (== -1)
|
||||
* If set, you can create mutexes and condition
|
||||
* variables that can be shared with another
|
||||
* process.If set, indicates the availability
|
||||
* of:
|
||||
* pthread_mutexattr_getpshared
|
||||
* pthread_mutexattr_setpshared
|
||||
* pthread_condattr_getpshared
|
||||
* pthread_condattr_setpshared
|
||||
*
|
||||
* _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L)
|
||||
* If == 200112L you can use the special *_r library
|
||||
* functions that provide thread-safe behaviour
|
||||
*
|
||||
* _POSIX_READER_WRITER_LOCKS (== 200112L)
|
||||
* If == 200112L, you can use read/write locks
|
||||
*
|
||||
* _POSIX_SPIN_LOCKS (== 200112L)
|
||||
* If == 200112L, you can use spin locks
|
||||
*
|
||||
* _POSIX_BARRIERS (== 200112L)
|
||||
* If == 200112L, you can use barriers
|
||||
*
|
||||
* + These functions provide both 'inherit' and/or
|
||||
* 'protect' protocol, based upon these macro
|
||||
* settings.
|
||||
*
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* POSIX Options
|
||||
*/
|
||||
#undef _POSIX_THREADS
|
||||
#define _POSIX_THREADS 200112L
|
||||
|
||||
#undef _POSIX_READER_WRITER_LOCKS
|
||||
#define _POSIX_READER_WRITER_LOCKS 200112L
|
||||
|
||||
#undef _POSIX_SPIN_LOCKS
|
||||
#define _POSIX_SPIN_LOCKS 200112L
|
||||
|
||||
#undef _POSIX_BARRIERS
|
||||
#define _POSIX_BARRIERS 200112L
|
||||
|
||||
#undef _POSIX_THREAD_SAFE_FUNCTIONS
|
||||
#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L
|
||||
|
||||
#undef _POSIX_THREAD_ATTR_STACKSIZE
|
||||
#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
|
||||
|
||||
/*
|
||||
* The following options are not supported
|
||||
*/
|
||||
#undef _POSIX_THREAD_ATTR_STACKADDR
|
||||
#define _POSIX_THREAD_ATTR_STACKADDR -1
|
||||
|
||||
#undef _POSIX_THREAD_PRIO_INHERIT
|
||||
#define _POSIX_THREAD_PRIO_INHERIT -1
|
||||
|
||||
#undef _POSIX_THREAD_PRIO_PROTECT
|
||||
#define _POSIX_THREAD_PRIO_PROTECT -1
|
||||
|
||||
/* TPS is not fully supported. */
|
||||
#undef _POSIX_THREAD_PRIORITY_SCHEDULING
|
||||
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
|
||||
|
||||
#undef _POSIX_THREAD_PROCESS_SHARED
|
||||
#define _POSIX_THREAD_PROCESS_SHARED -1
|
||||
|
||||
|
||||
/*
|
||||
* POSIX 1003.1-2001 Limits
|
||||
* ===========================
|
||||
*
|
||||
* These limits are normally set in <limits.h>, which is not provided with
|
||||
* pthreads-embedded.
|
||||
*
|
||||
* PTHREAD_DESTRUCTOR_ITERATIONS
|
||||
* Maximum number of attempts to destroy
|
||||
* a thread's thread-specific data on
|
||||
* termination (must be at least 4)
|
||||
*
|
||||
* PTHREAD_KEYS_MAX
|
||||
* Maximum number of thread-specific data keys
|
||||
* available per process (must be at least 128)
|
||||
*
|
||||
* PTHREAD_STACK_MIN
|
||||
* Minimum supported stack size for a thread
|
||||
*
|
||||
* PTHREAD_THREADS_MAX
|
||||
* Maximum number of threads supported per
|
||||
* process (must be at least 64).
|
||||
*
|
||||
* SEM_NSEMS_MAX
|
||||
* The maximum number of semaphores a process can have.
|
||||
* (must be at least 256)
|
||||
*
|
||||
* SEM_VALUE_MAX
|
||||
* The maximum value a semaphore can have.
|
||||
* (must be at least 32767)
|
||||
*
|
||||
*/
|
||||
#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS
|
||||
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
|
||||
|
||||
#undef PTHREAD_DESTRUCTOR_ITERATIONS
|
||||
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
|
||||
|
||||
#undef _POSIX_THREAD_KEYS_MAX
|
||||
#define _POSIX_THREAD_KEYS_MAX 128
|
||||
|
||||
#undef PTHREAD_KEYS_MAX
|
||||
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
|
||||
|
||||
#undef PTHREAD_STACK_MIN
|
||||
#define PTHREAD_STACK_MIN 0
|
||||
|
||||
#undef _POSIX_THREAD_THREADS_MAX
|
||||
#define _POSIX_THREAD_THREADS_MAX 64
|
||||
|
||||
/* Arbitrary value */
|
||||
#undef PTHREAD_THREADS_MAX
|
||||
#define PTHREAD_THREADS_MAX 2019
|
||||
|
||||
#undef _POSIX_SEM_NSEMS_MAX
|
||||
#define _POSIX_SEM_NSEMS_MAX 256
|
||||
|
||||
/* Arbitrary value */
|
||||
#undef SEM_NSEMS_MAX
|
||||
#define SEM_NSEMS_MAX 1024
|
||||
|
||||
#undef _POSIX_SEM_VALUE_MAX
|
||||
#define _POSIX_SEM_VALUE_MAX 32767
|
||||
|
||||
#undef SEM_VALUE_MAX
|
||||
#define SEM_VALUE_MAX INT_MAX
|
||||
|
||||
|
||||
/*
|
||||
* Generic handle type - intended to extend uniqueness beyond
|
||||
* that available with a simple pointer. It should scale for either
|
||||
* IA-32 or IA-64.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
void * p; /* Pointer to actual object */
|
||||
unsigned int x; /* Extra information - reuse count etc */
|
||||
} pte_handle_t;
|
||||
|
||||
typedef /* pte_handle_t */ void * pthread_t;
|
||||
typedef struct pthread_attr_t_ * pthread_attr_t;
|
||||
typedef struct pthread_once_t_ pthread_once_t;
|
||||
typedef struct pthread_key_t_ * pthread_key_t;
|
||||
typedef struct pthread_mutex_t_ * pthread_mutex_t;
|
||||
typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t;
|
||||
typedef struct pthread_cond_t_ * pthread_cond_t;
|
||||
typedef struct pthread_condattr_t_ * pthread_condattr_t;
|
||||
typedef struct pthread_rwlock_t_ * pthread_rwlock_t;
|
||||
typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t;
|
||||
typedef struct pthread_spinlock_t_ * pthread_spinlock_t;
|
||||
typedef struct pthread_barrier_t_ * pthread_barrier_t;
|
||||
typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t;
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* ====================
|
||||
* POSIX Threads
|
||||
* ====================
|
||||
* ====================
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
/*
|
||||
* pthread_attr_{get,set}detachstate
|
||||
*/
|
||||
PTHREAD_CREATE_JOINABLE = 0, /* Default */
|
||||
PTHREAD_CREATE_DETACHED = 1,
|
||||
|
||||
/*
|
||||
* pthread_attr_{get,set}inheritsched
|
||||
*/
|
||||
PTHREAD_INHERIT_SCHED = 0,
|
||||
PTHREAD_EXPLICIT_SCHED = 1, /* Default */
|
||||
|
||||
/*
|
||||
* pthread_{get,set}scope
|
||||
*/
|
||||
PTHREAD_SCOPE_PROCESS = 0,
|
||||
PTHREAD_SCOPE_SYSTEM = 1, /* Default */
|
||||
PTHREAD_SCOPE_PROCESS_VFPU = 2, /* PSP specific */
|
||||
|
||||
/*
|
||||
* pthread_setcancelstate paramters
|
||||
*/
|
||||
PTHREAD_CANCEL_ENABLE = 0, /* Default */
|
||||
PTHREAD_CANCEL_DISABLE = 1,
|
||||
|
||||
/*
|
||||
* pthread_setcanceltype parameters
|
||||
*/
|
||||
PTHREAD_CANCEL_ASYNCHRONOUS = 0,
|
||||
PTHREAD_CANCEL_DEFERRED = 1, /* Default */
|
||||
|
||||
/*
|
||||
* pthread_mutexattr_{get,set}pshared
|
||||
* pthread_condattr_{get,set}pshared
|
||||
*/
|
||||
PTHREAD_PROCESS_PRIVATE = 0,
|
||||
PTHREAD_PROCESS_SHARED = 1,
|
||||
|
||||
/*
|
||||
* pthread_barrier_wait
|
||||
*/
|
||||
PTHREAD_BARRIER_SERIAL_THREAD = -1
|
||||
};
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* ====================
|
||||
* Cancelation
|
||||
* ====================
|
||||
* ====================
|
||||
*/
|
||||
#define PTHREAD_CANCELED ((void *) -1)
|
||||
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* ====================
|
||||
* Once Key
|
||||
* ====================
|
||||
* ====================
|
||||
*/
|
||||
#define PTHREAD_ONCE_INIT { PTE_FALSE, 0, 0, 0}
|
||||
|
||||
struct pthread_once_t_
|
||||
{
|
||||
int state;
|
||||
void * semaphore;
|
||||
int numSemaphoreUsers;
|
||||
int done; /* indicates if user function has been executed */
|
||||
// void * lock;
|
||||
// int reserved1;
|
||||
// int reserved2;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* ====================
|
||||
* Object initialisers
|
||||
* ====================
|
||||
* ====================
|
||||
*/
|
||||
#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1)
|
||||
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2)
|
||||
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3)
|
||||
|
||||
/*
|
||||
* Compatibility with LinuxThreads
|
||||
*/
|
||||
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
|
||||
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
|
||||
|
||||
#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1)
|
||||
|
||||
#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1)
|
||||
|
||||
#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1)
|
||||
|
||||
/*
|
||||
* Mutex types.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
/* Compatibility with LinuxThreads */
|
||||
PTHREAD_MUTEX_FAST_NP,
|
||||
PTHREAD_MUTEX_RECURSIVE_NP,
|
||||
PTHREAD_MUTEX_ERRORCHECK_NP,
|
||||
PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
|
||||
PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
|
||||
/* For compatibility with POSIX */
|
||||
PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
|
||||
PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
|
||||
PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
|
||||
PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
|
||||
};
|
||||
|
||||
|
||||
typedef struct pte_cleanup_t pte_cleanup_t;
|
||||
|
||||
typedef void (* pte_cleanup_callback_t)(void *);
|
||||
|
||||
struct pte_cleanup_t
|
||||
{
|
||||
pte_cleanup_callback_t routine;
|
||||
void *arg;
|
||||
struct pte_cleanup_t *prev;
|
||||
};
|
||||
|
||||
/*
|
||||
* C implementation of PThreads cancel cleanup
|
||||
*/
|
||||
|
||||
#define pthread_cleanup_push( _rout, _arg ) \
|
||||
{ \
|
||||
pte_cleanup_t _cleanup; \
|
||||
\
|
||||
pte_push_cleanup( &_cleanup, (pte_cleanup_callback_t) (_rout), (_arg) ); \
|
||||
|
||||
#define pthread_cleanup_pop( _execute ) \
|
||||
(void) pte_pop_cleanup( _execute ); \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*
|
||||
* ===============
|
||||
* ===============
|
||||
* Methods
|
||||
* ===============
|
||||
* ===============
|
||||
*/
|
||||
|
||||
int pthread_init (void);
|
||||
void pthread_terminate (void);
|
||||
|
||||
/*
|
||||
* PThread Attribute Functions
|
||||
*/
|
||||
int pthread_attr_init (pthread_attr_t * attr);
|
||||
|
||||
int pthread_attr_destroy (pthread_attr_t * attr);
|
||||
|
||||
int pthread_attr_getdetachstate (const pthread_attr_t * attr,
|
||||
int *detachstate);
|
||||
|
||||
int pthread_attr_getstackaddr (const pthread_attr_t * attr,
|
||||
void **stackaddr);
|
||||
|
||||
int pthread_attr_getstacksize (const pthread_attr_t * attr,
|
||||
size_t * stacksize);
|
||||
|
||||
int pthread_attr_setdetachstate (pthread_attr_t * attr,
|
||||
int detachstate);
|
||||
|
||||
int pthread_attr_setstackaddr (pthread_attr_t * attr,
|
||||
void *stackaddr);
|
||||
|
||||
int pthread_attr_setstacksize (pthread_attr_t * attr,
|
||||
size_t stacksize);
|
||||
|
||||
int pthread_attr_getschedparam (const pthread_attr_t *attr,
|
||||
struct sched_param *param);
|
||||
|
||||
int pthread_attr_setschedparam (pthread_attr_t *attr,
|
||||
const struct sched_param *param);
|
||||
|
||||
int pthread_attr_setschedpolicy (pthread_attr_t *,
|
||||
int);
|
||||
|
||||
int pthread_attr_getschedpolicy (pthread_attr_t *,
|
||||
int *);
|
||||
|
||||
int pthread_attr_setinheritsched(pthread_attr_t * attr,
|
||||
int inheritsched);
|
||||
|
||||
int pthread_attr_getinheritsched(pthread_attr_t * attr,
|
||||
int * inheritsched);
|
||||
|
||||
int pthread_attr_setscope (pthread_attr_t *,
|
||||
int);
|
||||
|
||||
int pthread_attr_getscope (const pthread_attr_t *,
|
||||
int *);
|
||||
|
||||
/*
|
||||
* PThread Functions
|
||||
*/
|
||||
int pthread_create (pthread_t * tid,
|
||||
const pthread_attr_t * attr,
|
||||
void *(*start) (void *),
|
||||
void *arg);
|
||||
|
||||
int pthread_detach (pthread_t tid);
|
||||
|
||||
int pthread_equal (pthread_t t1,
|
||||
pthread_t t2);
|
||||
|
||||
void pthread_exit (void *value_ptr);
|
||||
|
||||
int pthread_join (pthread_t thread,
|
||||
void **value_ptr);
|
||||
|
||||
pthread_t pthread_self (void);
|
||||
|
||||
int pthread_cancel (pthread_t thread);
|
||||
|
||||
int pthread_setcancelstate (int state,
|
||||
int *oldstate);
|
||||
|
||||
int pthread_setcanceltype (int type,
|
||||
int *oldtype);
|
||||
|
||||
void pthread_testcancel (void);
|
||||
|
||||
int pthread_once (pthread_once_t * once_control,
|
||||
void (*init_routine) (void));
|
||||
|
||||
#if PTE_LEVEL >= PTE_LEVEL_MAX
|
||||
pte_cleanup_t * pte_pop_cleanup (int execute);
|
||||
|
||||
void pte_push_cleanup (pte_cleanup_t * cleanup,
|
||||
void (*routine) (void *),
|
||||
void *arg);
|
||||
#endif /* PTE_LEVEL >= PTE_LEVEL_MAX */
|
||||
|
||||
/*
|
||||
* Thread Specific Data Functions
|
||||
*/
|
||||
int pthread_key_create (pthread_key_t * key,
|
||||
void (*destructor) (void *));
|
||||
|
||||
int pthread_key_delete (pthread_key_t key);
|
||||
|
||||
int pthread_setspecific (pthread_key_t key,
|
||||
const void *value);
|
||||
|
||||
void * pthread_getspecific (pthread_key_t key);
|
||||
|
||||
|
||||
/*
|
||||
* Mutex Attribute Functions
|
||||
*/
|
||||
int pthread_mutexattr_init (pthread_mutexattr_t * attr);
|
||||
|
||||
int pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
|
||||
|
||||
int pthread_mutexattr_getpshared (const pthread_mutexattr_t
|
||||
* attr,
|
||||
int *pshared);
|
||||
|
||||
int pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
|
||||
int pshared);
|
||||
|
||||
int pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
|
||||
int pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind);
|
||||
|
||||
/*
|
||||
* Barrier Attribute Functions
|
||||
*/
|
||||
int pthread_barrierattr_init (pthread_barrierattr_t * attr);
|
||||
|
||||
int pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
|
||||
|
||||
int pthread_barrierattr_getpshared (const pthread_barrierattr_t
|
||||
* attr,
|
||||
int *pshared);
|
||||
|
||||
int pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
|
||||
int pshared);
|
||||
|
||||
/*
|
||||
* Mutex Functions
|
||||
*/
|
||||
int pthread_mutex_init (pthread_mutex_t * mutex,
|
||||
const pthread_mutexattr_t * attr);
|
||||
|
||||
int pthread_mutex_destroy (pthread_mutex_t * mutex);
|
||||
|
||||
int pthread_mutex_lock (pthread_mutex_t * mutex);
|
||||
|
||||
int pthread_mutex_timedlock(pthread_mutex_t *mutex,
|
||||
const struct timespec *abstime);
|
||||
|
||||
int pthread_mutex_trylock (pthread_mutex_t * mutex);
|
||||
|
||||
int pthread_mutex_unlock (pthread_mutex_t * mutex);
|
||||
|
||||
/*
|
||||
* Spinlock Functions
|
||||
*/
|
||||
int pthread_spin_init (pthread_spinlock_t * lock, int pshared);
|
||||
|
||||
int pthread_spin_destroy (pthread_spinlock_t * lock);
|
||||
|
||||
int pthread_spin_lock (pthread_spinlock_t * lock);
|
||||
|
||||
int pthread_spin_trylock (pthread_spinlock_t * lock);
|
||||
|
||||
int pthread_spin_unlock (pthread_spinlock_t * lock);
|
||||
|
||||
/*
|
||||
* Barrier Functions
|
||||
*/
|
||||
int pthread_barrier_init (pthread_barrier_t * barrier,
|
||||
const pthread_barrierattr_t * attr,
|
||||
unsigned int count);
|
||||
|
||||
int pthread_barrier_destroy (pthread_barrier_t * barrier);
|
||||
|
||||
int pthread_barrier_wait (pthread_barrier_t * barrier);
|
||||
|
||||
/*
|
||||
* Condition Variable Attribute Functions
|
||||
*/
|
||||
int pthread_condattr_init (pthread_condattr_t * attr);
|
||||
|
||||
int pthread_condattr_destroy (pthread_condattr_t * attr);
|
||||
|
||||
int pthread_condattr_getpshared (const pthread_condattr_t * attr,
|
||||
int *pshared);
|
||||
|
||||
int pthread_condattr_setpshared (pthread_condattr_t * attr,
|
||||
int pshared);
|
||||
|
||||
/*
|
||||
* Condition Variable Functions
|
||||
*/
|
||||
int pthread_cond_init (pthread_cond_t * cond,
|
||||
const pthread_condattr_t * attr);
|
||||
|
||||
int pthread_cond_destroy (pthread_cond_t * cond);
|
||||
|
||||
int pthread_cond_wait (pthread_cond_t * cond,
|
||||
pthread_mutex_t * mutex);
|
||||
|
||||
int pthread_cond_timedwait (pthread_cond_t * cond,
|
||||
pthread_mutex_t * mutex,
|
||||
const struct timespec *abstime);
|
||||
|
||||
int pthread_cond_signal (pthread_cond_t * cond);
|
||||
|
||||
int pthread_cond_broadcast (pthread_cond_t * cond);
|
||||
|
||||
/*
|
||||
* Scheduling
|
||||
*/
|
||||
int pthread_setschedparam (pthread_t thread,
|
||||
int policy,
|
||||
const struct sched_param *param);
|
||||
|
||||
int pthread_getschedparam (pthread_t thread,
|
||||
int *policy,
|
||||
struct sched_param *param);
|
||||
|
||||
int pthread_setconcurrency (int);
|
||||
|
||||
int pthread_getconcurrency (void);
|
||||
|
||||
/*
|
||||
* Read-Write Lock Functions
|
||||
*/
|
||||
int pthread_rwlock_init(pthread_rwlock_t *lock,
|
||||
const pthread_rwlockattr_t *attr);
|
||||
|
||||
int pthread_rwlock_destroy(pthread_rwlock_t *lock);
|
||||
|
||||
int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
|
||||
|
||||
int pthread_rwlock_trywrlock(pthread_rwlock_t *);
|
||||
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t *lock);
|
||||
|
||||
int pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
|
||||
const struct timespec *abstime);
|
||||
|
||||
int pthread_rwlock_wrlock(pthread_rwlock_t *lock);
|
||||
|
||||
int pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
|
||||
const struct timespec *abstime);
|
||||
|
||||
int pthread_rwlock_unlock(pthread_rwlock_t *lock);
|
||||
|
||||
int pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
|
||||
|
||||
int pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
|
||||
|
||||
int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
|
||||
int *pshared);
|
||||
|
||||
int pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
|
||||
int pshared);
|
||||
|
||||
#if PTE_LEVEL >= PTE_LEVEL_MAX - 1
|
||||
|
||||
/*
|
||||
* Signal Functions. Should be defined in <signal.h> but we might
|
||||
* already have signal.h that don't define these.
|
||||
*/
|
||||
int pthread_kill(pthread_t thread, int sig);
|
||||
|
||||
/*
|
||||
* Non-portable functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Compatibility with Linux.
|
||||
*/
|
||||
int pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
|
||||
int kind);
|
||||
int pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
|
||||
int *kind);
|
||||
|
||||
/*
|
||||
* Possibly supported by other POSIX threads implementations
|
||||
*/
|
||||
int pthread_delay_np (struct timespec * interval);
|
||||
int pthread_num_processors_np(void);
|
||||
|
||||
/*
|
||||
* Register a system time change with the library.
|
||||
* Causes the library to perform various functions
|
||||
* in response to the change. Should be called whenever
|
||||
* the application's top level window receives a
|
||||
* WM_TIMECHANGE message. It can be passed directly to
|
||||
* pthread_create() as a new thread if desired.
|
||||
*/
|
||||
void * pthread_timechange_handler_np(void *);
|
||||
|
||||
#endif /*PTE_LEVEL >= PTE_LEVEL_MAX - 1 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* cplusplus */
|
||||
|
||||
#if PTE_LEVEL >= PTE_LEVEL_MAX
|
||||
|
||||
#endif /* PTE_LEVEL >= PTE_LEVEL_MAX */
|
||||
|
||||
/*
|
||||
* Some compiler environments don't define some things.
|
||||
*/
|
||||
# define _ftime ftime
|
||||
# define _timeb timeb
|
||||
|
||||
#undef PTE_LEVEL
|
||||
#undef PTE_LEVEL_MAX
|
||||
|
||||
#endif /* PTHREAD_H */
|
||||
Vendored
-581
@@ -1,581 +0,0 @@
|
||||
/*
|
||||
* pthread_attr.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements operations on thread attribute objects.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
#include "sched.h"
|
||||
|
||||
int
|
||||
pthread_attr_destroy (pthread_attr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Destroys a thread attributes object.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_attr_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Destroys a thread attributes object.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Does not affect threads created with 'attr'.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully destroyed attr,
|
||||
* EINVAL 'attr' is invalid.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
if (pte_is_attr (attr) != 0)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* Set the attribute object to a specific invalid value.
|
||||
*/
|
||||
(*attr)->valid = 0;
|
||||
free (*attr);
|
||||
*attr = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_getdetachstate (const pthread_attr_t * attr, int *detachstate)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function determines whether threads created with
|
||||
* 'attr' will run detached.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_attr_t
|
||||
*
|
||||
* detachstate
|
||||
* pointer to an integer into which is returned one
|
||||
* of:
|
||||
*
|
||||
* PTHREAD_CREATE_JOINABLE
|
||||
* Thread ID is valid, must be joined
|
||||
*
|
||||
* PTHREAD_CREATE_DETACHED
|
||||
* Thread ID is invalid, cannot be joined,
|
||||
* canceled, or modified
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function determines whether threads created with
|
||||
* 'attr' will run detached.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) You cannot join or cancel detached threads.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully retrieved detach state,
|
||||
* EINVAL 'attr' is invalid
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
if (pte_is_attr (attr) != 0 || detachstate == NULL)
|
||||
{
|
||||
*detachstate = PTHREAD_CREATE_DETACHED;
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
*detachstate = (*attr)->detachstate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_getinheritsched (pthread_attr_t * attr, int *inheritsched)
|
||||
{
|
||||
if (pte_is_attr (attr) != 0 || inheritsched == NULL)
|
||||
return EINVAL;
|
||||
|
||||
*inheritsched = (*attr)->inheritsched;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_getschedparam (const pthread_attr_t * attr,
|
||||
struct sched_param *param)
|
||||
{
|
||||
if (pte_is_attr (attr) != 0 || param == NULL)
|
||||
return EINVAL;
|
||||
|
||||
memcpy (param, &(*attr)->param, sizeof (*param));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_getschedpolicy (pthread_attr_t * attr, int *policy)
|
||||
{
|
||||
if (pte_is_attr (attr) != 0 || policy == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* Validate the policy arg.
|
||||
* Check that a policy constant wasn't passed rather than &policy.
|
||||
*/
|
||||
if (policy <= (int *) SCHED_MAX)
|
||||
return EINVAL;
|
||||
|
||||
*policy = SCHED_OTHER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_getscope (const pthread_attr_t * attr, int *contentionscope)
|
||||
{
|
||||
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
|
||||
*contentionscope = (*attr)->contentionscope;
|
||||
return 0;
|
||||
#else
|
||||
return ENOSYS;
|
||||
#endif
|
||||
}
|
||||
|
||||
int pthread_attr_getstackaddr (const pthread_attr_t * attr, void **stackaddr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function determines the address of the stack
|
||||
* on which threads created with 'attr' will run.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_attr_t
|
||||
*
|
||||
* stackaddr
|
||||
* pointer into which is returned the stack address.
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function determines the address of the stack
|
||||
* on which threads created with 'attr' will run.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Function supported only if this macro is
|
||||
* defined:
|
||||
*
|
||||
* _POSIX_THREAD_ATTR_STACKADDR
|
||||
*
|
||||
* 2) Create only one thread for each stack
|
||||
* address..
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully retreived stack address,
|
||||
* EINVAL 'attr' is invalid
|
||||
* ENOSYS function not supported
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
#if defined( _POSIX_THREAD_ATTR_STACKADDR )
|
||||
|
||||
if (pte_is_attr (attr) != 0)
|
||||
return EINVAL;
|
||||
|
||||
*stackaddr = (*attr)->stackaddr;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
return ENOSYS;
|
||||
|
||||
#endif /* _POSIX_THREAD_ATTR_STACKADDR */
|
||||
}
|
||||
|
||||
int
|
||||
pthread_attr_getstacksize (const pthread_attr_t * attr, size_t * stacksize)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function determines the size of the stack on
|
||||
* which threads created with 'attr' will run.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_attr_t
|
||||
*
|
||||
* stacksize
|
||||
* pointer to size_t into which is returned the
|
||||
* stack size, in bytes.
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function determines the size of the stack on
|
||||
* which threads created with 'attr' will run.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Function supported only if this macro is
|
||||
* defined:
|
||||
*
|
||||
* _POSIX_THREAD_ATTR_STACKSIZE
|
||||
*
|
||||
* 2) Use on newly created attributes object to
|
||||
* find the default stack size.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully retrieved stack size,
|
||||
* EINVAL 'attr' is invalid
|
||||
* ENOSYS function not supported
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
|
||||
|
||||
if (pte_is_attr (attr) != 0)
|
||||
return EINVAL;
|
||||
|
||||
/* Everything is okay. */
|
||||
*stacksize = (*attr)->stacksize;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
return ENOSYS;
|
||||
|
||||
#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
|
||||
}
|
||||
|
||||
int pthread_attr_init (pthread_attr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Initializes a thread attributes object with default
|
||||
* attributes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_attr_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Initializes a thread attributes object with default
|
||||
* attributes.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Used to define thread attributes
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully initialized attr,
|
||||
* ENOMEM insufficient memory for attr.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
pthread_attr_t attr_result;
|
||||
|
||||
/* This is disallowed. */
|
||||
if (attr == NULL)
|
||||
return EINVAL;
|
||||
|
||||
attr_result = (pthread_attr_t) malloc (sizeof (*attr_result));
|
||||
|
||||
if (attr_result == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
|
||||
/*
|
||||
* Default to zero size?
|
||||
*/
|
||||
attr_result->stacksize = 0;
|
||||
#endif
|
||||
|
||||
#ifdef _POSIX_THREAD_ATTR_STACKADDR
|
||||
/* FIXME: Set this to something sensible when we support it. */
|
||||
attr_result->stackaddr = NULL;
|
||||
#endif
|
||||
|
||||
attr_result->detachstate = PTHREAD_CREATE_JOINABLE;
|
||||
|
||||
/*
|
||||
* Win32 sets new threads to THREAD_PRIORITY_NORMAL and
|
||||
* not to that of the parent thread. We choose to default to
|
||||
* this arrangement.
|
||||
*/
|
||||
attr_result->param.sched_priority = pte_osThreadGetDefaultPriority();
|
||||
attr_result->inheritsched = PTHREAD_EXPLICIT_SCHED;
|
||||
attr_result->contentionscope = PTHREAD_SCOPE_SYSTEM;
|
||||
|
||||
attr_result->valid = PTE_ATTR_VALID;
|
||||
|
||||
*attr = attr_result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function specifies whether threads created with
|
||||
* 'attr' will run detached.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_attr_t
|
||||
*
|
||||
* detachstate
|
||||
* an integer containing one of:
|
||||
*
|
||||
* PTHREAD_CREATE_JOINABLE
|
||||
* Thread ID is valid, must be joined
|
||||
*
|
||||
* PTHREAD_CREATE_DETACHED
|
||||
* Thread ID is invalid, cannot be joined,
|
||||
* canceled, or modified
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function specifies whether threads created with
|
||||
* 'attr' will run detached.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) You cannot join or cancel detached threads.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set detach state,
|
||||
* EINVAL 'attr' or 'detachstate' is invalid
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
if (pte_is_attr (attr) != 0)
|
||||
return EINVAL;
|
||||
|
||||
if (detachstate != PTHREAD_CREATE_JOINABLE &&
|
||||
detachstate != PTHREAD_CREATE_DETACHED)
|
||||
return EINVAL;
|
||||
|
||||
(*attr)->detachstate = detachstate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setinheritsched (pthread_attr_t * attr, int inheritsched)
|
||||
{
|
||||
if (pte_is_attr (attr) != 0)
|
||||
return EINVAL;
|
||||
|
||||
if (PTHREAD_INHERIT_SCHED != inheritsched
|
||||
&& PTHREAD_EXPLICIT_SCHED != inheritsched)
|
||||
return EINVAL;
|
||||
|
||||
(*attr)->inheritsched = inheritsched;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setschedparam (pthread_attr_t * attr,
|
||||
const struct sched_param *param)
|
||||
{
|
||||
int priority;
|
||||
|
||||
if (pte_is_attr (attr) != 0 || param == NULL)
|
||||
return EINVAL;
|
||||
|
||||
priority = param->sched_priority;
|
||||
|
||||
/* Validate priority level. */
|
||||
if (priority < sched_get_priority_min (SCHED_OTHER) ||
|
||||
priority > sched_get_priority_max (SCHED_OTHER))
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
memcpy (&(*attr)->param, param, sizeof (*param));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setschedpolicy (pthread_attr_t * attr, int policy)
|
||||
{
|
||||
if (pte_is_attr (attr) != 0)
|
||||
return EINVAL;
|
||||
|
||||
if (policy != SCHED_OTHER)
|
||||
return ENOTSUP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setscope (pthread_attr_t * attr, int contentionscope)
|
||||
{
|
||||
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
|
||||
switch (contentionscope)
|
||||
{
|
||||
case PTHREAD_SCOPE_SYSTEM:
|
||||
(*attr)->contentionscope = contentionscope;
|
||||
return 0;
|
||||
case PTHREAD_SCOPE_PROCESS:
|
||||
return ENOTSUP;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
#else
|
||||
return ENOSYS;
|
||||
#endif
|
||||
}
|
||||
|
||||
int pthread_attr_setstackaddr (pthread_attr_t * attr, void *stackaddr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Threads created with 'attr' will run on the stack
|
||||
* starting at 'stackaddr'.
|
||||
* Stack must be at least PTHREAD_STACK_MIN bytes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_attr_t
|
||||
*
|
||||
* stacksize
|
||||
* stack size, in bytes.
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Threads created with 'attr' will run on the stack
|
||||
* starting at 'stackaddr'.
|
||||
* Stack must be at least PTHREAD_STACK_MIN bytes.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Function supported only if this macro is
|
||||
* defined:
|
||||
*
|
||||
* _POSIX_THREAD_ATTR_STACKADDR
|
||||
*
|
||||
* 2) Create only one thread for each stack
|
||||
* address..
|
||||
*
|
||||
* 3) Ensure that stackaddr is aligned.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set stack address,
|
||||
* EINVAL 'attr' is invalid
|
||||
* ENOSYS function not supported
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
#if defined( _POSIX_THREAD_ATTR_STACKADDR )
|
||||
|
||||
if (pte_is_attr (attr) != 0)
|
||||
return EINVAL;
|
||||
|
||||
(*attr)->stackaddr = stackaddr;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
return ENOSYS;
|
||||
|
||||
#endif /* _POSIX_THREAD_ATTR_STACKADDR */
|
||||
}
|
||||
|
||||
int pthread_attr_setstacksize (pthread_attr_t * attr, size_t stacksize)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function specifies the size of the stack on
|
||||
* which threads created with 'attr' will run.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_attr_t
|
||||
*
|
||||
* stacksize
|
||||
* stack size, in bytes.
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function specifies the size of the stack on
|
||||
* which threads created with 'attr' will run.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Function supported only if this macro is
|
||||
* defined:
|
||||
*
|
||||
* _POSIX_THREAD_ATTR_STACKSIZE
|
||||
*
|
||||
* 2) Find the default first (using
|
||||
* pthread_attr_getstacksize), then increase
|
||||
* by multiplying.
|
||||
*
|
||||
* 3) Only use if thread needs more than the
|
||||
* default.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set stack size,
|
||||
* EINVAL 'attr' is invalid or stacksize too
|
||||
* small or too big.
|
||||
* ENOSYS function not supported
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
|
||||
|
||||
#if PTHREAD_STACK_MIN > 0
|
||||
|
||||
/* Verify that the stack size is within range. */
|
||||
if (stacksize < PTHREAD_STACK_MIN)
|
||||
return EINVAL;
|
||||
|
||||
#endif
|
||||
|
||||
if (pte_is_attr (attr) != 0)
|
||||
return EINVAL;
|
||||
|
||||
/* Everything is okay. */
|
||||
(*attr)->stacksize = stacksize;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
return ENOSYS;
|
||||
|
||||
#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
|
||||
}
|
||||
Vendored
-163
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* pthread_barrier.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements barrier primitives.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
int pthread_barrier_destroy (pthread_barrier_t * barrier)
|
||||
{
|
||||
int result = 0;
|
||||
pthread_barrier_t b;
|
||||
|
||||
if (barrier == NULL || *barrier == (pthread_barrier_t) PTE_OBJECT_INVALID)
|
||||
return EINVAL;
|
||||
|
||||
b = *barrier;
|
||||
*barrier = NULL;
|
||||
|
||||
if (0 == (result = sem_destroy (&(b->semBarrierBreeched[0]))))
|
||||
{
|
||||
if (0 == (result = sem_destroy (&(b->semBarrierBreeched[1]))))
|
||||
{
|
||||
(void) free (b);
|
||||
return 0;
|
||||
}
|
||||
(void) sem_init (&(b->semBarrierBreeched[0]), b->pshared, 0);
|
||||
}
|
||||
|
||||
*barrier = b;
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_barrier_init (pthread_barrier_t * barrier,
|
||||
const pthread_barrierattr_t * attr, unsigned int count)
|
||||
{
|
||||
pthread_barrier_t b;
|
||||
|
||||
if (barrier == NULL || count == 0)
|
||||
return EINVAL;
|
||||
|
||||
if (NULL != (b = (pthread_barrier_t) calloc (1, sizeof (*b))))
|
||||
{
|
||||
b->pshared = (attr != NULL && *attr != NULL
|
||||
? (*attr)->pshared : PTHREAD_PROCESS_PRIVATE);
|
||||
|
||||
b->nCurrentBarrierHeight = b->nInitialBarrierHeight = count;
|
||||
b->iStep = 0;
|
||||
|
||||
/*
|
||||
* Two semaphores are used in the same way as two stepping
|
||||
* stones might be used in crossing a stream. Once all
|
||||
* threads are safely on one stone, the other stone can
|
||||
* be moved ahead, and the threads can start moving to it.
|
||||
* If some threads decide to eat their lunch before moving
|
||||
* then the other threads have to wait.
|
||||
*/
|
||||
if (0 == sem_init (&(b->semBarrierBreeched[0]), b->pshared, 0))
|
||||
{
|
||||
if (0 == sem_init (&(b->semBarrierBreeched[1]), b->pshared, 0))
|
||||
{
|
||||
*barrier = b;
|
||||
return 0;
|
||||
}
|
||||
(void) sem_destroy (&(b->semBarrierBreeched[0]));
|
||||
}
|
||||
(void) free (b);
|
||||
}
|
||||
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
int pthread_barrier_wait (pthread_barrier_t * barrier)
|
||||
{
|
||||
int result;
|
||||
int step;
|
||||
pthread_barrier_t b;
|
||||
|
||||
if (barrier == NULL || *barrier == (pthread_barrier_t) PTE_OBJECT_INVALID)
|
||||
return EINVAL;
|
||||
|
||||
b = *barrier;
|
||||
step = b->iStep;
|
||||
|
||||
if (0 == PTE_ATOMIC_DECREMENT ((int *) &(b->nCurrentBarrierHeight)))
|
||||
{
|
||||
/* Must be done before posting the semaphore. */
|
||||
b->nCurrentBarrierHeight = b->nInitialBarrierHeight;
|
||||
|
||||
/*
|
||||
* There is no race condition between the semaphore wait and post
|
||||
* because we are using two alternating semas and all threads have
|
||||
* entered barrier_wait and checked nCurrentBarrierHeight before this
|
||||
* barrier's sema can be posted. Any threads that have not quite
|
||||
* entered sem_wait below when the multiple_post has completed
|
||||
* will nevertheless continue through the semaphore (barrier)
|
||||
* and will not be left stranded.
|
||||
*/
|
||||
result = (b->nInitialBarrierHeight > 1
|
||||
? sem_post_multiple (&(b->semBarrierBreeched[step]),
|
||||
b->nInitialBarrierHeight - 1) : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Use the non-cancelable version of sem_wait().
|
||||
*/
|
||||
result = sem_wait (&(b->semBarrierBreeched[step]));
|
||||
// result = sem_wait_nocancel (&(b->semBarrierBreeched[step]));
|
||||
}
|
||||
|
||||
/*
|
||||
* The first thread across will be the PTHREAD_BARRIER_SERIAL_THREAD.
|
||||
* This also sets up the alternate semaphore as the next barrier.
|
||||
*/
|
||||
if (0 == result)
|
||||
{
|
||||
result = (step ==
|
||||
PTE_ATOMIC_COMPARE_EXCHANGE (& (b->iStep),(1L - step),step) ?
|
||||
PTHREAD_BARRIER_SERIAL_THREAD : 0);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
Vendored
-257
@@ -1,257 +0,0 @@
|
||||
/*
|
||||
* pthread_barrier_attr.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements barrier primitives.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
|
||||
int
|
||||
pthread_barrierattr_destroy (pthread_barrierattr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Destroys a barrier attributes object. The object can
|
||||
* no longer be used.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_barrierattr_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Destroys a barrier attributes object. The object can
|
||||
* no longer be used.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Does not affect barrieres created using 'attr'
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully released attr,
|
||||
* EINVAL 'attr' is invalid.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (attr == NULL || *attr == NULL)
|
||||
result = EINVAL;
|
||||
else
|
||||
{
|
||||
pthread_barrierattr_t ba = *attr;
|
||||
|
||||
*attr = NULL;
|
||||
free (ba);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int
|
||||
pthread_barrierattr_getpshared (const pthread_barrierattr_t * attr,
|
||||
int *pshared)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Determine whether barriers created with 'attr' can be
|
||||
* shared between processes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_barrierattr_t
|
||||
*
|
||||
* pshared
|
||||
* will be set to one of:
|
||||
*
|
||||
* PTHREAD_PROCESS_SHARED
|
||||
* May be shared if in shared memory
|
||||
*
|
||||
* PTHREAD_PROCESS_PRIVATE
|
||||
* Cannot be shared.
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Mutexes creatd with 'attr' can be shared between
|
||||
* processes if pthread_barrier_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
* NOTES:
|
||||
* 1) pshared barriers MUST be allocated in shared
|
||||
* memory.
|
||||
* 2) The following macro is defined if shared barriers
|
||||
* are supported:
|
||||
* _POSIX_THREAD_PROCESS_SHARED
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully retrieved attribute,
|
||||
* EINVAL 'attr' is invalid,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((attr != NULL && *attr != NULL) && (pshared != NULL))
|
||||
{
|
||||
*pshared = (*attr)->pshared;
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_barrierattr_init (pthread_barrierattr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Initializes a barrier attributes object with default
|
||||
* attributes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_barrierattr_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Initializes a barrier attributes object with default
|
||||
* attributes.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Used to define barrier types
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully initialized attr,
|
||||
* ENOMEM insufficient memory for attr.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
pthread_barrierattr_t ba = (pthread_barrierattr_t) calloc (1, sizeof (*ba));
|
||||
|
||||
if (ba == NULL)
|
||||
result = ENOMEM;
|
||||
else
|
||||
ba->pshared = PTHREAD_PROCESS_PRIVATE;
|
||||
|
||||
*attr = ba;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, int pshared)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Barriers created with 'attr' can be shared between
|
||||
* processes if pthread_barrier_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_barrierattr_t
|
||||
*
|
||||
* pshared
|
||||
* must be one of:
|
||||
*
|
||||
* PTHREAD_PROCESS_SHARED
|
||||
* May be shared if in shared memory
|
||||
*
|
||||
* PTHREAD_PROCESS_PRIVATE
|
||||
* Cannot be shared.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Mutexes creatd with 'attr' can be shared between
|
||||
* processes if pthread_barrier_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) pshared barriers MUST be allocated in shared
|
||||
* memory.
|
||||
*
|
||||
* 2) The following macro is defined if shared barriers
|
||||
* are supported:
|
||||
* _POSIX_THREAD_PROCESS_SHARED
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set attribute,
|
||||
* EINVAL 'attr' or pshared is invalid,
|
||||
* ENOSYS PTHREAD_PROCESS_SHARED not supported,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((attr != NULL && *attr != NULL) &&
|
||||
((pshared == PTHREAD_PROCESS_SHARED) ||
|
||||
(pshared == PTHREAD_PROCESS_PRIVATE)))
|
||||
{
|
||||
if (pshared == PTHREAD_PROCESS_SHARED)
|
||||
{
|
||||
|
||||
#if !defined( _POSIX_THREAD_PROCESS_SHARED )
|
||||
|
||||
result = ENOSYS;
|
||||
pshared = PTHREAD_PROCESS_PRIVATE;
|
||||
|
||||
#else
|
||||
|
||||
result = 0;
|
||||
|
||||
#endif /* _POSIX_THREAD_PROCESS_SHARED */
|
||||
|
||||
}
|
||||
else
|
||||
result = 0;
|
||||
|
||||
(*attr)->pshared = pshared;
|
||||
}
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return (result);
|
||||
|
||||
} /* pthread_barrierattr_setpshared */
|
||||
Vendored
-807
@@ -1,807 +0,0 @@
|
||||
/*
|
||||
* pthread_cond.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements condition variables and their primitives.
|
||||
*
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
/*
|
||||
* Arguments for cond_wait_cleanup, since we can only pass a
|
||||
* single void * to it.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
pthread_mutex_t *mutexPtr;
|
||||
pthread_cond_t cv;
|
||||
int *resultPtr;
|
||||
} pte_cond_wait_cleanup_args_t;
|
||||
|
||||
static void pte_cond_wait_cleanup (void *args)
|
||||
{
|
||||
pte_cond_wait_cleanup_args_t *cleanup_args =
|
||||
(pte_cond_wait_cleanup_args_t *) args;
|
||||
pthread_cond_t cv = cleanup_args->cv;
|
||||
int *resultPtr = cleanup_args->resultPtr;
|
||||
int nSignalsWasLeft;
|
||||
int result;
|
||||
|
||||
/*
|
||||
* Whether we got here as a result of signal/broadcast or because of
|
||||
* timeout on wait or thread cancellation we indicate that we are no
|
||||
* longer waiting. The waiter is responsible for adjusting waiters
|
||||
* (to)unblock(ed) counts (protected by unblock lock).
|
||||
*/
|
||||
if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0)
|
||||
{
|
||||
*resultPtr = result;
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 != (nSignalsWasLeft = cv->nWaitersToUnblock))
|
||||
{
|
||||
--(cv->nWaitersToUnblock);
|
||||
}
|
||||
else if (INT_MAX / 2 == ++(cv->nWaitersGone))
|
||||
{
|
||||
/* Use the non-cancellable version of sem_wait() */
|
||||
// if (sem_wait_nocancel (&(cv->semBlockLock)) != 0)
|
||||
if (sem_wait (&(cv->semBlockLock)) != 0)
|
||||
{
|
||||
*resultPtr = errno;
|
||||
/*
|
||||
* This is a fatal error for this CV,
|
||||
* so we deliberately don't unlock
|
||||
* cv->mtxUnblockLock before returning.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
cv->nWaitersBlocked -= cv->nWaitersGone;
|
||||
if (sem_post (&(cv->semBlockLock)) != 0)
|
||||
{
|
||||
*resultPtr = errno;
|
||||
/*
|
||||
* This is a fatal error for this CV,
|
||||
* so we deliberately don't unlock
|
||||
* cv->mtxUnblockLock before returning.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
cv->nWaitersGone = 0;
|
||||
}
|
||||
|
||||
if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) != 0)
|
||||
{
|
||||
*resultPtr = result;
|
||||
return;
|
||||
}
|
||||
|
||||
if (1 == nSignalsWasLeft)
|
||||
{
|
||||
if (sem_post (&(cv->semBlockLock)) != 0)
|
||||
{
|
||||
*resultPtr = errno;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XSH: Upon successful return, the mutex has been locked and is owned
|
||||
* by the calling thread.
|
||||
*/
|
||||
if ((result = pthread_mutex_lock (cleanup_args->mutexPtr)) != 0)
|
||||
*resultPtr = result;
|
||||
}
|
||||
|
||||
static int pte_cond_timedwait (pthread_cond_t * cond,
|
||||
pthread_mutex_t * mutex, const struct timespec *abstime)
|
||||
{
|
||||
int result = 0;
|
||||
pthread_cond_t cv;
|
||||
pte_cond_wait_cleanup_args_t cleanup_args;
|
||||
|
||||
if (cond == NULL || *cond == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* We do a quick check to see if we need to do more work
|
||||
* to initialise a static condition variable. We check
|
||||
* again inside the guarded section of pte_cond_check_need_init()
|
||||
* to avoid race conditions.
|
||||
*/
|
||||
if (*cond == PTHREAD_COND_INITIALIZER)
|
||||
result = pte_cond_check_need_init (cond);
|
||||
|
||||
if (result != 0 && result != EBUSY)
|
||||
return result;
|
||||
|
||||
cv = *cond;
|
||||
|
||||
/* Thread can be cancelled in sem_wait() but this is OK */
|
||||
if (sem_wait (&(cv->semBlockLock)) != 0)
|
||||
return errno;
|
||||
|
||||
++(cv->nWaitersBlocked);
|
||||
|
||||
if (sem_post (&(cv->semBlockLock)) != 0)
|
||||
return errno;
|
||||
|
||||
/*
|
||||
* Setup this waiter cleanup handler
|
||||
*/
|
||||
cleanup_args.mutexPtr = mutex;
|
||||
cleanup_args.cv = cv;
|
||||
cleanup_args.resultPtr = &result;
|
||||
|
||||
pthread_cleanup_push (pte_cond_wait_cleanup, (void *) &cleanup_args);
|
||||
|
||||
/*
|
||||
* Now we can release 'mutex' and...
|
||||
*/
|
||||
if ((result = pthread_mutex_unlock (mutex)) == 0)
|
||||
{
|
||||
/*
|
||||
* ...wait to be awakened by
|
||||
* pthread_cond_signal, or
|
||||
* pthread_cond_broadcast, or
|
||||
* timeout, or
|
||||
* thread cancellation
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* sem_timedwait is a cancellation point,
|
||||
* hence providing the mechanism for making
|
||||
* pthread_cond_wait a cancellation point.
|
||||
* We use the cleanup mechanism to ensure we
|
||||
* re-lock the mutex and adjust (to)unblock(ed) waiters
|
||||
* counts if we are cancelled, timed out or signalled.
|
||||
*/
|
||||
if (sem_timedwait (&(cv->semBlockQueue), abstime) != 0)
|
||||
result = errno;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Always cleanup
|
||||
*/
|
||||
pthread_cleanup_pop (1);
|
||||
|
||||
/*
|
||||
* "result" can be modified by the cleanup handler.
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
pthread_cond_destroy (pthread_cond_t * cond)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function destroys a condition variable
|
||||
*
|
||||
*
|
||||
* PARAMETERS
|
||||
* cond
|
||||
* pointer to an instance of pthread_cond_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function destroys a condition variable.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) A condition variable can be destroyed
|
||||
* immediately after all the threads that
|
||||
* are blocked on it are awakened. e.g.
|
||||
*
|
||||
* struct list {
|
||||
* pthread_mutex_t lm;
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* struct elt {
|
||||
* key k;
|
||||
* int busy;
|
||||
* pthread_cond_t notbusy;
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
*
|
||||
* struct elt *
|
||||
* list_find(struct list *lp, key k)
|
||||
* {
|
||||
* struct elt *ep;
|
||||
*
|
||||
* pthread_mutex_lock(&lp->lm);
|
||||
* while ((ep = find_elt(l,k) != NULL) && ep->busy)
|
||||
* pthread_cond_wait(&ep->notbusy, &lp->lm);
|
||||
* if (ep != NULL)
|
||||
* ep->busy = 1;
|
||||
* pthread_mutex_unlock(&lp->lm);
|
||||
* return(ep);
|
||||
* }
|
||||
*
|
||||
* delete_elt(struct list *lp, struct elt *ep)
|
||||
* {
|
||||
* pthread_mutex_lock(&lp->lm);
|
||||
* assert(ep->busy);
|
||||
* ... remove ep from list ...
|
||||
* ep->busy = 0;
|
||||
* (A) pthread_cond_broadcast(&ep->notbusy);
|
||||
* pthread_mutex_unlock(&lp->lm);
|
||||
* (B) pthread_cond_destroy(&rp->notbusy);
|
||||
* free(ep);
|
||||
* }
|
||||
*
|
||||
* In this example, the condition variable
|
||||
* and its list element may be freed (line B)
|
||||
* immediately after all threads waiting for
|
||||
* it are awakened (line A), since the mutex
|
||||
* and the code ensure that no other thread
|
||||
* can touch the element to be deleted.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully released condition variable,
|
||||
* EINVAL 'cond' is invalid,
|
||||
* EBUSY 'cond' is in use,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
pthread_cond_t cv;
|
||||
int result = 0, result1 = 0, result2 = 0;
|
||||
|
||||
/*
|
||||
* Assuming any race condition here is harmless.
|
||||
*/
|
||||
if (cond == NULL || *cond == NULL)
|
||||
return EINVAL;
|
||||
|
||||
if (*cond != PTHREAD_COND_INITIALIZER)
|
||||
{
|
||||
|
||||
pte_osMutexLock (pte_cond_list_lock);
|
||||
|
||||
cv = *cond;
|
||||
|
||||
/*
|
||||
* Close the gate; this will synchronize this thread with
|
||||
* all already signaled waiters to let them retract their
|
||||
* waiter status - SEE NOTE 1 ABOVE!!!
|
||||
*/
|
||||
if (sem_wait (&(cv->semBlockLock)) != 0)
|
||||
return errno;
|
||||
|
||||
/*
|
||||
* !TRY! lock mtxUnblockLock; try will detect busy condition
|
||||
* and will not cause a deadlock with respect to concurrent
|
||||
* signal/broadcast.
|
||||
*/
|
||||
if ((result = pthread_mutex_trylock (&(cv->mtxUnblockLock))) != 0)
|
||||
{
|
||||
(void) sem_post (&(cv->semBlockLock));
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether cv is still busy (still has waiters)
|
||||
*/
|
||||
if (cv->nWaitersBlocked > cv->nWaitersGone)
|
||||
{
|
||||
if (sem_post (&(cv->semBlockLock)) != 0)
|
||||
result = errno;
|
||||
result1 = pthread_mutex_unlock (&(cv->mtxUnblockLock));
|
||||
result2 = EBUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Now it is safe to destroy
|
||||
*/
|
||||
*cond = NULL;
|
||||
|
||||
if (sem_destroy (&(cv->semBlockLock)) != 0)
|
||||
result = errno;
|
||||
if (sem_destroy (&(cv->semBlockQueue)) != 0)
|
||||
result1 = errno;
|
||||
if ((result2 = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
|
||||
result2 = pthread_mutex_destroy (&(cv->mtxUnblockLock));
|
||||
|
||||
/* Unlink the CV from the list */
|
||||
|
||||
if (pte_cond_list_head == cv)
|
||||
pte_cond_list_head = cv->next;
|
||||
else
|
||||
cv->prev->next = cv->next;
|
||||
|
||||
if (pte_cond_list_tail == cv)
|
||||
pte_cond_list_tail = cv->prev;
|
||||
else
|
||||
cv->next->prev = cv->prev;
|
||||
|
||||
(void) free (cv);
|
||||
}
|
||||
|
||||
pte_osMutexUnlock(pte_cond_list_lock);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* See notes in pte_cond_check_need_init() above also.
|
||||
*/
|
||||
|
||||
pte_osMutexLock (pte_cond_test_init_lock);
|
||||
|
||||
/*
|
||||
* Check again.
|
||||
*/
|
||||
if (*cond == PTHREAD_COND_INITIALIZER)
|
||||
{
|
||||
/*
|
||||
* This is all we need to do to destroy a statically
|
||||
* initialised cond that has not yet been used (initialised).
|
||||
* If we get to here, another thread waiting to initialise
|
||||
* this cond will get an EINVAL. That's OK.
|
||||
*/
|
||||
*cond = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The cv has been initialised while we were waiting
|
||||
* so assume it's in use.
|
||||
*/
|
||||
result = EBUSY;
|
||||
}
|
||||
|
||||
pte_osMutexUnlock(pte_cond_test_init_lock);
|
||||
}
|
||||
|
||||
return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
|
||||
}
|
||||
|
||||
int pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function initializes a condition variable.
|
||||
*
|
||||
* PARAMETERS
|
||||
* cond
|
||||
* pointer to an instance of pthread_cond_t
|
||||
*
|
||||
* attr
|
||||
* specifies optional creation attributes.
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function initializes a condition variable.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully created condition variable,
|
||||
* EINVAL 'attr' is invalid,
|
||||
* EAGAIN insufficient resources (other than
|
||||
* memory,
|
||||
* ENOMEM insufficient memory,
|
||||
* EBUSY 'cond' is already initialized,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result;
|
||||
pthread_cond_t cv = NULL;
|
||||
|
||||
if (cond == NULL)
|
||||
return EINVAL;
|
||||
|
||||
if ((attr != NULL && *attr != NULL) &&
|
||||
((*attr)->pshared == PTHREAD_PROCESS_SHARED))
|
||||
{
|
||||
/*
|
||||
* Creating condition variable that can be shared between
|
||||
* processes.
|
||||
*/
|
||||
result = ENOSYS;
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
cv = (pthread_cond_t) calloc (1, sizeof (*cv));
|
||||
|
||||
if (cv == NULL)
|
||||
{
|
||||
result = ENOMEM;
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
cv->nWaitersBlocked = 0;
|
||||
cv->nWaitersToUnblock = 0;
|
||||
cv->nWaitersGone = 0;
|
||||
|
||||
if (sem_init (&(cv->semBlockLock), 0, 1) != 0)
|
||||
{
|
||||
result = errno;
|
||||
goto FAIL0;
|
||||
}
|
||||
|
||||
if (sem_init (&(cv->semBlockQueue), 0, 0) != 0)
|
||||
{
|
||||
result = errno;
|
||||
goto FAIL1;
|
||||
}
|
||||
|
||||
if ((result = pthread_mutex_init (&(cv->mtxUnblockLock), 0)) != 0)
|
||||
{
|
||||
goto FAIL2;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
|
||||
goto DONE;
|
||||
|
||||
/*
|
||||
* -------------
|
||||
* Failed...
|
||||
* -------------
|
||||
*/
|
||||
FAIL2:
|
||||
(void) sem_destroy (&(cv->semBlockQueue));
|
||||
|
||||
FAIL1:
|
||||
(void) sem_destroy (&(cv->semBlockLock));
|
||||
|
||||
FAIL0:
|
||||
(void) free (cv);
|
||||
cv = NULL;
|
||||
|
||||
DONE:
|
||||
if (0 == result)
|
||||
{
|
||||
|
||||
pte_osMutexLock (pte_cond_list_lock);
|
||||
|
||||
cv->next = NULL;
|
||||
cv->prev = pte_cond_list_tail;
|
||||
|
||||
if (pte_cond_list_tail != NULL)
|
||||
pte_cond_list_tail->next = cv;
|
||||
|
||||
pte_cond_list_tail = cv;
|
||||
|
||||
if (pte_cond_list_head == NULL)
|
||||
pte_cond_list_head = cv;
|
||||
|
||||
pte_osMutexUnlock(pte_cond_list_lock);
|
||||
}
|
||||
|
||||
*cond = cv;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int pte_cond_unblock (pthread_cond_t * cond, int unblockAll)
|
||||
/*
|
||||
* Notes.
|
||||
*
|
||||
* Does not use the external mutex for synchronisation,
|
||||
* therefore semBlockLock is needed.
|
||||
* mtxUnblockLock is for LEVEL-2 synch. LEVEL-2 is the
|
||||
* state where the external mutex is not necessarily locked by
|
||||
* any thread, ie. between cond_wait unlocking and re-acquiring
|
||||
* the lock after having been signaled or a timeout or
|
||||
* cancellation.
|
||||
*
|
||||
* Uses the following CV elements:
|
||||
* nWaitersBlocked
|
||||
* nWaitersToUnblock
|
||||
* nWaitersGone
|
||||
* mtxUnblockLock
|
||||
* semBlockLock
|
||||
* semBlockQueue
|
||||
*/
|
||||
{
|
||||
int result;
|
||||
pthread_cond_t cv;
|
||||
int nSignalsToIssue;
|
||||
|
||||
if (cond == NULL || *cond == NULL)
|
||||
return EINVAL;
|
||||
|
||||
cv = *cond;
|
||||
|
||||
/*
|
||||
* No-op if the CV is static and hasn't been initialised yet.
|
||||
* Assuming that any race condition is harmless.
|
||||
*/
|
||||
if (cv == PTHREAD_COND_INITIALIZER)
|
||||
return 0;
|
||||
|
||||
if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0)
|
||||
return result;
|
||||
|
||||
if (0 != cv->nWaitersToUnblock)
|
||||
{
|
||||
if (0 == cv->nWaitersBlocked)
|
||||
return pthread_mutex_unlock (&(cv->mtxUnblockLock));
|
||||
|
||||
if (unblockAll)
|
||||
{
|
||||
cv->nWaitersToUnblock += (nSignalsToIssue = cv->nWaitersBlocked);
|
||||
cv->nWaitersBlocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSignalsToIssue = 1;
|
||||
cv->nWaitersToUnblock++;
|
||||
cv->nWaitersBlocked--;
|
||||
}
|
||||
}
|
||||
else if (cv->nWaitersBlocked > cv->nWaitersGone)
|
||||
{
|
||||
/* Use the non-cancellable version of sem_wait() */
|
||||
// if (sem_wait_nocancel (&(cv->semBlockLock)) != 0)
|
||||
if (sem_wait (&(cv->semBlockLock)) != 0)
|
||||
{
|
||||
result = errno;
|
||||
(void) pthread_mutex_unlock (&(cv->mtxUnblockLock));
|
||||
return result;
|
||||
}
|
||||
if (0 != cv->nWaitersGone)
|
||||
{
|
||||
cv->nWaitersBlocked -= cv->nWaitersGone;
|
||||
cv->nWaitersGone = 0;
|
||||
}
|
||||
if (unblockAll)
|
||||
{
|
||||
nSignalsToIssue = cv->nWaitersToUnblock = cv->nWaitersBlocked;
|
||||
cv->nWaitersBlocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSignalsToIssue = cv->nWaitersToUnblock = 1;
|
||||
cv->nWaitersBlocked--;
|
||||
}
|
||||
}
|
||||
else
|
||||
return pthread_mutex_unlock (&(cv->mtxUnblockLock));
|
||||
|
||||
if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
|
||||
{
|
||||
if (sem_post_multiple (&(cv->semBlockQueue), nSignalsToIssue) != 0)
|
||||
result = errno;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_cond_signal (pthread_cond_t * cond)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function signals a condition variable, waking
|
||||
* one waiting thread.
|
||||
* If SCHED_FIFO or SCHED_RR policy threads are waiting
|
||||
* the highest priority waiter is awakened; otherwise,
|
||||
* an unspecified waiter is awakened.
|
||||
*
|
||||
* PARAMETERS
|
||||
* cond
|
||||
* pointer to an instance of pthread_cond_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function signals a condition variable, waking
|
||||
* one waiting thread.
|
||||
* If SCHED_FIFO or SCHED_RR policy threads are waiting
|
||||
* the highest priority waiter is awakened; otherwise,
|
||||
* an unspecified waiter is awakened.
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
* 1) Use when any waiter can respond and only one need
|
||||
* respond (all waiters being equal).
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully signaled condition,
|
||||
* EINVAL 'cond' is invalid,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
/*
|
||||
* The '0'(FALSE) unblockAll arg means unblock ONE waiter.
|
||||
*/
|
||||
return (pte_cond_unblock (cond, 0));
|
||||
|
||||
} /* pthread_cond_signal */
|
||||
|
||||
int
|
||||
pthread_cond_broadcast (pthread_cond_t * cond)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function broadcasts the condition variable,
|
||||
* waking all current waiters.
|
||||
*
|
||||
* PARAMETERS
|
||||
* cond
|
||||
* pointer to an instance of pthread_cond_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function signals a condition variable, waking
|
||||
* all waiting threads.
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
* 1) Use when more than one waiter may respond to
|
||||
* predicate change or if any waiting thread may
|
||||
* not be able to respond
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully signalled condition to all
|
||||
* waiting threads,
|
||||
* EINVAL 'cond' is invalid
|
||||
* ENOSPC a required resource has been exhausted,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
/*
|
||||
* The TRUE unblockAll arg means unblock ALL waiters.
|
||||
*/
|
||||
return (pte_cond_unblock (cond, PTE_TRUE));
|
||||
}
|
||||
|
||||
int pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function waits on a condition variable until
|
||||
* awakened by a signal or broadcast.
|
||||
*
|
||||
* Caller MUST be holding the mutex lock; the
|
||||
* lock is released and the caller is blocked waiting
|
||||
* on 'cond'. When 'cond' is signaled, the mutex
|
||||
* is re-acquired before returning to the caller.
|
||||
*
|
||||
* PARAMETERS
|
||||
* cond
|
||||
* pointer to an instance of pthread_cond_t
|
||||
*
|
||||
* mutex
|
||||
* pointer to an instance of pthread_mutex_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function waits on a condition variable until
|
||||
* awakened by a signal or broadcast.
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
* 1) The function must be called with 'mutex' LOCKED
|
||||
* by the calling thread, or undefined behaviour
|
||||
* will result.
|
||||
*
|
||||
* 2) This routine atomically releases 'mutex' and causes
|
||||
* the calling thread to block on the condition variable.
|
||||
* The blocked thread may be awakened by
|
||||
* pthread_cond_signal or
|
||||
* pthread_cond_broadcast.
|
||||
*
|
||||
* Upon successful completion, the 'mutex' has been locked and
|
||||
* is owned by the calling thread.
|
||||
*
|
||||
*
|
||||
* RESULTS
|
||||
* 0 caught condition; mutex released,
|
||||
* EINVAL 'cond' or 'mutex' is invalid,
|
||||
* EINVAL different mutexes for concurrent waits,
|
||||
* EINVAL mutex is not held by the calling thread,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
/*
|
||||
* The NULL abstime arg means INFINITE waiting.
|
||||
*/
|
||||
return (pte_cond_timedwait (cond, mutex, NULL));
|
||||
|
||||
} /* pthread_cond_wait */
|
||||
|
||||
|
||||
int
|
||||
pthread_cond_timedwait (pthread_cond_t * cond,
|
||||
pthread_mutex_t * mutex,
|
||||
const struct timespec *abstime)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function waits on a condition variable either until
|
||||
* awakened by a signal or broadcast; or until the time
|
||||
* specified by abstime passes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* cond
|
||||
* pointer to an instance of pthread_cond_t
|
||||
*
|
||||
* mutex
|
||||
* pointer to an instance of pthread_mutex_t
|
||||
*
|
||||
* abstime
|
||||
* pointer to an instance of (const struct timespec)
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function waits on a condition variable either until
|
||||
* awakened by a signal or broadcast; or until the time
|
||||
* specified by abstime passes.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) The function must be called with 'mutex' LOCKED
|
||||
* by the calling thread, or undefined behaviour
|
||||
* will result.
|
||||
*
|
||||
* 2) This routine atomically releases 'mutex' and causes
|
||||
* the calling thread to block on the condition variable.
|
||||
* The blocked thread may be awakened by
|
||||
* pthread_cond_signal or
|
||||
* pthread_cond_broadcast.
|
||||
*
|
||||
*
|
||||
* RESULTS
|
||||
* 0 caught condition; mutex released,
|
||||
* EINVAL 'cond', 'mutex', or abstime is invalid,
|
||||
* EINVAL different mutexes for concurrent waits,
|
||||
* EINVAL mutex is not held by the calling thread,
|
||||
* ETIMEDOUT abstime ellapsed before cond was signaled.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
if (abstime == NULL)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return (pte_cond_timedwait (cond, mutex, abstime));
|
||||
}
|
||||
Vendored
-259
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* condvar_attr_destroy.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements condition variables and their primitives.
|
||||
*
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
|
||||
int
|
||||
pthread_condattr_destroy (pthread_condattr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Destroys a condition variable attributes object.
|
||||
* The object can no longer be used.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_condattr_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Destroys a condition variable attributes object.
|
||||
* The object can no longer be used.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Does not affect condition variables created
|
||||
* using 'attr'
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully released attr,
|
||||
* EINVAL 'attr' is invalid.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (attr == NULL || *attr == NULL)
|
||||
result = EINVAL;
|
||||
else
|
||||
{
|
||||
(void) free (*attr);
|
||||
|
||||
*attr = NULL;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_condattr_getpshared (const pthread_condattr_t * attr, int *pshared)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Determine whether condition variables created with 'attr'
|
||||
* can be shared between processes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_condattr_t
|
||||
*
|
||||
* pshared
|
||||
* will be set to one of:
|
||||
*
|
||||
* PTHREAD_PROCESS_SHARED
|
||||
* May be shared if in shared memory
|
||||
*
|
||||
* PTHREAD_PROCESS_PRIVATE
|
||||
* Cannot be shared.
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Condition Variables created with 'attr' can be shared
|
||||
* between processes if pthread_cond_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
* NOTES:
|
||||
* 1) pshared condition variables MUST be allocated in
|
||||
* shared memory.
|
||||
*
|
||||
* 2) The following macro is defined if shared mutexes
|
||||
* are supported:
|
||||
* _POSIX_THREAD_PROCESS_SHARED
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully retrieved attribute,
|
||||
* EINVAL 'attr' or 'pshared' is invalid,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((attr != NULL && *attr != NULL) && (pshared != NULL))
|
||||
{
|
||||
*pshared = (*attr)->pshared;
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_condattr_init (pthread_condattr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Initializes a condition variable attributes object
|
||||
* with default attributes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_condattr_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Initializes a condition variable attributes object
|
||||
* with default attributes.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Use to define condition variable types
|
||||
* 2) It is up to the application to ensure
|
||||
* that it doesn't re-init an attribute
|
||||
* without destroying it first. Otherwise
|
||||
* a memory leak is created.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully initialized attr,
|
||||
* ENOMEM insufficient memory for attr.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
pthread_condattr_t attr_result;
|
||||
int result = 0;
|
||||
|
||||
attr_result = (pthread_condattr_t) calloc (1, sizeof (*attr_result));
|
||||
|
||||
if (attr_result == NULL)
|
||||
result = ENOMEM;
|
||||
|
||||
*attr = attr_result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Mutexes created with 'attr' can be shared between
|
||||
* processes if pthread_mutex_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_mutexattr_t
|
||||
*
|
||||
* pshared
|
||||
* must be one of:
|
||||
*
|
||||
* PTHREAD_PROCESS_SHARED
|
||||
* May be shared if in shared memory
|
||||
*
|
||||
* PTHREAD_PROCESS_PRIVATE
|
||||
* Cannot be shared.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Mutexes creatd with 'attr' can be shared between
|
||||
* processes if pthread_mutex_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) pshared mutexes MUST be allocated in shared
|
||||
* memory.
|
||||
*
|
||||
* 2) The following macro is defined if shared mutexes
|
||||
* are supported:
|
||||
* _POSIX_THREAD_PROCESS_SHARED
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set attribute,
|
||||
* EINVAL 'attr' or pshared is invalid,
|
||||
* ENOSYS PTHREAD_PROCESS_SHARED not supported,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((attr != NULL && *attr != NULL)
|
||||
&& ((pshared == PTHREAD_PROCESS_SHARED)
|
||||
|| (pshared == PTHREAD_PROCESS_PRIVATE)))
|
||||
{
|
||||
if (pshared == PTHREAD_PROCESS_SHARED)
|
||||
{
|
||||
|
||||
#if !defined( _POSIX_THREAD_PROCESS_SHARED )
|
||||
result = ENOSYS;
|
||||
pshared = PTHREAD_PROCESS_PRIVATE;
|
||||
#else
|
||||
result = 0;
|
||||
|
||||
#endif /* _POSIX_THREAD_PROCESS_SHARED */
|
||||
|
||||
}
|
||||
else
|
||||
result = 0;
|
||||
|
||||
(*attr)->pshared = pshared;
|
||||
}
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
Vendored
-111
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* pthread_get.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements miscellaneous thread functions.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
#include "sched.h"
|
||||
|
||||
int pthread_getconcurrency (void)
|
||||
{
|
||||
return pte_concurrency;
|
||||
}
|
||||
|
||||
int pthread_getschedparam (pthread_t thread, int *policy,
|
||||
struct sched_param *param)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Validate the thread id. */
|
||||
result = pthread_kill (thread, 0);
|
||||
if (0 != result)
|
||||
return result;
|
||||
|
||||
/*
|
||||
* Validate the policy and param args.
|
||||
* Check that a policy constant wasn't passed rather than &policy.
|
||||
*/
|
||||
if (policy <= (int *) SCHED_MAX || param == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/* Fill out the policy. */
|
||||
*policy = SCHED_OTHER;
|
||||
|
||||
/*
|
||||
* This function must return the priority value set by
|
||||
* the most recent pthread_setschedparam() or pthread_create()
|
||||
* for the target thread. It must not return the actual thread
|
||||
* priority as altered by any system priority adjustments etc.
|
||||
*/
|
||||
param->sched_priority = ((pte_thread_t *)thread)->sched_priority;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *pthread_getspecific (pthread_key_t key)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function returns the current value of key in the
|
||||
* calling thread. If no value has been set for 'key' in
|
||||
* the thread, NULL is returned.
|
||||
*
|
||||
* PARAMETERS
|
||||
* key
|
||||
* an instance of pthread_key_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function returns the current value of key in the
|
||||
* calling thread. If no value has been set for 'key' in
|
||||
* the thread, NULL is returned.
|
||||
*
|
||||
* RESULTS
|
||||
* key value or NULL on failure
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
if (key == NULL)
|
||||
return NULL;
|
||||
|
||||
return pte_osTlsGetValue (key->key);
|
||||
}
|
||||
Vendored
-204
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* pthread_key.c
|
||||
*
|
||||
* Description:
|
||||
* POSIX thread functions which implement thread-specific data (TSD).
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pte_osal.h"
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
|
||||
int
|
||||
pthread_key_create (pthread_key_t * key, void (*destructor) (void *))
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function creates a thread-specific data key visible
|
||||
* to all threads. All existing and new threads have a value
|
||||
* NULL for key until set using pthread_setspecific. When any
|
||||
* thread with a non-NULL value for key terminates, 'destructor'
|
||||
* is called with key's current value for that thread.
|
||||
*
|
||||
* PARAMETERS
|
||||
* key
|
||||
* pointer to an instance of pthread_key_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function creates a thread-specific data key visible
|
||||
* to all threads. All existing and new threads have a value
|
||||
* NULL for key until set using pthread_setspecific. When any
|
||||
* thread with a non-NULL value for key terminates, 'destructor'
|
||||
* is called with key's current value for that thread.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully created semaphore,
|
||||
* EAGAIN insufficient resources or PTHREAD_KEYS_MAX
|
||||
* exceeded,
|
||||
* ENOMEM insufficient memory to create the key,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
pthread_key_t newkey;
|
||||
|
||||
if ((newkey = (pthread_key_t) calloc (1, sizeof (*newkey))) == NULL)
|
||||
result = ENOMEM;
|
||||
else
|
||||
{
|
||||
pte_osResult osResult = pte_osTlsAlloc(&(newkey->key));
|
||||
|
||||
if (osResult != PTE_OS_OK)
|
||||
{
|
||||
result = EAGAIN;
|
||||
|
||||
free (newkey);
|
||||
newkey = NULL;
|
||||
}
|
||||
else if (destructor != NULL)
|
||||
{
|
||||
/*
|
||||
* Have to manage associations between thread and key;
|
||||
* Therefore, need a lock that allows multiple threads
|
||||
* to gain exclusive access to the key->threads list.
|
||||
*
|
||||
* The mutex will only be created when it is first locked.
|
||||
*/
|
||||
newkey->keyLock = PTHREAD_MUTEX_INITIALIZER;
|
||||
newkey->destructor = destructor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*key = newkey;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_key_delete (pthread_key_t key)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function deletes a thread-specific data key. This
|
||||
* does not change the value of the thread specific data key
|
||||
* for any thread and does not run the key's destructor
|
||||
* in any thread so it should be used with caution.
|
||||
*
|
||||
* PARAMETERS
|
||||
* key
|
||||
* pointer to an instance of pthread_key_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function deletes a thread-specific data key. This
|
||||
* does not change the value of the thread specific data key
|
||||
* for any thread and does not run the key's destructor
|
||||
* in any thread so it should be used with caution.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully deleted the key,
|
||||
* EINVAL key is invalid,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (key != NULL)
|
||||
{
|
||||
if (key->threads != NULL &&
|
||||
key->destructor != NULL &&
|
||||
pthread_mutex_lock (&(key->keyLock)) == 0)
|
||||
{
|
||||
ThreadKeyAssoc *assoc;
|
||||
/*
|
||||
* Run through all Thread<-->Key associations
|
||||
* for this key.
|
||||
*
|
||||
* While we hold at least one of the locks guarding
|
||||
* the assoc, we know that the assoc pointed to by
|
||||
* key->threads is valid.
|
||||
*/
|
||||
while ((assoc = (ThreadKeyAssoc *) key->threads) != NULL)
|
||||
{
|
||||
pte_thread_t * thread = assoc->thread;
|
||||
|
||||
/* Finished */
|
||||
if (assoc == NULL)
|
||||
break;
|
||||
|
||||
if (pthread_mutex_lock (&(thread->threadLock)) == 0)
|
||||
{
|
||||
/*
|
||||
* Since we are starting at the head of the key's threads
|
||||
* chain, this will also point key->threads at the next assoc.
|
||||
* While we hold key->keyLock, no other thread can insert
|
||||
* a new assoc via pthread_setspecific.
|
||||
*/
|
||||
pte_tkAssocDestroy (assoc);
|
||||
(void) pthread_mutex_unlock (&(thread->threadLock));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Thread or lock is no longer valid? */
|
||||
pte_tkAssocDestroy (assoc);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock (&(key->keyLock));
|
||||
}
|
||||
|
||||
pte_osTlsFree (key->key);
|
||||
if (key->destructor != NULL)
|
||||
{
|
||||
/* A thread could be holding the keyLock */
|
||||
while (EBUSY == (result = pthread_mutex_destroy (&(key->keyLock))))
|
||||
pte_osThreadSleep(1); /* Ugly. */
|
||||
}
|
||||
|
||||
free (key);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
Vendored
-500
@@ -1,500 +0,0 @@
|
||||
/*
|
||||
* pthread_mutex.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements mutual exclusion (mutex) primitives.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pte_osal.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
#define TEST_IE InterlockedExchange
|
||||
|
||||
int pthread_mutex_destroy (pthread_mutex_t * mutex)
|
||||
{
|
||||
int result = 0;
|
||||
pthread_mutex_t mx;
|
||||
|
||||
/*
|
||||
* Let the system deal with invalid pointers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check to see if we have something to delete.
|
||||
*/
|
||||
if (*mutex < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
|
||||
{
|
||||
mx = *mutex;
|
||||
|
||||
result = pthread_mutex_trylock (&mx);
|
||||
|
||||
/*
|
||||
* If trylock succeeded and the mutex is not recursively locked it
|
||||
* can be destroyed.
|
||||
*/
|
||||
if (result == 0)
|
||||
{
|
||||
if (mx->kind != PTHREAD_MUTEX_RECURSIVE || 1 == mx->recursive_count)
|
||||
{
|
||||
/*
|
||||
* FIXME!!!
|
||||
* The mutex isn't held by another thread but we could still
|
||||
* be too late invalidating the mutex below since another thread
|
||||
* may already have entered mutex_lock and the check for a valid
|
||||
* *mutex != NULL.
|
||||
*
|
||||
* Note that this would be an unusual situation because it is not
|
||||
* common that mutexes are destroyed while they are still in
|
||||
* use by other threads.
|
||||
*/
|
||||
*mutex = NULL;
|
||||
|
||||
result = pthread_mutex_unlock (&mx);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
pte_osSemaphoreDelete(mx->handle);
|
||||
|
||||
free(mx);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Restore the mutex before we return the error.
|
||||
*/
|
||||
*mutex = mx;
|
||||
}
|
||||
}
|
||||
else /* mx->recursive_count > 1 */
|
||||
{
|
||||
/*
|
||||
* The mutex must be recursive and already locked by us (this thread).
|
||||
*/
|
||||
mx->recursive_count--; /* Undo effect of pthread_mutex_trylock() above */
|
||||
result = EBUSY;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* See notes in pte_mutex_check_need_init() above also.
|
||||
*/
|
||||
|
||||
pte_osMutexLock (pte_mutex_test_init_lock);
|
||||
|
||||
|
||||
/*
|
||||
* Check again.
|
||||
*/
|
||||
if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
|
||||
{
|
||||
/*
|
||||
* This is all we need to do to destroy a statically
|
||||
* initialised mutex that has not yet been used (initialised).
|
||||
* If we get to here, another thread
|
||||
* waiting to initialise this mutex will get an EINVAL.
|
||||
*/
|
||||
*mutex = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The mutex has been initialised while we were waiting
|
||||
* so assume it's in use.
|
||||
*/
|
||||
result = EBUSY;
|
||||
}
|
||||
|
||||
pte_osMutexUnlock(pte_mutex_test_init_lock);
|
||||
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr)
|
||||
{
|
||||
int result = 0;
|
||||
pthread_mutex_t mx;
|
||||
|
||||
if (mutex == NULL)
|
||||
return EINVAL;
|
||||
|
||||
mx = (pthread_mutex_t) calloc (1, sizeof (*mx));
|
||||
|
||||
if (mx == NULL)
|
||||
result = ENOMEM;
|
||||
else
|
||||
{
|
||||
mx->lock_idx = 0;
|
||||
mx->recursive_count = 0;
|
||||
mx->kind = (attr == NULL || *attr == NULL
|
||||
? PTHREAD_MUTEX_DEFAULT : (*attr)->kind);
|
||||
mx->ownerThread = NULL;
|
||||
|
||||
pte_osSemaphoreCreate(0,&mx->handle);
|
||||
|
||||
}
|
||||
|
||||
*mutex = mx;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_mutex_lock (pthread_mutex_t * mutex)
|
||||
{
|
||||
int result = 0;
|
||||
pthread_mutex_t mx;
|
||||
|
||||
/*
|
||||
* Let the system deal with invalid pointers.
|
||||
*/
|
||||
if (*mutex == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* We do a quick check to see if we need to do more work
|
||||
* to initialise a static mutex. We check
|
||||
* again inside the guarded section of pte_mutex_check_need_init()
|
||||
* to avoid race conditions.
|
||||
*/
|
||||
if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
|
||||
{
|
||||
if ((result = pte_mutex_check_need_init (mutex)) != 0)
|
||||
return (result);
|
||||
}
|
||||
|
||||
mx = *mutex;
|
||||
|
||||
if (mx->kind == PTHREAD_MUTEX_NORMAL)
|
||||
{
|
||||
if (PTE_ATOMIC_EXCHANGE(
|
||||
&mx->lock_idx,
|
||||
1) != 0)
|
||||
{
|
||||
while (PTE_ATOMIC_EXCHANGE(&mx->lock_idx,-1) != 0)
|
||||
{
|
||||
if (pte_osSemaphorePend(mx->handle,NULL) != PTE_OS_OK)
|
||||
{
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_t self = pthread_self();
|
||||
|
||||
if (PTE_ATOMIC_COMPARE_EXCHANGE(&mx->lock_idx,1,0) == 0)
|
||||
{
|
||||
mx->recursive_count = 1;
|
||||
mx->ownerThread = self;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pthread_equal (mx->ownerThread, self))
|
||||
{
|
||||
if (mx->kind == PTHREAD_MUTEX_RECURSIVE)
|
||||
mx->recursive_count++;
|
||||
else
|
||||
result = EDEADLK;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (PTE_ATOMIC_EXCHANGE(&mx->lock_idx,-1) != 0)
|
||||
{
|
||||
if (pte_osSemaphorePend(mx->handle,NULL) != PTE_OS_OK)
|
||||
{
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == result)
|
||||
{
|
||||
mx->recursive_count = 1;
|
||||
mx->ownerThread = self;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int pte_timed_eventwait (pte_osSemaphoreHandle event, const struct timespec *abstime)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DESCRIPTION
|
||||
* This function waits on an event until signaled or until
|
||||
* abstime passes.
|
||||
* If abstime has passed when this routine is called then
|
||||
* it returns a result to indicate this.
|
||||
*
|
||||
* If 'abstime' is a NULL pointer then this function will
|
||||
* block until it can successfully decrease the value or
|
||||
* until interrupted by a signal.
|
||||
*
|
||||
* This routine is not a cancelation point.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully signaled,
|
||||
* ETIMEDOUT abstime passed
|
||||
* EINVAL 'event' is not a valid event,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
unsigned int milliseconds;
|
||||
pte_osResult status;
|
||||
int retval;
|
||||
|
||||
if (abstime == NULL)
|
||||
status = pte_osSemaphorePend(event, NULL);
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Calculate timeout as milliseconds from current system time.
|
||||
*/
|
||||
milliseconds = pte_relmillisecs (abstime);
|
||||
|
||||
status = pte_osSemaphorePend(event, &milliseconds);
|
||||
}
|
||||
|
||||
|
||||
if (status == PTE_OS_TIMEOUT)
|
||||
{
|
||||
retval = ETIMEDOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
int pthread_mutex_timedlock (pthread_mutex_t * mutex,
|
||||
const struct timespec *abstime)
|
||||
{
|
||||
int result;
|
||||
pthread_mutex_t mx;
|
||||
|
||||
/*
|
||||
* Let the system deal with invalid pointers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We do a quick check to see if we need to do more work
|
||||
* to initialise a static mutex. We check
|
||||
* again inside the guarded section of pte_mutex_check_need_init()
|
||||
* to avoid race conditions.
|
||||
*/
|
||||
if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
|
||||
{
|
||||
if ((result = pte_mutex_check_need_init (mutex)) != 0)
|
||||
return (result);
|
||||
}
|
||||
|
||||
mx = *mutex;
|
||||
|
||||
if (mx->kind == PTHREAD_MUTEX_NORMAL)
|
||||
{
|
||||
if (PTE_ATOMIC_EXCHANGE(&mx->lock_idx,1) != 0)
|
||||
{
|
||||
while (PTE_ATOMIC_EXCHANGE(&mx->lock_idx,-1) != 0)
|
||||
{
|
||||
if (0 != (result = pte_timed_eventwait (mx->handle, abstime)))
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_t self = pthread_self();
|
||||
|
||||
if (PTE_ATOMIC_COMPARE_EXCHANGE(&mx->lock_idx,1,0) == 0)
|
||||
{
|
||||
mx->recursive_count = 1;
|
||||
mx->ownerThread = self;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pthread_equal (mx->ownerThread, self))
|
||||
{
|
||||
if (mx->kind == PTHREAD_MUTEX_RECURSIVE)
|
||||
mx->recursive_count++;
|
||||
else
|
||||
return EDEADLK;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (PTE_ATOMIC_EXCHANGE(&mx->lock_idx,-1) != 0)
|
||||
{
|
||||
if (0 != (result = pte_timed_eventwait (mx->handle, abstime)))
|
||||
return result;
|
||||
}
|
||||
|
||||
mx->recursive_count = 1;
|
||||
mx->ownerThread = self;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_trylock (pthread_mutex_t * mutex)
|
||||
{
|
||||
int result = 0;
|
||||
pthread_mutex_t mx;
|
||||
|
||||
/*
|
||||
* Let the system deal with invalid pointers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We do a quick check to see if we need to do more work
|
||||
* to initialise a static mutex. We check
|
||||
* again inside the guarded section of pte_mutex_check_need_init()
|
||||
* to avoid race conditions.
|
||||
*/
|
||||
if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
|
||||
{
|
||||
if ((result = pte_mutex_check_need_init (mutex)) != 0)
|
||||
return (result);
|
||||
}
|
||||
|
||||
mx = *mutex;
|
||||
|
||||
if (0 == PTE_ATOMIC_COMPARE_EXCHANGE (&mx->lock_idx,1,0))
|
||||
{
|
||||
if (mx->kind != PTHREAD_MUTEX_NORMAL)
|
||||
{
|
||||
mx->recursive_count = 1;
|
||||
mx->ownerThread = pthread_self ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mx->kind == PTHREAD_MUTEX_RECURSIVE &&
|
||||
pthread_equal (mx->ownerThread, pthread_self ()))
|
||||
mx->recursive_count++;
|
||||
else
|
||||
result = EBUSY;
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_mutex_unlock (pthread_mutex_t * mutex)
|
||||
{
|
||||
int result = 0;
|
||||
pthread_mutex_t mx = *mutex;
|
||||
|
||||
/*
|
||||
* Let the system deal with invalid pointers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If the thread calling us holds the mutex then there is no
|
||||
* race condition. If another thread holds the
|
||||
* lock then we shouldn't be in here.
|
||||
*/
|
||||
if (mx < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
|
||||
{
|
||||
if (mx->kind == PTHREAD_MUTEX_NORMAL)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = PTE_ATOMIC_EXCHANGE (&mx->lock_idx,0);
|
||||
if (idx != 0)
|
||||
{
|
||||
if (idx < 0)
|
||||
{
|
||||
/*
|
||||
* Someone may be waiting on that mutex.
|
||||
*/
|
||||
if (pte_osSemaphorePost(mx->handle,1) != PTE_OS_OK)
|
||||
result = EINVAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Was not locked (so can't be owned by us).
|
||||
*/
|
||||
result = EPERM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pthread_equal (mx->ownerThread, pthread_self ()))
|
||||
{
|
||||
if (mx->kind != PTHREAD_MUTEX_RECURSIVE
|
||||
|| 0 == --mx->recursive_count)
|
||||
{
|
||||
mx->ownerThread = NULL;
|
||||
|
||||
if (PTE_ATOMIC_EXCHANGE (&mx->lock_idx,0) < 0)
|
||||
{
|
||||
if (pte_osSemaphorePost(mx->handle,1) != PTE_OS_OK)
|
||||
result = EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
result = EPERM;
|
||||
}
|
||||
}
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return (result);
|
||||
}
|
||||
Vendored
-377
@@ -1,377 +0,0 @@
|
||||
/*
|
||||
* pthread_mutexattr.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements mutual exclusion (mutex) primitives.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
int pthread_mutexattr_destroy (pthread_mutexattr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Destroys a mutex attributes object. The object can
|
||||
* no longer be used.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_mutexattr_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Destroys a mutex attributes object. The object can
|
||||
* no longer be used.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Does not affect mutexes created using 'attr'
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully released attr,
|
||||
* EINVAL 'attr' is invalid.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (attr == NULL || *attr == NULL)
|
||||
result = EINVAL;
|
||||
else
|
||||
{
|
||||
pthread_mutexattr_t ma = *attr;
|
||||
|
||||
*attr = NULL;
|
||||
free (ma);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_mutexattr_getkind_np (pthread_mutexattr_t * attr, int *kind)
|
||||
{
|
||||
return pthread_mutexattr_gettype (attr, kind);
|
||||
}
|
||||
|
||||
int pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (attr != NULL && *attr != NULL && kind != NULL)
|
||||
*kind = (*attr)->kind;
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return (result);
|
||||
}
|
||||
int pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr, int *pshared)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Determine whether mutexes created with 'attr' can be
|
||||
* shared between processes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_mutexattr_t
|
||||
*
|
||||
* pshared
|
||||
* will be set to one of:
|
||||
*
|
||||
* PTHREAD_PROCESS_SHARED
|
||||
* May be shared if in shared memory
|
||||
*
|
||||
* PTHREAD_PROCESS_PRIVATE
|
||||
* Cannot be shared.
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Mutexes creatd with 'attr' can be shared between
|
||||
* processes if pthread_mutex_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
* NOTES:
|
||||
* 1) pshared mutexes MUST be allocated in shared
|
||||
* memory.
|
||||
* 2) The following macro is defined if shared mutexes
|
||||
* are supported:
|
||||
* _POSIX_THREAD_PROCESS_SHARED
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully retrieved attribute,
|
||||
* EINVAL 'attr' is invalid,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((attr != NULL && *attr != NULL) && (pshared != NULL))
|
||||
{
|
||||
*pshared = (*attr)->pshared;
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_mutexattr_init (pthread_mutexattr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Initializes a mutex attributes object with default
|
||||
* attributes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_mutexattr_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Initializes a mutex attributes object with default
|
||||
* attributes.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Used to define mutex types
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully initialized attr,
|
||||
* ENOMEM insufficient memory for attr.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
pthread_mutexattr_t ma = (pthread_mutexattr_t) calloc (1, sizeof (*ma));
|
||||
|
||||
if (ma == NULL)
|
||||
result = ENOMEM;
|
||||
else
|
||||
{
|
||||
ma->pshared = PTHREAD_PROCESS_PRIVATE;
|
||||
ma->kind = PTHREAD_MUTEX_DEFAULT;
|
||||
}
|
||||
|
||||
*attr = ma;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_mutexattr_setkind_np (pthread_mutexattr_t * attr, int kind)
|
||||
{
|
||||
return pthread_mutexattr_settype (attr, kind);
|
||||
}
|
||||
|
||||
int pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Mutexes created with 'attr' can be shared between
|
||||
* processes if pthread_mutex_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_mutexattr_t
|
||||
*
|
||||
* pshared
|
||||
* must be one of:
|
||||
*
|
||||
* PTHREAD_PROCESS_SHARED
|
||||
* May be shared if in shared memory
|
||||
*
|
||||
* PTHREAD_PROCESS_PRIVATE
|
||||
* Cannot be shared.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Mutexes creatd with 'attr' can be shared between
|
||||
* processes if pthread_mutex_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) pshared mutexes MUST be allocated in shared
|
||||
* memory.
|
||||
*
|
||||
* 2) The following macro is defined if shared mutexes
|
||||
* are supported:
|
||||
* _POSIX_THREAD_PROCESS_SHARED
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set attribute,
|
||||
* EINVAL 'attr' or pshared is invalid,
|
||||
* ENOSYS PTHREAD_PROCESS_SHARED not supported,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((attr != NULL && *attr != NULL) &&
|
||||
((pshared == PTHREAD_PROCESS_SHARED) ||
|
||||
(pshared == PTHREAD_PROCESS_PRIVATE)))
|
||||
{
|
||||
if (pshared == PTHREAD_PROCESS_SHARED)
|
||||
{
|
||||
|
||||
#if !defined( _POSIX_THREAD_PROCESS_SHARED )
|
||||
|
||||
result = ENOSYS;
|
||||
pshared = PTHREAD_PROCESS_PRIVATE;
|
||||
|
||||
#else
|
||||
|
||||
result = 0;
|
||||
|
||||
#endif /* _POSIX_THREAD_PROCESS_SHARED */
|
||||
|
||||
}
|
||||
else
|
||||
result = 0;
|
||||
|
||||
(*attr)->pshared = pshared;
|
||||
}
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* DOCPUBLIC
|
||||
* The pthread_mutexattr_settype() and
|
||||
* pthread_mutexattr_gettype() functions respectively set and
|
||||
* get the mutex type attribute. This attribute is set in the
|
||||
* type parameter to these functions.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_mutexattr_t
|
||||
*
|
||||
* type
|
||||
* must be one of:
|
||||
*
|
||||
* PTHREAD_MUTEX_DEFAULT
|
||||
*
|
||||
* PTHREAD_MUTEX_NORMAL
|
||||
*
|
||||
* PTHREAD_MUTEX_ERRORCHECK
|
||||
*
|
||||
* PTHREAD_MUTEX_RECURSIVE
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The pthread_mutexattr_settype() and
|
||||
* pthread_mutexattr_gettype() functions respectively set and
|
||||
* get the mutex type attribute. This attribute is set in the
|
||||
* type parameter to these functions. The default value of the
|
||||
* type attribute is PTHREAD_MUTEX_DEFAULT.
|
||||
*
|
||||
* The type of mutex is contained in the type attribute of the
|
||||
* mutex attributes. Valid mutex types include:
|
||||
*
|
||||
* PTHREAD_MUTEX_NORMAL
|
||||
* This type of mutex does not detect deadlock. A
|
||||
* thread attempting to relock this mutex without
|
||||
* first unlocking it will deadlock. Attempting to
|
||||
* unlock a mutex locked by a different thread
|
||||
* results in undefined behavior. Attempting to
|
||||
* unlock an unlocked mutex results in undefined
|
||||
* behavior.
|
||||
*
|
||||
* PTHREAD_MUTEX_ERRORCHECK
|
||||
* This type of mutex provides error checking. A
|
||||
* thread attempting to relock this mutex without
|
||||
* first unlocking it will return with an error. A
|
||||
* thread attempting to unlock a mutex which another
|
||||
* thread has locked will return with an error. A
|
||||
* thread attempting to unlock an unlocked mutex will
|
||||
* return with an error.
|
||||
*
|
||||
* PTHREAD_MUTEX_DEFAULT
|
||||
* Same as PTHREAD_MUTEX_NORMAL.
|
||||
*
|
||||
* PTHREAD_MUTEX_RECURSIVE
|
||||
* A thread attempting to relock this mutex without
|
||||
* first unlocking it will succeed in locking the
|
||||
* mutex. The relocking deadlock which can occur with
|
||||
* mutexes of type PTHREAD_MUTEX_NORMAL cannot occur
|
||||
* with this type of mutex. Multiple locks of this
|
||||
* mutex require the same number of unlocks to
|
||||
* release the mutex before another thread can
|
||||
* acquire the mutex. A thread attempting to unlock a
|
||||
* mutex which another thread has locked will return
|
||||
* with an error. A thread attempting to unlock an
|
||||
* unlocked mutex will return with an error. This
|
||||
* type of mutex is only supported for mutexes whose
|
||||
* process shared attribute is
|
||||
* PTHREAD_PROCESS_PRIVATE.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set attribute,
|
||||
* EINVAL 'attr' or 'type' is invalid,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if ((attr != NULL && *attr != NULL))
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case PTHREAD_MUTEX_FAST_NP:
|
||||
case PTHREAD_MUTEX_RECURSIVE_NP:
|
||||
case PTHREAD_MUTEX_ERRORCHECK_NP:
|
||||
(*attr)->kind = kind;
|
||||
break;
|
||||
default:
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return (result);
|
||||
}
|
||||
Vendored
-676
@@ -1,676 +0,0 @@
|
||||
/*
|
||||
* pthread_rwlock.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements read/write lock primitives.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
int pthread_rwlock_destroy (pthread_rwlock_t * rwlock)
|
||||
{
|
||||
pthread_rwlock_t rwl;
|
||||
int result = 0, result1 = 0, result2 = 0;
|
||||
|
||||
if (rwlock == NULL || *rwlock == NULL)
|
||||
return EINVAL;
|
||||
|
||||
if (*rwlock != PTHREAD_RWLOCK_INITIALIZER)
|
||||
{
|
||||
rwl = *rwlock;
|
||||
|
||||
if (rwl->nMagic != PTE_RWLOCK_MAGIC)
|
||||
return EINVAL;
|
||||
|
||||
if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
|
||||
return result;
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether any threads own/wait for the lock (wait for ex.access);
|
||||
* report "BUSY" if so.
|
||||
*/
|
||||
if (rwl->nExclusiveAccessCount > 0
|
||||
|| rwl->nSharedAccessCount > rwl->nCompletedSharedAccessCount)
|
||||
{
|
||||
result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
|
||||
result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
result2 = EBUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
rwl->nMagic = 0;
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
pthread_mutex_unlock (&rwl->mtxExclusiveAccess);
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) != 0)
|
||||
return result;
|
||||
|
||||
*rwlock = NULL; /* Invalidate rwlock before anything else */
|
||||
result = pthread_cond_destroy (&(rwl->cndSharedAccessCompleted));
|
||||
result1 = pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted));
|
||||
result2 = pthread_mutex_destroy (&(rwl->mtxExclusiveAccess));
|
||||
(void) free (rwl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* See notes in pte_rwlock_check_need_init() above also.
|
||||
*/
|
||||
|
||||
pte_osMutexLock (pte_rwlock_test_init_lock);
|
||||
|
||||
/*
|
||||
* Check again.
|
||||
*/
|
||||
if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
|
||||
{
|
||||
/*
|
||||
* This is all we need to do to destroy a statically
|
||||
* initialised rwlock that has not yet been used (initialised).
|
||||
* If we get to here, another thread
|
||||
* waiting to initialise this rwlock will get an EINVAL.
|
||||
*/
|
||||
*rwlock = NULL;
|
||||
}
|
||||
/*
|
||||
* The rwlock has been initialised while we were waiting
|
||||
* so assume it's in use.
|
||||
*/
|
||||
else
|
||||
result = EBUSY;
|
||||
|
||||
pte_osMutexUnlock(pte_rwlock_test_init_lock);
|
||||
|
||||
}
|
||||
|
||||
return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
|
||||
}
|
||||
|
||||
int pthread_rwlock_init (pthread_rwlock_t * rwlock,
|
||||
const pthread_rwlockattr_t * attr)
|
||||
{
|
||||
int result;
|
||||
pthread_rwlock_t rwl = 0;
|
||||
|
||||
if (rwlock == NULL)
|
||||
return EINVAL;
|
||||
|
||||
if (attr != NULL && *attr != NULL)
|
||||
{
|
||||
result = EINVAL; /* Not supported */
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
rwl = (pthread_rwlock_t) calloc (1, sizeof (*rwl));
|
||||
|
||||
if (rwl == NULL)
|
||||
{
|
||||
result = ENOMEM;
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
rwl->nSharedAccessCount = 0;
|
||||
rwl->nExclusiveAccessCount = 0;
|
||||
rwl->nCompletedSharedAccessCount = 0;
|
||||
|
||||
result = pthread_mutex_init (&rwl->mtxExclusiveAccess, NULL);
|
||||
if (result != 0)
|
||||
{
|
||||
goto FAIL0;
|
||||
}
|
||||
|
||||
result = pthread_mutex_init (&rwl->mtxSharedAccessCompleted, NULL);
|
||||
if (result != 0)
|
||||
{
|
||||
goto FAIL1;
|
||||
}
|
||||
|
||||
result = pthread_cond_init (&rwl->cndSharedAccessCompleted, NULL);
|
||||
if (result != 0)
|
||||
{
|
||||
goto FAIL2;
|
||||
}
|
||||
|
||||
rwl->nMagic = PTE_RWLOCK_MAGIC;
|
||||
|
||||
result = 0;
|
||||
goto DONE;
|
||||
|
||||
FAIL2:
|
||||
(void) pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted));
|
||||
|
||||
FAIL1:
|
||||
(void) pthread_mutex_destroy (&(rwl->mtxExclusiveAccess));
|
||||
|
||||
FAIL0:
|
||||
(void) free (rwl);
|
||||
rwl = NULL;
|
||||
|
||||
DONE:
|
||||
*rwlock = rwl;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_rwlock_rdlock (pthread_rwlock_t * rwlock)
|
||||
{
|
||||
int result;
|
||||
pthread_rwlock_t rwl;
|
||||
|
||||
if (rwlock == NULL || *rwlock == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* We do a quick check to see if we need to do more work
|
||||
* to initialise a static rwlock. We check
|
||||
* again inside the guarded section of pte_rwlock_check_need_init()
|
||||
* to avoid race conditions.
|
||||
*/
|
||||
if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
|
||||
{
|
||||
result = pte_rwlock_check_need_init (rwlock);
|
||||
|
||||
if (result != 0 && result != EBUSY)
|
||||
return result;
|
||||
}
|
||||
|
||||
rwl = *rwlock;
|
||||
|
||||
if (rwl->nMagic != PTE_RWLOCK_MAGIC)
|
||||
return EINVAL;
|
||||
|
||||
if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
|
||||
return result;
|
||||
|
||||
if (++rwl->nSharedAccessCount == INT_MAX)
|
||||
{
|
||||
if ((result =
|
||||
pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return result;
|
||||
}
|
||||
|
||||
rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
|
||||
rwl->nCompletedSharedAccessCount = 0;
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)));
|
||||
}
|
||||
|
||||
int pthread_rwlock_timedrdlock (pthread_rwlock_t * rwlock,
|
||||
const struct timespec *abstime)
|
||||
{
|
||||
int result;
|
||||
pthread_rwlock_t rwl;
|
||||
|
||||
if (rwlock == NULL || *rwlock == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* We do a quick check to see if we need to do more work
|
||||
* to initialise a static rwlock. We check
|
||||
* again inside the guarded section of pte_rwlock_check_need_init()
|
||||
* to avoid race conditions.
|
||||
*/
|
||||
if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
|
||||
{
|
||||
result = pte_rwlock_check_need_init (rwlock);
|
||||
|
||||
if (result != 0 && result != EBUSY)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
rwl = *rwlock;
|
||||
|
||||
if (rwl->nMagic != PTE_RWLOCK_MAGIC)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (++rwl->nSharedAccessCount == INT_MAX)
|
||||
{
|
||||
if ((result =
|
||||
pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted),
|
||||
abstime)) != 0)
|
||||
{
|
||||
if (result == ETIMEDOUT)
|
||||
{
|
||||
++rwl->nCompletedSharedAccessCount;
|
||||
}
|
||||
(void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return result;
|
||||
}
|
||||
|
||||
rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
|
||||
rwl->nCompletedSharedAccessCount = 0;
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)));
|
||||
}
|
||||
|
||||
int pthread_rwlock_timedwrlock (pthread_rwlock_t * rwlock,
|
||||
const struct timespec *abstime)
|
||||
{
|
||||
int result;
|
||||
pthread_rwlock_t rwl;
|
||||
|
||||
if (rwlock == NULL || *rwlock == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* We do a quick check to see if we need to do more work
|
||||
* to initialise a static rwlock. We check
|
||||
* again inside the guarded section of pte_rwlock_check_need_init()
|
||||
* to avoid race conditions.
|
||||
*/
|
||||
if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
|
||||
{
|
||||
result = pte_rwlock_check_need_init (rwlock);
|
||||
|
||||
if (result != 0 && result != EBUSY)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
rwl = *rwlock;
|
||||
|
||||
if (rwl->nMagic != PTE_RWLOCK_MAGIC)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted),
|
||||
abstime)) != 0)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (rwl->nExclusiveAccessCount == 0)
|
||||
{
|
||||
if (rwl->nCompletedSharedAccessCount > 0)
|
||||
{
|
||||
rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
|
||||
rwl->nCompletedSharedAccessCount = 0;
|
||||
}
|
||||
|
||||
if (rwl->nSharedAccessCount > 0)
|
||||
{
|
||||
rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
|
||||
|
||||
/*
|
||||
* This routine may be a cancelation point
|
||||
* according to POSIX 1003.1j section 18.1.2.
|
||||
*/
|
||||
pthread_cleanup_push (pte_rwlock_cancelwrwait, (void *) rwl);
|
||||
|
||||
do
|
||||
{
|
||||
result =
|
||||
pthread_cond_timedwait (&(rwl->cndSharedAccessCompleted),
|
||||
&(rwl->mtxSharedAccessCompleted),
|
||||
abstime);
|
||||
}
|
||||
while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
|
||||
|
||||
pthread_cleanup_pop ((result != 0) ? 1 : 0);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
rwl->nSharedAccessCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
rwl->nExclusiveAccessCount++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_rwlock_tryrdlock (pthread_rwlock_t * rwlock)
|
||||
{
|
||||
int result;
|
||||
pthread_rwlock_t rwl;
|
||||
|
||||
if (rwlock == NULL || *rwlock == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* We do a quick check to see if we need to do more work
|
||||
* to initialise a static rwlock. We check
|
||||
* again inside the guarded section of pte_rwlock_check_need_init()
|
||||
* to avoid race conditions.
|
||||
*/
|
||||
if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
|
||||
{
|
||||
result = pte_rwlock_check_need_init (rwlock);
|
||||
|
||||
if (result != 0 && result != EBUSY)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
rwl = *rwlock;
|
||||
|
||||
if (rwl->nMagic != PTE_RWLOCK_MAGIC)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (++rwl->nSharedAccessCount == INT_MAX)
|
||||
{
|
||||
if ((result =
|
||||
pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return result;
|
||||
}
|
||||
|
||||
rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
|
||||
rwl->nCompletedSharedAccessCount = 0;
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return (pthread_mutex_unlock (&rwl->mtxExclusiveAccess));
|
||||
}
|
||||
|
||||
int pthread_rwlock_trywrlock (pthread_rwlock_t * rwlock)
|
||||
{
|
||||
int result, result1;
|
||||
pthread_rwlock_t rwl;
|
||||
|
||||
if (rwlock == NULL || *rwlock == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* We do a quick check to see if we need to do more work
|
||||
* to initialise a static rwlock. We check
|
||||
* again inside the guarded section of pte_rwlock_check_need_init()
|
||||
* to avoid race conditions.
|
||||
*/
|
||||
if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
|
||||
{
|
||||
result = pte_rwlock_check_need_init (rwlock);
|
||||
|
||||
if (result != 0 && result != EBUSY)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
rwl = *rwlock;
|
||||
|
||||
if (rwl->nMagic != PTE_RWLOCK_MAGIC)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_trylock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return ((result1 != 0) ? result1 : result);
|
||||
}
|
||||
|
||||
if (rwl->nExclusiveAccessCount == 0)
|
||||
{
|
||||
if (rwl->nCompletedSharedAccessCount > 0)
|
||||
{
|
||||
rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
|
||||
rwl->nCompletedSharedAccessCount = 0;
|
||||
}
|
||||
|
||||
if (rwl->nSharedAccessCount > 0)
|
||||
{
|
||||
if ((result =
|
||||
pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((result =
|
||||
pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) == 0)
|
||||
{
|
||||
result = EBUSY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rwl->nExclusiveAccessCount = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = EBUSY;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_rwlock_unlock (pthread_rwlock_t * rwlock)
|
||||
{
|
||||
int result, result1;
|
||||
pthread_rwlock_t rwl;
|
||||
|
||||
if (rwlock == NULL || *rwlock == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
|
||||
{
|
||||
/*
|
||||
* Assume any race condition here is harmless.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
rwl = *rwlock;
|
||||
|
||||
if (rwl->nMagic != PTE_RWLOCK_MAGIC)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (rwl->nExclusiveAccessCount == 0)
|
||||
{
|
||||
if ((result =
|
||||
pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (++rwl->nCompletedSharedAccessCount == 0)
|
||||
{
|
||||
result = pthread_cond_signal (&(rwl->cndSharedAccessCompleted));
|
||||
}
|
||||
|
||||
result1 = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
|
||||
}
|
||||
else
|
||||
{
|
||||
rwl->nExclusiveAccessCount--;
|
||||
|
||||
result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
|
||||
result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
|
||||
}
|
||||
|
||||
return ((result != 0) ? result : result1);
|
||||
}
|
||||
|
||||
int pthread_rwlock_wrlock (pthread_rwlock_t * rwlock)
|
||||
{
|
||||
int result;
|
||||
pthread_rwlock_t rwl;
|
||||
|
||||
if (rwlock == NULL || *rwlock == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* We do a quick check to see if we need to do more work
|
||||
* to initialise a static rwlock. We check
|
||||
* again inside the guarded section of pte_rwlock_check_need_init()
|
||||
* to avoid race conditions.
|
||||
*/
|
||||
if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
|
||||
{
|
||||
result = pte_rwlock_check_need_init (rwlock);
|
||||
|
||||
if (result != 0 && result != EBUSY)
|
||||
return result;
|
||||
}
|
||||
|
||||
rwl = *rwlock;
|
||||
|
||||
if (rwl->nMagic != PTE_RWLOCK_MAGIC)
|
||||
return EINVAL;
|
||||
|
||||
if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
|
||||
return result;
|
||||
|
||||
if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (rwl->nExclusiveAccessCount == 0)
|
||||
{
|
||||
if (rwl->nCompletedSharedAccessCount > 0)
|
||||
{
|
||||
rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
|
||||
rwl->nCompletedSharedAccessCount = 0;
|
||||
}
|
||||
|
||||
if (rwl->nSharedAccessCount > 0)
|
||||
{
|
||||
rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
|
||||
|
||||
/*
|
||||
* This routine may be a cancelation point
|
||||
* according to POSIX 1003.1j section 18.1.2.
|
||||
*/
|
||||
pthread_cleanup_push (pte_rwlock_cancelwrwait, (void *) rwl);
|
||||
|
||||
do
|
||||
{
|
||||
result = pthread_cond_wait (&(rwl->cndSharedAccessCompleted),
|
||||
&(rwl->mtxSharedAccessCompleted));
|
||||
}
|
||||
while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
|
||||
|
||||
pthread_cleanup_pop ((result != 0) ? 1 : 0);
|
||||
|
||||
if (result == 0)
|
||||
rwl->nSharedAccessCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
rwl->nExclusiveAccessCount++;
|
||||
|
||||
return result;
|
||||
}
|
||||
Vendored
-259
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* pthread_rwlockattr_destroy.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements read/write lock primitives.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
int
|
||||
pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Destroys a rwlock attributes object. The object can
|
||||
* no longer be used.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_rwlockattr_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Destroys a rwlock attributes object. The object can
|
||||
* no longer be used.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Does not affect rwlockss created using 'attr'
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully released attr,
|
||||
* EINVAL 'attr' is invalid.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (attr == NULL || *attr == NULL)
|
||||
{
|
||||
result = EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_rwlockattr_t rwa = *attr;
|
||||
|
||||
*attr = NULL;
|
||||
free (rwa);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int
|
||||
pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
|
||||
int *pshared)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Determine whether rwlocks created with 'attr' can be
|
||||
* shared between processes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_rwlockattr_t
|
||||
*
|
||||
* pshared
|
||||
* will be set to one of:
|
||||
*
|
||||
* PTHREAD_PROCESS_SHARED
|
||||
* May be shared if in shared memory
|
||||
*
|
||||
* PTHREAD_PROCESS_PRIVATE
|
||||
* Cannot be shared.
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Rwlocks creatd with 'attr' can be shared between
|
||||
* processes if pthread_rwlock_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
* NOTES:
|
||||
* 1) pshared rwlocks MUST be allocated in shared
|
||||
* memory.
|
||||
* 2) The following macro is defined if shared rwlocks
|
||||
* are supported:
|
||||
* _POSIX_THREAD_PROCESS_SHARED
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully retrieved attribute,
|
||||
* EINVAL 'attr' is invalid,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((attr != NULL && *attr != NULL) && (pshared != NULL))
|
||||
{
|
||||
*pshared = (*attr)->pshared;
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_rwlockattr_init (pthread_rwlockattr_t * attr)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Initializes a rwlock attributes object with default
|
||||
* attributes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_rwlockattr_t
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Initializes a rwlock attributes object with default
|
||||
* attributes.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully initialized attr,
|
||||
* ENOMEM insufficient memory for attr.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
pthread_rwlockattr_t rwa;
|
||||
|
||||
rwa = (pthread_rwlockattr_t) calloc (1, sizeof (*rwa));
|
||||
|
||||
if (rwa == NULL)
|
||||
result = ENOMEM;
|
||||
else
|
||||
rwa->pshared = PTHREAD_PROCESS_PRIVATE;
|
||||
|
||||
*attr = rwa;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, int pshared)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* Rwlocks created with 'attr' can be shared between
|
||||
* processes if pthread_rwlock_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
*
|
||||
* PARAMETERS
|
||||
* attr
|
||||
* pointer to an instance of pthread_rwlockattr_t
|
||||
*
|
||||
* pshared
|
||||
* must be one of:
|
||||
*
|
||||
* PTHREAD_PROCESS_SHARED
|
||||
* May be shared if in shared memory
|
||||
*
|
||||
* PTHREAD_PROCESS_PRIVATE
|
||||
* Cannot be shared.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Rwlocks creatd with 'attr' can be shared between
|
||||
* processes if pthread_rwlock_t variable is allocated
|
||||
* in memory shared by these processes.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) pshared rwlocks MUST be allocated in shared
|
||||
* memory.
|
||||
*
|
||||
* 2) The following macro is defined if shared rwlocks
|
||||
* are supported:
|
||||
* _POSIX_THREAD_PROCESS_SHARED
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set attribute,
|
||||
* EINVAL 'attr' or pshared is invalid,
|
||||
* ENOSYS PTHREAD_PROCESS_SHARED not supported,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((attr != NULL && *attr != NULL) &&
|
||||
((pshared == PTHREAD_PROCESS_SHARED) ||
|
||||
(pshared == PTHREAD_PROCESS_PRIVATE)))
|
||||
{
|
||||
if (pshared == PTHREAD_PROCESS_SHARED)
|
||||
{
|
||||
|
||||
#if !defined( _POSIX_THREAD_PROCESS_SHARED )
|
||||
|
||||
result = ENOSYS;
|
||||
pshared = PTHREAD_PROCESS_PRIVATE;
|
||||
|
||||
#else
|
||||
|
||||
result = 0;
|
||||
|
||||
#endif /* _POSIX_THREAD_PROCESS_SHARED */
|
||||
|
||||
}
|
||||
else
|
||||
result = 0;
|
||||
|
||||
(*attr)->pshared = pshared;
|
||||
}
|
||||
else
|
||||
result = EINVAL;
|
||||
|
||||
return (result);
|
||||
|
||||
} /* pthread_rwlockattr_setpshared */
|
||||
Vendored
-399
@@ -1,399 +0,0 @@
|
||||
/*
|
||||
* pthread_set.c
|
||||
*
|
||||
* Description:
|
||||
* POSIX thread functions related to state.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
#include "sched.h"
|
||||
|
||||
int pthread_setcancelstate (int state, int *oldstate)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function atomically sets the calling thread's
|
||||
* cancelability state to 'state' and returns the previous
|
||||
* cancelability state at the location referenced by
|
||||
* 'oldstate'
|
||||
*
|
||||
* PARAMETERS
|
||||
* state,
|
||||
* oldstate
|
||||
* PTHREAD_CANCEL_ENABLE
|
||||
* cancellation is enabled,
|
||||
*
|
||||
* PTHREAD_CANCEL_DISABLE
|
||||
* cancellation is disabled
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function atomically sets the calling thread's
|
||||
* cancelability state to 'state' and returns the previous
|
||||
* cancelability state at the location referenced by
|
||||
* 'oldstate'.
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Use to disable cancellation around 'atomic' code that
|
||||
* includes cancellation points
|
||||
*
|
||||
* COMPATIBILITY ADDITIONS
|
||||
* If 'oldstate' is NULL then the previous state is not returned
|
||||
* but the function still succeeds. (Solaris)
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set cancelability type,
|
||||
* EINVAL 'state' is invalid
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
pthread_t self = pthread_self ();
|
||||
pte_thread_t * sp = (pte_thread_t *) self;
|
||||
|
||||
if (sp == NULL
|
||||
|| (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE))
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* Lock for async-cancel safety.
|
||||
*/
|
||||
(void) pthread_mutex_lock (&sp->cancelLock);
|
||||
|
||||
if (oldstate != NULL)
|
||||
*oldstate = sp->cancelState;
|
||||
|
||||
sp->cancelState = state;
|
||||
|
||||
/*
|
||||
* Check if there is a pending asynchronous cancel
|
||||
*/
|
||||
if (state == PTHREAD_CANCEL_ENABLE
|
||||
&& (sp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
&& (pte_osThreadCheckCancel(sp->threadId) == PTE_OS_INTERRUPTED) )
|
||||
{
|
||||
sp->state = PThreadStateCanceling;
|
||||
sp->cancelState = PTHREAD_CANCEL_DISABLE;
|
||||
(void) pthread_mutex_unlock (&sp->cancelLock);
|
||||
pte_throw (PTE_EPS_CANCEL);
|
||||
|
||||
/* Never reached */
|
||||
}
|
||||
|
||||
(void) pthread_mutex_unlock (&sp->cancelLock);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_setcanceltype (int type, int *oldtype)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function atomically sets the calling thread's
|
||||
* cancelability type to 'type' and returns the previous
|
||||
* cancelability type at the location referenced by
|
||||
* 'oldtype'
|
||||
*
|
||||
* PARAMETERS
|
||||
* type,
|
||||
* oldtype
|
||||
* PTHREAD_CANCEL_DEFERRED
|
||||
* only deferred cancelation is allowed,
|
||||
*
|
||||
* PTHREAD_CANCEL_ASYNCHRONOUS
|
||||
* Asynchronous cancellation is allowed
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function atomically sets the calling thread's
|
||||
* cancelability type to 'type' and returns the previous
|
||||
* cancelability type at the location referenced by
|
||||
* 'oldtype'
|
||||
*
|
||||
* NOTES:
|
||||
* 1) Use with caution; most code is not safe for use
|
||||
* with asynchronous cancelability.
|
||||
*
|
||||
* COMPATIBILITY ADDITIONS
|
||||
* If 'oldtype' is NULL then the previous type is not returned
|
||||
* but the function still succeeds. (Solaris)
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set cancelability type,
|
||||
* EINVAL 'type' is invalid
|
||||
* EPERM Async cancellation is not supported.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
pthread_t self = pthread_self ();
|
||||
pte_thread_t * sp = (pte_thread_t *) self;
|
||||
|
||||
#ifndef PTE_SUPPORT_ASYNC_CANCEL
|
||||
if (type == PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
{
|
||||
/* Async cancellation is not supported at this time. See notes in
|
||||
* pthread_cancel.
|
||||
*/
|
||||
return EPERM;
|
||||
}
|
||||
#endif /* PTE_SUPPORT_ASYNC_CANCEL */
|
||||
|
||||
if (sp == NULL
|
||||
|| (type != PTHREAD_CANCEL_DEFERRED
|
||||
&& type != PTHREAD_CANCEL_ASYNCHRONOUS))
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* Lock for async-cancel safety.
|
||||
*/
|
||||
(void) pthread_mutex_lock (&sp->cancelLock);
|
||||
|
||||
if (oldtype != NULL)
|
||||
*oldtype = sp->cancelType;
|
||||
|
||||
sp->cancelType = type;
|
||||
|
||||
/*
|
||||
* Check if there is a pending asynchronous cancel
|
||||
*/
|
||||
|
||||
if (sp->cancelState == PTHREAD_CANCEL_ENABLE
|
||||
&& (type == PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
&& (pte_osThreadCheckCancel(sp->threadId) == PTE_OS_INTERRUPTED) )
|
||||
{
|
||||
sp->state = PThreadStateCanceling;
|
||||
sp->cancelState = PTHREAD_CANCEL_DISABLE;
|
||||
(void) pthread_mutex_unlock (&sp->cancelLock);
|
||||
pte_throw (PTE_EPS_CANCEL);
|
||||
|
||||
/* Never reached */
|
||||
}
|
||||
|
||||
(void) pthread_mutex_unlock (&sp->cancelLock);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_setconcurrency (int level)
|
||||
{
|
||||
if (level < 0)
|
||||
return EINVAL;
|
||||
|
||||
pte_concurrency = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_setschedparam (pthread_t thread, int policy,
|
||||
const struct sched_param *param)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Validate the thread id. */
|
||||
result = pthread_kill (thread, 0);
|
||||
if (0 != result)
|
||||
return result;
|
||||
|
||||
/* Validate the scheduling policy. */
|
||||
if (policy < SCHED_MIN || policy > SCHED_MAX)
|
||||
return EINVAL;
|
||||
|
||||
/* Ensure the policy is SCHED_OTHER. */
|
||||
if (policy != SCHED_OTHER)
|
||||
return ENOTSUP;
|
||||
|
||||
return (pte_setthreadpriority (thread, policy, param->sched_priority));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pte_setthreadpriority (pthread_t thread, int policy, int priority)
|
||||
{
|
||||
int prio;
|
||||
int result;
|
||||
pte_thread_t * tp = (pte_thread_t *) thread;
|
||||
|
||||
prio = priority;
|
||||
|
||||
/* Validate priority level. */
|
||||
if (prio < sched_get_priority_min (policy) ||
|
||||
prio > sched_get_priority_max (policy))
|
||||
return EINVAL;
|
||||
|
||||
result = pthread_mutex_lock (&tp->threadLock);
|
||||
|
||||
if (0 == result)
|
||||
{
|
||||
/* If this fails, the current priority is unchanged. */
|
||||
|
||||
if (0 != pte_osThreadSetPriority(tp->threadId, prio))
|
||||
result = EINVAL;
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Must record the thread's sched_priority as given,
|
||||
* not as finally adjusted.
|
||||
*/
|
||||
tp->sched_priority = priority;
|
||||
}
|
||||
|
||||
(void) pthread_mutex_unlock (&tp->threadLock);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_setspecific (pthread_key_t key, const void *value)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function sets the value of the thread specific
|
||||
* key in the calling thread.
|
||||
*
|
||||
* PARAMETERS
|
||||
* key
|
||||
* an instance of pthread_key_t
|
||||
* value
|
||||
* the value to set key to
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function sets the value of the thread specific
|
||||
* key in the calling thread.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully set value
|
||||
* EAGAIN could not set value
|
||||
* ENOENT SERIOUS!!
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
pthread_t self;
|
||||
int result = 0;
|
||||
|
||||
if (key != pte_selfThreadKey)
|
||||
{
|
||||
/*
|
||||
* Using pthread_self will implicitly create
|
||||
* an instance of pthread_t for the current
|
||||
* thread if one wasn't explicitly created
|
||||
*/
|
||||
self = pthread_self ();
|
||||
if (self == NULL)
|
||||
return ENOENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Resolve catch-22 of registering thread with selfThread
|
||||
* key
|
||||
*/
|
||||
pte_thread_t * sp = (pte_thread_t *) pthread_getspecific (pte_selfThreadKey);
|
||||
|
||||
if (sp == NULL)
|
||||
{
|
||||
if (value == NULL)
|
||||
return ENOENT;
|
||||
|
||||
self = *((pthread_t *) value);
|
||||
}
|
||||
else
|
||||
self = sp;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
|
||||
if (key != NULL)
|
||||
{
|
||||
if (self != NULL && key->destructor != NULL && value != NULL)
|
||||
{
|
||||
/*
|
||||
* Only require associations if we have to
|
||||
* call user destroy routine.
|
||||
* Don't need to locate an existing association
|
||||
* when setting data to NULL since the
|
||||
* data is stored with the operating system; not
|
||||
* on the association; setting assoc to NULL short
|
||||
* circuits the search.
|
||||
*/
|
||||
ThreadKeyAssoc *assoc;
|
||||
|
||||
if (pthread_mutex_lock(&(key->keyLock)) == 0)
|
||||
{
|
||||
pte_thread_t * sp = (pte_thread_t *) self;
|
||||
|
||||
(void) pthread_mutex_lock(&(sp->threadLock));
|
||||
|
||||
assoc = (ThreadKeyAssoc *) sp->keys;
|
||||
/*
|
||||
* Locate existing association
|
||||
*/
|
||||
while (assoc != NULL)
|
||||
{
|
||||
/*
|
||||
* Association already exists
|
||||
*/
|
||||
if (assoc->key == key)
|
||||
break;
|
||||
assoc = assoc->nextKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* create an association if not found
|
||||
*/
|
||||
if (assoc == NULL)
|
||||
result = pte_tkAssocCreate (sp, key);
|
||||
|
||||
(void) pthread_mutex_unlock(&(sp->threadLock));
|
||||
}
|
||||
(void) pthread_mutex_unlock(&(key->keyLock));
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
if (pte_osTlsSetValue (key->key, (void *) value) != PTE_OS_OK)
|
||||
result = EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
Vendored
-295
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
* pthread_spin.c
|
||||
*
|
||||
* Description:
|
||||
* This translation unit implements spin lock primitives.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
|
||||
|
||||
int
|
||||
pthread_spin_destroy (pthread_spinlock_t * lock)
|
||||
{
|
||||
register pthread_spinlock_t s;
|
||||
int result = 0;
|
||||
|
||||
if (lock == NULL || *lock == NULL)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((s = *lock) != PTHREAD_SPINLOCK_INITIALIZER)
|
||||
{
|
||||
if (s->interlock == PTE_SPIN_USE_MUTEX)
|
||||
{
|
||||
result = pthread_mutex_destroy (&(s->u.mutex));
|
||||
}
|
||||
else if (PTE_SPIN_UNLOCKED !=
|
||||
PTE_ATOMIC_COMPARE_EXCHANGE (
|
||||
& (s->interlock),
|
||||
(int) PTE_OBJECT_INVALID,
|
||||
PTE_SPIN_UNLOCKED))
|
||||
{
|
||||
result = EINVAL;
|
||||
}
|
||||
|
||||
if (0 == result)
|
||||
{
|
||||
/*
|
||||
* We are relying on the application to ensure that all other threads
|
||||
* have finished with the spinlock before destroying it.
|
||||
*/
|
||||
*lock = NULL;
|
||||
(void) free (s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* See notes in pte_spinlock_check_need_init() above also.
|
||||
*/
|
||||
|
||||
pte_osMutexLock (pte_spinlock_test_init_lock);
|
||||
|
||||
/*
|
||||
* Check again.
|
||||
*/
|
||||
if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
|
||||
{
|
||||
/*
|
||||
* This is all we need to do to destroy a statically
|
||||
* initialised spinlock that has not yet been used (initialised).
|
||||
* If we get to here, another thread
|
||||
* waiting to initialise this mutex will get an EINVAL.
|
||||
*/
|
||||
*lock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The spinlock has been initialised while we were waiting
|
||||
* so assume it's in use.
|
||||
*/
|
||||
result = EBUSY;
|
||||
}
|
||||
|
||||
pte_osMutexUnlock(pte_spinlock_test_init_lock);
|
||||
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_spin_init (pthread_spinlock_t * lock, int pshared)
|
||||
{
|
||||
pthread_spinlock_t s;
|
||||
int cpus = 0;
|
||||
int result = 0;
|
||||
|
||||
if (lock == NULL)
|
||||
return EINVAL;
|
||||
|
||||
if (0 != pte_getprocessors (&cpus))
|
||||
{
|
||||
cpus = 1;
|
||||
}
|
||||
|
||||
if (cpus > 1)
|
||||
{
|
||||
if (pshared == PTHREAD_PROCESS_SHARED)
|
||||
{
|
||||
/*
|
||||
* Creating spinlock that can be shared between
|
||||
* processes.
|
||||
*/
|
||||
#if _POSIX_THREAD_PROCESS_SHARED >= 0
|
||||
|
||||
/*
|
||||
* Not implemented yet.
|
||||
*/
|
||||
|
||||
#error ERROR [__FILE__, line __LINE__]: Process shared spin locks are not supported yet.
|
||||
|
||||
#else
|
||||
|
||||
return ENOSYS;
|
||||
|
||||
#endif /* _POSIX_THREAD_PROCESS_SHARED */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
s = (pthread_spinlock_t) calloc (1, sizeof (*s));
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (cpus > 1)
|
||||
{
|
||||
s->u.cpus = cpus;
|
||||
s->interlock = PTE_SPIN_UNLOCKED;
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_mutexattr_t ma;
|
||||
result = pthread_mutexattr_init (&ma);
|
||||
|
||||
if (0 == result)
|
||||
{
|
||||
ma->pshared = pshared;
|
||||
result = pthread_mutex_init (&(s->u.mutex), &ma);
|
||||
if (0 == result)
|
||||
{
|
||||
s->interlock = PTE_SPIN_USE_MUTEX;
|
||||
}
|
||||
}
|
||||
(void) pthread_mutexattr_destroy (&ma);
|
||||
}
|
||||
|
||||
if (0 == result)
|
||||
{
|
||||
*lock = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) free (s);
|
||||
*lock = NULL;
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int pthread_spin_lock (pthread_spinlock_t * lock)
|
||||
{
|
||||
register pthread_spinlock_t s;
|
||||
|
||||
if (NULL == lock || NULL == *lock)
|
||||
return (EINVAL);
|
||||
|
||||
if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((result = pte_spinlock_check_need_init (lock)) != 0)
|
||||
return (result);
|
||||
}
|
||||
|
||||
s = *lock;
|
||||
|
||||
while ( PTE_SPIN_LOCKED ==
|
||||
PTE_ATOMIC_COMPARE_EXCHANGE (&(s->interlock),
|
||||
PTE_SPIN_LOCKED,
|
||||
PTE_SPIN_UNLOCKED))
|
||||
{
|
||||
}
|
||||
|
||||
if (s->interlock == PTE_SPIN_LOCKED)
|
||||
return 0;
|
||||
|
||||
if (s->interlock == PTE_SPIN_USE_MUTEX)
|
||||
return pthread_mutex_lock (&(s->u.mutex));
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
int pthread_spin_trylock (pthread_spinlock_t * lock)
|
||||
{
|
||||
register pthread_spinlock_t s;
|
||||
|
||||
if (NULL == lock || NULL == *lock)
|
||||
return (EINVAL);
|
||||
|
||||
if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((result = pte_spinlock_check_need_init (lock)) != 0)
|
||||
return (result);
|
||||
}
|
||||
|
||||
s = *lock;
|
||||
|
||||
switch ((long)
|
||||
PTE_ATOMIC_COMPARE_EXCHANGE (&(s->interlock),
|
||||
PTE_SPIN_LOCKED,
|
||||
PTE_SPIN_UNLOCKED))
|
||||
{
|
||||
case PTE_SPIN_UNLOCKED:
|
||||
return 0;
|
||||
case PTE_SPIN_LOCKED:
|
||||
return EBUSY;
|
||||
case PTE_SPIN_USE_MUTEX:
|
||||
return pthread_mutex_trylock (&(s->u.mutex));
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
int pthread_spin_unlock (pthread_spinlock_t * lock)
|
||||
{
|
||||
register pthread_spinlock_t s;
|
||||
|
||||
if (NULL == lock || NULL == *lock)
|
||||
return (EINVAL);
|
||||
|
||||
s = *lock;
|
||||
|
||||
if (s == PTHREAD_SPINLOCK_INITIALIZER)
|
||||
return EPERM;
|
||||
|
||||
switch ((long)
|
||||
PTE_ATOMIC_COMPARE_EXCHANGE (&(s->interlock),
|
||||
PTE_SPIN_UNLOCKED,
|
||||
PTE_SPIN_LOCKED))
|
||||
{
|
||||
case PTE_SPIN_LOCKED:
|
||||
return 0;
|
||||
case PTE_SPIN_UNLOCKED:
|
||||
return EPERM;
|
||||
case PTE_SPIN_USE_MUTEX:
|
||||
return pthread_mutex_unlock (&(s->u.mutex));
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
Vendored
-101
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* sched_setscheduler.c
|
||||
*
|
||||
* Description:
|
||||
* POSIX thread functions that deal with thread scheduling.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pte_osal.h"
|
||||
|
||||
#include "pthread.h"
|
||||
#include "implement.h"
|
||||
#include "sched.h"
|
||||
|
||||
int
|
||||
sched_setscheduler (pid_t pid, int policy)
|
||||
{
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sched_yield (void)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function indicates that the calling thread is
|
||||
* willing to give up some time slices to other threads.
|
||||
*
|
||||
* PARAMETERS
|
||||
* N/A
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function indicates that the calling thread is
|
||||
* willing to give up some time slices to other threads.
|
||||
* NOTE: Since this is part of POSIX 1003.1b
|
||||
* (realtime extensions), it is defined as returning
|
||||
* -1 if an error occurs and sets errno to the actual
|
||||
* error.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully created semaphore,
|
||||
* ENOSYS sched_yield not supported,
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
pte_osThreadSleep (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sched_get_priority_min (int policy)
|
||||
{
|
||||
return pte_osThreadGetMinPriority();
|
||||
}
|
||||
|
||||
int
|
||||
sched_get_priority_max (int policy)
|
||||
{
|
||||
return pte_osThreadGetMaxPriority();
|
||||
}
|
||||
Vendored
-137
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Module: sched.h
|
||||
*
|
||||
* Purpose:
|
||||
* Provides an implementation of POSIX realtime extensions
|
||||
* as defined in
|
||||
*
|
||||
* POSIX 1003.1b-1993 (POSIX.1b)
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef _SCHED_H
|
||||
#define _SCHED_H
|
||||
|
||||
#include <pte_types.h>
|
||||
|
||||
#undef PTE_LEVEL
|
||||
|
||||
#if defined(_POSIX_SOURCE)
|
||||
#define PTE_LEVEL 0
|
||||
/* Early POSIX */
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
|
||||
#undef PTE_LEVEL
|
||||
#define PTE_LEVEL 1
|
||||
/* Include 1b, 1c and 1d */
|
||||
#endif
|
||||
|
||||
#if defined(INCLUDE_NP)
|
||||
#undef PTE_LEVEL
|
||||
#define PTE_LEVEL 2
|
||||
/* Include Non-Portable extensions */
|
||||
#endif
|
||||
|
||||
#define PTE_LEVEL_MAX 3
|
||||
|
||||
#if !defined(PTE_LEVEL)
|
||||
#define PTE_LEVEL PTE_LEVEL_MAX
|
||||
/* Include everything */
|
||||
#endif
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
/* Thread scheduling policies */
|
||||
|
||||
enum
|
||||
{
|
||||
SCHED_OTHER = 0,
|
||||
SCHED_FIFO,
|
||||
SCHED_RR,
|
||||
SCHED_MIN = SCHED_OTHER,
|
||||
SCHED_MAX = SCHED_RR
|
||||
};
|
||||
|
||||
struct sched_param
|
||||
{
|
||||
int sched_priority;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int sched_yield (void);
|
||||
|
||||
int sched_get_priority_min (int policy);
|
||||
|
||||
int sched_get_priority_max (int policy);
|
||||
|
||||
int sched_setscheduler (pid_t pid, int policy);
|
||||
|
||||
/*
|
||||
* Note that this macro returns ENOTSUP rather than
|
||||
* ENOSYS as might be expected. However, returning ENOSYS
|
||||
* should mean that sched_get_priority_{min,max} are
|
||||
* not implemented as well as sched_rr_get_interval.
|
||||
* This is not the case, since we just don't support
|
||||
* round-robin scheduling. Therefore I have chosen to
|
||||
* return the same value as sched_setscheduler when
|
||||
* SCHED_RR is passed to it.
|
||||
*/
|
||||
#define sched_rr_get_interval(_pid, _interval) \
|
||||
( errno = ENOTSUP, (int) -1 )
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#undef PTE_LEVEL
|
||||
#undef PTE_LEVEL_MAX
|
||||
|
||||
#endif /* !_SCHED_H */
|
||||
|
||||
Vendored
-895
@@ -1,895 +0,0 @@
|
||||
/*
|
||||
* -------------------------------------------------------------
|
||||
*
|
||||
* Module: sem.c
|
||||
*
|
||||
* Purpose:
|
||||
* Semaphores aren't actually part of the PThreads standard.
|
||||
* They are defined by the POSIX Standard:
|
||||
*
|
||||
* POSIX 1003.1b-1993 (POSIX.1b)
|
||||
*
|
||||
* -------------------------------------------------------------
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
|
||||
* Copyright(C) 2008 Jason Schmidlapp
|
||||
*
|
||||
* Contact Email: jschmidlapp@users.sourceforge.net
|
||||
*
|
||||
*
|
||||
* Based upon Pthreads-win32 - POSIX Threads Library for Win32
|
||||
* Copyright(C) 1998 John E. Bossom
|
||||
* Copyright(C) 1999,2005 Pthreads-win32 contributors
|
||||
*
|
||||
* Contact Email: rpj@callisto.canberra.edu.au
|
||||
*
|
||||
* The original list of contributors to the Pthreads-win32 project
|
||||
* is contained in the file CONTRIBUTORS.ptw32 included with the
|
||||
* source code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
* http://sources.redhat.com/pthreads-win32/contributors.html
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library in the file COPYING.LIB;
|
||||
* if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pte_osal.h"
|
||||
|
||||
#include "pthread.h"
|
||||
#include "semaphore.h"
|
||||
#include "implement.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sem_t sem;
|
||||
int * resultPtr;
|
||||
} sem_timedwait_cleanup_args_t;
|
||||
|
||||
static void pte_sem_wait_cleanup(void * sem)
|
||||
{
|
||||
sem_t s = (sem_t) sem;
|
||||
unsigned int timeout;
|
||||
|
||||
if (pthread_mutex_lock (&s->lock) == 0)
|
||||
{
|
||||
/*
|
||||
* If sema is destroyed do nothing, otherwise:-
|
||||
* If the sema is posted between us being cancelled and us locking
|
||||
* the sema again above then we need to consume that post but cancel
|
||||
* anyway. If we don't get the semaphore we indicate that we're no
|
||||
* longer waiting.
|
||||
*/
|
||||
timeout = 0;
|
||||
if (pte_osSemaphorePend(s->sem, &timeout) != PTE_OS_OK)
|
||||
{
|
||||
++s->value;
|
||||
|
||||
/*
|
||||
* Don't release the W32 sema, it doesn't need adjustment
|
||||
* because it doesn't record the number of waiters.
|
||||
*/
|
||||
|
||||
}
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void pte_sem_timedwait_cleanup (void * args)
|
||||
{
|
||||
sem_timedwait_cleanup_args_t * a = (sem_timedwait_cleanup_args_t *)args;
|
||||
sem_t s = a->sem;
|
||||
|
||||
if (pthread_mutex_lock (&s->lock) == 0)
|
||||
{
|
||||
/*
|
||||
* We either timed out or were cancelled.
|
||||
* If someone has posted between then and now we try to take the semaphore.
|
||||
* Otherwise the semaphore count may be wrong after we
|
||||
* return. In the case of a cancellation, it is as if we
|
||||
* were cancelled just before we return (after taking the semaphore)
|
||||
* which is ok.
|
||||
*/
|
||||
unsigned int timeout = 0;
|
||||
if (pte_osSemaphorePend(s->sem, &timeout) == PTE_OS_OK)
|
||||
{
|
||||
/* We got the semaphore on the second attempt */
|
||||
*(a->resultPtr) = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Indicate we're no longer waiting */
|
||||
s->value++;
|
||||
|
||||
/*
|
||||
* Don't release the OS sema, it doesn't need adjustment
|
||||
* because it doesn't record the number of waiters.
|
||||
*/
|
||||
|
||||
}
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
}
|
||||
}
|
||||
|
||||
int sem_close (sem_t * sem)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sem_destroy (sem_t * sem)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function destroys an unnamed semaphore.
|
||||
*
|
||||
* PARAMETERS
|
||||
* sem
|
||||
* pointer to an instance of sem_t
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function destroys an unnamed semaphore.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully destroyed semaphore,
|
||||
* -1 failed, error in errno
|
||||
* ERRNO
|
||||
* EINVAL 'sem' is not a valid semaphore,
|
||||
* ENOSYS semaphores are not supported,
|
||||
* EBUSY threads (or processes) are currently
|
||||
* blocked on 'sem'
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
sem_t s = NULL;
|
||||
|
||||
if (sem == NULL || *sem == NULL)
|
||||
result = EINVAL;
|
||||
else
|
||||
{
|
||||
s = *sem;
|
||||
|
||||
if ((result = pthread_mutex_lock (&s->lock)) == 0)
|
||||
{
|
||||
if (s->value < 0)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
result = EBUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There are no threads currently blocked on this semaphore. */
|
||||
pte_osResult osResult = pte_osSemaphoreDelete(s->sem);
|
||||
|
||||
if (osResult != PTE_OS_OK)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
result = EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Invalidate the semaphore handle when we have the lock.
|
||||
* Other sema operations should test this after acquiring the lock
|
||||
* to check that the sema is still valid, i.e. before performing any
|
||||
* operations. This may only be necessary before the sema op routine
|
||||
* returns so that the routine can return EINVAL - e.g. if setting
|
||||
* s->value to SEM_VALUE_MAX below does force a fall-through.
|
||||
*/
|
||||
*sem = NULL;
|
||||
|
||||
/* Prevent anyone else actually waiting on or posting this sema.
|
||||
*/
|
||||
s->value = SEM_VALUE_MAX;
|
||||
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
|
||||
do
|
||||
{
|
||||
/* Give other threads a chance to run and exit any sema op
|
||||
* routines. Due to the SEM_VALUE_MAX value, if sem_post or
|
||||
* sem_wait were blocked by us they should fall through.
|
||||
*/
|
||||
pte_osThreadSleep(1);
|
||||
}
|
||||
while (pthread_mutex_destroy (&s->lock) == EBUSY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
errno = result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sem_getvalue (sem_t * sem, int *sval)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function stores the current count value of the
|
||||
* semaphore.
|
||||
* RESULTS
|
||||
*
|
||||
* Return value
|
||||
*
|
||||
* 0 sval has been set.
|
||||
* -1 failed, error in errno
|
||||
*
|
||||
* in global errno
|
||||
*
|
||||
* EINVAL 'sem' is not a valid semaphore,
|
||||
* ENOSYS this function is not supported,
|
||||
*
|
||||
*
|
||||
* PARAMETERS
|
||||
*
|
||||
* sem pointer to an instance of sem_t
|
||||
*
|
||||
* sval pointer to int.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function stores the current count value of the semaphore
|
||||
* pointed to by sem in the int pointed to by sval.
|
||||
*/
|
||||
{
|
||||
if (sem == NULL || *sem == NULL || sval == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
register sem_t s = *sem;
|
||||
int result = 0;
|
||||
|
||||
if ((result = pthread_mutex_lock(&s->lock)) == 0)
|
||||
{
|
||||
if (*sem == NULL)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
value = s->value;
|
||||
(void) pthread_mutex_unlock(&s->lock);
|
||||
*sval = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sem_init (sem_t * sem, int pshared, unsigned int value)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function initializes a semaphore. The
|
||||
* initial value of the semaphore is 'value'
|
||||
*
|
||||
* PARAMETERS
|
||||
* sem
|
||||
* pointer to an instance of sem_t
|
||||
*
|
||||
* pshared
|
||||
* if zero, this semaphore may only be shared between
|
||||
* threads in the same process.
|
||||
* if nonzero, the semaphore can be shared between
|
||||
* processes
|
||||
*
|
||||
* value
|
||||
* initial value of the semaphore counter
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function initializes a semaphore. The
|
||||
* initial value of the semaphore is set to 'value'.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully created semaphore,
|
||||
* -1 failed, error in errno
|
||||
* ERRNO
|
||||
* EINVAL 'sem' is not a valid semaphore, or
|
||||
* 'value' >= SEM_VALUE_MAX
|
||||
* ENOMEM out of memory,
|
||||
* ENOSPC a required resource has been exhausted,
|
||||
* ENOSYS semaphores are not supported,
|
||||
* EPERM the process lacks appropriate privilege
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
sem_t s = NULL;
|
||||
|
||||
if (pshared != 0)
|
||||
{
|
||||
/*
|
||||
* Creating a semaphore that can be shared between
|
||||
* processes
|
||||
*/
|
||||
result = EPERM;
|
||||
}
|
||||
else if (value > (unsigned int)SEM_VALUE_MAX)
|
||||
{
|
||||
result = EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = (sem_t) calloc (1, sizeof (*s));
|
||||
|
||||
if (NULL == s)
|
||||
{
|
||||
result = ENOMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
s->value = value;
|
||||
if (pthread_mutex_init(&s->lock, NULL) == 0)
|
||||
{
|
||||
|
||||
pte_osResult osResult = pte_osSemaphoreCreate(0, &s->sem);
|
||||
|
||||
|
||||
|
||||
if (osResult != PTE_OS_OK)
|
||||
{
|
||||
(void) pthread_mutex_destroy(&s->lock);
|
||||
result = ENOSPC;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ENOSPC;
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
errno = result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*sem = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_open (const char *name, int oflag, mode_t mode, unsigned int value)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sem_post (sem_t * sem)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function posts a wakeup to a semaphore.
|
||||
*
|
||||
* PARAMETERS
|
||||
* sem
|
||||
* pointer to an instance of sem_t
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function posts a wakeup to a semaphore. If there
|
||||
* are waiting threads (or processes), one is awakened;
|
||||
* otherwise, the semaphore value is incremented by one.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully posted semaphore,
|
||||
* -1 failed, error in errno
|
||||
* ERRNO
|
||||
* EINVAL 'sem' is not a valid semaphore,
|
||||
* ENOSYS semaphores are not supported,
|
||||
* ERANGE semaphore count is too big
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
sem_t s = *sem;
|
||||
|
||||
if (s == NULL)
|
||||
result = EINVAL;
|
||||
else if ((result = pthread_mutex_lock (&s->lock)) == 0)
|
||||
{
|
||||
/* See sem_destroy.c
|
||||
*/
|
||||
if (*sem == NULL)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
result = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s->value < SEM_VALUE_MAX)
|
||||
{
|
||||
pte_osResult osResult = pte_osSemaphorePost(s->sem, 1);
|
||||
|
||||
if (++s->value <= 0
|
||||
&& (osResult != PTE_OS_OK))
|
||||
{
|
||||
s->value--;
|
||||
result = EINVAL;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
result = ERANGE;
|
||||
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
errno = result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sem_post_multiple (sem_t * sem, int count)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function posts multiple wakeups to a semaphore.
|
||||
*
|
||||
* PARAMETERS
|
||||
* sem
|
||||
* pointer to an instance of sem_t
|
||||
*
|
||||
* count
|
||||
* counter, must be greater than zero.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function posts multiple wakeups to a semaphore. If there
|
||||
* are waiting threads (or processes), n <= count are awakened;
|
||||
* the semaphore value is incremented by count - n.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully posted semaphore,
|
||||
* -1 failed, error in errno
|
||||
* ERRNO
|
||||
* EINVAL 'sem' is not a valid semaphore
|
||||
* or count is less than or equal to zero.
|
||||
* ERANGE semaphore count is too big
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
long waiters;
|
||||
sem_t s = *sem;
|
||||
|
||||
if (s == NULL || count <= 0)
|
||||
result = EINVAL;
|
||||
else if ((result = pthread_mutex_lock (&s->lock)) == 0)
|
||||
{
|
||||
/* See sem_destroy.c
|
||||
*/
|
||||
if (*sem == NULL)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
result = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s->value <= (SEM_VALUE_MAX - count))
|
||||
{
|
||||
waiters = -s->value;
|
||||
s->value += count;
|
||||
if (waiters > 0)
|
||||
{
|
||||
|
||||
pte_osSemaphorePost(s->sem, (waiters<=count)?waiters:count);
|
||||
result = 0;
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
s->value -= count;
|
||||
result = EINVAL;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ERANGE;
|
||||
}
|
||||
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
errno = result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sem_timedwait (sem_t * sem, const struct timespec *abstime)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function waits on a semaphore possibly until
|
||||
* 'abstime' time.
|
||||
*
|
||||
* PARAMETERS
|
||||
* sem
|
||||
* pointer to an instance of sem_t
|
||||
*
|
||||
* abstime
|
||||
* pointer to an instance of struct timespec
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function waits on a semaphore. If the
|
||||
* semaphore value is greater than zero, it decreases
|
||||
* its value by one. If the semaphore value is zero, then
|
||||
* the calling thread (or process) is blocked until it can
|
||||
* successfully decrease the value or until interrupted by
|
||||
* a signal.
|
||||
*
|
||||
* If 'abstime' is a NULL pointer then this function will
|
||||
* block until it can successfully decrease the value or
|
||||
* until interrupted by a signal.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully decreased semaphore,
|
||||
* -1 failed, error in errno
|
||||
* ERRNO
|
||||
* EINVAL 'sem' is not a valid semaphore,
|
||||
* ENOSYS semaphores are not supported,
|
||||
* EINTR the function was interrupted by a signal,
|
||||
* EDEADLK a deadlock condition was detected.
|
||||
* ETIMEDOUT abstime elapsed before success.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
sem_t s = *sem;
|
||||
|
||||
pthread_testcancel();
|
||||
|
||||
if (sem == NULL)
|
||||
result = EINVAL;
|
||||
else
|
||||
{
|
||||
unsigned int milliseconds;
|
||||
unsigned int *pTimeout;
|
||||
|
||||
if (abstime == NULL)
|
||||
{
|
||||
pTimeout = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Calculate timeout as milliseconds from current system time.
|
||||
*/
|
||||
milliseconds = pte_relmillisecs (abstime);
|
||||
pTimeout = &milliseconds;
|
||||
}
|
||||
|
||||
if ((result = pthread_mutex_lock (&s->lock)) == 0)
|
||||
{
|
||||
int v;
|
||||
|
||||
/* See sem_destroy.c
|
||||
*/
|
||||
if (*sem == NULL)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
v = --s->value;
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
|
||||
if (v < 0)
|
||||
{
|
||||
|
||||
{
|
||||
sem_timedwait_cleanup_args_t cleanup_args;
|
||||
|
||||
cleanup_args.sem = s;
|
||||
cleanup_args.resultPtr = &result;
|
||||
|
||||
/* Must wait */
|
||||
pthread_cleanup_push(pte_sem_timedwait_cleanup, (void *) &cleanup_args);
|
||||
|
||||
result = pte_cancellable_wait(s->sem,pTimeout);
|
||||
|
||||
pthread_cleanup_pop(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
|
||||
errno = result;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_trywait (sem_t * sem)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function tries to wait on a semaphore.
|
||||
*
|
||||
* PARAMETERS
|
||||
* sem
|
||||
* pointer to an instance of sem_t
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function tries to wait on a semaphore. If the
|
||||
* semaphore value is greater than zero, it decreases
|
||||
* its value by one. If the semaphore value is zero, then
|
||||
* this function returns immediately with the error EAGAIN
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully decreased semaphore,
|
||||
* -1 failed, error in errno
|
||||
* ERRNO
|
||||
* EAGAIN the semaphore was already locked,
|
||||
* EINVAL 'sem' is not a valid semaphore,
|
||||
* ENOTSUP sem_trywait is not supported,
|
||||
* EINTR the function was interrupted by a signal,
|
||||
* EDEADLK a deadlock condition was detected.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
sem_t s = *sem;
|
||||
|
||||
if (s == NULL)
|
||||
result = EINVAL;
|
||||
else if ((result = pthread_mutex_lock (&s->lock)) == 0)
|
||||
{
|
||||
/* See sem_destroy.c
|
||||
*/
|
||||
if (*sem == NULL)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s->value > 0)
|
||||
s->value--;
|
||||
else
|
||||
result = EAGAIN;
|
||||
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
errno = result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_unlink (const char *name)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sem_wait (sem_t * sem)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function waits on a semaphore.
|
||||
*
|
||||
* PARAMETERS
|
||||
* sem
|
||||
* pointer to an instance of sem_t
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function waits on a semaphore. If the
|
||||
* semaphore value is greater than zero, it decreases
|
||||
* its value by one. If the semaphore value is zero, then
|
||||
* the calling thread (or process) is blocked until it can
|
||||
* successfully decrease the value or until interrupted by
|
||||
* a signal.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully decreased semaphore,
|
||||
* -1 failed, error in errno
|
||||
* ERRNO
|
||||
* EINVAL 'sem' is not a valid semaphore,
|
||||
* ENOSYS semaphores are not supported,
|
||||
* EINTR the function was interrupted by a signal,
|
||||
* EDEADLK a deadlock condition was detected.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
sem_t s = *sem;
|
||||
|
||||
pthread_testcancel();
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
result = EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((result = pthread_mutex_lock (&s->lock)) == 0)
|
||||
{
|
||||
int v;
|
||||
|
||||
/* See sem_destroy.c
|
||||
*/
|
||||
if (*sem == NULL)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
v = --s->value;
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
|
||||
if (v < 0)
|
||||
{
|
||||
/* Must wait */
|
||||
pthread_cleanup_push(pte_sem_wait_cleanup, (void *) s);
|
||||
result = pte_cancellable_wait(s->sem,NULL);
|
||||
/* Cleanup if we're canceled or on any other error */
|
||||
pthread_cleanup_pop(result);
|
||||
|
||||
// Wait was cancelled, indicate that we're no longer waiting on this semaphore.
|
||||
/*
|
||||
if (result == PTE_OS_INTERRUPTED)
|
||||
{
|
||||
result = EINTR;
|
||||
++s->value;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
errno = result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
} /* sem_wait */
|
||||
|
||||
|
||||
int
|
||||
sem_wait_nocancel (sem_t * sem)
|
||||
/*
|
||||
* ------------------------------------------------------
|
||||
* DOCPUBLIC
|
||||
* This function waits on a semaphore, and doesn't
|
||||
* allow cancellation.
|
||||
*
|
||||
* PARAMETERS
|
||||
* sem
|
||||
* pointer to an instance of sem_t
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function waits on a semaphore. If the
|
||||
* semaphore value is greater than zero, it decreases
|
||||
* its value by one. If the semaphore value is zero, then
|
||||
* the calling thread (or process) is blocked until it can
|
||||
* successfully decrease the value or until interrupted by
|
||||
* a signal.
|
||||
*
|
||||
* RESULTS
|
||||
* 0 successfully decreased semaphore,
|
||||
* -1 failed, error in errno
|
||||
* ERRNO
|
||||
* EINVAL 'sem' is not a valid semaphore,
|
||||
* ENOSYS semaphores are not supported,
|
||||
* EINTR the function was interrupted by a signal,
|
||||
* EDEADLK a deadlock condition was detected.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int result = 0;
|
||||
sem_t s = *sem;
|
||||
|
||||
pthread_testcancel();
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
result = EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((result = pthread_mutex_lock (&s->lock)) == 0)
|
||||
{
|
||||
int v;
|
||||
|
||||
/* See sem_destroy.c
|
||||
*/
|
||||
if (*sem == NULL)
|
||||
{
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
v = --s->value;
|
||||
(void) pthread_mutex_unlock (&s->lock);
|
||||
|
||||
if (v < 0)
|
||||
{
|
||||
pte_osSemaphorePend(s->sem, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
errno = result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loaded 100 of 462 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user