1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #if defined LINUX
21 // to define __USE_UNIX98, via _XOPEN_SOURCE, enabling pthread_mutexattr_settype
22 #ifndef _GNU_SOURCE
23 #define _GNU_SOURCE 1
24 #endif
25 #endif
26 #include "system.hxx"
27 #include "unixerrnostring.hxx"
28 
29 #include <sal/log.hxx>
30 #include <osl/mutex.h>
31 
32 #include <pthread.h>
33 #include <stdlib.h>
34 
35 
36 typedef struct _oslMutexImpl
37 {
38     pthread_mutex_t mutex;
39 } oslMutexImpl;
40 
osl_createMutex()41 oslMutex SAL_CALL osl_createMutex()
42 {
43     oslMutexImpl* pMutex = static_cast<oslMutexImpl*>(malloc(sizeof(oslMutexImpl)));
44     pthread_mutexattr_t aMutexAttr;
45     int nRet=0;
46 
47     SAL_WARN_IF(!pMutex, "sal.osl.mutex", "null pMutex");
48 
49     if ( pMutex == nullptr )
50     {
51         return nullptr;
52     }
53 
54     pthread_mutexattr_init(&aMutexAttr);
55 
56     nRet = pthread_mutexattr_settype(&aMutexAttr, PTHREAD_MUTEX_RECURSIVE);
57     if( nRet == 0 )
58         nRet = pthread_mutex_init(&(pMutex->mutex), &aMutexAttr);
59     if ( nRet != 0 )
60     {
61         SAL_WARN("sal.osl.mutex", "pthread_muxex_init failed: " << UnixErrnoString(nRet));
62 
63         free(pMutex);
64         pMutex = nullptr;
65     }
66 
67     pthread_mutexattr_destroy(&aMutexAttr);
68 
69     return pMutex;
70 }
71 
osl_destroyMutex(oslMutex pMutex)72 void SAL_CALL osl_destroyMutex(oslMutex pMutex)
73 {
74     SAL_WARN_IF(!pMutex, "sal.osl.mutex", "null pMutex");
75 
76     if ( pMutex != nullptr )
77     {
78         int nRet = pthread_mutex_destroy(&(pMutex->mutex));
79         if ( nRet != 0 )
80         {
81             SAL_WARN("sal.osl.mutex", "pthread_mutex_destroy failed: " << UnixErrnoString(nRet));
82         }
83 
84         free(pMutex);
85     }
86 }
87 
88 #ifdef __COVERITY__
89     extern void __coverity_recursive_lock_acquire__(void*);
90     extern void __coverity_recursive_lock_release__(void*);
91     extern void __coverity_assert_locked__(void*);
92 #endif
93 
osl_acquireMutex(oslMutex pMutex)94 sal_Bool SAL_CALL osl_acquireMutex(oslMutex pMutex)
95 {
96     SAL_WARN_IF(!pMutex, "sal.osl.mutex", "null pMutex");
97 
98     if ( pMutex != nullptr )
99     {
100         int nRet = pthread_mutex_lock(&(pMutex->mutex));
101         if ( nRet != 0 )
102         {
103             SAL_WARN("sal.osl.mutex", "pthread_mutex_lock failed: " << UnixErrnoString(nRet));
104             return false;
105         }
106 #ifdef __COVERITY__
107     __coverity_recursive_lock_acquire__(pMutex);
108 #endif
109         return true;
110     }
111 
112     /* not initialized */
113     return false;
114 }
115 
osl_tryToAcquireMutex(oslMutex pMutex)116 sal_Bool SAL_CALL osl_tryToAcquireMutex(oslMutex pMutex)
117 {
118     bool result = false;
119 
120     SAL_WARN_IF(!pMutex, "sal.osl.mutex", "null pMutex");
121 
122     if ( pMutex )
123     {
124         int nRet = pthread_mutex_trylock(&(pMutex->mutex));
125         if ( nRet == 0  )
126         {
127 #ifdef __COVERITY__
128             __coverity_recursive_lock_acquire__(pMutex);
129 #endif
130             result = true;
131         }
132     }
133 
134     return result;
135 }
136 
osl_releaseMutex(oslMutex pMutex)137 sal_Bool SAL_CALL osl_releaseMutex(oslMutex pMutex)
138 {
139 #ifdef __COVERITY__
140     __coverity_assert_locked__(pMutex);
141 #endif
142     SAL_WARN_IF(!pMutex, "sal.osl.mutex", "null pMutex");
143 
144     if ( pMutex )
145     {
146         int nRet = pthread_mutex_unlock(&(pMutex->mutex));
147         if ( nRet != 0 )
148         {
149             SAL_WARN("sal.osl.mutex", "pthread_mutex_unlock failed: " << UnixErrnoString(nRet));
150             return false;
151         }
152 
153 #ifdef __COVERITY__
154             __coverity_recursive_lock_release__(pMutex);
155 #endif
156         return true;
157     }
158 
159     /* not initialized */
160     return false;
161 }
162 
163 static oslMutexImpl globalMutexImpl;
164 
globalMutexInitImpl()165 static void globalMutexInitImpl() {
166     pthread_mutexattr_t attr;
167     if (pthread_mutexattr_init(&attr) != 0 ||
168         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) ||
169         pthread_mutex_init(&globalMutexImpl.mutex, &attr) != 0 ||
170         pthread_mutexattr_destroy(&attr) != 0)
171     {
172         abort();
173     }
174 }
175 
osl_getGlobalMutex()176 oslMutex * SAL_CALL osl_getGlobalMutex()
177 {
178     /* necessary to get a "oslMutex *" */
179     static oslMutex globalMutex = &globalMutexImpl;
180 
181     static pthread_once_t once = PTHREAD_ONCE_INIT;
182     if (pthread_once(&once, &globalMutexInitImpl) != 0) {
183         abort();
184     }
185 
186     return &globalMutex;
187 }
188 
189 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
190