1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 
6 #include <stddef.h>
7 #include <string.h>
8 
9 #include <zircon/syscalls.h>
10 #include <zircon/syscalls/object.h>
11 #include <zircon/syscalls/port.h>
12 
13 #include <runtime/thread.h>
14 
15 #include "thread-functions.h"
16 
threads_test_sleep_fn(void * arg)17 void threads_test_sleep_fn(void* arg) {
18     // Note: You shouldn't use C standard library functions from this thread.
19     zx_time_t time = (zx_time_t)arg;
20     zx_nanosleep(time);
21 }
22 
threads_test_wait_fn(void * arg)23 void threads_test_wait_fn(void* arg) {
24     zx_handle_t event = *(zx_handle_t*)arg;
25     zx_object_wait_one(event, ZX_USER_SIGNAL_0, ZX_TIME_INFINITE, NULL);
26     zx_object_signal(event, 0u, ZX_USER_SIGNAL_1);
27 }
28 
threads_test_wait_detach_fn(void * arg)29 void threads_test_wait_detach_fn(void* arg) {
30     threads_test_wait_fn(arg);
31     // Since we're detached, we are not allowed to return into the default zxr_thread
32     // exit path.
33     zx_thread_exit();
34 }
35 
threads_test_wait_break_infinite_sleep_fn(void * arg)36 void threads_test_wait_break_infinite_sleep_fn(void* arg) {
37     zx_handle_t event = *(zx_handle_t*)arg;
38     zx_object_wait_one(event, ZX_USER_SIGNAL_0, ZX_TIME_INFINITE, NULL);
39 
40     // Don't use builtin_trap since the compiler might assume everything after that call can't
41     // execute and will remove the zx_nanosleep below.
42 #if defined(__aarch64__)
43     __asm__ volatile("brk 0");
44 #elif defined(__x86_64__)
45     __asm__ volatile("int3");
46 #else
47 #error Not supported on this platform.
48 #endif
49 
50     zx_nanosleep(ZX_TIME_INFINITE);
51 }
52 
threads_test_busy_fn(void * arg)53 void threads_test_busy_fn(void* arg) {
54     volatile uint64_t i = 0u;
55     while (true) {
56         ++i;
57     }
58     __builtin_trap();
59 }
60 
threads_test_infinite_sleep_fn(void * arg)61 void threads_test_infinite_sleep_fn(void* arg) {
62     zx_nanosleep(ZX_TIME_INFINITE);
63     __builtin_trap();
64 }
65 
threads_test_infinite_wait_fn(void * arg)66 void threads_test_infinite_wait_fn(void* arg) {
67     zx_handle_t event = *(zx_handle_t*)arg;
68     zx_object_wait_one(event, ZX_USER_SIGNAL_0, ZX_TIME_INFINITE, NULL);
69     __builtin_trap();
70 }
71 
threads_test_port_fn(void * arg)72 void threads_test_port_fn(void* arg) {
73     zx_handle_t* port = (zx_handle_t*)arg;
74     zx_port_packet_t packet = {};
75     zx_port_wait(port[0], ZX_TIME_INFINITE, &packet);
76     packet.key += 5u;
77     zx_port_queue(port[1], &packet);
78 }
79 
threads_test_channel_call_fn(void * arg_)80 void threads_test_channel_call_fn(void* arg_) {
81     channel_call_suspend_test_arg* arg = static_cast<channel_call_suspend_test_arg*>(arg_);
82 
83     uint8_t send_buf[9] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' };
84     uint8_t recv_buf[9];
85     uint32_t actual_bytes, actual_handles;
86 
87     zx_channel_call_args_t call_args = {
88         .wr_bytes = send_buf,
89         .wr_handles = NULL,
90         .rd_bytes = recv_buf,
91         .rd_handles = NULL,
92         .wr_num_bytes = sizeof(send_buf),
93         .wr_num_handles = 0,
94         .rd_num_bytes = sizeof(recv_buf),
95         .rd_num_handles = 0,
96     };
97 
98     arg->call_status = zx_channel_call(arg->channel, 0, ZX_TIME_INFINITE, &call_args,
99                                        &actual_bytes, &actual_handles);
100     if (arg->call_status == ZX_OK) {
101         if (actual_bytes != sizeof(recv_buf) ||
102             memcmp(recv_buf + sizeof(zx_txid_t), "abcdefghj" + sizeof(zx_txid_t), sizeof(recv_buf) - sizeof(zx_txid_t))) {
103             arg->call_status = ZX_ERR_BAD_STATE;
104         }
105     }
106 
107     zx_handle_close(arg->channel);
108 }
109