VirtualBox

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

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

IPRT: Implemented RTSemEventWaitEx[Debug] for ring-0 linux.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.9 KB
Line 
1/* $Id: semevent-r0drv-linux.c 33033 2010-10-11 09:55:12Z 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 rtR0SemEventLnxRetain(pThis);
181
182 /*
183 * Try grab the event without setting up the wait.
184 */
185 if ( 1 /** @todo check if there are someone waiting already - waitqueue_active, but then what do we do below? */
186 && ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
187 rc = VINF_SUCCESS;
188 else
189 {
190 /*
191 * We have to wait.
192 */
193 RTR0SEMLNXWAIT Wait;
194 rc = rtR0SemLnxWaitInit(&Wait, fFlags, uTimeout, &pThis->Head);
195 if (RT_SUCCESS(rc))
196 {
197 IPRT_DEBUG_SEMS_STATE(pThis, 'E');
198 for (;;)
199 {
200 /* The destruction test. */
201 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
202 rc = VERR_SEM_DESTROYED;
203 else
204 {
205 rtR0SemLnxWaitPrepare(&Wait);
206
207 /* Check the exit conditions. */
208 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
209 rc = VERR_SEM_DESTROYED;
210 else if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
211 rc = VINF_SUCCESS;
212 else if (rtR0SemLnxWaitHasTimedOut(&Wait))
213 rc = VERR_TIMEOUT;
214 else if (rtR0SemLnxWaitWasInterrupted(&Wait))
215 rc = VERR_INTERRUPTED;
216 else
217 {
218 /* Do the wait and then recheck the conditions. */
219 rtR0SemLnxWaitDoIt(&Wait);
220 continue;
221 }
222 }
223 break;
224 }
225
226 rtR0SemLnxWaitDelete(&Wait);
227 IPRT_DEBUG_SEMS_STATE_RC(pThis, 'E', rc);
228 }
229 }
230
231 rtR0SemEventLnxRelease(pThis);
232 return rc;
233}
234
235
236#undef RTSemEventWaitEx
237RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
238{
239#ifndef RTSEMEVENT_STRICT
240 return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, NULL);
241#else
242 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
243 return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos);
244#endif
245}
246RT_EXPORT_SYMBOL(RTSemEventWaitEx);
247
248
249RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
250 RTHCUINTPTR uId, RT_SRC_POS_DECL)
251{
252 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
253 return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos);
254}
255RT_EXPORT_SYMBOL(RTSemEventWaitExDebug);
256
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