VirtualBox

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

Last change on this file since 8256 was 8245, checked in by vboxsync, 17 years ago

rebranding: IPRT files again.

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