diff --git a/Cargo.lock b/Cargo.lock index f441241..589a0c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,39 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anyhow" version = "1.0.68" @@ -19,12 +52,38 @@ dependencies = [ "syn", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bincode" version = "1.3.3" @@ -34,13 +93,59 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.55.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b13ce559e6433d360c26305643803cb52cfbabbc2b9c47ce04a58493dfb443" +dependencies = [ + "bitflags", + "cexpr 0.4.0", + "cfg-if 0.1.10", + "clang-sys", + "clap", + "env_logger", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex 0.1.1", + "which 3.1.1", +] + +[[package]] +name = "bindgen" +version = "0.63.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +dependencies = [ + "bitflags", + "cexpr 0.6.0", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex 1.1.0", + "syn", + "which 4.4.0", +] + [[package]] name = "bindgen" version = "0.63.0" source = "git+https://github.com/rust-lang/rust-bindgen?branch=main#a7ff8e136027c9542f65eca97a7ff3c0b870518d" dependencies = [ "bitflags", - "cexpr", + "cexpr 0.6.0", "clang-sys", "lazy_static", "lazycell", @@ -50,9 +155,9 @@ dependencies = [ "quote", "regex", "rustc-hash", - "shlex", + "shlex 1.1.0", "syn", - "which", + "which 4.4.0", ] [[package]] @@ -73,15 +178,58 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714a157da7991e23d90686b9524b9e12e0407a108647f52e9328f4b3d51ac7f" +dependencies = [ + "cargo-platform", + "semver 0.11.0", + "semver-parser", + "serde", + "serde_json", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cexpr" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +dependencies = [ + "nom 5.1.2", +] + [[package]] name = "cexpr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom", + "nom 7.1.3", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -99,13 +247,47 @@ dependencies = [ "libloading", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clib" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052e725c89ab3736a86000ddb52337004750bf25cf7e78f77d599fa52c66ebb5" +dependencies = [ + "anyhow", + "bindgen 0.55.1", + "inwelling", + "pkg-config", + "serde_json", +] + +[[package]] +name = "cmdline_words_parser" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75d8078f03daf673d8bd34a1ef48c680ea4a895204882ce5f0ccfb2487b2bd29" + [[package]] name = "crossbeam-channel" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", ] @@ -115,7 +297,7 @@ version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -150,6 +332,50 @@ dependencies = [ "syn", ] +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime 1.3.0", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "escape8259" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4911e3666fcd7826997b4745c8224295a6f3072f1418c3067b97a67557ee" +dependencies = [ + "rustversion", +] + +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "fnv" version = "1.0.7" @@ -251,17 +477,32 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] +[[package]] +name = "gimli" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "221996f774192f0f718773def8201c4ae31f02616a54ccfc2d358bb0e5cefdec" + [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.2.6" @@ -271,12 +512,32 @@ dependencies = [ "libc", ] +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "inwelling" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1da5b58facc2f029f6c01ba403b26bd89fd3819929f769b22dfe35925f4c3044" +dependencies = [ + "cargo_metadata", + "pals", + "serde_json", +] + [[package]] name = "itoa" version = "1.0.5" @@ -316,7 +577,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "winapi", ] @@ -326,7 +587,7 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -341,6 +602,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.5" @@ -353,6 +623,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "memchr", + "version_check", +] + [[package]] name = "nom" version = "7.1.3" @@ -399,10 +679,19 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.17.0" @@ -428,6 +717,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "pals" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ae908b04f9c1ea173c4851b9f88f2a53c48319254cdb0942a0aaae94f6c804" +dependencies = [ + "anyhow", + "cmdline_words_parser", + "escape8259", + "serde", + "serde_json", + "trees", + "utf16_reader", +] + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -440,6 +744,16 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "pest" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ab62d2fa33726dbe6321cc97ef96d8cde531e3eeaf858a058de53a8a6d40d8f" +dependencies = [ + "thiserror", + "ucd-trie", +] + [[package]] name = "pin-project" version = "1.0.12" @@ -472,6 +786,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -487,6 +807,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.23" @@ -532,6 +858,8 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", ] @@ -541,6 +869,12 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -553,9 +887,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.16", ] +[[package]] +name = "rustversion" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" + [[package]] name = "ryu" version = "1.0.12" @@ -567,6 +907,8 @@ name = "sdac-lib" version = "0.1.0" dependencies = [ "anyhow", + "bindgen 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clib", "futures", "futures-util", "libc", @@ -582,7 +924,7 @@ name = "sdac-server" version = "0.1.0" dependencies = [ "anyhow", - "bindgen", + "bindgen 0.63.0 (git+https://github.com/rust-lang/rust-bindgen?branch=main)", "futures", "futures-util", "libc", @@ -593,12 +935,31 @@ dependencies = [ "tokio-serde", ] +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", + "serde", +] + [[package]] name = "semver" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.152" @@ -634,6 +995,10 @@ dependencies = [ name = "service" version = "0.0.0" dependencies = [ + "bindgen 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure", + "regex", + "serde", "tarpc", ] @@ -646,6 +1011,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + [[package]] name = "shlex" version = "1.1.0" @@ -677,6 +1048,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "syn" version = "1.0.107" @@ -688,6 +1065,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "tarpc" version = "0.31.0" @@ -697,7 +1086,7 @@ dependencies = [ "anyhow", "fnv", "futures", - "humantime", + "humantime 2.1.0", "opentelemetry", "pin-project", "rand", @@ -723,6 +1112,24 @@ dependencies = [ "syn", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.38" @@ -816,7 +1223,7 @@ version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -868,18 +1275,60 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "trees" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de5f738ceab88e2491a94ddc33c3feeadfa95fedc60363ef110845df12f3878" + +[[package]] +name = "ucd-trie" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" + [[package]] name = "unicode-ident" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "utf16_reader" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa1b25084cb80e5e6cd0aa8281ff55dd1f3b969737797e97a42e6e3f7340ee" + [[package]] name = "valuable" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -892,7 +1341,7 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -940,6 +1389,15 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +[[package]] +name = "which" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" +dependencies = [ + "libc", +] + [[package]] name = "which" version = "4.4.0" @@ -967,6 +1425,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/sdac-lib/Cargo.toml b/sdac-lib/Cargo.toml index 5f9fab0..65a110c 100644 --- a/sdac-lib/Cargo.toml +++ b/sdac-lib/Cargo.toml @@ -6,10 +6,14 @@ license = "MIT" description = "Software Defined Acclerated Compute" homepage = "https://github.com/xertai/sdac" edition = "2021" +build = "build-cuda-types.rs" [lib] crate-type = ["cdylib"] +[build-dependencies] +bindgen = "0.63.0" + [dependencies] tarpc = { version = "0.31.0", features = ["full"] } tokio = { version = "1.24.2", features = ["macros", "net", "rt-multi-thread"] } @@ -20,3 +24,4 @@ libc = "0.2.139" futures = "0.3.25" anyhow = "1.0.68" service = { version = "0.0.0", path = "../service" } +clib = "0.2.1" diff --git a/sdac-lib/build-cuda-types.rs b/sdac-lib/build-cuda-types.rs new file mode 100644 index 0000000..51377b0 --- /dev/null +++ b/sdac-lib/build-cuda-types.rs @@ -0,0 +1,31 @@ +extern crate bindgen; + +use std::env; +use std::path::{Path, PathBuf}; + +// Install NVIDIA CUDA prior to building the bindings with `cargo build`. +// https://docs.rs/bindgen/latest/bindgen/struct.Builder.html +fn main() { + let cdir = std::env::var("CUDA_DIR").unwrap_or("/usr/local/cuda-11.8".to_string()); + let cuda_dir = Path::new(&cdir); + + let bindings = bindgen::Builder::default() + .header(cuda_dir.join("include/cuda.h").display().to_string()) + .header(cuda_dir.join("include/cuda_runtime_api.h").display().to_string()) + .allowlist_type("CU.*") + .allowlist_type("cuda.*") + .derive_eq(true) + .array_pointers_in_arguments(true) + .generate() + .unwrap(); + + let target_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(target_path.join("cuda_types.rs")) + .expect("Couldn't write bindings!"); + + println!( + "Wrote bindings to {}", + target_path.join("cuda_types.rs").display() + ); +} diff --git a/sdac-lib/src/device.rs b/sdac-lib/src/device.rs new file mode 100644 index 0000000..441d202 --- /dev/null +++ b/sdac-lib/src/device.rs @@ -0,0 +1,213 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +use service::*; +use futures::executor::block_on; +use std::mem::size_of; +use std::ffi::CString; +use std::sync::{Mutex}; +use tarpc::{context}; + +pub fn cuGetErrorString( + client: &Mutex, + error: CUresult, + pStr: *mut ::std::os::raw::c_char, +) -> CUresult { + let (strName, res) = block_on( + client + .lock() + .unwrap() + .cuGetErrorString(context::current(), error), + ) + .unwrap(); + + if res != cudaError_enum_CUDA_SUCCESS { + return res; + } + + let cs = CString::new(strName).unwrap(); + unsafe { + libc::strcpy(pStr, cs.as_ptr()); + } + + res +} + +pub fn cuGetErrorName( + client: &Mutex, + error: CUresult, + pStr: *mut ::std::os::raw::c_char, +) -> CUresult { + let (strName, res) = block_on( + client + .lock() + .unwrap() + .cuGetErrorName(context::current(), error), + ) + .unwrap(); + + if res != cudaError_enum_CUDA_SUCCESS { + return res; + } + + let cs = CString::new(strName).unwrap(); + unsafe { + libc::strcpy(pStr, cs.as_ptr()); + } + + res +} + +pub fn cuInit(client: &Mutex,flags: ::std::os::raw::c_uint) -> CUresult { + block_on( + client + .lock() + .unwrap() + .cuInit(context::current(), flags), + ) + .unwrap() +} + +pub fn cuDeviceGetName(client: &Mutex, + name: *mut ::std::os::raw::c_char, + len: ::std::os::raw::c_int, + dev: CUdevice, +) -> CUresult { + let (strName, res) = block_on(client.lock().unwrap().cuDeviceGetName( + context::current(), + len, + dev, + )) + .unwrap(); + + let cs = CString::new(strName).unwrap(); + unsafe { + libc::strcpy(name, cs.as_ptr()); + } + + res +} + +pub fn cuDeviceGetCount(client: &Mutex,count: *mut ::std::os::raw::c_int) -> CUresult { + let (cnt, res) = block_on( + client + .lock() + .unwrap() + .cuDeviceGetCount(context::current()), + ) + .unwrap(); + + unsafe { + *count = cnt; + } + + res +} + +pub fn cuDeviceGet(client: &Mutex, + device: *mut CUdevice, + ordinal: ::std::os::raw::c_int, +) -> CUresult { + let (dev, res) = block_on( + client + .lock() + .unwrap() + .cuDeviceGet(context::current(), ordinal), + ) + .unwrap(); + + unsafe { + *device = dev; + } + + res +} + +pub fn cuMemAlloc_v2(client: &Mutex, + dptr: *mut CUdeviceptr, + bytesize: ::std::os::raw::c_ulonglong, +) -> CUresult { + let (ptr, res) = block_on( + client + .lock() + .unwrap() + .cuMemAlloc_v2(context::current(), bytesize as usize), + ) + .unwrap(); + + unsafe { + *dptr = ptr; + } + + res +} + +pub fn cuMemcpyDtoH_v2(client: &Mutex, + dstHost: *mut ::std::os::raw::c_void, + srcDevice: CUdeviceptr, + ByteCount: ::std::os::raw::c_ulonglong, +) -> CUresult { +let (data, res) = block_on( + client + .lock() + .unwrap() + .cuMemcpyDtoH_v2(context::current(), srcDevice, ByteCount as usize), + ) + .unwrap(); + + if res!= cudaError_enum_CUDA_SUCCESS { + return res; + } + + unsafe { + libc::memcpy(dstHost, data.as_ptr() as *const libc::c_void, ByteCount as usize); + } + + 0 +} + +pub fn cuMemcpyHtoD_v2(client: &Mutex, + dstDevice: CUdeviceptr, + srcHost: *const ::std::os::raw::c_void, + ByteCount: ::std::os::raw::c_ulonglong, +) -> CUresult { + let data = unsafe{ Vec::::from_raw_parts(srcHost, ByteCount, size_of(u8))}; + block_on( + client + .lock() + .unwrap() + .cuMemcpyHtoD_v2(context::current(), dstDevice, data, ByteCount as usize), + ) + .unwrap() +} + +pub fn cuMemFree_v2(client: &Mutex,dptr: CUdeviceptr) -> CUresult { + block_on( + client + .lock() + .unwrap() + .cuMemFree_v2(context::current(), dptr), + ) + .unwrap() +} + +pub fn cuDeviceTotalMem_v2( + client: &Mutex, + bytes: *mut usize, + dev: CUdevice, +) -> CUresult{ + let (cnt, res) = block_on( + client + .lock() + .unwrap() + .cuDeviceTotalMem_v2(context::current(), dev), + ) + .unwrap(); + + unsafe { + *bytes = cnt; + } + + res +} \ No newline at end of file diff --git a/sdac-lib/src/global.rs b/sdac-lib/src/global.rs new file mode 100644 index 0000000..5acfd09 --- /dev/null +++ b/sdac-lib/src/global.rs @@ -0,0 +1,33 @@ +use futures::executor::block_on; + +use std::borrow::BorrowMut; + +use std::sync::{Mutex, Once}; +use tarpc::{client, tokio_serde::formats::Json}; + +static mut CUDA_CLIENT: Option> = None; +static INIT: Once = Once::new(); + +pub fn client<'a>() -> &'a Mutex { + INIT.call_once(|| { + // Since this access is inside a call_once, before any other accesses, it is safe + unsafe { + let transport = block_on(tarpc::serde_transport::tcp::connect( + "[::1]:50055", + Json::default, + )) + .unwrap(); + + // WorldClient is generated by the service attribute. It has a constructor `new` that takes a + // config and any Transport as input. + let client = service::CudaClient::new(client::Config::default(), transport).spawn(); + + *CUDA_CLIENT.borrow_mut() = Some(Mutex::new(client)); + } + }); + + // As long as this function is the only place with access to the static variable, + // giving out a read-only borrow here is safe because it is guaranteed no more mutable + // references will exist at this point or in the future. + unsafe { CUDA_CLIENT.as_ref().unwrap() } +} diff --git a/sdac-lib/src/lib.rs b/sdac-lib/src/lib.rs index 54f81d4..1993896 100644 --- a/sdac-lib/src/lib.rs +++ b/sdac-lib/src/lib.rs @@ -2,60 +2,32 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use std::borrow::BorrowMut; -use std::ffi::CString; -use std::sync::{Mutex, Once}; -use futures::executor::block_on; -use tarpc::{client, context, tokio_serde::formats::Json}; -use service; - -// TODO(asalkeld) use autogenerated code for this. -// not including everything as the externs will conflict with the definitions -// in this file. https://github.com/xertai/sdac/issues/37 -pub type CUresult = ::std::os::raw::c_uint; -pub type cuuint32_t = u32; -pub type cuuint64_t = u64; -pub type CUdeviceptr_v2 = ::std::os::raw::c_ulonglong; -pub type CUdeviceptr = CUdeviceptr_v2; -pub type CUdevice_v1 = ::std::os::raw::c_int; -pub type CUdevice = CUdevice_v1; - -static mut CUDA_CLIENT: Option> = None; -static INIT: Once = Once::new(); - -fn cudaClient<'a>() -> &'a Mutex { - INIT.call_once(|| { - // Since this access is inside a call_once, before any other accesses, it is safe - unsafe { - let transport = block_on(tarpc::serde_transport::tcp::connect( - "[::1]:50055", - Json::default, - )) - .unwrap(); - - // WorldClient is generated by the service attribute. It has a constructor `new` that takes a - // config and any Transport as input. - let client = service::CudaClient::new(client::Config::default(), transport).spawn(); - - *CUDA_CLIENT.borrow_mut() = Some(Mutex::new(client)); - } - }); - - // As long as this function is the only place with access to the static variable, - // giving out a read-only borrow here is safe because it is guaranteed no more mutable - // references will exist at this point or in the future. - unsafe { CUDA_CLIENT.as_ref().unwrap() } -} +use service::*; + +mod device; +mod global; +mod runtime; +// CUDA Driver API #[no_mangle] unsafe extern "C" fn cuInit(flags: ::std::os::raw::c_uint) -> CUresult { - block_on( - cudaClient() - .lock() - .unwrap() - .cuInit(context::current(), flags), - ) - .unwrap() + device::cuInit(global::client(), flags) +} + +#[no_mangle] +unsafe extern "C" fn cuGetErrorString( + error: CUresult, + pStr: *mut ::std::os::raw::c_char, +) -> CUresult { + device::cuGetErrorString(global::client(), error, pStr) +} + +#[no_mangle] +unsafe extern "C" fn cuGetErrorName( + error: CUresult, + pStr: *mut ::std::os::raw::c_char, +) -> CUresult { + device::cuGetErrorName(global::client(), error, pStr) } #[no_mangle] @@ -64,32 +36,12 @@ unsafe extern "C" fn cuDeviceGetName( len: ::std::os::raw::c_int, dev: CUdevice, ) -> CUresult { - let (strName, res) = block_on(cudaClient().lock().unwrap().cuDeviceGetName( - context::current(), - len, - dev, - )) - .unwrap(); - - let cs = CString::new(strName).unwrap(); - libc::strcpy(name, cs.as_ptr()); - - res + device::cuDeviceGetName(global::client(), name, len, dev) } #[no_mangle] unsafe extern "C" fn cuDeviceGetCount(count: *mut ::std::os::raw::c_int) -> CUresult { - let (cnt, res) = block_on( - cudaClient() - .lock() - .unwrap() - .cuDeviceGetCount(context::current()), - ) - .unwrap(); - - *count = cnt; - - res + device::cuDeviceGetCount(global::client(), count) } #[no_mangle] @@ -97,15 +49,116 @@ unsafe extern "C" fn cuDeviceGet( device: *mut CUdevice, ordinal: ::std::os::raw::c_int, ) -> CUresult { - let (dev, res) = block_on( - cudaClient() - .lock() - .unwrap() - .cuDeviceGet(context::current(), ordinal), - ) - .unwrap(); + device::cuDeviceGet(global::client(), device, ordinal) +} + +#[no_mangle] +unsafe extern "C" fn cuDeviceTotalMem_v2( + bytes: *mut usize, + dev: CUdevice, +) -> CUresult { + device::cuDeviceTotalMem_v2(global::client(), bytes, dev) +} + +// ====================== +// Runtime API + +#[no_mangle] +unsafe extern "C" fn cudaMalloc( + devPtr: *mut *mut ::std::os::raw::c_void, + size: usize, +) -> cudaError_t { + runtime::cudaMalloc(global::client(), devPtr, size) +} - *device = dev; +#[no_mangle] +unsafe extern "C" fn cudaFree(devPtr: *mut ::std::os::raw::c_void) -> cudaError_t { + runtime::cudaFree(global::client(), devPtr) +} + +#[no_mangle] +unsafe extern "C" fn cudaMemcpy( + dst: *mut ::std::os::raw::c_void, + src: *const ::std::os::raw::c_void, + count: usize, + kind: cudaMemcpyKind, +) -> cudaError_t { + runtime::cudaMemcpy(global::client(), dst, src, count, kind) +} + +#[no_mangle] +unsafe extern "C" fn cudaMemset( + devPtr: *mut ::std::os::raw::c_void, + value: ::std::os::raw::c_int, + count: usize, +) -> cudaError_t { + runtime::cudaMemset(global::client(), devPtr, value, count) +} - res +#[no_mangle] +unsafe extern "C" fn cudaGetLastError() -> cudaError_t { + runtime::cudaGetLastError(global::client()) +} + +#[no_mangle] +unsafe extern "C" fn cudaPeekAtLastError() -> cudaError_t { + runtime::cudaPeekAtLastError(global::client()) +} + +#[no_mangle] +unsafe extern "C" fn cudaGetErrorName(error: cudaError_t) -> *const ::std::os::raw::c_char { + runtime::cudaGetErrorName(global::client(), error) +} + +#[no_mangle] +unsafe extern "C" fn cudaGetErrorString(error: cudaError_t) -> *const ::std::os::raw::c_char { + runtime::cudaGetErrorString(global::client(), error) +} + +#[no_mangle] +unsafe extern "C" fn cudaGetDeviceCount(count: *mut ::std::os::raw::c_int) -> cudaError_t { + runtime::cudaGetDeviceCount(global::client(), count) +} + +#[no_mangle] +unsafe extern "C" fn cudaSetDevice(device: ::std::os::raw::c_int) -> cudaError_t { + runtime::cudaSetDevice(global::client(), device) +} + +#[no_mangle] +unsafe extern "C" fn cudaDeviceGetAttribute( + value: *mut ::std::os::raw::c_int, + attr: cudaDeviceAttr, + device: ::std::os::raw::c_int, +) -> cudaError_t { + runtime::cudaDeviceGetAttribute(global::client(), value, attr, device) +} + +#[no_mangle] +unsafe extern "C" fn cuModuleLoad( + module: *mut CUmodule, + fname: *const ::std::os::raw::c_char, +) -> cudaError_t { + runtime::cuModuleLoad(global::client(), module, fname) +} + +#[no_mangle] +unsafe extern "C" fn cuModuleLoadData( + module: *mut CUmodule, + image: *const ::std::os::raw::c_void, +) -> cudaError_t { + runtime::cuModuleLoadData(global::client(), module, image) +} + +#[no_mangle] +unsafe extern "C" fn cuModuleLoadFatBinary( + module: *mut CUmodule, + fatCubin: *const ::std::os::raw::c_void, +) -> cudaError_t { + runtime::cuModuleLoadFatBinary(global::client(), module, fatCubin) +} + +#[no_mangle] +unsafe extern "C" fn cuModuleUnload(module: CUmodule) -> cudaError_t { + runtime::cuModuleUnload(global::client(), module) } diff --git a/sdac-lib/src/runtime.rs b/sdac-lib/src/runtime.rs new file mode 100644 index 0000000..9a549d0 --- /dev/null +++ b/sdac-lib/src/runtime.rs @@ -0,0 +1,323 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +use ::std::os::raw::*; +use std::fs; +use clib::memcpy; +use futures::executor::block_on; +use service::*; +use std::ffi::CString; +use std::sync::Mutex; +use tarpc::context; + +/// Allocate memory on the device +/// Allocates \\p size bytes of linear memory on the device and returns in +/// *devPtr a pointer to the allocated memory. The allocated memory is +/// suitably aligned for any kind of variable. The memory is not cleared. +/// ::cudaMalloc() returns ::cudaErrorMemoryAllocation in case of failure. +/// +/// The device version of ::cudaFree cannot be used with a \\p *devPtr +/// allocated using the host API, and vice versa. +/// \\param devPtr - Pointer to allocated device memory +/// \\param size - Requested allocation size in bytes\n\n \\return +/// ::cudaSuccess,\n ::cudaErrorInvalidValue,\n ::cudaErrorMemoryAllocation\n \\notefnerr\n \\note_init_rt\n \\note_callback +/// +/// \\sa ::cudaMallocPitch, ::cudaFree, ::cudaMallocArray, ::cudaFreeArray, +/// ::cudaMalloc3D, ::cudaMalloc3DArray,\n \\ref ::cudaMallocHost(void**, size_t) \"cudaMallocHost (C API)\", +/// ::cudaFreeHost, ::cudaHostAlloc,\n ::cuMemAlloc"] +pub fn cudaMalloc( + client: &Mutex, + devPtr: *mut *mut c_void, + size: usize, +) -> cudaError_t { + let (remotePtr, res) = + block_on(client.lock().unwrap().cudaMalloc(context::current(), size)).unwrap(); + + if res != 0 { + return res; + } + + unsafe { + *devPtr = remotePtr as *mut c_void; + } + + res +} + +pub fn cudaFree( + client: &Mutex, + devPtr: *mut ::std::os::raw::c_void, +) -> cudaError_t { + block_on( + client + .lock() + .unwrap() + .cudaFree(context::current(), devPtr as usize), + ) + .unwrap() +} + +pub fn cudaMemcpy( + client: &Mutex, + dst: *mut ::std::os::raw::c_void, + src: *const ::std::os::raw::c_void, + count: usize, + kind: cudaMemcpyKind, +) -> cudaError_t { + let c = client.lock().unwrap(); + + match kind { + cudaMemcpyKind_cudaMemcpyHostToHost => { + memcpy(dst as usize, src as usize, count) + }, + + cudaMemcpyKind_cudaMemcpyHostToDevice => { + let data = unsafe { Vec::::from_raw_parts(src as *mut u8, count, count) }; + block_on(c.cudaMemcpyHtoD(context::current(), dst as usize, data, count)) + .unwrap() + } + + cudaMemcpyKind_cudaMemcpyDeviceToHost => { + let (data, res) = + block_on(c.cudaMemcpyDtoH(context::current(), dst as usize, src as usize, count)) + .unwrap(); + if res != 0 { + return res; + } + + unsafe { + memcpy(dst as usize, data.as_ptr() as usize, count); + } + + res + } + + cudaMemcpyKind_cudaMemcpyDeviceToDevice => { + block_on(c.cudaMemcpyDtoD(context::current(), dst as usize, src as usize, count)) + .unwrap() + } + + cudaMemcpyKind_cudaMemcpyDefault => { + // "< Direction of the transfer is inferred from the pointer values. Requires unified virtual addressing"] + // TODO(asalkeld) not sure how to figure out which direction this is.. + cudaError_enum_CUDA_ERROR_STUB_LIBRARY + } + } +} + +pub fn cudaMemset( + client: &Mutex, + devPtr: *mut ::std::os::raw::c_void, + value: ::std::os::raw::c_int, + count: usize, +) -> cudaError_t { + block_on( + client + .lock() + .unwrap() + .cudaMemset(context::current(), devPtr as usize, value, count), + ) + .unwrap() +} + +pub fn cudaGetLastError(client: &Mutex) -> cudaError_t { + block_on(client.lock().unwrap().cudaGetLastError(context::current())).unwrap() +} + +pub fn cudaPeekAtLastError(client: &Mutex) -> cudaError_t { + block_on( + client + .lock() + .unwrap() + .cudaPeekAtLastError(context::current()), + ) + .unwrap() +} + +pub fn cudaGetErrorName( + client: &Mutex, + error: cudaError_t, +) -> *const ::std::os::raw::c_char { + let c_str = block_on( + client + .lock() + .unwrap() + .cudaGetErrorName(context::current(), error), + ) + .unwrap(); + + CString::new(c_str).unwrap().into_raw() +} + +pub fn cudaGetErrorString( + client: &Mutex, + error: cudaError_t, +) -> *const ::std::os::raw::c_char { + let c_str = block_on( + client + .lock() + .unwrap() + .cudaGetErrorString(context::current(), error), + ) + .unwrap(); + + CString::new(c_str).unwrap().into_raw() +} + +pub fn cudaGetDeviceCount( + client: &Mutex, + count: *mut ::std::os::raw::c_int, +) -> cudaError_t { + let (cnt, res) = block_on( + client + .lock() + .unwrap() + .cudaGetDeviceCount(context::current()), + ) + .unwrap(); + + if res != 0 { + return res; + } + + unsafe { + *count = cnt; + } + + res +} + +pub fn cudaSetDevice( + client: &Mutex, + device: ::std::os::raw::c_int, +) -> cudaError_t { + block_on( + client + .lock() + .unwrap() + .cudaSetDevice(context::current(), device), + ) + .unwrap() +} + +pub fn cudaDeviceGetAttribute( + client: &Mutex, + value: *mut ::std::os::raw::c_int, + attr: cudaDeviceAttr, + device: ::std::os::raw::c_int, +) -> cudaError_t { + let (v, res) = block_on(client.lock().unwrap().cudaDeviceGetAttribute( + context::current(), + attr, + device, + )) + .unwrap(); + + if res != 0 { + return res; + } + + unsafe { + *value = v; + } + + res +} + +pub fn cuModuleLoad( + client: &Mutex, + module: *mut CUmodule, + fname: *const ::std::os::raw::c_char, +) -> cudaError_t { + let contents = fs::read_to_string(fname).expect("Should have been able to read the file"); + + let (remotePtr, res) = block_on( + client + .lock() + .unwrap() + .cuModuleLoadData(context::current(), contents.into_bytes()), + ) + .unwrap(); + + if res != 0 { + return res; + } + + unsafe { + *module = remotePtr as *mut cuModule_t; + } + + res +} + +/// Load a module's data +/// Takes a pointer \\p image and loads the corresponding module into the current context. +/// The pointer may be obtained by mapping a cubin or PTX or fatbin file, +/// passing a cubin or PTX or fatbin file as a NULL-terminated text string +/// or incorporating a cubin or fatbin object into the executable resources and +/// using operating system calls such as Windows FindResource() to obtain the pointer. +/// +/// module - Returned module +/// image - Module data to load +pub fn cuModuleLoadData( + client: &Mutex, + module: *mut CUmodule, + image: *const ::std::os::raw::c_void, +) -> cudaError_t { + let str = unsafe{CString::from_raw(image as *mut i8)}; + + let (remotePtr, res) = block_on( + client + .lock() + .unwrap() + .cuModuleLoadData(context::current(), str.into_bytes()), + ) + .unwrap(); + + if res != 0 { + return res; + } + + unsafe { + *module = remotePtr as CUmodule; + } + + res +} + +pub fn cuModuleLoadFatBinary( + client: &Mutex, + module: *mut CUmodule, + fatCubin: *const ::std::os::raw::c_void, +) -> cudaError_t { + let str = unsafe{CString::from_raw(fatCubin as *mut i8)}; + + let (remotePtr, res) = block_on( + client + .lock() + .unwrap() + .cuModuleLoadFatBinary(context::current(), str.into_bytes()), + ) + .unwrap(); + + if res != 0 { + return res; + } + + unsafe { + *module = remotePtr as CUmodule; + } + + res +} + +pub fn cuModuleUnload(client: &Mutex, module: CUmodule) -> cudaError_t { + block_on( + client + .lock() + .unwrap() + .cuModuleUnload(context::current(), module as usize), + ) + .unwrap() +} diff --git a/sdac-server/build-cuda-driver.rs b/sdac-server/build-cuda-driver.rs index b706d29..b7730a6 100644 --- a/sdac-server/build-cuda-driver.rs +++ b/sdac-server/build-cuda-driver.rs @@ -1,7 +1,7 @@ extern crate bindgen; use std::env; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use bindgen::callbacks::*; @@ -33,13 +33,24 @@ impl ParseCallbacks for NetworkEmitter { } fn main() { + let cdir = std::env::var("CUDA_DIR").unwrap_or("/usr/local/cuda-11.8".to_string()); + let cuda_dir = Path::new(&cdir); + let cuda_lib = cuda_dir.join("targets/x86_64-linux/lib/stubs"); + println!("cargo:rustc-link-lib=dylib=cuda"); - println!("cargo:rustc-link-search=native=/usr/local/cuda-11.8/targets/x86_64-linux/lib/stubs"); + println!("cargo:rustc-link-search=native={}", cuda_lib.display()); let bindings = bindgen::Builder::default() - .header("/usr/local/cuda-11.8/include/cuda.h") + .header(cuda_dir.join("include/cuda.h").display().to_string()) + .header( + cuda_dir + .join("include/cuda_runtime_api.h") + .display() + .to_string(), + ) .allowlist_function("cu.*") .allowlist_type("CU.*") + .allowlist_type("cuda.*") .derive_eq(true) .array_pointers_in_arguments(true) .parse_callbacks(Box::new(NetworkEmitter {})) diff --git a/sdac-server/src/main.rs b/sdac-server/src/main.rs index 7b079d3..cdcf882 100644 --- a/sdac-server/src/main.rs +++ b/sdac-server/src/main.rs @@ -5,13 +5,13 @@ include!(concat!(env!("OUT_DIR"), "/cuda_driver_bindings.rs")); use futures_util::StreamExt; +use service::Cuda as CudaService; use std::ffi::CString; -use anyhow; use tarpc::{ - context, server::{BaseChannel, Channel}, + context, + server::{BaseChannel, Channel}, tokio_serde::formats::Json, }; -use service::Cuda as CudaService; // This is the type that implements the generated World trait. It is the business logic // and is used to start the server. @@ -20,6 +20,40 @@ struct RemoteCuda; #[tarpc::server] impl service::Cuda for RemoteCuda { + async fn cuGetErrorName(self, _: context::Context, error: u32) -> (String, u32) { + let mut nameV: i8 = 1; + let name: *mut i8 = &mut nameV; + + unsafe { + let res = cuGetErrorName(error, name as *mut *const i8); + if res != cudaError_enum_CUDA_SUCCESS { + return (String::new(), res); + } + + let str = CString::from_raw(name) + .into_string() + .expect("failed to convert name"); + + (str, res) + } + } + async fn cuGetErrorString(self, _: context::Context, error: u32) -> (String, u32) { + let mut descrV: i8 = 1; + let descr: *mut i8 = &mut descrV; + + unsafe { + let res = cuGetErrorString(error, descr as *mut *const i8); + if res != cudaError_enum_CUDA_SUCCESS { + return (String::new(), res); + } + + let str = CString::from_raw(descr) + .into_string() + .expect("failed to convert name"); + + (str, res) + } + } async fn cuInit(self, _: context::Context, flags: u32) -> u32 { // TODO(asalkeld) This does not look right. cuInit should be called once per process or once for the server. // https://github.com/xertai/sdac/issues/38 @@ -61,6 +95,88 @@ impl service::Cuda for RemoteCuda { (strName, res) } } + async fn cuDeviceTotalMem_v2(dev: CUdevice) -> (usize, CUresult) { + let mut bytes: usize = 0; + unsafe { + let res = cuDeviceTotalMem_v2(&bytes, dev); + + (bytes, res) + } + } + async fn cuDeviceGetAttribute(self, _: context::Context, attrib: u32, dev: i32) -> (i32, u32) { + let mut value: i32 = 0; + + unsafe { + let res = cuDeviceGetAttribute(&mut value, attrib, dev); + + (value, res) + } + } + async fn cuModuleLoadData(self, _: context::Context, image: Vec::) -> (i32, u32) { + let mut module: CUmodule = 0; + let modulePtr: *mut CUmodule = &mut module; + + unsafe { + let res = cuModuleLoadData(modulePtr, image.as_ptr()); + + (*modulePtr, res) + } + } + async fn cuModuleLoadFatBinary(self, _: context::Context, fatCubin: Vec::) -> (i32, u32) { + let mut module: CUmodule = 0; + let modulePtr: *mut CUmodule = &mut module; + + unsafe { + let res = cuModuleLoadFatBinary(modulePtr, fatCubin.as_ptr()); + + (*modulePtr, res) + } + } + async fn cudaGetLastError(self, _: context::Context) -> u32 { + unsafe { cudaGetLastError() } + } + async fn cudaPeekAtLastError(self, _: context::Context) -> u32 { + unsafe { cudaPeekAtLastError() } + } + async fn cudaGetErrorName(self, _: context::Context, error: cudaError_t) -> String{ + unsafe { cudaGetErrorName(error) + } + async fn cudaGetErrorString(self, _: context::Context, error: cudaError_t) -> String{ + unsafe { cudaGetErrorString(error) + } + async fn cudaMalloc(self, _: context::Context, size: usize) -> (usize, cudaError_t) { + unsafe { cudaMalloc(devPtr as *mut *mut std::os::raw::c_void, size) } + } + async fn cudaFree(self, _: context::Context, devPtr: usize) -> u32 { + unsafe { cudaFree(devPtr as *mut std::os::raw::c_void) } + } + async fn cudaMemcpyDtoH(dst: usize, src: usize, count: usize) -> (Vec::, CUresult){ + let mut data = vec![0; count]; + unsafe { + let res = cudaMemcpyDtoH(data.as_mut_ptr(), src, count); + (data, res) + } + } + async fn cudaMemcpyHtoD(dst: usize, data: Vec::,size: usize) -> CUresult{ + unsafe { cudaMemcpyHtoD(dst, data.as_ptr(), size) + } + async fn cudaMemcpyDtoD(dst: usize, src: usize,size: usize) -> CUresult{ + unsafe { cudaMemcpyDtoD(dst, src, size) + } + async fn cudaMemset(devPtr: usize, value: c_int, count: usize) -> cudaError_t{ + unsafe { cudaMemset(devPtr, value, count) + } + async fn cudaGetDeviceCount() -> (i32, cudaError_t){ + let mut count: i32 = 0; + unsafe { cudaGetDeviceCount(&mut count) } + } + async fn cudaSetDevice(device: c_int) -> cudaError_t{ + unsafe { cudaSetDevice(device) } + } + async fn cudaDeviceGetAttribute(attr: cudaDeviceAttr, device: c_int) -> (c_int,cudaError_t){ + let mut value: c_int = 0; + unsafe { cudaDeviceGetAttribute(&mut value, attr, device) } + } } #[tokio::main] diff --git a/service/Cargo.toml b/service/Cargo.toml index d41ec19..7e767db 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -3,9 +3,16 @@ name = "service" version = "0.0.0" edition = "2021" publish = false +build = "build-cuda-types.rs" [lib] path = "service.rs" [dependencies] +serde = { version = "1.0.152", features = ["derive"] } tarpc = { version = "0.31.0", features = ["full"] } + +[build-dependencies] +bindgen = "0.63.0" +failure = "0.1.8" +regex = "1.7.1" diff --git a/service/build-cuda-types.rs b/service/build-cuda-types.rs new file mode 100644 index 0000000..118401d --- /dev/null +++ b/service/build-cuda-types.rs @@ -0,0 +1,35 @@ +extern crate bindgen; + +use std::{ + env, + path::{Path, PathBuf}, +}; + + +// Install NVIDIA CUDA prior to building the bindings with `cargo build`. +// https://docs.rs/bindgen/latest/bindgen/struct.Builder.html +fn main() { + let cdir = std::env::var("CUDA_DIR").unwrap_or("/usr/local/cuda-11.8".to_string()); + let cuda_dir = Path::new(&cdir); + + let bindings = bindgen::Builder::default() + .header(cuda_dir.join("include/cuda.h").display().to_string()) + .header(cuda_dir.join("include/cuda_runtime_api.h").display().to_string()) + .allowlist_type("CU.*") + .allowlist_type("cuda.*") + .derive_eq(true) + .array_pointers_in_arguments(true) + .generate() + .unwrap(); + + let target_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + let binding_file = target_path.join("cuda_types.rs"); + bindings + .write_to_file(binding_file) + .expect("Couldn't write bindings!"); + + println!( + "Wrote bindings to {}", + target_path.join("cuda_types.rs").display() + ); +} diff --git a/service/service.rs b/service/service.rs index 35e9a8c..244fe0c 100644 --- a/service/service.rs +++ b/service/service.rs @@ -2,12 +2,49 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] +include!(concat!(env!("OUT_DIR"), "/cuda_types.rs")); + +use ::std::os::raw::*; + /// This is the service definition. It looks a lot like a trait definition. // TODO(asalkeld) auto generate this interface. https://github.com/xertai/sdac/issues/40 #[tarpc::service] pub trait Cuda { - async fn cuInit(flags: u32) -> u32; - async fn cuDeviceGet(ordinal: i32) -> (i32, u32); - async fn cuDeviceGetCount() -> (i32, u32); - async fn cuDeviceGetName(maxLen: i32, dev: i32) -> (String, u32); + // CUDA Driver API + async fn cuGetErrorName(error: CUresult) -> (String, CUresult); + async fn cuGetErrorString(error: CUresult) -> (String, CUresult); + async fn cuInit(flags: u32) -> CUresult; + async fn cuDeviceGet(ordinal: i32) -> (i32, CUresult); + async fn cuDeviceGetCount() -> (i32, CUresult); + async fn cuDeviceGetName(maxLen: i32, dev: CUdevice) -> (String, CUresult); + async fn cuDeviceTotalMem_v2(dev: CUdevice) -> (usize, CUresult); + + async fn cuMemAlloc_v2(size: usize) -> (CUdeviceptr, CUresult); + async fn cuMemFree_v2(devPtr: CUdeviceptr) -> CUresult; + + async fn cuMemcpyDtoH_v2(src: CUdeviceptr, size: usize) -> (Vec::, CUresult); + async fn cuMemcpyHtoD_v2(dst: CUdeviceptr, data: Vec::,size: usize) -> CUresult; + + // Runtime API + async fn cudaGetLastError() -> cudaError_t; + async fn cudaPeekAtLastError() -> cudaError_t; + async fn cudaGetErrorName(error: cudaError_t) -> String; + async fn cudaGetErrorString(error: cudaError_t) -> String; + + async fn cudaGetDeviceCount() -> (i32, cudaError_t); + async fn cudaSetDevice(device: c_int) -> cudaError_t; + async fn cudaDeviceGetAttribute(attr: cudaDeviceAttr, device: c_int) -> (c_int,cudaError_t); + + async fn cudaMalloc(size: usize) -> (usize,cudaError_t); + async fn cudaFree(devPtr: usize) -> cudaError_t; + + async fn cudaMemcpyDtoH(dst: usize, src: usize, count: usize) -> (Vec::, CUresult); + async fn cudaMemcpyHtoD(dst: usize, data: Vec::,size: usize) -> CUresult; + async fn cudaMemcpyDtoD(dst: usize, src: usize,size: usize) -> CUresult; + + async fn cudaMemset(devPtr: usize, value: c_int, count: usize) -> cudaError_t; + + async fn cuModuleLoadData(data: Vec::) -> (usize, cudaError_t); + async fn cuModuleLoadFatBinary(data: Vec::) -> (usize, cudaError_t); + async fn cuModuleUnload(hmod: usize) -> cudaError_t; }