Skip to content

Commit

Permalink
sdk: common types and declarations for C++ modules
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddrysdale committed May 26, 2020
1 parent d7ff631 commit 820fa28
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 133 deletions.
2 changes: 1 addition & 1 deletion examples/hello_world/module/cpp/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
],
Expand Down
59 changes: 16 additions & 43 deletions examples/hello_world/module/cpp/hello_world.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,70 +17,43 @@
#include <stddef.h>
#include <stdint.h>

#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"

// 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;
}

// Create a gRPC server pseudo-Node
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);
Expand All @@ -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).
Expand Down
4 changes: 2 additions & 2 deletions examples/tensorflow/module/cpp/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
37 changes: 6 additions & 31 deletions examples/tensorflow/module/cpp/tensorflow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,13 @@
#include <stddef.h>
#include <stdint.h>

#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,
Expand Down Expand Up @@ -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<uint8_t>(grpc_in_handle & 0xff),
Expand All @@ -105,21 +80,21 @@ 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;
}

// 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).
Expand Down
37 changes: 6 additions & 31 deletions examples/tensorflow/module/cpp/tensorflow_micro.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,11 @@
#include <stddef.h>
#include <stdint.h>

#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
Expand Down Expand Up @@ -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<uint8_t>(grpc_in_handle & 0xff),
Expand All @@ -134,21 +109,21 @@ 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;
}

// 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).
Expand Down
4 changes: 2 additions & 2 deletions oak/module/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ package(
)

cc_library(
name = "defines",
hdrs = ["defines.h"],
name = "oak_abi",
hdrs = ["oak_abi.h"],
visibility = ["//visibility:public"],
)

Expand Down
23 changes: 0 additions & 23 deletions oak/module/defines.h

This file was deleted.

63 changes: 63 additions & 0 deletions oak/module/oak_abi.h
Original file line number Diff line number Diff line change
@@ -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 <stdint.h>

#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_

0 comments on commit 820fa28

Please sign in to comment.