| /* |
| * Copyright (c) 2019, Google Inc. All rights reserved |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining |
| * a copy of this software and associated documentation files |
| * (the "Software"), to deal in the Software without restriction, |
| * including without limitation the rights to use, copy, modify, merge, |
| * publish, distribute, sublicense, and/or sell copies of the Software, |
| * and to permit persons to whom the Software is furnished to do so, |
| * subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #include <err.h> |
| #include <kernel/event.h> |
| #include <kernel/thread.h> |
| #include <lib/trusty/ipc.h> |
| #include <lk/init.h> |
| #include <lk/trace.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| |
| #define LOCAL_TRACE (0) |
| |
| static struct event busy_test_event = |
| EVENT_INITIAL_VALUE(busy_test_event, false, 0); |
| |
| static void busy_test_connected(handle_t* chandle) { |
| int ret; |
| uint32_t event; |
| |
| LTRACEF("event wait count: %d\n", busy_test_event.wait.count); |
| |
| ret = event_signal(&busy_test_event, true); |
| if (ret) { |
| TRACEF("event_signal failed %d\n", ret); |
| goto err; |
| } |
| ret = handle_wait(chandle, &event, INFINITE_TIME); |
| LTRACEF("got channel event (ret=%d): ev=%x\n", ret, event); |
| |
| err: |
| ret = event_unsignal(&busy_test_event); |
| if (ret) { |
| TRACEF("event_unsignal failed %d\n", ret); |
| } |
| handle_close(chandle); |
| } |
| |
| static int busy_test_server(void* arg) { |
| handle_t* phandle = arg; |
| handle_t* chandle; |
| const uuid_t* dummy_uuid_p; |
| uint32_t event; |
| int ret; |
| |
| while (true) { |
| ret = handle_wait(phandle, &event, INFINITE_TIME); |
| if (ret < 0) { |
| TRACEF("handle_wait failed: %d\n", ret); |
| break; |
| } |
| LTRACEF("got port event (ret=%d): ev=%x\n", ret, event); |
| if (event & IPC_HANDLE_POLL_READY) { |
| /* get connection request */ |
| ret = ipc_port_accept(phandle, &chandle, &dummy_uuid_p); |
| LTRACEF("accept returned %d\n", ret); |
| if (ret >= 0) { |
| busy_test_connected(chandle); |
| } |
| } |
| } |
| return 0; |
| } |
| |
| static void busy_test_init(uint level) { |
| int ret; |
| thread_t* thread; |
| handle_t* phandle; |
| |
| const uuid_t uuid = UUID_INITIAL_VALUE(uuid); |
| ret = ipc_port_create(&uuid, "com.android.kernel.busy-test", 1, 1, |
| IPC_PORT_ALLOW_NS_CONNECT, &phandle); |
| if (ret) { |
| goto err_port_create; |
| } |
| |
| ret = ipc_port_publish(phandle); |
| if (ret) { |
| goto err_port_publish; |
| } |
| |
| thread = thread_create("busy-test-server", busy_test_server, phandle, |
| DEFAULT_PRIORITY, DEFAULT_STACK_SIZE); |
| if (!thread) { |
| ret = ERR_NO_MEMORY; |
| goto err_thread_create; |
| } |
| thread_resume(thread); |
| return; |
| |
| err_thread_create: |
| handle_close(phandle); |
| err_port_publish: |
| handle_close(phandle); |
| err_port_create: |
| TRACEF("Failed to add busy_test: %d\n", ret); |
| return; |
| } |
| |
| LK_INIT_HOOK(busy_test_init, busy_test_init, LK_INIT_LEVEL_APPS); |
| |
| static int busy_test_busy_func(void* arg) { |
| TRACEF("cpu %d ready\n", arch_curr_cpu_num()); |
| while (true) { |
| event_wait(&busy_test_event); |
| } |
| return 0; |
| } |
| |
| static void busy_test_cpu_init(uint level) { |
| thread_t* thread; |
| char thread_name[32]; |
| uint cpu = arch_curr_cpu_num(); |
| snprintf(thread_name, sizeof(thread_name), "busy-test-%d", cpu); |
| thread = thread_create(thread_name, busy_test_busy_func, NULL, LOW_PRIORITY, |
| DEFAULT_STACK_SIZE); |
| #if WITH_SMP |
| thread->pinned_cpu = cpu; |
| #endif |
| thread_resume(thread); |
| } |
| |
| LK_INIT_HOOK_FLAGS(busy_test_cpu_init, |
| busy_test_cpu_init, |
| LK_INIT_LEVEL_APPS, |
| LK_INIT_FLAG_ALL_CPUS); |