1 // Copyright 2017 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6 
7 #include <inttypes.h>
8 
9 #include <trace.h>
10 
11 #include <object/process_dispatcher.h>
12 #include <zircon/types.h>
13 
14 #include "priv.h"
15 
16 #define LOCAL_TRACE 0
17 
18 // zx_status_t zx_futex_wait
sys_futex_wait(user_in_ptr<const zx_futex_t> value_ptr,zx_futex_t current_value,zx_handle_t current_futex_owner,zx_time_t deadline)19 zx_status_t sys_futex_wait(user_in_ptr<const zx_futex_t> value_ptr, zx_futex_t current_value,
20                            zx_handle_t current_futex_owner, zx_time_t deadline) {
21     LTRACEF("futex %p current %d\n", value_ptr.get(), current_value);
22 
23     ProcessDispatcher* dispatcher = ThreadDispatcher::GetCurrent()->process();
24     const TimerSlack slack = dispatcher->GetTimerSlackPolicy();
25     return dispatcher->futex_context()->FutexWait(value_ptr, current_value, current_futex_owner,
26                                                   deadline, slack);
27 }
28 
29 // zx_status_t zx_futex_wake
sys_futex_wake(user_in_ptr<const zx_futex_t> value_ptr,uint32_t count)30 zx_status_t sys_futex_wake(user_in_ptr<const zx_futex_t> value_ptr, uint32_t count) {
31     LTRACEF("futex %p count %" PRIu32 "\n", value_ptr.get(), count);
32 
33     return ProcessDispatcher::GetCurrent()->futex_context()->FutexWake(
34         value_ptr, count, FutexContext::OwnerAction::RELEASE);
35 }
36 
37 // zx_status_t zx_futex_requeue
sys_futex_requeue(user_in_ptr<const zx_futex_t> wake_ptr,uint32_t wake_count,zx_futex_t current_value,user_in_ptr<const zx_futex_t> requeue_ptr,uint32_t requeue_count,zx_handle_t requeue_owner)38 zx_status_t sys_futex_requeue(user_in_ptr<const zx_futex_t> wake_ptr,
39                               uint32_t wake_count,
40                               zx_futex_t current_value,
41                               user_in_ptr<const zx_futex_t> requeue_ptr,
42                               uint32_t requeue_count,
43                               zx_handle_t requeue_owner) {
44     LTRACEF("futex %p wake_count %" PRIu32 "current_value %d "
45            "requeue_futex %p requeue_count %" PRIu32 "\n",
46            wake_ptr.get(), wake_count, current_value, requeue_ptr.get(), requeue_count);
47 
48     return ProcessDispatcher::GetCurrent()->futex_context()->FutexRequeue(
49         wake_ptr, wake_count, current_value, FutexContext::OwnerAction::RELEASE,
50         requeue_ptr, requeue_count, requeue_owner);
51 }
52 
53 // zx_status_t zx_futex_wake_single_owner
sys_futex_wake_single_owner(user_in_ptr<const zx_futex_t> value_ptr)54 zx_status_t sys_futex_wake_single_owner(user_in_ptr<const zx_futex_t> value_ptr) {
55     LTRACEF("futex %p\n", value_ptr.get());
56 
57     return ProcessDispatcher::GetCurrent()->futex_context()->FutexWake(
58         value_ptr, 1u, FutexContext::OwnerAction::ASSIGN_WOKEN);
59 }
60 
61 // zx_status_t zx_futex_requeue_single_owner
sys_futex_requeue_single_owner(user_in_ptr<const zx_futex_t> wake_ptr,zx_futex_t current_value,user_in_ptr<const zx_futex_t> requeue_ptr,uint32_t requeue_count,zx_handle_t requeue_owner)62 zx_status_t sys_futex_requeue_single_owner(user_in_ptr<const zx_futex_t> wake_ptr,
63                                            zx_futex_t current_value,
64                                            user_in_ptr<const zx_futex_t> requeue_ptr,
65                                            uint32_t requeue_count,
66                                            zx_handle_t requeue_owner) {
67     LTRACEF("futex %p current_value %d requeue_futex %p requeue_count %" PRIu32 "\n",
68            wake_ptr.get(), current_value, requeue_ptr.get(), requeue_count);
69 
70     return ProcessDispatcher::GetCurrent()->futex_context()->FutexRequeue(
71         wake_ptr, 1u, current_value, FutexContext::OwnerAction::ASSIGN_WOKEN,
72         requeue_ptr, requeue_count, requeue_owner);
73 }
74 
sys_futex_get_owner(user_in_ptr<const zx_futex_t> value_ptr,user_out_ptr<zx_koid_t> koid)75 zx_status_t sys_futex_get_owner(user_in_ptr<const zx_futex_t> value_ptr,
76                                 user_out_ptr<zx_koid_t> koid) {
77     LTRACEF("futex %p\n", value_ptr.get());
78     return ProcessDispatcher::GetCurrent()->futex_context()->FutexGetOwner(value_ptr, koid);
79 }
80 
81 // zx_status_t zx_futex_wait_deprecated
sys_futex_wait_deprecated(user_in_ptr<const zx_futex_t> value_ptr,int32_t current_value,zx_time_t deadline)82 zx_status_t sys_futex_wait_deprecated(
83         user_in_ptr<const zx_futex_t> value_ptr, int32_t current_value, zx_time_t deadline) {
84     return sys_futex_wait(value_ptr, current_value, ZX_HANDLE_INVALID, deadline);
85 }
86 
87 // zx_status_t zx_futex_requeue_deprecated
sys_futex_requeue_deprecated(user_in_ptr<const zx_futex_t> wake_ptr,uint32_t wake_count,int32_t current_value,user_in_ptr<const zx_futex_t> requeue_ptr,uint32_t requeue_count)88 zx_status_t sys_futex_requeue_deprecated(
89         user_in_ptr<const zx_futex_t> wake_ptr, uint32_t wake_count, int32_t current_value,
90         user_in_ptr<const zx_futex_t> requeue_ptr, uint32_t requeue_count) {
91     return sys_futex_requeue(wake_ptr, wake_count, current_value,
92                              requeue_ptr, requeue_count, ZX_HANDLE_INVALID);
93 }
94