1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef LIB_SYNC_MUTEX_H_
6 #define LIB_SYNC_MUTEX_H_
7 
8 #include <zircon/compiler.h>
9 #include <zircon/types.h>
10 
11 __BEGIN_CDECLS
12 
13 // An optimal, non-recursive mutex on Fuchsia.
14 //
15 // The |mutex_t| mutex in the standard library has several quirks in its design
16 // that prevent it from being optimal. For example, the |mutex_t| interface
17 // supports recursion, which adds a branch to |mutex_init| to check that the
18 // client has not asked for recusion, and |mutex_timedlock| operates in
19 // |struct timespec| rather than |zx_time_t|.
20 //
21 // |sync_mutex| resolves these issues.
22 typedef struct __TA_CAPABILITY("mutex") sync_mutex {
23     zx_futex_t futex;
24 
25 #ifdef __cplusplus
sync_mutexsync_mutex26     sync_mutex()
27         : futex(0) {}
28 #endif
29 } sync_mutex_t;
30 
31 #if !defined(__cplusplus)
32 #define SYNC_MUTEX_INIT ((sync_mutex_t){0})
33 #endif
34 
35 // Locks the mutex.
36 //
37 // The current thread will block until the mutex is acquired. The mutex is
38 // non-recursive, which means attempting to lock a mutex that is already held by
39 // this thread will deadlock.
40 void sync_mutex_lock(sync_mutex_t* mutex) __TA_ACQUIRE(mutex);
41 
42 // Locks the mutex and mark the mutex as having a waiter.
43 //
44 // Similar to |sync_mutex_lock| but markes the mutex as having a waiter. Intended
45 // to be used by the condition variable implementation.
46 void sync_mutex_lock_with_waiter(sync_mutex_t* mutex) __TA_ACQUIRE(mutex);
47 
48 // Attempt to lock the mutex until |deadline|.
49 //
50 // The current thread will block until either the mutex is acquired or
51 // |deadline| passes.
52 //
53 // |deadline| is expressed as an absolute time in the ZX_CLOCK_MONOTONIC
54 // timebase.
55 //
56 // Returns |ZX_OK| if the lock is acquired, and |ZX_ERR_TIMED_OUT| if the
57 // deadline passes.
58 zx_status_t sync_mutex_timedlock(sync_mutex_t* mutex, zx_time_t deadline);
59 
60 // Attempts to lock the mutex without blocking.
61 //
62 // Returns |ZX_OK| if the lock is obtained, and |ZX_ERR_BAD_STATE| if not.
63 zx_status_t sync_mutex_trylock(sync_mutex_t* mutex);
64 
65 // Unlocks the mutex.
66 //
67 // Does nothing if the mutex is already unlocked.
68 void sync_mutex_unlock(sync_mutex_t* mutex) __TA_RELEASE(mutex);
69 
70 __END_CDECLS
71 
72 #endif // LIB_SYNC_MUTEX_H_
73