From 820fa287c288e698342e4d1e4d65adde85768e85 Mon Sep 17 00:00:00 2001 From: David Drysdale Date: Tue, 26 May 2020 09:32:11 +0100 Subject: [PATCH] sdk: common types and declarations for C++ modules --- examples/hello_world/module/cpp/BUILD | 2 +- .../hello_world/module/cpp/hello_world.cc | 59 +++++------------ examples/tensorflow/module/cpp/BUILD | 4 +- examples/tensorflow/module/cpp/tensorflow.cc | 37 ++--------- .../tensorflow/module/cpp/tensorflow_micro.cc | 37 ++--------- oak/module/BUILD | 4 +- oak/module/defines.h | 23 ------- oak/module/oak_abi.h | 63 +++++++++++++++++++ 8 files changed, 96 insertions(+), 133 deletions(-) delete mode 100644 oak/module/defines.h create mode 100644 oak/module/oak_abi.h diff --git a/examples/hello_world/module/cpp/BUILD b/examples/hello_world/module/cpp/BUILD index a2bf652fc77..21c5bb9ad9b 100644 --- a/examples/hello_world/module/cpp/BUILD +++ b/examples/hello_world/module/cpp/BUILD @@ -25,7 +25,7 @@ cc_binary( name = "hello_world.wasm", srcs = ["hello_world.cc"], deps = [ - "//oak/module:defines", + "//oak/module:oak_abi", # TODO(#422): Sort out inclusion of protobuf files # "//oak/proto:oak_api_cc_proto", ], diff --git a/examples/hello_world/module/cpp/hello_world.cc b/examples/hello_world/module/cpp/hello_world.cc index 88bfc59adef..81b93be0d03 100644 --- a/examples/hello_world/module/cpp/hello_world.cc +++ b/examples/hello_world/module/cpp/hello_world.cc @@ -17,7 +17,7 @@ #include #include -#include "oak/module/defines.h" // for imports and exports +#include "oak/module/oak_abi.h" // TODO(#422): Sort out inclusion of protobuf files // #include "oak/proto/oak_api.pb.h" @@ -25,41 +25,14 @@ // Local copy of oak_api.pb.h contents for now. namespace oak { -enum OakStatus { - OAK_STATUS_UNSPECIFIED = 0, - OK = 1, - ERR_BAD_HANDLE = 2, - ERR_INVALID_ARGS = 3, - ERR_CHANNEL_CLOSED = 4, - ERR_BUFFER_TOO_SMALL = 5, - ERR_OUT_OF_RANGE = 6, - ERR_INTERNAL = 7, -}; - } // namespace oak -WASM_IMPORT("oak") uint32_t wait_on_channels(uint8_t* buff, int32_t count); -WASM_IMPORT("oak") -uint32_t channel_read(uint64_t handle, uint8_t* buff, size_t usize, uint32_t* actual_size, - uint64_t* handle_buff, size_t handle_count, uint32_t* actual_handle_count); -WASM_IMPORT("oak") -uint32_t channel_write(uint64_t handle, uint8_t* buff, size_t usize, uint8_t* handle_buff, - size_t handle_count); -WASM_IMPORT("oak") uint32_t channel_close(uint64_t handle); -WASM_IMPORT("oak") -uint32_t channel_create(uint64_t* write_handle, uint64_t* read_handle, uint8_t* label_buf, - size_t label_size); -WASM_IMPORT("oak") -uint32_t node_create(uint8_t* config_buf, size_t config_size, uint8_t* entrypoint_buf, - size_t entrypoint_size, uint8_t* label_buf, size_t label_size, - uint64_t handle); - -WASM_EXPORT void grpc_oak_main(uint64_t _handle) { +WASM_EXPORT void grpc_oak_main(oak_abi::Handle _handle) { // Create a channel to the gRPC server pseudo-Node. - uint64_t write_handle; - uint64_t read_handle; - uint32_t result = channel_create(&write_handle, &read_handle, nullptr, 0); - if (result != oak::OakStatus::OK) { + oak_abi::Handle write_handle; + oak_abi::Handle read_handle; + oak_abi::OakStatus result = channel_create(&write_handle, &read_handle, nullptr, 0); + if (result != oak_abi::OakStatus::OK) { return; } @@ -67,20 +40,20 @@ WASM_EXPORT void grpc_oak_main(uint64_t _handle) { char config_name[] = "grpc-server"; result = node_create((uint8_t*)config_name, sizeof(config_name) - 1, nullptr, 0, nullptr, 0, read_handle); - if (result != oak::OakStatus::OK) { + if (result != oak_abi::OakStatus::OK) { return; } channel_close(read_handle); // Create a separate channel for receiving invocations and pass it to the gRPC pseudo-Node. - uint64_t grpc_out_handle; - uint64_t grpc_in_handle; + oak_abi::Handle grpc_out_handle; + oak_abi::Handle grpc_in_handle; result = channel_create(&grpc_out_handle, &grpc_in_handle, nullptr, 0); - if (result != oak::OakStatus::OK) { + if (result != oak_abi::OakStatus::OK) { return; } result = channel_write(write_handle, nullptr, 0, (uint8_t*)&grpc_out_handle, 1); - if (result != oak::OakStatus::OK) { + if (result != oak_abi::OakStatus::OK) { return; } channel_close(grpc_out_handle); @@ -100,21 +73,21 @@ WASM_EXPORT void grpc_oak_main(uint64_t _handle) { }; while (true) { - uint32_t result = wait_on_channels(handle_space, 1); - if (result != oak::OakStatus::OK) { + result = wait_on_channels(handle_space, 1); + if (result != oak_abi::OakStatus::OK) { return; } // Reading from main channel should give no data and a (read, write) pair of handles. uint32_t actual_size; uint32_t handle_count; - uint64_t handles[2]; + oak_abi::Handle handles[2]; channel_read(grpc_in_handle, nullptr, 0, &actual_size, handles, 2, &handle_count); if ((actual_size != 0) || (handle_count != 2)) { return; } - uint64_t req_handle = handles[0]; - uint64_t rsp_handle = handles[1]; + oak_abi::Handle req_handle = handles[0]; + oak_abi::Handle rsp_handle = handles[1]; // Read an incoming request from the read handle, expecting data but no handles. // (However, ignore its contents for now). diff --git a/examples/tensorflow/module/cpp/BUILD b/examples/tensorflow/module/cpp/BUILD index ca8db41fb92..b66ddd64137 100644 --- a/examples/tensorflow/module/cpp/BUILD +++ b/examples/tensorflow/module/cpp/BUILD @@ -44,7 +44,7 @@ cc_binary( "-s WASM=1", ], deps = [ - "//oak/module:defines", + "//oak/module:oak_abi", "//oak/module:placeholders", # TODO(#422): Sort out inclusion of protobuf files # "//oak/proto:oak_api_cc_proto", @@ -77,7 +77,7 @@ cc_binary( "-s WASM=1", ], deps = [ - "//oak/module:defines", + "//oak/module:oak_abi", "//oak/module:placeholders", # TODO(#422): Sort out inclusion of protobuf files # "//oak/proto:oak_api_cc_proto", diff --git a/examples/tensorflow/module/cpp/tensorflow.cc b/examples/tensorflow/module/cpp/tensorflow.cc index bdca09268eb..dc3fee26120 100644 --- a/examples/tensorflow/module/cpp/tensorflow.cc +++ b/examples/tensorflow/module/cpp/tensorflow.cc @@ -17,29 +17,13 @@ #include #include -#include "oak/module/defines.h" // for imports and exports +#include "oak/module/oak_abi.h" #include "oak/module/placeholders.h" #include "tensorflow/lite/interpreter.h" #include "tensorflow/lite/kernels/register.h" #include "tensorflow/lite/model.h" #include "tensorflow/lite/optional_debug_tools.h" -// Local copy of oak_api.pb.h contents for now. -namespace oak { - -enum OakStatus { - OAK_STATUS_UNSPECIFIED = 0, - OK = 1, - ERR_BAD_HANDLE = 2, - ERR_INVALID_ARGS = 3, - ERR_CHANNEL_CLOSED = 4, - ERR_BUFFER_TOO_SMALL = 5, - ERR_OUT_OF_RANGE = 6, - ERR_INTERNAL = 7, -}; - -} // namespace oak - const char kModelBuffer[] = { 0x18, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x03, 0x00, @@ -81,16 +65,7 @@ std::string init_tensorflow() { return std::string("Success: Model was loaded correctly"); } -WASM_IMPORT("oak") uint32_t wait_on_channels(uint8_t* buff, int32_t count); -WASM_IMPORT("oak") -uint32_t channel_read(uint64_t handle, uint8_t* buff, size_t usize, uint32_t* actual_size, - uint64_t* handle_buff, size_t handle_count, uint32_t* actual_handle_count); -WASM_IMPORT("oak") -uint32_t channel_write(uint64_t handle, uint8_t* buff, size_t usize, uint8_t* handle_buff, - size_t handle_count); -WASM_IMPORT("oak") uint32_t channel_close(uint64_t handle); - -WASM_EXPORT void oak_main(uint64_t grpc_in_handle) { +WASM_EXPORT void oak_main(oak_abi::Handle grpc_in_handle) { // TODO(#744): Add C++ helpers for dealing with handle notification space. uint8_t handle_space[9] = { static_cast(grpc_in_handle & 0xff), @@ -105,7 +80,7 @@ WASM_EXPORT void oak_main(uint64_t grpc_in_handle) { }; while (true) { - int32_t result = wait_on_channels(handle_space, 1); + oak_abi::OakStatus result = wait_on_channels(handle_space, 1); if (result != oak::OakStatus::OK) { return; } @@ -113,13 +88,13 @@ WASM_EXPORT void oak_main(uint64_t grpc_in_handle) { // Reading from main channel should return no bytes and a (read, write) pair of handles. uint32_t actual_size; uint32_t handle_count; - uint64_t handles[2]; + oak_abi::Handle handles[2]; channel_read(grpc_in_handle, nullptr, 0, &actual_size, handles, 2, &handle_count); if ((actual_size != 0) || (handle_count != 2)) { return; } - uint64_t req_handle = handles[0]; - uint64_t rsp_handle = handles[1]; + oak_abi::Handle req_handle = handles[0]; + oak_abi::Handle rsp_handle = handles[1]; // Read an incoming request from the read handle, expecting data but no handles. // (However, ignore its contents for now). diff --git a/examples/tensorflow/module/cpp/tensorflow_micro.cc b/examples/tensorflow/module/cpp/tensorflow_micro.cc index 3cb5cfab8ab..fbe8033cbf6 100644 --- a/examples/tensorflow/module/cpp/tensorflow_micro.cc +++ b/examples/tensorflow/module/cpp/tensorflow_micro.cc @@ -17,27 +17,11 @@ #include #include -#include "oak/module/defines.h" // for imports and exports +#include "oak/module/oak_abi.h" #include "oak/module/placeholders.h" #include "tensorflow/lite/micro/kernels/all_ops_resolver.h" #include "tensorflow/lite/micro/micro_interpreter.h" -// Local copy of oak_api.pb.h contents for now. -namespace oak { - -enum OakStatus { - OAK_STATUS_UNSPECIFIED = 0, - OK = 1, - ERR_BAD_HANDLE = 2, - ERR_INVALID_ARGS = 3, - ERR_CHANNEL_CLOSED = 4, - ERR_BUFFER_TOO_SMALL = 5, - ERR_OUT_OF_RANGE = 6, - ERR_INTERNAL = 7, -}; - -} // namespace oak - // Constants were taken from the TFLite exapmles: // https://github.com/tensorflow/tensorflow/blob/11bed638b14898cdde967f6b108e45732aa4798a/tensorflow/lite/micro/examples/network_tester/network_tester_test.cc#L25 // https://github.com/tensorflow/tensorflow/blob/11bed638b14898cdde967f6b108e45732aa4798a/tensorflow/lite/micro/examples/network_tester/network_model.h#L16-L64 @@ -110,16 +94,7 @@ std::string init_tensorflow() { return std::string("Success: Model was loaded correctly"); } -WASM_IMPORT("oak") uint32_t wait_on_channels(uint8_t* buff, int32_t count); -WASM_IMPORT("oak") -uint32_t channel_read(uint64_t handle, uint8_t* buff, size_t usize, uint32_t* actual_size, - uint64_t* handle_buff, size_t handle_count, uint32_t* actual_handle_count); -WASM_IMPORT("oak") -uint32_t channel_write(uint64_t handle, uint8_t* buff, size_t usize, uint8_t* handle_buff, - size_t handle_count); -WASM_IMPORT("oak") uint32_t channel_close(uint64_t handle); - -WASM_EXPORT void oak_main(uint64_t grpc_in_handle) { +WASM_EXPORT void oak_main(oak_abi::Handle grpc_in_handle) { // TODO(#744): Add C++ helpers for dealing with handle notification space. uint8_t handle_space[9] = { static_cast(grpc_in_handle & 0xff), @@ -134,7 +109,7 @@ WASM_EXPORT void oak_main(uint64_t grpc_in_handle) { }; while (true) { - int32_t result = wait_on_channels(handle_space, 1); + oak_abi::OakStatus result = wait_on_channels(handle_space, 1); if (result != oak::OakStatus::OK) { return; } @@ -142,13 +117,13 @@ WASM_EXPORT void oak_main(uint64_t grpc_in_handle) { // Reading from main channel should return no bytes and a (read, write) pair of handles. uint32_t actual_size; uint32_t handle_count; - uint64_t handles[2]; + oak_abi::Handle handles[2]; channel_read(grpc_in_handle, nullptr, 0, &actual_size, handles, 2, &handle_count); if ((actual_size != 0) || (handle_count != 2)) { return; } - uint64_t req_handle = handles[0]; - uint64_t rsp_handle = handles[1]; + oak_abi::Handle req_handle = handles[0]; + oak_abi::Handle rsp_handle = handles[1]; // Read an incoming request from the read handle, expecting data but no handles. // (However, ignore its contents for now). diff --git a/oak/module/BUILD b/oak/module/BUILD index 3ce9b0bf27d..389be9db702 100644 --- a/oak/module/BUILD +++ b/oak/module/BUILD @@ -21,8 +21,8 @@ package( ) cc_library( - name = "defines", - hdrs = ["defines.h"], + name = "oak_abi", + hdrs = ["oak_abi.h"], visibility = ["//visibility:public"], ) diff --git a/oak/module/defines.h b/oak/module/defines.h deleted file mode 100644 index c74c406357e..00000000000 --- a/oak/module/defines.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2019 The Project Oak Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OAK_MODULE_DEFINES_H_ -#define OAK_MODULE_DEFINES_H_ - -#define WASM_EXPORT extern "C" __attribute__((visibility("default"))) -#define WASM_IMPORT(module_name) extern "C" __attribute__((import_module(module_name))) - -#endif // OAK_MODULE_DEFINES_H_ \ No newline at end of file diff --git a/oak/module/oak_abi.h b/oak/module/oak_abi.h new file mode 100644 index 00000000000..8d7664599c3 --- /dev/null +++ b/oak/module/oak_abi.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 The Project Oak Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OAK_MODULE_OAK_ABI_H_ +#define OAK_MODULE_OAK_ABI_H_ + +#include + +#define WASM_EXPORT extern "C" __attribute__((visibility("default"))) +#define WASM_IMPORT(module_name) extern "C" __attribute__((import_module(module_name))) + +// Types and enum values used on the Oak ABI. +namespace oak_abi { + +using Handle = uint64_t; + +enum OakStatus : uint32_t { + OAK_STATUS_UNSPECIFIED = 0, + OK = 1, + ERR_BAD_HANDLE = 2, + ERR_INVALID_ARGS = 3, + ERR_CHANNEL_CLOSED = 4, + ERR_BUFFER_TOO_SMALL = 5, + ERR_OUT_OF_RANGE = 6, + ERR_INTERNAL = 7, +}; + +} // namespace oak_abi + +// Function declarations for the host functions available on the Oak ABI. +WASM_IMPORT("oak") oak_abi::OakStatus wait_on_channels(uint8_t* buff, int32_t count); +WASM_IMPORT("oak") +oak_abi::OakStatus channel_read(oak_abi::Handle handle, uint8_t* buff, size_t usize, + uint32_t* actual_size, oak_abi::Handle* handle_buff, + size_t handle_count, uint32_t* actual_handle_count); +WASM_IMPORT("oak") +oak_abi::OakStatus channel_write(oak_abi::Handle handle, uint8_t* buff, size_t usize, + uint8_t* handle_buff, size_t handle_count); +WASM_IMPORT("oak") oak_abi::OakStatus channel_close(oak_abi::Handle handle); +WASM_IMPORT("oak") +oak_abi::OakStatus channel_create(oak_abi::Handle* write_handle, oak_abi::Handle* read_handle, + uint8_t* label_buf, size_t label_size); +WASM_IMPORT("oak") +oak_abi::OakStatus node_create(uint8_t* config_buf, size_t config_size, uint8_t* entrypoint_buf, + size_t entrypoint_size, uint8_t* label_buf, size_t label_size, + oak_abi::Handle handle); +WASM_IMPORT("oak") +oak_abi::OakStatus random_get(uint8_t* buf, size_t buf_size); + +#endif // OAK_MODULE_OAK_ABI_H_