VirtualBox

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

Last change on this file since 18587 was 8651, checked in by vboxsync, 17 years ago

Moved the strictness indicators into internal/strict.h.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.0 KB
Line 
1/* $Id: semmutex-posix.cpp 8651 2008-05-07 12:16:29Z 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.virtualbox.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#include "internal/strict.h"
41
42#include <errno.h>
43#include <pthread.h>
44#include <unistd.h>
45#include <sys/time.h>
46
47
48/*******************************************************************************
49* Structures and Typedefs *
50*******************************************************************************/
51/** Posix internal representation of a Mutex semaphore. */
52struct RTSEMMUTEXINTERNAL
53{
54 /** pthread mutex. */
55 pthread_mutex_t Mutex;
56 /** The owner of the mutex. */
57 volatile pthread_t Owner;
58 /** Nesting count. */
59 volatile uint32_t cNesting;
60};
61
62
63
64/**
65 * Validate a Mutex semaphore handle passed to one of the interface.
66 *
67 * @returns true if valid.
68 * @returns false if invalid.
69 * @param pIntMutexSem Pointer to the mutex semaphore to validate.
70 */
71DECLINLINE(bool) rtsemMutexValid(struct RTSEMMUTEXINTERNAL *pIntMutexSem)
72{
73 if ((uintptr_t)pIntMutexSem < 0x10000)
74 return false;
75
76 if (pIntMutexSem->cNesting == (uint32_t)~0)
77 return false;
78
79 return true;
80}
81
82
83RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
84{
85 int rc;
86
87 /*
88 * Allocate semaphore handle.
89 */
90 struct RTSEMMUTEXINTERNAL *pIntMutexSem = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL));
91 if (pIntMutexSem)
92 {
93 /*
94 * Create the semaphore.
95 */
96 pthread_mutexattr_t MutexAttr;
97 rc = pthread_mutexattr_init(&MutexAttr);
98 if (!rc)
99 {
100 rc = pthread_mutex_init(&pIntMutexSem->Mutex, &MutexAttr);
101 if (!rc)
102 {
103 pthread_mutexattr_destroy(&MutexAttr);
104
105 pIntMutexSem->Owner = (pthread_t)-1;
106 pIntMutexSem->cNesting = 0;
107
108 *pMutexSem = pIntMutexSem;
109 return VINF_SUCCESS;
110 }
111 pthread_mutexattr_destroy(&MutexAttr);
112 }
113 RTMemFree(pIntMutexSem);
114 }
115 else
116 rc = VERR_NO_MEMORY;
117
118 return rc;
119}
120
121
122RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)
123{
124 /*
125 * Validate input.
126 */
127 if (!rtsemMutexValid(MutexSem))
128 {
129 AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
130 return VERR_INVALID_HANDLE;
131 }
132
133 /*
134 * Try destroy it.
135 */
136 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
137 int rc = pthread_mutex_destroy(&pIntMutexSem->Mutex);
138 if (rc)
139 {
140 AssertMsgFailed(("Failed to destroy mutex sem %p, rc=%d.\n", MutexSem, rc));
141 return RTErrConvertFromErrno(rc);
142 }
143
144 /*
145 * Free the memory and be gone.
146 */
147 pIntMutexSem->Owner = (pthread_t)-1;
148 pIntMutexSem->cNesting = ~0;
149 RTMemTmpFree(pIntMutexSem);
150
151 return VINF_SUCCESS;
152}
153
154
155RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
156{
157 /*
158 * Validate input.
159 */
160 if (!rtsemMutexValid(MutexSem))
161 {
162 AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
163 return VERR_INVALID_HANDLE;
164 }
165
166 /*
167 * Check if nested request.
168 */
169 pthread_t Self = pthread_self();
170 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
171 if ( pIntMutexSem->Owner == Self
172 && pIntMutexSem->cNesting > 0)
173 {
174 pIntMutexSem->cNesting++;
175 return VINF_SUCCESS;
176 }
177
178 /*
179 * Lock it.
180 */
181 if (cMillies == RT_INDEFINITE_WAIT)
182 {
183 /* take mutex */
184 int rc = pthread_mutex_lock(&pIntMutexSem->Mutex);
185 if (rc)
186 {
187 AssertMsgFailed(("Failed to lock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
188 return RTErrConvertFromErrno(rc);
189 }
190 }
191 else
192 {
193#ifdef RT_OS_DARWIN
194 AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
195 return VERR_NOT_IMPLEMENTED;
196#else /* !RT_OS_DARWIN */
197 /*
198 * Get current time and calc end of wait time.
199 */
200 struct timespec ts = {0,0};
201 clock_gettime(CLOCK_REALTIME, &ts);
202 if (cMillies != 0)
203 {
204 ts.tv_nsec += (cMillies % 1000) * 1000000;
205 ts.tv_sec += cMillies / 1000;
206 if (ts.tv_nsec >= 1000000000)
207 {
208 ts.tv_nsec -= 1000000000;
209 ts.tv_sec++;
210 }
211 }
212
213 /* take mutex */
214 int rc = pthread_mutex_timedlock(&pIntMutexSem->Mutex, &ts);
215 if (rc)
216 {
217 AssertMsg(rc == ETIMEDOUT, ("Failed to lock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
218 return RTErrConvertFromErrno(rc);
219 }
220#endif /* !RT_OS_DARWIN */
221 }
222
223 /*
224 * Set the owner and nesting.
225 */
226 pIntMutexSem->Owner = Self;
227 ASMAtomicXchgU32(&pIntMutexSem->cNesting, 1);
228#ifdef RTSEMMUTEX_STRICT
229 RTTHREAD Thread = RTThreadSelf();
230 if (Thread != NIL_RTTHREAD)
231 RTThreadWriteLockInc(Thread);
232#endif
233
234 return VINF_SUCCESS;
235}
236
237
238RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
239{
240 /* EINTR isn't returned by the wait functions we're using. */
241 return RTSemMutexRequest(MutexSem, cMillies);
242}
243
244
245RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)
246{
247 /*
248 * Validate input.
249 */
250 if (!rtsemMutexValid(MutexSem))
251 {
252 AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
253 return VERR_INVALID_HANDLE;
254 }
255
256 /*
257 * Check if nested.
258 */
259 pthread_t Self = pthread_self();
260 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
261 if ( pIntMutexSem->Owner != Self
262 || pIntMutexSem->cNesting == (uint32_t)~0)
263 {
264 AssertMsgFailed(("Not owner of mutex %p!! Self=%08x Owner=%08x cNesting=%d\n",
265 pIntMutexSem, Self, pIntMutexSem->Owner, pIntMutexSem->cNesting));
266 return VERR_NOT_OWNER;
267 }
268
269 /*
270 * If nested we'll just pop a nesting.
271 */
272 if (pIntMutexSem->cNesting > 1)
273 {
274 pIntMutexSem->cNesting--;
275 return VINF_SUCCESS;
276 }
277
278 /*
279 * Clear the state. (cNesting == 1)
280 */
281#ifdef RTSEMMUTEX_STRICT
282 RTTHREAD Thread = RTThreadSelf();
283 if (Thread != NIL_RTTHREAD)
284 RTThreadWriteLockDec(Thread);
285#endif
286 pIntMutexSem->Owner = (pthread_t)-1;
287 ASMAtomicXchgU32(&pIntMutexSem->cNesting, 0);
288
289 /*
290 * Unlock mutex semaphore.
291 */
292 int rc = pthread_mutex_unlock(&pIntMutexSem->Mutex);
293 if (rc)
294 {
295 AssertMsgFailed(("Failed to unlock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
296 return RTErrConvertFromErrno(rc);
297 }
298
299 return VINF_SUCCESS;
300}
301
Note: See TracBrowser for help on using the repository browser.

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