add asynchronous switchless example
This commit is contained in:
parent
bf8d8ca924
commit
ec31d3e30c
860
0053-asynchronous-switchless-example.patch
Normal file
860
0053-asynchronous-switchless-example.patch
Normal file
@ -0,0 +1,860 @@
|
||||
From 508f9aed76b8f6788be60a8e39849ee6c1a32fcc Mon Sep 17 00:00:00 2001
|
||||
From: modric <wangyu283@huawei.com>
|
||||
Date: Wed, 9 Nov 2022 15:19:58 +0800
|
||||
Subject: [PATCH 4/4] asynchronous switchless example
|
||||
|
||||
---
|
||||
.../enclave/CMakeLists.txt | 16 +-
|
||||
.../switchless_performance/enclave/enclave.c | 77 ++
|
||||
examples/switchless_performance/host/main.c | 656 +++++++++++++++++-
|
||||
.../switchless_performance/switchless.edl | 13 +
|
||||
4 files changed, 750 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/examples/switchless_performance/enclave/CMakeLists.txt b/examples/switchless_performance/enclave/CMakeLists.txt
|
||||
index 69aab4c..f7b72b1 100644
|
||||
--- a/examples/switchless_performance/enclave/CMakeLists.txt
|
||||
+++ b/examples/switchless_performance/enclave/CMakeLists.txt
|
||||
@@ -62,7 +62,21 @@ set(COMMON_C_FLAGS "-W -Wall -Werror -fno-short-enums -fno-omit-frame-pointer -f
|
||||
set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles")
|
||||
|
||||
if(CC_GP)
|
||||
- set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a")
|
||||
+ if (CMAKE_COMPILER_IS_GNUCC)
|
||||
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpfullversion -dumpversion
|
||||
+ OUTPUT_VARIABLE GCC_VERSION)
|
||||
+ string(REGEX MATCHALL "[0-9]+" GCC_VERSION_COMPONENTS ${GCC_VERSION})
|
||||
+ list(GET GCC_VERSION_COMPONENTS 0 GCC_MAJOR)
|
||||
+ list(GET GCC_VERSION_COMPONENTS 1 GCC_MINOR)
|
||||
+ set(GCC_VERSION "${GCC_MAJOR}.${GCC_MINOR}")
|
||||
+ endif()
|
||||
+
|
||||
+ if (GCC_VERSION GREATER_EQUAL "9.4")
|
||||
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a -mno-outline-atomics")
|
||||
+ else()
|
||||
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a")
|
||||
+ endif()
|
||||
+
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s")
|
||||
|
||||
diff --git a/examples/switchless_performance/enclave/enclave.c b/examples/switchless_performance/enclave/enclave.c
|
||||
index 1320e53..8b1466f 100644
|
||||
--- a/examples/switchless_performance/enclave/enclave.c
|
||||
+++ b/examples/switchless_performance/enclave/enclave.c
|
||||
@@ -28,10 +28,87 @@ void test_toupper(char *buf, int len)
|
||||
}
|
||||
}
|
||||
|
||||
+static int i = 0;
|
||||
+static int j = 0;
|
||||
+
|
||||
void ecall_empty(void)
|
||||
{
|
||||
+ printf("normal %d\n", __atomic_add_fetch(&i, 1, __ATOMIC_ACQ_REL));
|
||||
+}
|
||||
+
|
||||
+int ecall_empty1(char *buf, int len)
|
||||
+{
|
||||
+ printf("normal1 %d\n", __atomic_add_fetch(&i, 1, __ATOMIC_ACQ_REL));
|
||||
+
|
||||
+ if (buf == NULL || len < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < len; ++i) {
|
||||
+ if (buf[i] >= 'a' && buf[i] <= 'z') {
|
||||
+ buf[i] = buf[i] - ('a' - 'A');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+int ecall_empty2(char *buf1, int len1, char *buf2, int len2)
|
||||
+{
|
||||
+ printf("normal2 %d\n", __atomic_add_fetch(&i, 1, __ATOMIC_ACQ_REL));
|
||||
+
|
||||
+ if (buf1 == NULL || len1 < 0 || buf2 == NULL || len2 < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < len2; ++i) {
|
||||
+ if (buf1[i] >= 'a' && buf1[i] <= 'z') {
|
||||
+ buf2[i] = buf1[i] - ('a' - 'A');
|
||||
+ } else {
|
||||
+ buf2[i] = buf1[i];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 2;
|
||||
}
|
||||
|
||||
void ecall_empty_switchless(void)
|
||||
{
|
||||
+ printf("sl %d\n", __atomic_add_fetch(&j, 1, __ATOMIC_ACQ_REL));
|
||||
+}
|
||||
+
|
||||
+int ecall_empty_switchless1(char *buf, int len)
|
||||
+{
|
||||
+ printf("sl1 %d\n", __atomic_add_fetch(&j, 1, __ATOMIC_ACQ_REL));
|
||||
+
|
||||
+ if (buf == NULL || len < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < len; ++i) {
|
||||
+ if (buf[i] >= 'a' && buf[i] <= 'z') {
|
||||
+ buf[i] = buf[i] - ('a' - 'A');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+int ecall_empty_switchless2(char *buf1, int len1, char *buf2, int len2)
|
||||
+{
|
||||
+ printf("sl2 %d\n", __atomic_add_fetch(&j, 1, __ATOMIC_ACQ_REL));
|
||||
+
|
||||
+ if (buf1 == NULL || len1 < 0 || buf2 == NULL || len2 < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < len2; ++i) {
|
||||
+ if (buf1[i] >= 'a' && buf1[i] <= 'z') {
|
||||
+ buf2[i] = buf1[i] - ('a' - 'A');
|
||||
+ } else {
|
||||
+ buf2[i] = buf1[i];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 2;
|
||||
}
|
||||
diff --git a/examples/switchless_performance/host/main.c b/examples/switchless_performance/host/main.c
|
||||
index f80db25..ea4994f 100644
|
||||
--- a/examples/switchless_performance/host/main.c
|
||||
+++ b/examples/switchless_performance/host/main.c
|
||||
@@ -63,23 +63,600 @@ void fini_enclave(cc_enclave_t *enclave)
|
||||
|
||||
void benchmark_ecall_empty(bool is_switchless, unsigned long nrepeats)
|
||||
{
|
||||
- struct timespec time_start;
|
||||
- struct timespec time_end;
|
||||
- struct timespec duration = {0, 0};
|
||||
+ struct timeval tval_before;
|
||||
+ struct timeval tval_after;
|
||||
+ struct timeval duration;
|
||||
cc_enclave_result_t(*ecall_fn)(cc_enclave_t *) = is_switchless ? ecall_empty_switchless : ecall_empty;
|
||||
|
||||
- clock_gettime(CLOCK_REALTIME, &time_start);
|
||||
+ gettimeofday(&tval_before, NULL);
|
||||
unsigned long tmp_nrepeats = nrepeats;
|
||||
while (tmp_nrepeats--) {
|
||||
ecall_fn(&g_enclave);
|
||||
}
|
||||
- clock_gettime(CLOCK_REALTIME, &time_end);
|
||||
|
||||
- duration.tv_sec += time_end.tv_sec - time_start.tv_sec;
|
||||
- duration.tv_nsec += time_end.tv_nsec - time_start.tv_nsec;
|
||||
+ gettimeofday(&tval_after, NULL);
|
||||
+ timersub(&tval_after, &tval_before, &duration);
|
||||
|
||||
- printf("Repeating an %s empty ecall for %lu times takes %lu.%09lus\n",
|
||||
- is_switchless ? "[switchless]" : "[ ordinary ]", nrepeats, duration.tv_sec, duration.tv_nsec);
|
||||
+ printf("Repeating an %s empty ecall for %lu times takes %ld.%06lds\n",
|
||||
+ is_switchless ? "[switchless]" : "[ ordinary ]", nrepeats, (long)duration.tv_sec, (long)duration.tv_usec);
|
||||
+}
|
||||
+
|
||||
+/* ecall_empty_switchless */
|
||||
+void benchmark_ecall_empty_sl_async(unsigned long nrepeats)
|
||||
+{
|
||||
+ cc_enclave_result_t ret_code;
|
||||
+ cc_enclave_result_t ret;
|
||||
+ struct timeval tval_before;
|
||||
+ struct timeval tval_after;
|
||||
+ struct timeval duration;
|
||||
+ int processed_cursor = 0;
|
||||
+ int retry_count = 0;
|
||||
+
|
||||
+ int *arr = (int *)calloc(nrepeats, sizeof(int));
|
||||
+ if (arr == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // BEGIN
|
||||
+ gettimeofday(&tval_before, NULL);
|
||||
+
|
||||
+ for (int i = 0; i < nrepeats; ++i) {
|
||||
+ ret_code = ecall_empty_switchless_async(&g_enclave, &arr[i]);
|
||||
+ if (ret_code != CC_SUCCESS) {
|
||||
+ if (ret_code == CC_ERROR_SWITCHLESS_TASK_POOL_FULL) {
|
||||
+ // The task pool is full. You should try again later.
|
||||
+ --i;
|
||||
+ ++retry_count;
|
||||
+ } else {
|
||||
+ // Asynchronous invocation failed
|
||||
+ printf("Asynchronous invocation failed, ret=%x\n", ret_code);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], NULL);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ while (processed_cursor < nrepeats) {
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], NULL);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ continue;
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // END
|
||||
+ gettimeofday(&tval_after, NULL);
|
||||
+ timersub(&tval_after, &tval_before, &duration);
|
||||
+
|
||||
+ free(arr);
|
||||
+
|
||||
+ printf("retry_count:%d, processed_cursor:%d\n", retry_count, processed_cursor);
|
||||
+ printf("Repeating an empty sl async ecall for %lu times takes %ld.%06lds\n", nrepeats,
|
||||
+ (long int)duration.tv_sec, (long int)duration.tv_usec);
|
||||
+}
|
||||
+
|
||||
+void benchmark_ecall_empty_sl_async_rollback(unsigned long nrepeats)
|
||||
+{
|
||||
+ cc_enclave_result_t ret_code;
|
||||
+ cc_enclave_result_t ret;
|
||||
+ struct timeval tval_before;
|
||||
+ struct timeval tval_after;
|
||||
+ struct timeval duration;
|
||||
+ int processed_cursor = 0;
|
||||
+ int rollback_count = 0;
|
||||
+ unsigned long tmp_nrepeats = nrepeats;
|
||||
+
|
||||
+ int *arr = (int *)calloc(nrepeats, sizeof(int));
|
||||
+ if (arr == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // BEGIN
|
||||
+ gettimeofday(&tval_before, NULL);
|
||||
+
|
||||
+ for (int i = 0; i < tmp_nrepeats; ++i) {
|
||||
+ ret_code = ecall_empty_switchless_async(&g_enclave, &arr[i]);
|
||||
+ if (ret_code == CC_SUCCESS) {
|
||||
+ if (arr[i] == -1) {
|
||||
+ // rollback to common invoking when asynchronous switchless fails, and the common call is successful now
|
||||
+ --i;
|
||||
+ --tmp_nrepeats;
|
||||
+ rollback_count++;
|
||||
+ }
|
||||
+ } else {
|
||||
+ // Asynchronous invocation failed
|
||||
+ printf("Asynchronous invocation failed, ret=%x\n", ret_code);
|
||||
+ }
|
||||
+
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], NULL);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ while (processed_cursor < tmp_nrepeats) {
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], NULL);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ continue;
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // END
|
||||
+ gettimeofday(&tval_after, NULL);
|
||||
+ timersub(&tval_after, &tval_before, &duration);
|
||||
+
|
||||
+ free(arr);
|
||||
+
|
||||
+ printf("rollback_count:%d, processed_cursor:%d\n", rollback_count, processed_cursor);
|
||||
+ printf("Repeating an empty sl async ecall rollback for %lu times takes %ld.%06lds\n", nrepeats,
|
||||
+ (long int)duration.tv_sec, (long int)duration.tv_usec);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* ecall_empty_switchless1 */
|
||||
+void benchmark_ecall_empty_sl_async1(unsigned long nrepeats)
|
||||
+{
|
||||
+ cc_enclave_result_t ret_code;
|
||||
+ cc_enclave_result_t ret;
|
||||
+ struct timeval tval_before;
|
||||
+ struct timeval tval_after;
|
||||
+ struct timeval duration;
|
||||
+ int processed_cursor = 0;
|
||||
+ int retry_count = 0;
|
||||
+ int one_share_buf_len = 32;
|
||||
+ int retval;
|
||||
+
|
||||
+ int *arr = (int *)calloc(nrepeats, sizeof(int));
|
||||
+ if (arr == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ char *sharebuf = (char *)cc_malloc_shared_memory(&g_enclave, nrepeats * one_share_buf_len);
|
||||
+ if (sharebuf == NULL) {
|
||||
+ free(arr);
|
||||
+ printf("Error: malloc shared memory failed.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // BEGIN
|
||||
+ gettimeofday(&tval_before, NULL);
|
||||
+
|
||||
+ for (int i = 0; i < nrepeats; ++i) {
|
||||
+ strcpy(sharebuf + i * one_share_buf_len, "aAbBcCdD");
|
||||
+ ret_code = ecall_empty_switchless1_async(&g_enclave, &arr[i], NULL, sharebuf + i * one_share_buf_len,
|
||||
+ sizeof("aAbBcCdD"));
|
||||
+ if (ret_code != CC_SUCCESS) {
|
||||
+ if (ret_code == CC_ERROR_SWITCHLESS_TASK_POOL_FULL) {
|
||||
+ // The task pool is full. You should try again later.
|
||||
+ --i;
|
||||
+ ++retry_count;
|
||||
+ } else {
|
||||
+ // Asynchronous invocation failed
|
||||
+ printf("Asynchronous invocation failed, ret=%x\n", ret_code);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], &retval);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded, and check the execution result.
|
||||
+ if (retval != 1) {
|
||||
+ printf("get result retval err:%d, index:%d\n", retval, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp("AABBCCDD", sharebuf + processed_cursor * one_share_buf_len)) {
|
||||
+ printf("get result buffer err:%s, index:%d\n", sharebuf + processed_cursor * one_share_buf_len,
|
||||
+ processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ while (processed_cursor < nrepeats) {
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], &retval);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ continue;
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded, and check the execution result.
|
||||
+ if (retval != 1) {
|
||||
+ printf("get result retval err:%d, index:%d\n", retval, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp("AABBCCDD", sharebuf + processed_cursor * one_share_buf_len)) {
|
||||
+ printf("get result buffer err:%s, index:%d\n", sharebuf + processed_cursor * one_share_buf_len,
|
||||
+ processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // END
|
||||
+ gettimeofday(&tval_after, NULL);
|
||||
+ timersub(&tval_after, &tval_before, &duration);
|
||||
+
|
||||
+ free(arr);
|
||||
+
|
||||
+ ret = cc_free_shared_memory(&g_enclave, sharebuf);
|
||||
+ if (ret != CC_SUCCESS) {
|
||||
+ printf("Error: free shared memory failed:%x.\n", ret);
|
||||
+ }
|
||||
+
|
||||
+ printf("retry_count:%d, processed_cursor:%d\n", retry_count, processed_cursor);
|
||||
+ printf("Repeating an empty sl async ecall [1] for %lu times takes %ld.%06lds\n", nrepeats,
|
||||
+ (long int)duration.tv_sec, (long int)duration.tv_usec);
|
||||
+}
|
||||
+
|
||||
+void benchmark_ecall_empty_sl_async_rollback1(unsigned long nrepeats)
|
||||
+{
|
||||
+ cc_enclave_result_t ret_code;
|
||||
+ cc_enclave_result_t ret;
|
||||
+ struct timeval tval_before;
|
||||
+ struct timeval tval_after;
|
||||
+ struct timeval duration;
|
||||
+ int processed_cursor = 0;
|
||||
+ int one_share_buf_len = 32;
|
||||
+ int rollback_count = 0;
|
||||
+ int retval;
|
||||
+ unsigned long tmp_nrepeats = nrepeats;
|
||||
+
|
||||
+ int *arr = (int *)calloc(nrepeats, sizeof(int));
|
||||
+ if (arr == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ char *sharebuf = (char *)cc_malloc_shared_memory(&g_enclave, nrepeats * one_share_buf_len);
|
||||
+ if (sharebuf == NULL) {
|
||||
+ free(arr);
|
||||
+ printf("Error: malloc shared memory failed.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // BEGIN
|
||||
+ gettimeofday(&tval_before, NULL);
|
||||
+
|
||||
+ for (int i = 0; i < tmp_nrepeats; ++i) {
|
||||
+ strcpy(sharebuf + i * one_share_buf_len, "aAbBcCdD");
|
||||
+ ret_code = ecall_empty_switchless1_async(&g_enclave, &arr[i], &retval, sharebuf + i * one_share_buf_len,
|
||||
+ sizeof("aAbBcCdD"));
|
||||
+ if (ret_code == CC_SUCCESS) {
|
||||
+ if (arr[i] == -1) {
|
||||
+ /*
|
||||
+ * rollback to common invoking when asynchronous switchless fails, and the common call
|
||||
+ * is successful now, check the execution result.
|
||||
+ */
|
||||
+ if (retval != 1) {
|
||||
+ printf("get result retval err:%d, index:%d\n", retval, i);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp("AABBCCDD", sharebuf + i * one_share_buf_len)) {
|
||||
+ printf("get result buffer err:%s, index:%d\n", sharebuf + i * one_share_buf_len, i);
|
||||
+ }
|
||||
+
|
||||
+ --i;
|
||||
+ --tmp_nrepeats;
|
||||
+ rollback_count++;
|
||||
+ }
|
||||
+ } else {
|
||||
+ // Asynchronous invocation failed
|
||||
+ printf("Asynchronous invocation failed, ret=%x\n", ret_code);
|
||||
+ }
|
||||
+
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], &retval);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded, check the execution result.
|
||||
+ if (retval != 1) {
|
||||
+ printf("get result retval err:%d, index:%d\n", retval, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp("AABBCCDD", sharebuf + processed_cursor * one_share_buf_len)) {
|
||||
+ printf("get result buffer err:%s, index:%d\n", sharebuf + processed_cursor * one_share_buf_len,
|
||||
+ processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ while (processed_cursor < tmp_nrepeats) {
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], &retval);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ continue;
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded, check the execution result.
|
||||
+ if (retval != 1) {
|
||||
+ printf("get result retval err:%d, index:%d\n", retval, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp("AABBCCDD", sharebuf + processed_cursor * one_share_buf_len)) {
|
||||
+ printf("get result buffer err:%s, index:%d\n", sharebuf + processed_cursor * one_share_buf_len,
|
||||
+ processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // END
|
||||
+ gettimeofday(&tval_after, NULL);
|
||||
+ timersub(&tval_after, &tval_before, &duration);
|
||||
+
|
||||
+ free(arr);
|
||||
+ ret = cc_free_shared_memory(&g_enclave, sharebuf);
|
||||
+ if (ret != CC_SUCCESS) {
|
||||
+ printf("Error: free shared memory failed:%x.\n", ret);
|
||||
+ }
|
||||
+
|
||||
+ printf("rollback_count:%d, processed_cursor:%d\n", rollback_count, processed_cursor);
|
||||
+ printf("Repeating an empty sl async ecall rollback [1] for %lu times takes %ld.%06lds\n", nrepeats,
|
||||
+ (long int)duration.tv_sec, (long int)duration.tv_usec);
|
||||
+}
|
||||
+
|
||||
+/* ecall_empty_switchless2 */
|
||||
+void benchmark_ecall_empty_sl_async2(unsigned long nrepeats)
|
||||
+{
|
||||
+ cc_enclave_result_t ret_code;
|
||||
+ cc_enclave_result_t ret;
|
||||
+ struct timeval tval_before;
|
||||
+ struct timeval tval_after;
|
||||
+ struct timeval duration;
|
||||
+ int processed_cursor = 0;
|
||||
+ int retry_count = 0;
|
||||
+ int one_share_buf_len = 32;
|
||||
+ int half_one_share_buf_len = 16;
|
||||
+ int retval;
|
||||
+
|
||||
+ int *arr = (int *)calloc(nrepeats, sizeof(int));
|
||||
+ if (arr == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ char *sharebuf = (char *)cc_malloc_shared_memory(&g_enclave, nrepeats * one_share_buf_len);
|
||||
+ if (sharebuf == NULL) {
|
||||
+ free(arr);
|
||||
+ printf("Error: malloc shared memory failed.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ memset(sharebuf, 0, nrepeats * one_share_buf_len);
|
||||
+
|
||||
+ // BEGIN
|
||||
+ gettimeofday(&tval_before, NULL);
|
||||
+
|
||||
+ for (int i = 0; i < nrepeats; ++i) {
|
||||
+ strcpy(sharebuf + i * one_share_buf_len, "aAbBcCdD");
|
||||
+ ret_code = ecall_empty_switchless2_async(&g_enclave, &arr[i], NULL, sharebuf + i * one_share_buf_len,
|
||||
+ sizeof("aAbBcCdD"), sharebuf + i * one_share_buf_len + half_one_share_buf_len, sizeof("aAbBcCdD"));
|
||||
+ if (ret_code != CC_SUCCESS) {
|
||||
+ if (ret_code == CC_ERROR_SWITCHLESS_TASK_POOL_FULL) {
|
||||
+ // The task pool is full. You should try again later.
|
||||
+ --i;
|
||||
+ ++retry_count;
|
||||
+ } else {
|
||||
+ // Asynchronous invocation failed
|
||||
+ printf("Asynchronous invocation failed, ret=%x\n", ret_code);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], &retval);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded, check the execution result.
|
||||
+ if (retval != 2) {
|
||||
+ printf("get result retval err:%d, index:%d\n", retval, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp("AABBCCDD", sharebuf + processed_cursor * one_share_buf_len + half_one_share_buf_len)) {
|
||||
+ printf("get result buffer err:%s, index:%d\n",
|
||||
+ sharebuf + processed_cursor * one_share_buf_len + half_one_share_buf_len, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ while (processed_cursor < nrepeats) {
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], &retval);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ continue;
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded, check the execution result.
|
||||
+ if (retval != 2) {
|
||||
+ printf("get result retval err:%d, index:%d\n", retval, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp("AABBCCDD", sharebuf + processed_cursor * one_share_buf_len + half_one_share_buf_len)) {
|
||||
+ printf("get result buffer err:%s, index:%d\n",
|
||||
+ sharebuf + processed_cursor * one_share_buf_len + half_one_share_buf_len, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // END
|
||||
+ gettimeofday(&tval_after, NULL);
|
||||
+ timersub(&tval_after, &tval_before, &duration);
|
||||
+
|
||||
+ free(arr);
|
||||
+
|
||||
+ ret = cc_free_shared_memory(&g_enclave, sharebuf);
|
||||
+ if (ret != CC_SUCCESS) {
|
||||
+ printf("Error: free shared memory failed:%x.\n", ret);
|
||||
+ }
|
||||
+
|
||||
+ printf("retry_count:%d, processed_cursor:%d\n", retry_count, processed_cursor);
|
||||
+ printf("Repeating an empty sl async ecall [2] for %lu times takes %ld.%06lds\n", nrepeats,
|
||||
+ (long int)duration.tv_sec, (long int)duration.tv_usec);
|
||||
+}
|
||||
+
|
||||
+void benchmark_ecall_empty_sl_async_rollback2(unsigned long nrepeats)
|
||||
+{
|
||||
+ cc_enclave_result_t ret_code;
|
||||
+ cc_enclave_result_t ret;
|
||||
+ struct timeval tval_before;
|
||||
+ struct timeval tval_after;
|
||||
+ struct timeval duration;
|
||||
+ int processed_cursor = 0;
|
||||
+ int one_share_buf_len = 32;
|
||||
+ int half_one_share_buf_len = 16;
|
||||
+ int rollback_count = 0;
|
||||
+ int retval;
|
||||
+ unsigned long tmp_nrepeats = nrepeats;
|
||||
+
|
||||
+ int *arr = (int *)calloc(nrepeats, sizeof(int));
|
||||
+ if (arr == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ char *sharebuf = (char *)cc_malloc_shared_memory(&g_enclave, nrepeats * one_share_buf_len);
|
||||
+ if (sharebuf == NULL) {
|
||||
+ free(arr);
|
||||
+ printf("Error: malloc shared memory failed.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // BEGIN
|
||||
+ gettimeofday(&tval_before, NULL);
|
||||
+
|
||||
+ for (int i = 0; i < tmp_nrepeats; ++i) {
|
||||
+ strcpy(sharebuf + i * one_share_buf_len, "aAbBcCdD");
|
||||
+ ret_code = ecall_empty_switchless2_async(&g_enclave, &arr[i], &retval, sharebuf + i * one_share_buf_len,
|
||||
+ sizeof("aAbBcCdD"), sharebuf + i * one_share_buf_len + half_one_share_buf_len, sizeof("aAbBcCdD"));
|
||||
+ if (ret_code == CC_SUCCESS) {
|
||||
+ if (arr[i] == -1) {
|
||||
+ /*
|
||||
+ * rollback to common invoking when asynchronous switchless fails, and the common call
|
||||
+ * is successful now, check the execution result.
|
||||
+ */
|
||||
+ if (retval != 2) {
|
||||
+ printf("get result retval err:%d, index:%d\n", retval, i);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp("AABBCCDD", sharebuf + i * one_share_buf_len + half_one_share_buf_len)) {
|
||||
+ printf("get result buffer err:%s, index:%d\n",
|
||||
+ sharebuf + i * one_share_buf_len + half_one_share_buf_len, i);
|
||||
+ }
|
||||
+
|
||||
+ --i;
|
||||
+ --tmp_nrepeats;
|
||||
+ rollback_count++;
|
||||
+ }
|
||||
+ } else {
|
||||
+ // Asynchronous invocation failed
|
||||
+ printf("Asynchronous invocation failed, ret=%x\n", ret_code);
|
||||
+ }
|
||||
+
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], &retval);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded, check the execution result.
|
||||
+ if (retval != 2) {
|
||||
+ printf("get result retval err:%d, index:%d\n", retval, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp("AABBCCDD", sharebuf + processed_cursor * one_share_buf_len + half_one_share_buf_len)) {
|
||||
+ printf("get result buffer err:%s, index:%d\n",
|
||||
+ sharebuf + processed_cursor * one_share_buf_len + half_one_share_buf_len, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ while (processed_cursor < tmp_nrepeats) {
|
||||
+ ret = cc_sl_get_async_result(&g_enclave, arr[processed_cursor], &retval);
|
||||
+ if (ret == CC_ERROR_SWITCHLESS_ASYNC_TASK_UNFINISHED) {
|
||||
+ // Invoking processing
|
||||
+ continue;
|
||||
+ } else if (ret == CC_SUCCESS) {
|
||||
+ // Obtaining the result succeeded, check the execution result.
|
||||
+ if (retval != 2) {
|
||||
+ printf("get result retval err:%d, index:%d\n", retval, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp("AABBCCDD", sharebuf + processed_cursor * one_share_buf_len + half_one_share_buf_len)) {
|
||||
+ printf("get result buffer err:%s, index:%d\n",
|
||||
+ sharebuf + processed_cursor * one_share_buf_len + half_one_share_buf_len, processed_cursor);
|
||||
+ }
|
||||
+
|
||||
+ processed_cursor++;
|
||||
+ } else {
|
||||
+ // Failed to obtain the result
|
||||
+ processed_cursor++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // END
|
||||
+ gettimeofday(&tval_after, NULL);
|
||||
+ timersub(&tval_after, &tval_before, &duration);
|
||||
+
|
||||
+ free(arr);
|
||||
+ ret = cc_free_shared_memory(&g_enclave, sharebuf);
|
||||
+ if (ret != CC_SUCCESS) {
|
||||
+ printf("Error: free shared memory failed:%x.\n", ret);
|
||||
+ }
|
||||
+
|
||||
+ printf("rollback_count:%d, processed_cursor:%d\n", rollback_count, processed_cursor);
|
||||
+ printf("Repeating an empty sl async ecall rollback [2] for %lu times takes %ld.%06lds\n", nrepeats,
|
||||
+ (long int)duration.tv_sec, (long int)duration.tv_usec);
|
||||
}
|
||||
|
||||
#define TEST_STR "switchless"
|
||||
@@ -106,11 +683,35 @@ void transfer_data_using_shared_memory()
|
||||
}
|
||||
}
|
||||
|
||||
+void onetime_normal(void)
|
||||
+{
|
||||
+ cc_enclave_result_t ret;
|
||||
+ int retval;
|
||||
+
|
||||
+ char buf[] = "aAbBcCdD";
|
||||
+ ret = ecall_empty1(&g_enclave, &retval, buf, sizeof(buf));
|
||||
+ if (ret != CC_SUCCESS) {
|
||||
+ printf("Error: ecall_empty1, ret:%x.\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+ printf("buf:%s, retval:%d\n", buf, retval);
|
||||
+
|
||||
+ char buf1[] = "aAbBcCdD";
|
||||
+ char buf2[32] = {0};
|
||||
+ ret = ecall_empty2(&g_enclave, &retval, buf1, sizeof(buf1), buf2, sizeof(buf1) - 3);
|
||||
+ if (ret != CC_SUCCESS) {
|
||||
+ printf("Error: ecall_empty2, ret:%x.\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+ printf("buf2:%s, retval:%d\n", buf2, retval);
|
||||
+}
|
||||
+
|
||||
int main(void)
|
||||
{
|
||||
cc_sl_config_t sl_cfg = CC_USWITCHLESS_CONFIG_INITIALIZER;
|
||||
sl_cfg.num_tworkers = 2; /* 2 tworkers */
|
||||
- sl_cfg.sl_call_pool_size_qwords = 2; /* 2 * 64 tasks */
|
||||
+ sl_cfg.sl_call_pool_size_qwords = 8; /* 2 * 64 tasks */
|
||||
+ sl_cfg.rollback_to_common = false;
|
||||
enclave_features_t features = {ENCLAVE_FEATURE_SWITCHLESS, (void *)&sl_cfg};
|
||||
|
||||
if (!init_enclave(&features)) {
|
||||
@@ -119,14 +720,47 @@ int main(void)
|
||||
}
|
||||
|
||||
printf("\n1. Running a benchmark that compares [ordinary] and [switchless] ecall\n");
|
||||
- unsigned long nrepeats = 100000;
|
||||
+ unsigned long nrepeats = 10000;
|
||||
+ benchmark_ecall_empty(false, nrepeats);
|
||||
+ benchmark_ecall_empty(true, nrepeats);
|
||||
+
|
||||
+ benchmark_ecall_empty_sl_async(nrepeats);
|
||||
+ benchmark_ecall_empty_sl_async1(nrepeats);
|
||||
+ benchmark_ecall_empty_sl_async2(nrepeats);
|
||||
+
|
||||
+ printf("\n2. Transfer data using shared memory\n");
|
||||
+ transfer_data_using_shared_memory();
|
||||
+
|
||||
+ printf("\n3. normal ecall\n");
|
||||
+ onetime_normal();
|
||||
+
|
||||
+ fini_enclave(&g_enclave);
|
||||
+
|
||||
+#if 1
|
||||
+ printf("\n=================================================\n");
|
||||
+
|
||||
+ sl_cfg.rollback_to_common = true;
|
||||
+ if (!init_enclave(&features)) {
|
||||
+ printf("Error: init enclave failed\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ printf("\n1. Running a benchmark that compares [ordinary] and [switchless] ecall\n");
|
||||
benchmark_ecall_empty(false, nrepeats);
|
||||
benchmark_ecall_empty(true, nrepeats);
|
||||
|
||||
+ benchmark_ecall_empty_sl_async_rollback(nrepeats);
|
||||
+ benchmark_ecall_empty_sl_async_rollback1(nrepeats);
|
||||
+ benchmark_ecall_empty_sl_async_rollback2(nrepeats);
|
||||
+
|
||||
printf("\n2. Transfer data using shared memory\n");
|
||||
transfer_data_using_shared_memory();
|
||||
|
||||
+ printf("\n3. normal ecall\n");
|
||||
+ onetime_normal();
|
||||
+
|
||||
fini_enclave(&g_enclave);
|
||||
+#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/examples/switchless_performance/switchless.edl b/examples/switchless_performance/switchless.edl
|
||||
index 344ee57..3c6f32e 100644
|
||||
--- a/examples/switchless_performance/switchless.edl
|
||||
+++ b/examples/switchless_performance/switchless.edl
|
||||
@@ -16,8 +16,21 @@ enclave {
|
||||
from "secgear_tswitchless.edl" import *;
|
||||
trusted {
|
||||
public void ecall_empty(void);
|
||||
+
|
||||
+ /* test [in, out] params */
|
||||
+ public int ecall_empty1([in, out, size=len]char *buf, int len);
|
||||
+
|
||||
+ /* test [in] and [out] params */
|
||||
+ public int ecall_empty2([in, size=len1]char *buf1, int len1, [out, size=len2]char *buf2, int len2);
|
||||
+
|
||||
public void ecall_empty_switchless(void) transition_using_threads;
|
||||
|
||||
+ /* test [in, out] params */
|
||||
+ public int ecall_empty_switchless1([in, out, size=len]char *buf, int len) transition_using_threads;
|
||||
+
|
||||
+ /* test [in] and [out] params */
|
||||
+ public int ecall_empty_switchless2([in, size=len1]char *buf1, int len1, [out, size=len2]char *buf2, int len2) transition_using_threads;
|
||||
+
|
||||
public void test_toupper([in, out, size=len]char *buf, int len) transition_using_threads;
|
||||
};
|
||||
};
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
Name: secGear
|
||||
Version: 0.1.0
|
||||
Release: 33
|
||||
Release: 34
|
||||
Summary: secGear is an SDK to develop confidential computing apps based on hardware enclave features
|
||||
|
||||
|
||||
@ -61,6 +61,7 @@ Patch48: 0049-support-switchless-feature.patch
|
||||
Patch49: 0050-switchless-schedule-policy.patch
|
||||
Patch50: 0051-asynchronous-switchless.patch
|
||||
Patch51: 0052-rollback-to-common-invoking-when-async-invoking-fail.patch
|
||||
Patch52: 0053-asynchronous-switchless-example.patch
|
||||
|
||||
BuildRequires: gcc python automake autoconf libtool
|
||||
BUildRequires: glibc glibc-devel cmake ocaml-dune rpm gcc-c++
|
||||
@ -179,6 +180,9 @@ popd
|
||||
systemctl restart rsyslog
|
||||
|
||||
%changelog
|
||||
* Tue Dec 20 2022 houmingyong<houmingyong@huawei.com> - 0.1.0-34
|
||||
- add asynchronous switchless example
|
||||
|
||||
* Sat Dec 17 2022 houmingyong<houmingyong@huawei.com> - 0.1.0-33
|
||||
- switchless support asynchronous ecall
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user