1 /*
2  * Copyright © 2016 Mozilla Foundation
3  *
4  * This program is made available under an ISC-style license.  See the
5  * accompanying file LICENSE for details.
6  */
7 
8 #if !defined(CUBEB_UTILS_UNIX)
9 #define CUBEB_UTILS_UNIX
10 
11 #include <errno.h>
12 #include <pthread.h>
13 #include <stdio.h>
14 
15 /* This wraps a critical section to track the owner in debug mode. */
16 class owned_critical_section {
17 public:
owned_critical_section()18   owned_critical_section()
19   {
20     pthread_mutexattr_t attr;
21     pthread_mutexattr_init(&attr);
22 #ifndef NDEBUG
23     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
24 #else
25     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
26 #endif
27 
28 #ifndef NDEBUG
29     int r =
30 #endif
31         pthread_mutex_init(&mutex, &attr);
32 #ifndef NDEBUG
33     assert(r == 0);
34 #endif
35 
36     pthread_mutexattr_destroy(&attr);
37   }
38 
~owned_critical_section()39   ~owned_critical_section()
40   {
41 #ifndef NDEBUG
42     int r =
43 #endif
44         pthread_mutex_destroy(&mutex);
45 #ifndef NDEBUG
46     assert(r == 0);
47 #endif
48   }
49 
lock()50   void lock()
51   {
52 #ifndef NDEBUG
53     int r =
54 #endif
55         pthread_mutex_lock(&mutex);
56 #ifndef NDEBUG
57     assert(r == 0 && "Deadlock");
58 #endif
59   }
60 
unlock()61   void unlock()
62   {
63 #ifndef NDEBUG
64     int r =
65 #endif
66         pthread_mutex_unlock(&mutex);
67 #ifndef NDEBUG
68     assert(r == 0 && "Unlocking unlocked mutex");
69 #endif
70   }
71 
assert_current_thread_owns()72   void assert_current_thread_owns()
73   {
74 #ifndef NDEBUG
75     int r = pthread_mutex_lock(&mutex);
76     assert(r == EDEADLK);
77 #endif
78   }
79 
80 private:
81   pthread_mutex_t mutex;
82 
83   // Disallow copy and assignment because pthread_mutex_t cannot be copied.
84   owned_critical_section(const owned_critical_section &);
85   owned_critical_section & operator=(const owned_critical_section &);
86 };
87 
88 #endif /* CUBEB_UTILS_UNIX */
89