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
17void 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
23void 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
29void 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
36void 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
53void threads_test_busy_fn(void* arg) {
54    volatile uint64_t i = 0u;
55    while (true) {
56        ++i;
57    }
58    __builtin_trap();
59}
60
61void threads_test_infinite_sleep_fn(void* arg) {
62    zx_nanosleep(ZX_TIME_INFINITE);
63    __builtin_trap();
64}
65
66void 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
72void 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
80void 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