secGear/0053-asynchronous-switchless-example.patch

861 lines
30 KiB
Diff

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