Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "mozilla/Assertions.h"
8 :
9 : #include <errno.h>
10 : #include <pthread.h>
11 : #include <stdio.h>
12 :
13 : #include "mozilla/PlatformMutex.h"
14 : #include "MutexPlatformData_posix.h"
15 :
16 : #define TRY_CALL_PTHREADS(call, msg) \
17 : { \
18 : int result = (call); \
19 : if (result != 0) { \
20 : errno = result; \
21 : perror(msg); \
22 : MOZ_CRASH(msg); \
23 : } \
24 : }
25 :
26 1411 : mozilla::detail::MutexImpl::MutexImpl()
27 : {
28 1411 : pthread_mutexattr_t* attrp = nullptr;
29 :
30 : // Linux with glibc and FreeBSD support adaptive mutexes that spin
31 : // for a short number of tries before sleeping. NSPR's locks did
32 : // this, too, and it seems like a reasonable thing to do.
33 : #if (defined(__linux__) && defined(__GLIBC__)) || defined(__FreeBSD__)
34 : #define ADAPTIVE_MUTEX_SUPPORTED
35 : #endif
36 :
37 : #if defined(DEBUG)
38 : #define ATTR_REQUIRED
39 : #define MUTEX_KIND PTHREAD_MUTEX_ERRORCHECK
40 : #elif defined(ADAPTIVE_MUTEX_SUPPORTED)
41 : #define ATTR_REQUIRED
42 : #define MUTEX_KIND PTHREAD_MUTEX_ADAPTIVE_NP
43 : #endif
44 :
45 : #if defined(ATTR_REQUIRED)
46 : pthread_mutexattr_t attr;
47 :
48 1411 : TRY_CALL_PTHREADS(pthread_mutexattr_init(&attr),
49 : "mozilla::detail::MutexImpl::MutexImpl: pthread_mutexattr_init failed");
50 :
51 1411 : TRY_CALL_PTHREADS(pthread_mutexattr_settype(&attr, MUTEX_KIND),
52 : "mozilla::detail::MutexImpl::MutexImpl: pthread_mutexattr_settype failed");
53 1411 : attrp = &attr;
54 : #endif
55 :
56 1411 : TRY_CALL_PTHREADS(pthread_mutex_init(&platformData()->ptMutex, attrp),
57 : "mozilla::detail::MutexImpl::MutexImpl: pthread_mutex_init failed");
58 :
59 : #if defined(ATTR_REQUIRED)
60 1411 : TRY_CALL_PTHREADS(pthread_mutexattr_destroy(&attr),
61 : "mozilla::detail::MutexImpl::MutexImpl: pthread_mutexattr_destroy failed");
62 : #endif
63 1411 : }
64 :
65 498 : mozilla::detail::MutexImpl::~MutexImpl()
66 : {
67 249 : TRY_CALL_PTHREADS(pthread_mutex_destroy(&platformData()->ptMutex),
68 : "mozilla::detail::MutexImpl::~MutexImpl: pthread_mutex_destroy failed");
69 249 : }
70 :
71 : void
72 318587 : mozilla::detail::MutexImpl::lock()
73 : {
74 318587 : TRY_CALL_PTHREADS(pthread_mutex_lock(&platformData()->ptMutex),
75 : "mozilla::detail::MutexImpl::lock: pthread_mutex_lock failed");
76 318669 : }
77 :
78 : void
79 318531 : mozilla::detail::MutexImpl::unlock()
80 : {
81 318531 : TRY_CALL_PTHREADS(pthread_mutex_unlock(&platformData()->ptMutex),
82 : "mozilla::detail::MutexImpl::unlock: pthread_mutex_unlock failed");
83 318580 : }
84 :
85 : #undef TRY_CALL_PTHREADS
86 :
87 : mozilla::detail::MutexImpl::PlatformData*
88 638997 : mozilla::detail::MutexImpl::platformData()
89 : {
90 : static_assert(sizeof(platformData_) >= sizeof(PlatformData),
91 : "platformData_ is too small");
92 638997 : return reinterpret_cast<PlatformData*>(platformData_);
93 : }
|