VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c@ 33043

Last change on this file since 33043 was 33043, checked in by vboxsync, 14 years ago

nt,linux: Added missing flag validation in the RTSemEventMultiWaitEx* implementations.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.0 KB
Line 
1/* $Id: semevent-r0drv-linux.c 33043 2010-10-11 15:56:04Z vboxsync $ */
2/** @file
3 * IPRT - Single Release Event Semaphores, Ring-0 Driver, Linux.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
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
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include "the-linux-kernel.h"
32#include "internal/iprt.h"
33#include <iprt/semaphore.h>
34
35#include <iprt/asm.h>
36#include <iprt/assert.h>
37#include <iprt/err.h>
38#include <iprt/lockvalidator.h>
39#include <iprt/mem.h>
40
41#include "waitqueue-r0drv-linux.h"
42#include "internal/magics.h"
43
44
45/*******************************************************************************
46* Structures and Typedefs *
47*******************************************************************************/
48/**
49 * Linux event semaphore.
50 */
51typedef struct RTSEMEVENTINTERNAL
52{
53 /** Magic value (RTSEMEVENT_MAGIC). */
54 uint32_t volatile u32Magic;
55 /** The object status - !0 when signaled and 0 when reset. */
56 uint32_t volatile fState;
57 /** Reference counter. */
58 uint32_t volatile cRefs;
59 /** The wait queue. */
60 wait_queue_head_t Head;
61} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
62
63
64
65RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem)
66{
67 return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
68}
69
70
71RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
72{
73 PRTSEMEVENTINTERNAL pThis;
74
75 AssertReturn(!(fFlags & ~RTSEMEVENT_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
76 pThis = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pThis));
77 if (!pThis)
78 return VERR_NO_MEMORY;
79
80 pThis->u32Magic = RTSEMEVENT_MAGIC;
81 pThis->fState = 0;
82 pThis->cRefs = 1;
83 init_waitqueue_head(&pThis->Head);
84
85 *phEventSem = pThis;
86 return VINF_SUCCESS;
87}
88RT_EXPORT_SYMBOL(RTSemEventCreate);
89
90
91/**
92 * Retains a reference to the event semaphore.
93 *
94 * @param pThis The event semaphore.
95 */
96DECLINLINE(void) rtR0SemEventLnxRetain(PRTSEMEVENTINTERNAL pThis)
97{
98 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
99 Assert(cRefs < 100000); NOREF(cRefs);
100}
101
102
103/**
104 * Releases a reference to the event semaphore.
105 *
106 * @param pThis The event semaphore.
107 */
108DECLINLINE(void) rtR0SemEventLnxRelease(PRTSEMEVENTINTERNAL pThis)
109{
110 if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
111 RTMemFree(pThis);
112}
113
114
115RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem)
116{
117 /*
118 * Validate input.
119 */
120 PRTSEMEVENTINTERNAL pThis = hEventSem;
121 if (pThis == NIL_RTSEMEVENT)
122 return VINF_SUCCESS;
123 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
124 Assert(pThis->cRefs > 0);
125
126 /*
127 * Invalidate it and signal the object just in case.
128 */
129 ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENT_MAGIC);
130 ASMAtomicWriteU32(&pThis->fState, 0);
131 Assert(!waitqueue_active(&pThis->Head));
132 wake_up_all(&pThis->Head);
133 rtR0SemEventLnxRelease(pThis);
134 return VINF_SUCCESS;
135}
136RT_EXPORT_SYMBOL(RTSemEventDestroy);
137
138
139RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
140{
141 /*
142 * Validate input.
143 */
144 PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
145 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
146 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
147 rtR0SemEventLnxRetain(pThis);
148
149 /*
150 * Signal the event object.
151 */
152 ASMAtomicWriteU32(&pThis->fState, 1);
153 wake_up(&pThis->Head);
154
155 rtR0SemEventLnxRelease(pThis);
156 return VINF_SUCCESS;
157}
158RT_EXPORT_SYMBOL(RTSemEventSignal);
159
160
161/**
162 * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug.
163 *
164 * @returns VBox status code.
165 * @param pThis The event semaphore.
166 * @param fFlags See RTSemEventWaitEx.
167 * @param uTimeout See RTSemEventWaitEx.
168 * @param pSrcPos The source code position of the wait.
169 */
170static int rtR0SemEventLnxWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
171 PCRTLOCKVALSRCPOS pSrcPos)
172{
173 int rc;
174
175 /*
176 * Validate the input.
177 */
178 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
179 AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
180 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
181 rtR0SemEventLnxRetain(pThis);
182
183 /*
184 * Try grab the event without setting up the wait.
185 */
186 if ( 1 /** @todo check if there are someone waiting already - waitqueue_active, but then what do we do below? */
187 && ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
188 rc = VINF_SUCCESS;
189 else
190 {
191 /*
192 * We have to wait.
193 */
194 RTR0SEMLNXWAIT Wait;
195 rc = rtR0SemLnxWaitInit(&Wait, fFlags, uTimeout, &pThis->Head);
196 if (RT_SUCCESS(rc))
197 {
198 IPRT_DEBUG_SEMS_STATE(pThis, 'E');
199 for (;;)
200 {
201 /* The destruction test. */
202 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
203 rc = VERR_SEM_DESTROYED;
204 else
205 {
206 rtR0SemLnxWaitPrepare(&Wait);
207
208 /* Check the exit conditions. */
209 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
210 rc = VERR_SEM_DESTROYED;
211 else if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
212 rc = VINF_SUCCESS;
213 else if (rtR0SemLnxWaitHasTimedOut(&Wait))
214 rc = VERR_TIMEOUT;
215 else if (rtR0SemLnxWaitWasInterrupted(&Wait))
216 rc = VERR_INTERRUPTED;
217 else
218 {
219 /* Do the wait and then recheck the conditions. */
220 rtR0SemLnxWaitDoIt(&Wait);
221 continue;
222 }
223 }
224 break;
225 }
226
227 rtR0SemLnxWaitDelete(&Wait);
228 IPRT_DEBUG_SEMS_STATE_RC(pThis, 'E', rc);
229 }
230 }
231
232 rtR0SemEventLnxRelease(pThis);
233 return rc;
234}
235
236
237#undef RTSemEventWaitEx
238RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
239{
240#ifndef RTSEMEVENT_STRICT
241 return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, NULL);
242#else
243 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
244 return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos);
245#endif
246}
247RT_EXPORT_SYMBOL(RTSemEventWaitEx);
248
249
250RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
251 RTHCUINTPTR uId, RT_SRC_POS_DECL)
252{
253 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
254 return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos);
255}
256RT_EXPORT_SYMBOL(RTSemEventWaitExDebug);
257
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