Get pcid to work using this pthread impl.

4lDO2 b9f19f43 6a658bc3

+1
.gitignore
··· 6 6 *.patch 7 7 *.swp 8 8 *.swo 9 + /.vim
+152 -91
Cargo.lock
··· 8 8 source = "registry+https://github.com/rust-lang/crates.io-index" 9 9 checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 10 10 dependencies = [ 11 - "hermit-abi", 11 + "hermit-abi 0.1.19", 12 12 "libc", 13 13 "winapi", 14 14 ] ··· 35 35 "heck", 36 36 "indexmap", 37 37 "log", 38 - "proc-macro2 1.0.51", 39 - "quote 1.0.23", 38 + "proc-macro2 1.0.56", 39 + "quote 1.0.26", 40 40 "serde", 41 41 "serde_json", 42 42 "syn 1.0.109", ··· 110 110 111 111 [[package]] 112 112 name = "errno" 113 - version = "0.2.8" 113 + version = "0.3.1" 114 114 source = "registry+https://github.com/rust-lang/crates.io-index" 115 - checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" 115 + checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" 116 116 dependencies = [ 117 117 "errno-dragonfly", 118 118 "libc", 119 - "winapi", 119 + "windows-sys 0.48.0", 120 120 ] 121 121 122 122 [[package]] ··· 171 171 ] 172 172 173 173 [[package]] 174 + name = "hermit-abi" 175 + version = "0.3.1" 176 + source = "registry+https://github.com/rust-lang/crates.io-index" 177 + checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" 178 + 179 + [[package]] 174 180 name = "indexmap" 175 - version = "1.9.2" 181 + version = "1.9.3" 176 182 source = "registry+https://github.com/rust-lang/crates.io-index" 177 - checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 183 + checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 178 184 dependencies = [ 179 185 "autocfg", 180 186 "hashbrown", ··· 191 197 192 198 [[package]] 193 199 name = "io-lifetimes" 194 - version = "1.0.6" 200 + version = "1.0.10" 195 201 source = "registry+https://github.com/rust-lang/crates.io-index" 196 - checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" 202 + checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" 197 203 dependencies = [ 204 + "hermit-abi 0.3.1", 198 205 "libc", 199 - "windows-sys 0.45.0", 206 + "windows-sys 0.48.0", 200 207 ] 201 208 202 209 [[package]] ··· 220 227 221 228 [[package]] 222 229 name = "libc" 223 - version = "0.2.140" 230 + version = "0.2.141" 224 231 source = "registry+https://github.com/rust-lang/crates.io-index" 225 - checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" 232 + checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" 226 233 227 234 [[package]] 228 235 name = "linux-raw-sys" 229 - version = "0.1.4" 236 + version = "0.3.1" 230 237 source = "registry+https://github.com/rust-lang/crates.io-index" 231 - checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" 238 + checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" 232 239 233 240 [[package]] 234 241 name = "lock_api" ··· 275 282 276 283 [[package]] 277 284 name = "os_str_bytes" 278 - version = "6.4.1" 285 + version = "6.5.0" 279 286 source = "registry+https://github.com/rust-lang/crates.io-index" 280 - checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" 287 + checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" 281 288 282 289 [[package]] 283 290 name = "plain" ··· 300 307 301 308 [[package]] 302 309 name = "proc-macro2" 303 - version = "1.0.51" 310 + version = "1.0.56" 304 311 source = "registry+https://github.com/rust-lang/crates.io-index" 305 - checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" 312 + checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" 306 313 dependencies = [ 307 314 "unicode-ident", 308 315 ] ··· 318 325 319 326 [[package]] 320 327 name = "quote" 321 - version = "1.0.23" 328 + version = "1.0.26" 322 329 source = "registry+https://github.com/rust-lang/crates.io-index" 323 - checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 330 + checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" 324 331 dependencies = [ 325 - "proc-macro2 1.0.51", 332 + "proc-macro2 1.0.56", 326 333 ] 327 334 328 335 [[package]] ··· 371 378 dependencies = [ 372 379 "goblin", 373 380 "plain", 374 - "redox_syscall 0.3.4", 381 + "redox_syscall 0.3.5", 375 382 ] 376 383 377 384 [[package]] ··· 382 389 383 390 [[package]] 384 391 name = "redox_syscall" 385 - version = "0.2.16" 386 - source = "registry+https://github.com/rust-lang/crates.io-index" 387 - checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 388 - dependencies = [ 389 - "bitflags", 390 - ] 391 - 392 - [[package]] 393 - name = "redox_syscall" 394 - version = "0.3.4" 392 + version = "0.3.5" 395 393 source = "registry+https://github.com/rust-lang/crates.io-index" 396 - checksum = "fb02a9aee8e8c7ad8d86890f1e16b49e0bbbffc9961ff3788c31d57c98bcbf03" 394 + checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 397 395 dependencies = [ 398 396 "bitflags", 399 397 ] ··· 402 400 name = "relibc" 403 401 version = "0.2.5" 404 402 dependencies = [ 403 + "bitflags", 405 404 "cbindgen", 406 405 "cbitset", 407 406 "cc", ··· 415 414 "ralloc", 416 415 "rand", 417 416 "redox-exec", 418 - "redox_syscall 0.3.4", 417 + "redox_syscall 0.3.5", 419 418 "sc", 420 - "spin 0.9.5", 419 + "spin 0.9.8", 421 420 "unicode-width", 422 421 ] 423 422 ··· 441 440 442 441 [[package]] 443 442 name = "rustix" 444 - version = "0.36.9" 443 + version = "0.37.11" 445 444 source = "registry+https://github.com/rust-lang/crates.io-index" 446 - checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" 445 + checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" 447 446 dependencies = [ 448 447 "bitflags", 449 448 "errno", 450 449 "io-lifetimes", 451 450 "libc", 452 451 "linux-raw-sys", 453 - "windows-sys 0.45.0", 452 + "windows-sys 0.48.0", 454 453 ] 455 454 456 455 [[package]] ··· 515 514 516 515 [[package]] 517 516 name = "serde" 518 - version = "1.0.154" 517 + version = "1.0.160" 519 518 source = "registry+https://github.com/rust-lang/crates.io-index" 520 - checksum = "8cdd151213925e7f1ab45a9bbfb129316bd00799784b174b7cc7bcd16961c49e" 519 + checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" 521 520 dependencies = [ 522 521 "serde_derive", 523 522 ] 524 523 525 524 [[package]] 526 525 name = "serde_derive" 527 - version = "1.0.154" 526 + version = "1.0.160" 528 527 source = "registry+https://github.com/rust-lang/crates.io-index" 529 - checksum = "4fc80d722935453bcafdc2c9a73cd6fac4dc1938f0346035d84bf99fa9e33217" 528 + checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" 530 529 dependencies = [ 531 - "proc-macro2 1.0.51", 532 - "quote 1.0.23", 533 - "syn 1.0.109", 530 + "proc-macro2 1.0.56", 531 + "quote 1.0.26", 532 + "syn 2.0.15", 534 533 ] 535 534 536 535 [[package]] 537 536 name = "serde_json" 538 - version = "1.0.94" 537 + version = "1.0.96" 539 538 source = "registry+https://github.com/rust-lang/crates.io-index" 540 - checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" 539 + checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" 541 540 dependencies = [ 542 541 "itoa", 543 542 "ryu", ··· 552 551 553 552 [[package]] 554 553 name = "spin" 555 - version = "0.9.5" 554 + version = "0.9.8" 556 555 source = "registry+https://github.com/rust-lang/crates.io-index" 557 - checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" 556 + checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 558 557 dependencies = [ 559 558 "lock_api", 560 559 ] ··· 582 581 source = "registry+https://github.com/rust-lang/crates.io-index" 583 582 checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 584 583 dependencies = [ 585 - "proc-macro2 1.0.51", 586 - "quote 1.0.23", 584 + "proc-macro2 1.0.56", 585 + "quote 1.0.26", 586 + "unicode-ident", 587 + ] 588 + 589 + [[package]] 590 + name = "syn" 591 + version = "2.0.15" 592 + source = "registry+https://github.com/rust-lang/crates.io-index" 593 + checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" 594 + dependencies = [ 595 + "proc-macro2 1.0.56", 596 + "quote 1.0.26", 587 597 "unicode-ident", 588 598 ] 589 599 590 600 [[package]] 591 601 name = "tempfile" 592 - version = "3.4.0" 602 + version = "3.5.0" 593 603 source = "registry+https://github.com/rust-lang/crates.io-index" 594 - checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" 604 + checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" 595 605 dependencies = [ 596 606 "cfg-if", 597 607 "fastrand", 598 - "redox_syscall 0.2.16", 608 + "redox_syscall 0.3.5", 599 609 "rustix", 600 - "windows-sys 0.42.0", 610 + "windows-sys 0.45.0", 601 611 ] 602 612 603 613 [[package]] ··· 681 691 682 692 [[package]] 683 693 name = "windows-sys" 684 - version = "0.42.0" 694 + version = "0.45.0" 685 695 source = "registry+https://github.com/rust-lang/crates.io-index" 686 - checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 696 + checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 687 697 dependencies = [ 688 - "windows_aarch64_gnullvm", 689 - "windows_aarch64_msvc", 690 - "windows_i686_gnu", 691 - "windows_i686_msvc", 692 - "windows_x86_64_gnu", 693 - "windows_x86_64_gnullvm", 694 - "windows_x86_64_msvc", 698 + "windows-targets 0.42.2", 695 699 ] 696 700 697 701 [[package]] 698 702 name = "windows-sys" 699 - version = "0.45.0" 703 + version = "0.48.0" 704 + source = "registry+https://github.com/rust-lang/crates.io-index" 705 + checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 706 + dependencies = [ 707 + "windows-targets 0.48.0", 708 + ] 709 + 710 + [[package]] 711 + name = "windows-targets" 712 + version = "0.42.2" 700 713 source = "registry+https://github.com/rust-lang/crates.io-index" 701 - checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 714 + checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 702 715 dependencies = [ 703 - "windows-targets", 716 + "windows_aarch64_gnullvm 0.42.2", 717 + "windows_aarch64_msvc 0.42.2", 718 + "windows_i686_gnu 0.42.2", 719 + "windows_i686_msvc 0.42.2", 720 + "windows_x86_64_gnu 0.42.2", 721 + "windows_x86_64_gnullvm 0.42.2", 722 + "windows_x86_64_msvc 0.42.2", 704 723 ] 705 724 706 725 [[package]] 707 726 name = "windows-targets" 708 - version = "0.42.1" 727 + version = "0.48.0" 709 728 source = "registry+https://github.com/rust-lang/crates.io-index" 710 - checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" 729 + checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" 711 730 dependencies = [ 712 - "windows_aarch64_gnullvm", 713 - "windows_aarch64_msvc", 714 - "windows_i686_gnu", 715 - "windows_i686_msvc", 716 - "windows_x86_64_gnu", 717 - "windows_x86_64_gnullvm", 718 - "windows_x86_64_msvc", 731 + "windows_aarch64_gnullvm 0.48.0", 732 + "windows_aarch64_msvc 0.48.0", 733 + "windows_i686_gnu 0.48.0", 734 + "windows_i686_msvc 0.48.0", 735 + "windows_x86_64_gnu 0.48.0", 736 + "windows_x86_64_gnullvm 0.48.0", 737 + "windows_x86_64_msvc 0.48.0", 719 738 ] 720 739 721 740 [[package]] 722 741 name = "windows_aarch64_gnullvm" 723 - version = "0.42.1" 742 + version = "0.42.2" 743 + source = "registry+https://github.com/rust-lang/crates.io-index" 744 + checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 745 + 746 + [[package]] 747 + name = "windows_aarch64_gnullvm" 748 + version = "0.48.0" 749 + source = "registry+https://github.com/rust-lang/crates.io-index" 750 + checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" 751 + 752 + [[package]] 753 + name = "windows_aarch64_msvc" 754 + version = "0.42.2" 724 755 source = "registry+https://github.com/rust-lang/crates.io-index" 725 - checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" 756 + checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 726 757 727 758 [[package]] 728 759 name = "windows_aarch64_msvc" 729 - version = "0.42.1" 760 + version = "0.48.0" 730 761 source = "registry+https://github.com/rust-lang/crates.io-index" 731 - checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" 762 + checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" 732 763 733 764 [[package]] 734 765 name = "windows_i686_gnu" 735 - version = "0.42.1" 766 + version = "0.42.2" 736 767 source = "registry+https://github.com/rust-lang/crates.io-index" 737 - checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" 768 + checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 769 + 770 + [[package]] 771 + name = "windows_i686_gnu" 772 + version = "0.48.0" 773 + source = "registry+https://github.com/rust-lang/crates.io-index" 774 + checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" 738 775 739 776 [[package]] 740 777 name = "windows_i686_msvc" 741 - version = "0.42.1" 778 + version = "0.42.2" 779 + source = "registry+https://github.com/rust-lang/crates.io-index" 780 + checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 781 + 782 + [[package]] 783 + name = "windows_i686_msvc" 784 + version = "0.48.0" 742 785 source = "registry+https://github.com/rust-lang/crates.io-index" 743 - checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" 786 + checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" 744 787 745 788 [[package]] 746 789 name = "windows_x86_64_gnu" 747 - version = "0.42.1" 790 + version = "0.42.2" 791 + source = "registry+https://github.com/rust-lang/crates.io-index" 792 + checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 793 + 794 + [[package]] 795 + name = "windows_x86_64_gnu" 796 + version = "0.48.0" 748 797 source = "registry+https://github.com/rust-lang/crates.io-index" 749 - checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" 798 + checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" 750 799 751 800 [[package]] 752 801 name = "windows_x86_64_gnullvm" 753 - version = "0.42.1" 802 + version = "0.42.2" 754 803 source = "registry+https://github.com/rust-lang/crates.io-index" 755 - checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" 804 + checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 805 + 806 + [[package]] 807 + name = "windows_x86_64_gnullvm" 808 + version = "0.48.0" 809 + source = "registry+https://github.com/rust-lang/crates.io-index" 810 + checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" 756 811 757 812 [[package]] 758 813 name = "windows_x86_64_msvc" 759 - version = "0.42.1" 814 + version = "0.42.2" 815 + source = "registry+https://github.com/rust-lang/crates.io-index" 816 + checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 817 + 818 + [[package]] 819 + name = "windows_x86_64_msvc" 820 + version = "0.48.0" 760 821 source = "registry+https://github.com/rust-lang/crates.io-index" 761 - checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" 822 + checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+2
Cargo.toml
··· 15 15 [build-dependencies] 16 16 cbindgen = "0.24.3" 17 17 cc = "1.0.25" 18 + #env_logger = "0.10" 18 19 19 20 [dependencies] 21 + bitflags = "1" 20 22 cbitset = "0.1.0" 21 23 core_io = { path = "core_io", features = ["collections"] } 22 24 lazy_static = { version = "1.4.0", default-features = false, features = ["spin_no_std"] }
+37
src/header/bits_pthread/cbindgen.toml
··· 1 + sys_includes = ["bits/sched.h"] 2 + include_guard = "_RELIBC_BITS_PTHREAD_H" 3 + language = "C" 4 + style = "type" 5 + no_includes = true 6 + cpp_compat = true 7 + trailer = """ 8 + #define PTHREAD_COND_INITIALIZER {0} 9 + #define PTHREAD_MUTEX_INITIALIZER {0} 10 + #define PTHREAD_ONCE_INIT {0} 11 + #define PTHREAD_RWLOCK_INITIALIZER {0} 12 + """ 13 + 14 + [export.rename] 15 + "sched_param" = "struct sched_param" 16 + "AtomicInt" = "int" 17 + "AtomicUint" = "unsigned" 18 + 19 + [export] 20 + include = [ 21 + "pthread_attr_t", 22 + "pthread_rwlockattr_t", 23 + "pthread_rwlock_t", 24 + "pthread_barrier_t", 25 + "pthread_barrierattr_t", 26 + "pthread_mutex_t", 27 + "pthread_mutexattr_t", 28 + "pthread_condattr_t", 29 + "pthread_cond_t", 30 + "pthread_spinlock_t", 31 + "pthread_once_t", 32 + "pthread_t", 33 + "pthread_key_t", 34 + ] 35 + 36 + [enum] 37 + prefix_with_name = true
+81
src/header/bits_pthread/mod.rs
··· 1 + #![allow(non_camel_case_types)] 2 + 3 + use crate::platform::types::*; 4 + 5 + use crate::header::sched::sched_param; 6 + 7 + use crate::sync::AtomicLock; 8 + use core::sync::atomic::{AtomicU32 as AtomicUint, AtomicI32 as AtomicInt}; 9 + 10 + #[repr(C)] 11 + #[derive(Clone, Copy)] 12 + pub struct pthread_attr_t { 13 + pub detachstate: c_uchar, 14 + pub inheritsched: c_uchar, 15 + pub schedpolicy: c_uchar, 16 + pub scope: c_uchar, 17 + pub guardsize: size_t, 18 + pub stacksize: size_t, 19 + pub stack: size_t, 20 + pub param: sched_param, 21 + } 22 + 23 + #[repr(C)] 24 + pub struct pthread_rwlockattr_t { 25 + pub pshared: c_int, 26 + } 27 + 28 + #[repr(C)] 29 + pub struct pthread_rwlock_t { 30 + pub state: AtomicInt, 31 + } 32 + 33 + #[repr(C)] 34 + pub struct pthread_barrier_t { 35 + pub count: AtomicUint, 36 + pub original_count: c_uint, 37 + pub epoch: AtomicInt, 38 + } 39 + 40 + #[repr(C)] 41 + pub struct pthread_barrierattr_t { 42 + pub pshared: c_int, 43 + } 44 + 45 + #[repr(C)] 46 + pub struct pthread_mutex_t { 47 + pub inner: AtomicInt, 48 + } 49 + 50 + #[repr(C)] 51 + pub struct pthread_mutexattr_t { 52 + pub prioceiling: c_int, 53 + pub protocol: c_int, 54 + pub pshared: c_int, 55 + pub robust: c_int, 56 + pub ty: c_int, 57 + } 58 + 59 + #[repr(C)] 60 + pub struct pthread_condattr_t { 61 + pub clock: clockid_t, 62 + pub pshared: c_int, 63 + } 64 + 65 + #[repr(C)] 66 + pub struct pthread_cond_t { 67 + pub cur: AtomicInt, 68 + pub prev: AtomicInt, 69 + } 70 + #[repr(C)] 71 + pub struct pthread_spinlock_t { 72 + pub inner: AtomicInt, 73 + } 74 + 75 + #[repr(C)] 76 + pub struct pthread_once_t { 77 + pub inner: AtomicInt, 78 + } 79 + 80 + pub type pthread_t = *mut (); 81 + pub type pthread_key_t = c_ulong;
+11
src/header/bits_sched/cbindgen.toml
··· 1 + sys_includes = [] 2 + include_guard = "_RELIBC_BITS_SCHED_H" 3 + language = "C" 4 + style = "tag" 5 + no_includes = true 6 + cpp_compat = true 7 + 8 + [export] 9 + include = [ 10 + "sched_param", 11 + ]
+9
src/header/bits_sched/mod.rs
··· 1 + #![allow(non_camel_case_types)] 2 + 3 + use crate::platform::types::*; 4 + 5 + #[repr(C)] 6 + #[derive(Clone, Copy, Debug)] 7 + pub struct sched_param { 8 + pub sched_priority: c_int, 9 + }
+2
src/header/mod.rs
··· 2 2 pub mod _fenv; 3 3 pub mod arpa_inet; 4 4 pub mod assert; 5 + pub mod bits_pthread; 6 + pub mod bits_sched; 5 7 pub mod ctype; 6 8 pub mod dirent; 7 9 #[path = "dl-tls/mod.rs"]
+1 -1
src/header/netdb/dns/mod.rs
··· 25 25 26 26 impl n16 { 27 27 pub fn as_bytes(&self) -> &[u8] { 28 - unsafe { slice::from_raw_parts((&self.inner as *const u16) as *const u8, 2) } 28 + unsafe { slice::from_raw_parts(core::ptr::addr_of!(self.inner).cast::<u8>(), 2) } 29 29 } 30 30 31 31 pub fn from_bytes(bytes: &[u8]) -> Self {
+4 -14
src/header/pthread/attr.rs
··· 1 1 use super::*; 2 2 3 - #[repr(C)] 4 - #[derive(Clone, Copy)] 5 - pub struct Attr { 6 - pub detachstate: u8, 7 - pub inheritsched: u8, 8 - pub schedpolicy: u8, 9 - pub scope: u8, 10 - pub guardsize: usize, 11 - pub stacksize: usize, 12 - pub stack: usize, 13 - pub param: sched_param, 14 - } 15 - impl Default for Attr { 3 + use crate::header::bits_pthread::pthread_attr_t; 4 + 5 + impl Default for pthread_attr_t { 16 6 fn default() -> Self { 17 7 Self { 18 8 // Default according to POSIX. ··· 93 83 94 84 #[no_mangle] 95 85 pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int { 96 - core::ptr::write(attr, Attr::default()); 86 + core::ptr::write(attr, pthread_attr_t::default()); 97 87 0 98 88 } 99 89
+4 -17
src/header/pthread/barrier.rs
··· 1 1 use crate::header::errno::*; 2 2 3 - use crate::sync::AtomicLock; 4 - use core::sync::atomic::{AtomicU32, Ordering}; 3 + use core::sync::atomic::{AtomicU32, AtomicI32 as AtomicInt, Ordering}; 5 4 6 5 use super::*; 7 6 8 - #[repr(C)] 9 - pub struct Barrier { 10 - count: AtomicU32, 11 - original_count: u32, 12 - epoch: AtomicLock, 13 - } 14 - 15 - #[repr(C)] 16 - pub struct BarrierAttr { 17 - pshared: c_int, 18 - } 19 - 20 7 #[no_mangle] 21 8 pub unsafe extern "C" fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> c_int { 22 9 // Behavior is undefined if any thread is currently waiting. ··· 29 16 return EINVAL; 30 17 } 31 18 32 - core::ptr::write(barrier, Barrier { 19 + core::ptr::write(barrier, pthread_barrier_t { 33 20 count: AtomicU32::new(0), 34 21 original_count: count, 35 - epoch: AtomicLock::new(0), 22 + epoch: AtomicInt::new(0), 36 23 }); 37 24 0 38 25 } ··· 73 60 #[no_mangle] 74 61 pub unsafe extern "C" fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int { 75 62 // PTHREAD_PROCESS_PRIVATE is default according to POSIX. 76 - core::ptr::write(attr, BarrierAttr { pshared: PTHREAD_PROCESS_PRIVATE }); 63 + core::ptr::write(attr, pthread_barrierattr_t { pshared: PTHREAD_PROCESS_PRIVATE }); 77 64 78 65 0 79 66 }
+6 -2
src/header/pthread/cbindgen.toml
··· 1 - sys_includes = ["sched.h", "time.h"] 1 + sys_includes = ["sched.h", "time.h", "bits/pthread.h"] 2 2 include_guard = "_RELIBC_PTHREAD_H" 3 3 language = "C" 4 - style = "Tag" 4 + style = "tag" 5 5 no_includes = true 6 6 cpp_compat = true 7 + 8 + [export.rename] 9 + "sched_param" = "struct sched_param" 10 + "timespec" = "struct timespec" 7 11 8 12 [enum] 9 13 prefix_with_name = true
+6 -19
src/header/pthread/cond.rs
··· 6 6 7 7 // PTHREAD_COND_INITIALIZER 8 8 9 - #[repr(C)] 10 - pub struct CondAttr { 11 - clock: clockid_t, 12 - pshared: c_int, 13 - } 14 - 15 - #[repr(C)] 16 - pub struct Cond { 17 - cur: AtomicInt, 18 - prev: AtomicInt, 19 - } 20 - 21 9 #[no_mangle] 22 10 pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int { 23 11 wake(cond, i32::MAX) ··· 43 31 44 32 #[no_mangle] 45 33 pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, _attr: *const pthread_condattr_t) -> c_int { 46 - cond.write(Cond { 34 + cond.write(pthread_cond_t { 47 35 cur: AtomicInt::new(0), 48 36 prev: AtomicInt::new(0), 49 37 }); ··· 56 44 } 57 45 58 46 #[no_mangle] 59 - pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex_ptr: *const pthread_mutex_t, timeout: *const timespec) -> c_int { 47 + pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex_ptr: *mut pthread_mutex_t, timeout: *const timespec) -> c_int { 60 48 // TODO: Error checking for certain types (i.e. robust and errorcheck) of mutexes, e.g. if the 61 49 // mutex is not locked. 62 50 let cond: &pthread_cond_t = &*cond; 63 - let mutex: &pthread_mutex_t = &*mutex_ptr; 64 51 let timeout: Option<&timespec> = timeout.as_ref(); 65 52 66 53 let current = cond.cur.load(Ordering::Relaxed); 67 54 cond.prev.store(current, Ordering::SeqCst); 68 55 69 - mutex.inner.manual_unlock(); 56 + pthread_mutex_unlock(mutex_ptr); 70 57 crate::sync::futex_wait(&cond.cur, current, timeout); 71 - mutex.inner.manual_lock(); 58 + pthread_mutex_lock(mutex_ptr); 72 59 73 60 0 74 61 } 75 62 76 63 #[no_mangle] 77 - pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *const pthread_mutex_t) -> c_int { 64 + pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t) -> c_int { 78 65 pthread_cond_timedwait(cond, mutex, core::ptr::null()) 79 66 } 80 67 ··· 97 84 98 85 #[no_mangle] 99 86 pub unsafe extern "C" fn pthread_condattr_init(condattr: *mut pthread_condattr_t) -> c_int { 100 - core::ptr::write(condattr, CondAttr { 87 + core::ptr::write(condattr, pthread_condattr_t { 101 88 // FIXME: system clock 102 89 clock: 0, 103 90 // Default
+1
src/header/pthread/mod.rs
··· 126 126 pub mod rwlock; 127 127 pub use self::rwlock::*; 128 128 129 + #[no_mangle] 129 130 pub unsafe extern "C" fn pthread_self() -> pthread_t { 130 131 pthread::current_thread().unwrap_unchecked() as *const _ as *mut _ 131 132 }
+9 -22
src/header/pthread/mutex.rs
··· 4 4 5 5 // PTHREAD_MUTEX_INITIALIZER 6 6 7 - #[repr(C)] 8 - pub struct Mutex { 9 - pub(crate) inner: crate::sync::Mutex<()>, 10 - } 11 - 12 - #[repr(C)] 13 - pub struct MutexAttr { 14 - prioceiling: c_int, 15 - protocol: c_int, 16 - pshared: c_int, 17 - robust: c_int, 18 - ty: c_int, 19 - } 20 - 21 7 // #[no_mangle] 22 8 pub extern "C" fn pthread_mutex_consistent(mutex: *mut pthread_mutex_t) -> c_int { 23 9 todo!(); ··· 36 22 #[no_mangle] 37 23 pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, _attr: *const pthread_mutexattr_t) -> c_int { 38 24 // TODO: attr 39 - mutex.write(Mutex { 40 - inner: crate::sync::Mutex::new(()), 25 + mutex.write(pthread_mutex_t { 26 + inner: crate::sync::mutex::UNLOCKED.into(), 41 27 }); 42 28 0 43 29 } 44 30 #[no_mangle] 45 31 pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int { 46 - (&*mutex).inner.manual_lock(); 32 + crate::sync::mutex::manual_lock_generic(&(&*mutex).inner); 47 33 48 34 0 49 35 } ··· 59 45 } 60 46 #[no_mangle] 61 47 pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int { 62 - match (&*mutex).inner.manual_try_lock() { 63 - Ok(_) => 0, 64 - Err(_) => EBUSY, 48 + if crate::sync::mutex::manual_try_lock_generic(&(&*mutex).inner) { 49 + 0 50 + } else { 51 + EBUSY 65 52 } 66 53 } 67 54 #[no_mangle] 68 55 pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int { 69 - (&*mutex).inner.manual_unlock(); 56 + crate::sync::mutex::manual_unlock_generic(&(&*mutex).inner); 70 57 0 71 58 } 72 59 ··· 105 92 } 106 93 #[no_mangle] 107 94 pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int { 108 - attr.write(MutexAttr { 95 + attr.write(pthread_mutexattr_t { 109 96 robust: PTHREAD_MUTEX_STALLED, 110 97 pshared: PTHREAD_PROCESS_PRIVATE, 111 98 protocol: PTHREAD_PRIO_NONE,
+1 -6
src/header/pthread/once.rs
··· 1 1 use super::*; 2 2 3 - #[repr(C)] 4 - pub struct Once { 5 - inner: crate::sync::Once<()>, 6 - } 7 - 8 3 // PTHREAD_ONCE_INIT 9 4 10 5 #[no_mangle] ··· 12 7 let once: &pthread_once_t = &*once; 13 8 14 9 // TODO: Cancellation points 15 - once.inner.call_once(|| constructor()); 10 + crate::sync::once::call_once_generic(&once.inner, || constructor()); 16 11 17 12 0 18 13 }
+17 -19
src/header/pthread/rwlock.rs
··· 1 1 use super::*; 2 2 3 - use crate::sync::AtomicLock; 4 - use core::sync::atomic::Ordering; 3 + use core::sync::atomic::{AtomicI32 as AtomicInt, Ordering}; 5 4 6 5 use crate::header::errno::EBUSY; 7 6 ··· 15 14 // Separate "waiting for wrlocks" and "waiting for rdlocks"? 16 15 //const WAITING: u32 = 1 << (u32::BITS - 1); 17 16 18 - #[repr(C)] 19 - pub struct Rwlock { 20 - state: AtomicLock, 21 - } 22 - 23 - #[repr(C)] 24 - pub struct RwlockAttr { 25 - pshared: c_int, 26 - } 27 - 28 17 #[no_mangle] 29 18 pub unsafe extern "C" fn pthread_rwlock_destroy(rwlock: *mut pthread_rwlock_t) -> c_int { 30 19 // (Informing the compiler that this pointer is valid, might improve optimizations.) ··· 33 22 } 34 23 #[no_mangle] 35 24 pub unsafe extern "C" fn pthread_rwlock_init(rwlock: *mut pthread_rwlock_t, _attr: *const pthread_rwlockattr_t) -> c_int { 36 - core::ptr::write(rwlock, Rwlock { 37 - state: AtomicLock::new(0), 25 + core::ptr::write(rwlock, pthread_rwlock_t { 26 + state: AtomicInt::new(0), 38 27 }); 39 28 40 29 0 ··· 50 39 51 40 loop { 52 41 if pthread_rwlock_tryrdlock(rwlock as *const _ as *mut _) == EBUSY { 53 - rwlock.state.wait_if(EXCLUSIVE as i32, timeout); 42 + crate::sync::futex_wait(&rwlock.state, EXCLUSIVE as i32, timeout); 54 43 } 55 44 return 0; 56 45 } ··· 60 49 let rwlock: &pthread_rwlock_t = &*rwlock; 61 50 let timeout = timeout.as_ref(); 62 51 63 - loop { 52 + /*loop { 64 53 if pthread_rwlock_trywrlock(rwlock as *const _ as *mut _) == EBUSY { 65 - rwlock.state.wait_if(EXCLUSIVE as i32, timeout); 54 + crate::sync::futex_wait(&rwlock.state, EXCLUSIVE as i32, timeout); 66 55 } 67 56 return 0; 57 + }*/ 58 + loop { 59 + match rwlock.state.compare_exchange(0, EXCLUSIVE as i32, Ordering::Acquire, Ordering::Relaxed) { 60 + Ok(_) => return 0, 61 + Err(value) => { 62 + // TODO: More than just forwarding the timeout. 63 + crate::sync::futex_wait(&rwlock.state, value, timeout); 64 + } 65 + } 68 66 } 69 67 } 70 68 #[no_mangle] ··· 105 103 let old = rwlock.state.swap(0, Ordering::Release) as u32; 106 104 107 105 if old == EXCLUSIVE { 108 - rwlock.state.notify_all(); 106 + crate::sync::futex_wake(&rwlock.state, i32::MAX); 109 107 } 110 108 111 109 0 ··· 129 127 130 128 #[no_mangle] 131 129 pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int { 132 - core::ptr::write(attr, RwlockAttr { 130 + core::ptr::write(attr, pthread_rwlockattr_t { 133 131 // Default according to POSIX. 134 132 pshared: PTHREAD_PROCESS_PRIVATE, 135 133 });
+4 -9
src/header/pthread/spin.rs
··· 4 4 5 5 use super::*; 6 6 7 - #[repr(C)] 8 - pub struct Spinlock { 9 - inner: AtomicInt, 10 - } 11 - 12 7 pub const UNLOCKED: c_int = 0; 13 8 pub const LOCKED: c_int = 1; 14 9 ··· 19 14 // TODO: pshared doesn't matter in most situations, as memory is just memory, but this may be 20 15 // different on some architectures... 21 16 22 - core::ptr::write(spinlock, Spinlock { inner: AtomicInt::new(UNLOCKED) }); 17 + core::ptr::write(spinlock, pthread_spinlock_t { inner: AtomicInt::new(UNLOCKED) }); 23 18 24 19 0 25 20 } 26 21 pub unsafe extern "C" fn pthread_spin_lock(spinlock: *mut pthread_spinlock_t) -> c_int { 27 - let spinlock: &Spinlock = &*spinlock; 22 + let spinlock: &pthread_spinlock_t = &*spinlock; 28 23 29 24 loop { 30 25 match spinlock.inner.compare_exchange_weak(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed) { ··· 34 29 } 35 30 } 36 31 pub unsafe extern "C" fn pthread_spin_trylock(spinlock: *mut pthread_spinlock_t) -> c_int { 37 - let spinlock: &Spinlock = &*spinlock; 32 + let spinlock: &pthread_spinlock_t = &*spinlock; 38 33 39 34 match spinlock.inner.compare_exchange(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed) { 40 35 Ok(_) => 0, ··· 42 37 } 43 38 } 44 39 pub unsafe extern "C" fn pthread_spin_unlock(spinlock: *mut pthread_spinlock_t) -> c_int { 45 - let spinlock: &Spinlock = &*spinlock; 40 + let spinlock: &pthread_spinlock_t = &*spinlock; 46 41 47 42 spinlock.inner.store(UNLOCKED, Ordering::Release); 48 43
+34 -11
src/header/pthread/tls.rs
··· 6 6 use core::cell::{Cell, RefCell}; 7 7 8 8 use crate::header::errno::EINVAL; 9 + use crate::sync::Mutex; 9 10 10 11 // TODO: What should this limit be? 11 12 pub const PTHREAD_KEYS_MAX: u32 = 4096 * 32; 12 13 13 14 #[no_mangle] 14 15 pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void { 15 - let Some(&Record { data, .. }) = DICT.borrow_mut().get(&key) else { 16 + //print!("pthread_getspecific key={:#0x}: ", key); 17 + 18 + // TODO: Right? 19 + if !KEYS.lock().contains_key(&key) { 20 + //println!("= not found"); 21 + return core::ptr::null_mut(); 22 + } 23 + 24 + let Some(&Record { data, .. }) = VALUES.borrow_mut().get(&key) else { 25 + //println!("= NULL"); 16 26 return core::ptr::null_mut(); 17 27 }; 28 + //println!("= {:p}", data); 18 29 19 30 data 20 31 } ··· 22 33 pub unsafe extern "C" fn pthread_key_create(key_ptr: *mut pthread_key_t, destructor: extern "C" fn(value: *mut c_void)) -> c_int { 23 34 let key = NEXTKEY.get(); 24 35 NEXTKEY.set(key + 1); 36 + //println!("pthread_key_create new key {:#0x}, dtor {:p}", key, destructor); 25 37 26 38 // TODO 27 39 //if key >= PTHREAD_KEYS_MAX { 28 40 //} 29 41 30 - DICT.borrow_mut().insert(key, Record { 42 + KEYS.lock().insert(key, Dtor { destructor }); 43 + 44 + VALUES.borrow_mut().insert(key, Record { 31 45 data: core::ptr::null_mut(), 32 - destructor, 33 46 }); 34 47 35 48 key_ptr.write(key); ··· 39 52 40 53 #[no_mangle] 41 54 pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int { 42 - if DICT.borrow_mut().remove(&key).is_none() { 55 + if KEYS.lock().remove(&key).is_none() || VALUES.borrow_mut().remove(&key).is_none() { 43 56 // We don't have to return anything, but it's not less expensive to ignore it. 44 57 return EINVAL; 45 58 } 59 + //println!("pthread_key_delete {:#0x}", key); 46 60 47 61 0 48 62 } 49 63 50 64 #[no_mangle] 51 65 pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int { 52 - let mut guard = DICT.borrow_mut(); 53 - 54 - let Some(Record { data, .. }) = guard.get_mut(&key) else { 66 + if !KEYS.lock().contains_key(&key) { 55 67 // We don't have to return anything, but it's not less expensive to ignore it. 68 + //println!("Invalid key for pthread_setspecific key {:#0x} value {:p}", key, value); 56 69 return EINVAL; 57 - }; 70 + } 71 + 72 + let mut guard = VALUES.borrow_mut(); 73 + 74 + let Record { ref mut data, .. } = guard.entry(key).or_insert(Record { data: core::ptr::null_mut() }); 75 + //println!("Valid key for pthread_setspecific key {:#0x} value {:p} (was {:p})", key, value, *data); 58 76 59 77 *data = value as *mut c_void; 60 78 61 79 0 62 80 } 63 81 82 + static KEYS: Mutex<BTreeMap<pthread_key_t, Dtor>> = Mutex::new(BTreeMap::new()); 83 + 84 + struct Dtor { 85 + destructor: extern "C" fn(value: *mut c_void) 86 + } 87 + 64 88 #[thread_local] 65 - static DICT: RefCell<BTreeMap<u32, Record>> = RefCell::new(BTreeMap::new()); 89 + static VALUES: RefCell<BTreeMap<pthread_key_t, Record>> = RefCell::new(BTreeMap::new()); 66 90 67 91 struct Record { 68 92 data: *mut c_void, 69 - destructor: extern "C" fn(value: *mut c_void), 70 93 } 71 94 72 95 #[thread_local] 73 - static NEXTKEY: Cell<u32> = Cell::new(1); 96 + static NEXTKEY: Cell<pthread_key_t> = Cell::new(1);
+1 -1
src/header/sched/cbindgen.toml
··· 1 - sys_includes = ["time.h"] 1 + sys_includes = ["time.h", "bits/sched.h"] 2 2 include_guard = "_RELIBC_SCHED_H" 3 3 language = "C" 4 4 style = "Tag"
+1 -5
src/header/sched/mod.rs
··· 3 3 use crate::platform::{Pal, Sys, types::*}; 4 4 use crate::header::time::timespec; 5 5 6 - #[repr(C)] 7 - #[derive(Clone, Copy, Debug)] 8 - pub struct sched_param { 9 - pub sched_priority: c_int, 10 - } 6 + pub use crate::header::bits_sched::sched_param; 11 7 12 8 pub const SCHED_FIFO: c_int = 0; 13 9 pub const SCHED_RR: c_int = 1;
+1 -2
src/header/stdlib/mod.rs
··· 275 275 static __fini_array_start: extern "C" fn(); 276 276 static __fini_array_end: extern "C" fn(); 277 277 278 - fn pthread_terminate(); 279 278 fn _fini(); 280 279 } 281 280 ··· 297 296 298 297 ld_so::fini(); 299 298 300 - pthread_terminate(); 299 + crate::pthread::terminate_from_main_thread(); 301 300 302 301 flush_io_streams(); 303 302
+2 -1
src/header/sys_types/cbindgen.toml
··· 5 5 "sys/types_internal.h", 6 6 7 7 "stddef.h", 8 - "sys/select.h" 8 + "sys/select.h", 9 + "bits/pthread.h", 9 10 ] 10 11 11 12 include_guard = "_SYS_TYPES_H"
+15 -15
src/platform/redox/clone.rs
··· 14 14 pub use redox_exec::*; 15 15 16 16 /// Spawns a new context sharing the same address space as the current one (i.e. a new thread). 17 - pub unsafe fn pte_clone_impl(stack: *mut usize) -> Result<usize> { 17 + pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result<usize> { 18 18 let cur_pid_fd = FdGuard::new(syscall::open("thisproc:current/open_via_dup", O_CLOEXEC)?); 19 19 let (new_pid_fd, new_pid) = new_context()?; 20 20 ··· 47 47 48 48 let buf = create_set_addr_space_buf( 49 49 *cur_addr_space_fd, 50 - __relibc_internal_pte_clone_ret as usize, 50 + __relibc_internal_rlct_clone_ret as usize, 51 51 stack as usize, 52 52 ); 53 53 let _ = syscall::write(*new_addr_space_sel_fd, &buf)?; ··· 86 86 } 87 87 88 88 extern "C" { 89 - fn __relibc_internal_pte_clone_ret(); 89 + fn __relibc_internal_rlct_clone_ret(); 90 90 } 91 91 92 92 #[cfg(target_arch = "aarch64")] 93 93 core::arch::global_asm!( 94 94 " 95 - .globl __relibc_internal_pte_clone_ret 96 - .type __relibc_internal_pte_clone_ret, @function 95 + .globl __relibc_internal_rlct_clone_ret 96 + .type __relibc_internal_rlct_clone_ret, @function 97 97 .p2align 6 98 - __relibc_internal_pte_clone_ret: 98 + __relibc_internal_rlct_clone_ret: 99 99 # Load registers 100 100 ldr x8, [sp], #8 101 101 ldr x0, [sp], #8 ··· 109 109 blr x8 110 110 111 111 ret 112 - .size __relibc_internal_pte_clone_ret, . - __relibc_internal_pte_clone_ret 112 + .size __relibc_internal_rlct_clone_ret, . - __relibc_internal_rlct_clone_ret 113 113 " 114 114 ); 115 115 116 116 #[cfg(target_arch = "x86")] 117 117 core::arch::global_asm!( 118 118 " 119 - .globl __relibc_internal_pte_clone_ret 120 - .type __relibc_internal_pte_clone_ret, @function 119 + .globl __relibc_internal_rlct_clone_ret 120 + .type __relibc_internal_rlct_clone_ret, @function 121 121 .p2align 6 122 - __relibc_internal_pte_clone_ret: 122 + __relibc_internal_rlct_clone_ret: 123 123 # Load registers 124 124 pop eax 125 125 ··· 136 136 call eax 137 137 138 138 ret 139 - .size __relibc_internal_pte_clone_ret, . - __relibc_internal_pte_clone_ret 139 + .size __relibc_internal_rlct_clone_ret, . - __relibc_internal_rlct_clone_ret 140 140 " 141 141 ); 142 142 143 143 #[cfg(target_arch = "x86_64")] 144 144 core::arch::global_asm!( 145 145 " 146 - .globl __relibc_internal_pte_clone_ret 147 - .type __relibc_internal_pte_clone_ret, @function 146 + .globl __relibc_internal_rlct_clone_ret 147 + .type __relibc_internal_rlct_clone_ret, @function 148 148 .p2align 6 149 - __relibc_internal_pte_clone_ret: 149 + __relibc_internal_rlct_clone_ret: 150 150 # Load registers 151 151 pop rax 152 152 pop rdi ··· 169 169 call rax 170 170 171 171 ret 172 - .size __relibc_internal_pte_clone_ret, . - __relibc_internal_pte_clone_ret 172 + .size __relibc_internal_rlct_clone_ret, . - __relibc_internal_rlct_clone_ret 173 173 " 174 174 );
+1 -1
src/platform/redox/mod.rs
··· 759 759 } 760 760 761 761 unsafe fn rlct_clone(stack: *mut usize) -> Result<crate::pthread::OsTid, crate::pthread::Errno> { 762 - clone::pte_clone_impl(stack).map(|context_id| crate::pthread::OsTid { context_id }).map_err(|error| crate::pthread::Errno(error.errno)) 762 + clone::rlct_clone_impl(stack).map(|context_id| crate::pthread::OsTid { context_id }).map_err(|error| crate::pthread::Errno(error.errno)) 763 763 } 764 764 unsafe fn rlct_kill(os_tid: crate::pthread::OsTid, signal: usize) -> Result<(), crate::pthread::Errno> { 765 765 syscall::kill(os_tid.context_id, signal).map_err(|error| crate::pthread::Errno(error.errno))?;
+2 -13
src/platform/types.rs
··· 77 77 pub type clockid_t = c_int; 78 78 pub type timer_t = *mut c_void; 79 79 80 - pub type pthread_attr_t = crate::header::pthread::attr::Attr; 81 - pub type pthread_barrier_t = crate::header::pthread::barrier::Barrier; 82 - pub type pthread_barrierattr_t = crate::header::pthread::barrier::BarrierAttr; 83 - pub type pthread_cond_t = crate::header::pthread::cond::Cond; 84 - pub type pthread_condattr_t = crate::header::pthread::cond::CondAttr; 85 - pub type pthread_key_t = u32; 86 - pub type pthread_mutex_t = crate::header::pthread::mutex::Mutex; 87 - pub type pthread_mutexattr_t = crate::header::pthread::mutex::MutexAttr; 88 - pub type pthread_once_t = crate::header::pthread::once::Once; 89 - pub type pthread_rwlock_t = crate::header::pthread::rwlock::Rwlock; 90 - pub type pthread_rwlockattr_t = crate::header::pthread::rwlock::RwlockAttr; 91 - pub type pthread_spinlock_t = crate::header::pthread::spin::Spinlock; 92 - pub type pthread_t = *mut c_void; 80 + pub use crate::header::bits_pthread::*; 81 + pub use crate::header::bits_sched::*;
+83 -14
src/pthread/mod.rs
··· 2 2 3 3 use core::cell::{Cell, UnsafeCell}; 4 4 use core::ptr::NonNull; 5 - use core::sync::atomic::{AtomicBool, Ordering}; 5 + use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; 6 6 7 7 use alloc::boxed::Box; 8 8 use alloc::collections::BTreeMap; ··· 12 12 use crate::header::sched::sched_param; 13 13 use crate::header::errno::*; 14 14 use crate::header::sys_mman; 15 + use crate::header::pthread as header; 15 16 use crate::ld_so::{linker::Linker, tcb::{Master, Tcb}}; 16 17 use crate::ALLOCATOR; 17 18 18 19 use crate::sync::{Mutex, waitval::Waitval}; 19 20 20 - #[no_mangle] 21 - extern "C" fn pthread_init() { 21 + const MAIN_PTHREAD_ID: usize = 1; 22 + 23 + /// Called only by the main thread, as part of relibc_start. 24 + pub unsafe fn init() { 25 + let obj = Box::into_raw(Box::new(Pthread { 26 + waitval: Waitval::new(), 27 + wants_cancel: AtomicBool::new(false), 28 + flags: PthreadFlags::empty().bits().into(), 29 + 30 + // TODO 31 + stack_base: core::ptr::null_mut(), 32 + stack_size: 0, 33 + 34 + os_tid: UnsafeCell::new(Sys::current_os_tid()), 35 + })); 36 + 37 + PTHREAD_SELF.set(obj); 38 + } 39 + pub unsafe fn terminate_from_main_thread() { 40 + for (tid, pthread) in OS_TID_TO_PTHREAD.lock().iter() { 41 + // TODO: Cancel? 42 + Sys::rlct_kill(*tid, crate::header::signal::SIGTERM); 43 + } 22 44 } 23 - #[no_mangle] 24 - extern "C" fn pthread_terminate() { 45 + 46 + bitflags::bitflags! { 47 + struct PthreadFlags: usize { 48 + const DETACHED = 1; 49 + } 25 50 } 26 51 27 52 pub struct Pthread { 28 53 waitval: Waitval<Retval>, 29 54 wants_cancel: AtomicBool, 55 + flags: AtomicUsize, 30 56 31 57 stack_base: *mut c_void, 32 58 stack_size: usize, ··· 45 71 unsafe impl Send for Pthread {} 46 72 unsafe impl Sync for Pthread {} 47 73 48 - use crate::header::pthread::attr::Attr; 74 + use crate::header::bits_pthread::pthread_attr_t; 49 75 50 76 /// Positive error codes (EINVAL, not -EINVAL). 51 77 #[derive(Debug, Eq, PartialEq)] ··· 75 101 // TODO: Custom stacks 76 102 let stack_base = sys_mman::mmap( 77 103 core::ptr::null_mut(), 78 - attrs.stacksize, 104 + stack_size, 79 105 sys_mman::PROT_READ | sys_mman::PROT_WRITE, 80 106 sys_mman::MAP_SHARED | sys_mman::MAP_ANONYMOUS, 81 107 -1, ··· 86 112 return Err(Errno(EAGAIN)); 87 113 } 88 114 115 + let mut flags = PthreadFlags::empty(); 116 + match i32::from(attrs.detachstate) { 117 + header::PTHREAD_CREATE_DETACHED => flags |= PthreadFlags::DETACHED, 118 + header::PTHREAD_CREATE_JOINABLE => (), 119 + 120 + other => unreachable!("unknown detachstate {}", other), 121 + } 122 + 89 123 let pthread = Pthread { 90 124 waitval: Waitval::new(), 125 + flags: flags.bits().into(), 91 126 wants_cancel: AtomicBool::new(false), 92 127 stack_base, 93 128 stack_size, ··· 134 169 let Ok(os_tid) = Sys::rlct_clone(stack) else { 135 170 return Err(Errno(EAGAIN)); 136 171 }; 172 + core::mem::forget(stack_raii); 137 173 138 174 let _ = (&*synchronization_mutex).lock(); 139 175 140 176 OS_TID_TO_PTHREAD.lock().insert(os_tid, ForceSendSync(ptr.cast())); 141 - 142 - core::mem::forget(stack_raii); 143 177 144 178 Ok(ptr.cast()) 145 179 } ··· 180 214 if core::ptr::eq(thread, current_thread().unwrap_unchecked()) { 181 215 return Err(Errno(EDEADLK)); 182 216 } 217 + 183 218 // Waitval starts locked, and is unlocked when the thread finishes. 184 219 let retval = *thread.waitval.wait(); 185 220 186 - // TODO: Deinitialization code 221 + // We have now awaited the thread and received its return value. POSIX states that the 222 + // pthread_t of this thread, will no longer be valid. In practice, we can thus deallocate the 223 + // thread state. 224 + 225 + OS_TID_TO_PTHREAD.lock().remove(&thread.os_tid.get().read()); 226 + 227 + dealloc_thread(thread); 187 228 188 229 Ok(retval) 189 230 } 190 231 191 232 pub unsafe fn detach(thread: &Pthread) -> Result<(), Errno> { 192 - todo!() 233 + thread.flags.fetch_or(PthreadFlags::DETACHED.bits(), Ordering::Release); 234 + Ok(()) 193 235 } 194 236 195 237 // Returns option because that's a no-op, but PTHREAD_SELF should always be initialized except in ··· 208 250 } 209 251 210 252 pub unsafe fn exit_current_thread(retval: Retval) -> ! { 211 - let this = current_thread().unwrap_unchecked(); 212 - this.waitval.post(retval); 253 + let this = current_thread().expect("failed to obtain current thread when exiting"); 254 + 255 + if this.flags.load(Ordering::Acquire) & PthreadFlags::DETACHED.bits() != 0 { 256 + // When detached, the thread state no longer makes any sense, and can immediately be 257 + // deallocated. 258 + dealloc_thread(this); 259 + } else { 260 + // When joinable, the return value should be made available to other threads. 261 + this.waitval.post(retval); 262 + } 213 263 214 264 Sys::exit_thread() 215 265 } 216 266 267 + // TODO: Use Arc? One strong reference from each OS_TID_TO_PTHREAD and one strong reference from 268 + // PTHREAD_SELF. The latter ref disappears when the thread exits, while the former disappears when 269 + // detaching. Isn't that sufficient? 270 + unsafe fn dealloc_thread(thread: &Pthread) { 271 + drop(Box::from_raw(thread as *const Pthread as *mut Pthread)); 272 + } 217 273 pub const SIGRT_RLCT_CANCEL: usize = 32; 218 274 pub const SIGRT_RLCT_TIMER: usize = 33; 219 275 276 + unsafe fn cancel_sighandler(_: c_int) { 277 + // TODO: pthread_cleanup_push stack 278 + // TODO: thread-specific data 279 + 280 + // Terminate the thread 281 + exit_current_thread(Retval(header::PTHREAD_CANCELED)); 282 + } 283 + 220 284 pub unsafe fn cancel(thread: &Pthread) -> Result<(), Errno> { 285 + // TODO: Ordering 221 286 thread.wants_cancel.store(true, Ordering::SeqCst); 287 + 222 288 Sys::rlct_kill(thread.os_tid.get().read(), SIGRT_RLCT_CANCEL)?; 289 + 223 290 todo!(); 224 291 Ok(()) 225 292 } 226 293 227 294 // TODO: Hash map? 228 - static OS_TID_TO_PTHREAD: Mutex<BTreeMap<OsTid, ForceSendSync<pthread_t>>> = Mutex::new(BTreeMap::new()); 295 + // TODO: RwLock 296 + static OS_TID_TO_PTHREAD: Mutex<BTreeMap<OsTid, ForceSendSync<*mut Pthread>>> = Mutex::new(BTreeMap::new()); 229 297 298 + #[derive(Clone, Copy)] 230 299 struct ForceSendSync<T>(T); 231 300 unsafe impl<T> Send for ForceSendSync<T> {} 232 301 unsafe impl<T> Sync for ForceSendSync<T> {}
+1 -4
src/start.rs
··· 112 112 } 113 113 } 114 114 115 - extern "C" { 116 - fn pthread_init(); 117 - } 118 115 unsafe { 119 - pthread_init(); 116 + crate::pthread::init(); 120 117 init_complete = true 121 118 } 122 119 }
+40 -33
src/sync/mod.rs
··· 37 37 Sys::futex(ptr, FUTEX_WAIT, value, timeout_opt.map_or(0, |t| t as *const _ as usize)) == Ok(0) 38 38 } 39 39 pub fn futex_wake(atomic: &AtomicInt, n: i32) -> usize { 40 - unsafe { futex_wake_ptr(atomic.as_mut_ptr(), n) } 40 + unsafe { futex_wake_ptr(atomic.as_ptr(), n) } 41 41 } 42 42 pub fn futex_wait(atomic: &AtomicInt, value: i32, timeout_opt: Option<&timespec>) -> bool { 43 - unsafe { futex_wait_ptr(atomic.as_mut_ptr(), value, timeout_opt) } 43 + unsafe { futex_wait_ptr(atomic.as_ptr(), value, timeout_opt) } 44 + } 45 + pub fn wait_until_generic<F1, F2>(word: &AtomicInt, attempt: F1, mark_long: F2, long: c_int) 46 + where 47 + F1: Fn(&AtomicInt) -> AttemptStatus, 48 + F2: Fn(&AtomicInt) -> AttemptStatus, 49 + { 50 + // First, try spinning for really short durations 51 + for _ in 0..999 { 52 + atomic::spin_loop_hint(); 53 + if attempt(word) == AttemptStatus::Desired { 54 + return; 55 + } 56 + } 57 + 58 + // One last attempt, to initiate "previous" 59 + let mut previous = attempt(word); 60 + 61 + // Ok, that seems to take quite some time. Let's go into a 62 + // longer, more patient, wait. 63 + loop { 64 + if previous == AttemptStatus::Desired { 65 + return; 66 + } 67 + 68 + if 69 + // If we or somebody else already initiated a long 70 + // wait, OR 71 + previous == AttemptStatus::Waiting || 72 + // Otherwise, unless our attempt to initiate a long 73 + // wait informed us that we might be done waiting 74 + mark_long(word) != AttemptStatus::Desired 75 + { 76 + futex_wait(word, long, None); 77 + } 78 + 79 + previous = attempt(word); 80 + } 44 81 } 45 82 46 83 /// Convenient wrapper around the "futex" system call for ··· 92 129 F1: Fn(&AtomicInt) -> AttemptStatus, 93 130 F2: Fn(&AtomicInt) -> AttemptStatus, 94 131 { 95 - // First, try spinning for really short durations 96 - for _ in 0..999 { 97 - atomic::spin_loop_hint(); 98 - if attempt(self) == AttemptStatus::Desired { 99 - return; 100 - } 101 - } 102 - 103 - // One last attempt, to initiate "previous" 104 - let mut previous = attempt(self); 105 - 106 - // Ok, that seems to take quite some time. Let's go into a 107 - // longer, more patient, wait. 108 - loop { 109 - if previous == AttemptStatus::Desired { 110 - return; 111 - } 112 - 113 - if 114 - // If we or somebody else already initiated a long 115 - // wait, OR 116 - previous == AttemptStatus::Waiting || 117 - // Otherwise, unless our attempt to initiate a long 118 - // wait informed us that we might be done waiting 119 - mark_long(self) != AttemptStatus::Desired 120 - { 121 - self.wait_if(long, None); 122 - } 123 - 124 - previous = attempt(self); 125 - } 132 + wait_until_generic(&self.atomic, attempt, mark_long, long) 126 133 } 127 134 } 128 135 impl Deref for AtomicLock {
+44 -29
src/sync/mutex.rs
··· 3 3 use core::{ 4 4 cell::UnsafeCell, 5 5 ops::{Deref, DerefMut}, 6 - sync::atomic::Ordering::SeqCst, 6 + sync::atomic::{AtomicI32 as AtomicInt, Ordering}, 7 7 }; 8 8 9 - const UNLOCKED: c_int = 0; 10 - const LOCKED: c_int = 1; 11 - const WAITING: c_int = 2; 9 + pub(crate) const UNLOCKED: c_int = 0; 10 + pub(crate) const LOCKED: c_int = 1; 11 + pub(crate) const WAITING: c_int = 2; 12 12 13 13 pub struct Mutex<T> { 14 14 pub(crate) lock: AtomicLock, ··· 16 16 } 17 17 unsafe impl<T: Send> Send for Mutex<T> {} 18 18 unsafe impl<T: Send> Sync for Mutex<T> {} 19 + 20 + pub(crate) unsafe fn manual_try_lock_generic(word: &AtomicInt) -> bool { 21 + word.compare_exchange(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed).is_ok() 22 + } 23 + pub(crate) unsafe fn manual_lock_generic(word: &AtomicInt) { 24 + crate::sync::wait_until_generic( 25 + word, 26 + |lock| { 27 + lock.compare_exchange_weak(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed) 28 + .map(|_| AttemptStatus::Desired) 29 + .unwrap_or_else(|e| match e { 30 + WAITING => AttemptStatus::Waiting, 31 + _ => AttemptStatus::Other, 32 + }) 33 + }, 34 + |lock| match lock 35 + // TODO: Ordering 36 + .compare_exchange_weak(LOCKED, WAITING, Ordering::SeqCst, Ordering::SeqCst) 37 + .unwrap_or_else(|e| e) 38 + { 39 + UNLOCKED => AttemptStatus::Desired, 40 + WAITING => AttemptStatus::Waiting, 41 + _ => AttemptStatus::Other, 42 + }, 43 + WAITING, 44 + ); 45 + } 46 + pub(crate) unsafe fn manual_unlock_generic(word: &AtomicInt) { 47 + if word.swap(UNLOCKED, Ordering::Release) == WAITING { 48 + crate::sync::futex_wake(word, 1); 49 + } 50 + } 51 + 19 52 impl<T> Mutex<T> { 20 53 /// Create a new mutex 21 54 pub const fn new(content: T) -> Self { ··· 42 75 /// on failure. You should probably not worry about this, it's used for 43 76 /// internal optimizations. 44 77 pub unsafe fn manual_try_lock(&self) -> Result<&mut T, c_int> { 45 - self.lock 46 - .compare_exchange(UNLOCKED, LOCKED, SeqCst, SeqCst) 47 - .map(|_| &mut *self.content.get()) 78 + if manual_try_lock_generic(&self.lock) { 79 + Ok(&mut *self.content.get()) 80 + } else { 81 + Err(0) 82 + } 48 83 } 49 84 /// Lock the mutex, returning the inner content. After doing this, it's 50 85 /// your responsibility to unlock it after usage. Mostly useful for FFI: 51 86 /// Prefer normal .lock() where possible. 52 87 pub unsafe fn manual_lock(&self) -> &mut T { 53 - self.lock.wait_until( 54 - |lock| { 55 - lock.compare_exchange_weak(UNLOCKED, LOCKED, SeqCst, SeqCst) 56 - .map(|_| AttemptStatus::Desired) 57 - .unwrap_or_else(|e| match e { 58 - WAITING => AttemptStatus::Waiting, 59 - _ => AttemptStatus::Other, 60 - }) 61 - }, 62 - |lock| match lock 63 - .compare_exchange_weak(LOCKED, WAITING, SeqCst, SeqCst) 64 - .unwrap_or_else(|e| e) 65 - { 66 - UNLOCKED => AttemptStatus::Desired, 67 - WAITING => AttemptStatus::Waiting, 68 - _ => AttemptStatus::Other, 69 - }, 70 - WAITING, 71 - ); 88 + manual_lock_generic(&self.lock); 72 89 &mut *self.content.get() 73 90 } 74 91 /// Unlock the mutex, if it's locked. 75 92 pub unsafe fn manual_unlock(&self) { 76 - if self.lock.swap(UNLOCKED, SeqCst) == WAITING { 77 - self.lock.notify_one(); 78 - } 93 + manual_unlock_generic(&self.lock) 79 94 } 80 95 81 96 /// Tries to lock the mutex and returns a guard that automatically unlocks
+42 -36
src/sync/once.rs
··· 1 1 use super::{AtomicLock, AttemptStatus}; 2 2 use crate::platform::types::*; 3 - use core::{cell::UnsafeCell, mem::MaybeUninit, sync::atomic::Ordering::SeqCst}; 3 + use core::{cell::UnsafeCell, mem::MaybeUninit}; 4 + use core::sync::atomic::{AtomicI32 as AtomicInt, Ordering::SeqCst}; 4 5 5 6 const UNINITIALIZED: c_int = 0; 6 7 const INITIALIZING: c_int = 1; 7 8 const WAITING: c_int = 2; 8 9 const INITIALIZED: c_int = 3; 9 10 11 + pub(crate) fn call_once_generic(word: &AtomicInt, f: impl FnOnce()) { 12 + match word.compare_and_swap(UNINITIALIZED, INITIALIZING, SeqCst) { 13 + UNINITIALIZED => { 14 + // We now have a lock, let's initiate things! 15 + 16 + // Mark the data as initialized 17 + if word.swap(INITIALIZED, SeqCst) == WAITING { 18 + // At least one thread is waiting on this to finish 19 + crate::sync::futex_wake(word, i32::MAX); 20 + } 21 + } 22 + INITIALIZING | WAITING => crate::sync::wait_until_generic( 23 + word, 24 + |lock| match lock.load(SeqCst) { 25 + WAITING => AttemptStatus::Waiting, 26 + INITIALIZED => AttemptStatus::Desired, 27 + _ => AttemptStatus::Other, 28 + }, 29 + |lock| match lock 30 + .compare_exchange_weak(INITIALIZING, WAITING, SeqCst, SeqCst) 31 + .unwrap_or_else(|e| e) 32 + { 33 + WAITING => AttemptStatus::Waiting, 34 + INITIALIZED => AttemptStatus::Desired, 35 + _ => AttemptStatus::Other, 36 + }, 37 + WAITING, 38 + ), 39 + INITIALIZED => (), 40 + _ => unreachable!("invalid state for Once<T>"), 41 + } 42 + 43 + } 44 + 10 45 pub struct Once<T> { 11 - status: AtomicLock, 46 + status: AtomicInt, 12 47 data: UnsafeCell<MaybeUninit<T>>, 13 48 } 14 49 unsafe impl<T: Send> Send for Once<T> {} ··· 16 51 impl<T> Once<T> { 17 52 pub const fn new() -> Self { 18 53 Self { 19 - status: AtomicLock::new(UNINITIALIZED), 54 + status: AtomicInt::new(UNINITIALIZED), 20 55 data: UnsafeCell::new(MaybeUninit::uninit()), 21 56 } 22 57 } 58 + // FIXME: Isn't &mut UB? 23 59 pub fn call_once<F>(&self, f: F) -> &mut T 24 60 where 25 61 F: FnOnce() -> T, 26 62 { 27 - match self 28 - .status 29 - .compare_and_swap(UNINITIALIZED, INITIALIZING, SeqCst) 30 - { 31 - UNINITIALIZED => { 32 - // We now have a lock, let's initiate things! 33 - let ret = unsafe { &mut *self.data.get() }.write(f()); 34 - 35 - // Mark the data as initialized 36 - if self.status.swap(INITIALIZED, SeqCst) == WAITING { 37 - // At least one thread is waiting on this to finish 38 - self.status.notify_all(); 39 - } 40 - } 41 - INITIALIZING | WAITING => self.status.wait_until( 42 - |lock| match lock.load(SeqCst) { 43 - WAITING => AttemptStatus::Waiting, 44 - INITIALIZED => AttemptStatus::Desired, 45 - _ => AttemptStatus::Other, 46 - }, 47 - |lock| match lock 48 - .compare_exchange_weak(INITIALIZING, WAITING, SeqCst, SeqCst) 49 - .unwrap_or_else(|e| e) 50 - { 51 - WAITING => AttemptStatus::Waiting, 52 - INITIALIZED => AttemptStatus::Desired, 53 - _ => AttemptStatus::Other, 54 - }, 55 - WAITING, 56 - ), 57 - INITIALIZED => (), 58 - _ => unreachable!("invalid state for Once<T>"), 59 - } 63 + call_once_generic(&self.status, || { 64 + unsafe { &mut *self.data.get() }.write(f()); 65 + }); 60 66 61 67 // At this point the data must be initialized! 62 68 unsafe { &mut *(&mut *self.data.get()).as_mut_ptr() }