1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef NATIVE_BRIDGE_SUPPORT_LIBC_PROXY_PTHREAD_TRANSLATION_H_
18 #define NATIVE_BRIDGE_SUPPORT_LIBC_PROXY_PTHREAD_TRANSLATION_H_
19 
20 #include <pthread.h>
21 #include <sched.h>
22 #include <time.h>  // struct timespec
23 
24 #include "berberis/base/struct_check.h"
25 #include "berberis/guest_state/guest_state_opaque.h"
26 #include "berberis/runtime_primitives/host_code.h"
27 #include "bionic/pthread_internal.h"  // pthread_internal_t
28 
29 namespace berberis {
30 
31 #define GUEST_PTHREAD_ATTR_FLAG_DETACHED 1
32 
33 // ATTENTION: layouts of pthread_internal_t and bionic_tls are verified by
34 // bionic. See bionic/tests/struct_layout_test.cpp
35 
36 #if defined(NATIVE_BRIDGE_GUEST_ARCH_ARM)
37 
38 CHECK_STRUCT_LAYOUT(pthread_attr_t, 192, 32);
39 CHECK_FIELD_LAYOUT(pthread_attr_t, flags, 0, 32);
40 CHECK_FIELD_LAYOUT(pthread_attr_t, stack_base, 32, 32);
41 CHECK_FIELD_LAYOUT(pthread_attr_t, stack_size, 64, 32);
42 CHECK_FIELD_LAYOUT(pthread_attr_t, guard_size, 96, 32);
43 CHECK_FIELD_LAYOUT(pthread_attr_t, sched_policy, 128, 32);
44 CHECK_FIELD_LAYOUT(pthread_attr_t, sched_priority, 160, 32);
45 
46 // pthread_barrier_t and appropriate functions were introduced in NYC, they are
47 // not available on earlier versions of bionic.
48 CHECK_STRUCT_LAYOUT(pthread_barrier_t, 256, 32);
49 CHECK_FIELD_LAYOUT(pthread_barrier_t, __private, 0, 256);
50 
51 CHECK_STRUCT_LAYOUT(pthread_barrierattr_t, 32, 32);
52 
53 CHECK_STRUCT_LAYOUT(pthread_cond_t, 32, 32);
54 CHECK_FIELD_LAYOUT(pthread_cond_t, __private, 0, 32);
55 
56 CHECK_STRUCT_LAYOUT(pthread_condattr_t, 32, 32);
57 
58 CHECK_STRUCT_LAYOUT(pthread_key_t, 32, 32);
59 
60 CHECK_STRUCT_LAYOUT(pthread_mutex_t, 32, 32);
61 CHECK_FIELD_LAYOUT(pthread_mutex_t, __private, 0, 32);
62 
63 CHECK_STRUCT_LAYOUT(pthread_mutexattr_t, 32, 32);
64 
65 CHECK_STRUCT_LAYOUT(pthread_once_t, 32, 32);
66 
67 CHECK_STRUCT_LAYOUT(pthread_rwlock_t, 320, 32);
68 CHECK_FIELD_LAYOUT(pthread_rwlock_t, __private, 0, 320);
69 
70 CHECK_STRUCT_LAYOUT(pthread_rwlockattr_t, 32, 32);
71 
72 // pthread_spinlock_t and appropriate functions were introduced in NYC, they are
73 // not available on earlier versions of bionic.
74 CHECK_STRUCT_LAYOUT(pthread_spinlock_t, 64, 32);
75 CHECK_FIELD_LAYOUT(pthread_spinlock_t, __private, 0, 64);
76 
77 #endif  // defined(NATIVE_BRIDGE_GUEST_ARCH_ARM)
78 
79 // Check that host attribute constants coincide with bionic attribute constants
80 // from pthread.h.
81 static_assert(PTHREAD_PROCESS_PRIVATE == 0,
82               "PTHREAD_PROCESS_PRIVATE must be 0 because it's 0 on guest");
83 static_assert(PTHREAD_PROCESS_SHARED == 1,
84               "PTHREAD_PROCESS_SHARED must be 1 because it's 1 on guest");
85 static_assert(PTHREAD_MUTEX_NORMAL == 0,
86               "PTHREAD_MUTEX_NORMAL must be 0 because it's 0 on guest");
87 static_assert(PTHREAD_MUTEX_RECURSIVE == 1,
88               "PTHREAD_MUTEX_RECURSIVE must be 1 because it's 1 on guest");
89 static_assert(PTHREAD_MUTEX_ERRORCHECK == 2,
90               "PTHREAD_MUTEX_ERRORCHECK must be 2 because it's 2 on guest");
91 static_assert(PTHREAD_MUTEX_DEFAULT == 0,
92               "PTHREAD_MUTEX_DEFAULT must be 0 because it's 0 on guest");
93 static_assert(PTHREAD_CREATE_JOINABLE == 0,
94               "PTHREAD_CREATE_JOINABLE must be 0 because it's 0 on guest");
95 static_assert(PTHREAD_CREATE_DETACHED == 1,
96               "PTHREAD_CREATE_DETACHED must be 1 because it's 1 on guest");
97 
98 // Check that host attribute constants coincide with bionic attribute constants
99 // from sched.h.
100 static_assert(SCHED_NORMAL == 0,
101               "SCHED_NORMAL must be 0 because it's 0 on guest");
102 static_assert(SCHED_FIFO == 1, "SCHED_FIFO must be 1 because it's 1 on guest");
103 static_assert(SCHED_RR == 2, "SCHED_RR must be 2 because it's 2 on guest");
104 static_assert(
105     SCHED_OTHER == SCHED_NORMAL,
106     "SCHED_OTHER must be SCHED_NORMAL because it's SCHED_NORMAL on guest");
107 
108 // TODO(b/65052237): Currently we don't expose __register_atfork and
109 // __unregister_atfork to the guest code.  This means that functions registered
110 // with __register_atfork by guest are not called when host calls fork().
111 // Investigate and fix the issue.
112 
113 // int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
114 //                    void *(*start_routine)(void*), void *arg);
115 void DoCustomTrampoline_pthread_create(HostCode callee, ProcessState* state);
116 
117 // int pthread_join(pthread_t thread, void **retval);
118 void DoCustomTrampoline_pthread_join(HostCode /* callee */,
119                                      ProcessState* state);
120 
121 // int pthread_getattr_np(pthread_t thread, pthread_attr_t* attr);
122 void DoCustomTrampoline_pthread_getattr_np(HostCode callee,
123                                            ProcessState* state);
124 
125 // int pthread_key_create(pthread_key_t* key, void (*destructor)(void*));
126 void DoCustomTrampoline_pthread_key_create(HostCode callee,
127                                            ProcessState* state);
128 
129 // void __pthread_cleanup_push(__pthread_cleanup_t* c,
130 //                           void (*routine)(void *), void *arg);
131 void DoCustomTrampoline___pthread_cleanup_push(HostCode callee,
132                                                ProcessState* state);
133 
134 // uintptr_t __get_thread_stack_top();
135 void DoCustomTrampoline___get_thread_stack_top(HostCode callee,
136                                                ProcessState* state);
137 
138 }  // namespace berberis
139 
140 #endif  // NATIVE_BRIDGE_SUPPORT_LIBC_PROXY_PTHREAD_TRANSLATION_H_
141