VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/semmutex-posix.cpp@ 8649

最後變更 在這個檔案從8649是 8649,由 vboxsync 提交於 17 年 前

Count mutex locks.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 8.5 KB
 
1/* $Id: semmutex-posix.cpp 8649 2008-05-07 12:04:03Z vboxsync $ */
2/** @file
3 * IPRT - Mutex Semaphore, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#include <iprt/semaphore.h>
35#include <iprt/assert.h>
36#include <iprt/alloc.h>
37#include <iprt/thread.h>
38#include <iprt/asm.h>
39#include <iprt/err.h>
40
41#include <errno.h>
42#include <pthread.h>
43#include <unistd.h>
44#include <sys/time.h>
45
46
47/*******************************************************************************
48* Defined Constants And Macros *
49*******************************************************************************/
50/** @def RTSEMMUTEX_STRICT
51 * Enables strictness checks and lock accounting.
52 */
53#ifndef RTSEMMUTEX_STRICT
54# if defined(RT_STRICT) || defined(RT_LOCK_STRICT) || defined(RTSEM_STRICT) || defined(DOXYGEN_RUNNING)
55# define RTSEMMUTEX_STRICT
56# endif
57#endif
58
59
60/*******************************************************************************
61* Structures and Typedefs *
62*******************************************************************************/
63/** Posix internal representation of a Mutex semaphore. */
64struct RTSEMMUTEXINTERNAL
65{
66 /** pthread mutex. */
67 pthread_mutex_t Mutex;
68 /** The owner of the mutex. */
69 volatile pthread_t Owner;
70 /** Nesting count. */
71 volatile uint32_t cNesting;
72};
73
74
75
76/**
77 * Validate a Mutex semaphore handle passed to one of the interface.
78 *
79 * @returns true if valid.
80 * @returns false if invalid.
81 * @param pIntMutexSem Pointer to the mutex semaphore to validate.
82 */
83DECLINLINE(bool) rtsemMutexValid(struct RTSEMMUTEXINTERNAL *pIntMutexSem)
84{
85 if ((uintptr_t)pIntMutexSem < 0x10000)
86 return false;
87
88 if (pIntMutexSem->cNesting == (uint32_t)~0)
89 return false;
90
91 return true;
92}
93
94
95RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
96{
97 int rc;
98
99 /*
100 * Allocate semaphore handle.
101 */
102 struct RTSEMMUTEXINTERNAL *pIntMutexSem = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL));
103 if (pIntMutexSem)
104 {
105 /*
106 * Create the semaphore.
107 */
108 pthread_mutexattr_t MutexAttr;
109 rc = pthread_mutexattr_init(&MutexAttr);
110 if (!rc)
111 {
112 rc = pthread_mutex_init(&pIntMutexSem->Mutex, &MutexAttr);
113 if (!rc)
114 {
115 pthread_mutexattr_destroy(&MutexAttr);
116
117 pIntMutexSem->Owner = (pthread_t)-1;
118 pIntMutexSem->cNesting = 0;
119
120 *pMutexSem = pIntMutexSem;
121 return VINF_SUCCESS;
122 }
123 pthread_mutexattr_destroy(&MutexAttr);
124 }
125 RTMemFree(pIntMutexSem);
126 }
127 else
128 rc = VERR_NO_MEMORY;
129
130 return rc;
131}
132
133
134RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)
135{
136 /*
137 * Validate input.
138 */
139 if (!rtsemMutexValid(MutexSem))
140 {
141 AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
142 return VERR_INVALID_HANDLE;
143 }
144
145 /*
146 * Try destroy it.
147 */
148 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
149 int rc = pthread_mutex_destroy(&pIntMutexSem->Mutex);
150 if (rc)
151 {
152 AssertMsgFailed(("Failed to destroy mutex sem %p, rc=%d.\n", MutexSem, rc));
153 return RTErrConvertFromErrno(rc);
154 }
155
156 /*
157 * Free the memory and be gone.
158 */
159 pIntMutexSem->Owner = (pthread_t)-1;
160 pIntMutexSem->cNesting = ~0;
161 RTMemTmpFree(pIntMutexSem);
162
163 return VINF_SUCCESS;
164}
165
166
167RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
168{
169 /*
170 * Validate input.
171 */
172 if (!rtsemMutexValid(MutexSem))
173 {
174 AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
175 return VERR_INVALID_HANDLE;
176 }
177
178 /*
179 * Check if nested request.
180 */
181 pthread_t Self = pthread_self();
182 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
183 if ( pIntMutexSem->Owner == Self
184 && pIntMutexSem->cNesting > 0)
185 {
186 pIntMutexSem->cNesting++;
187 return VINF_SUCCESS;
188 }
189
190 /*
191 * Lock it.
192 */
193 if (cMillies == RT_INDEFINITE_WAIT)
194 {
195 /* take mutex */
196 int rc = pthread_mutex_lock(&pIntMutexSem->Mutex);
197 if (rc)
198 {
199 AssertMsgFailed(("Failed to lock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
200 return RTErrConvertFromErrno(rc);
201 }
202 }
203 else
204 {
205#ifdef RT_OS_DARWIN
206 AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
207 return VERR_NOT_IMPLEMENTED;
208#else /* !RT_OS_DARWIN */
209 /*
210 * Get current time and calc end of wait time.
211 */
212 struct timespec ts = {0,0};
213 clock_gettime(CLOCK_REALTIME, &ts);
214 if (cMillies != 0)
215 {
216 ts.tv_nsec += (cMillies % 1000) * 1000000;
217 ts.tv_sec += cMillies / 1000;
218 if (ts.tv_nsec >= 1000000000)
219 {
220 ts.tv_nsec -= 1000000000;
221 ts.tv_sec++;
222 }
223 }
224
225 /* take mutex */
226 int rc = pthread_mutex_timedlock(&pIntMutexSem->Mutex, &ts);
227 if (rc)
228 {
229 AssertMsg(rc == ETIMEDOUT, ("Failed to lock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
230 return RTErrConvertFromErrno(rc);
231 }
232#endif /* !RT_OS_DARWIN */
233 }
234
235 /*
236 * Set the owner and nesting.
237 */
238 pIntMutexSem->Owner = Self;
239 ASMAtomicXchgU32(&pIntMutexSem->cNesting, 1);
240#ifdef RTSEMMUTEX_STRICT
241 RTTHREAD Thread = RTThreadSelf();
242 if (Thread != NIL_RTTHREAD)
243 RTThreadWriteLockInc(Thread);
244#endif
245
246 return VINF_SUCCESS;
247}
248
249
250RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
251{
252 /* EINTR isn't returned by the wait functions we're using. */
253 return RTSemMutexRequest(MutexSem, cMillies);
254}
255
256
257RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)
258{
259 /*
260 * Validate input.
261 */
262 if (!rtsemMutexValid(MutexSem))
263 {
264 AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
265 return VERR_INVALID_HANDLE;
266 }
267
268 /*
269 * Check if nested.
270 */
271 pthread_t Self = pthread_self();
272 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
273 if ( pIntMutexSem->Owner != Self
274 || pIntMutexSem->cNesting == (uint32_t)~0)
275 {
276 AssertMsgFailed(("Not owner of mutex %p!! Self=%08x Owner=%08x cNesting=%d\n",
277 pIntMutexSem, Self, pIntMutexSem->Owner, pIntMutexSem->cNesting));
278 return VERR_NOT_OWNER;
279 }
280
281 /*
282 * If nested we'll just pop a nesting.
283 */
284 if (pIntMutexSem->cNesting > 1)
285 {
286 pIntMutexSem->cNesting--;
287 return VINF_SUCCESS;
288 }
289
290 /*
291 * Clear the state. (cNesting == 1)
292 */
293#ifdef RTSEMMUTEX_STRICT
294 RTTHREAD Thread = RTThreadSelf();
295 if (Thread != NIL_RTTHREAD)
296 RTThreadWriteLockDec(Thread);
297#endif
298 pIntMutexSem->Owner = (pthread_t)-1;
299 ASMAtomicXchgU32(&pIntMutexSem->cNesting, 0);
300
301 /*
302 * Unlock mutex semaphore.
303 */
304 int rc = pthread_mutex_unlock(&pIntMutexSem->Mutex);
305 if (rc)
306 {
307 AssertMsgFailed(("Failed to unlock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
308 return RTErrConvertFromErrno(rc);
309 }
310
311 return VINF_SUCCESS;
312}
313
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette