VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c@ 20554

Last change on this file since 20554 was 19886, checked in by vboxsync, 16 years ago

semevetnmulti-r0drv-linux.c: Fixed missing initialization of the fState variable in RTsemEventMultiCreate. This usually resulted in the semaphore being created in the signalled state, which is wrong.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.2 KB
Line 
1/* $Id: semeventmulti-r0drv-linux.c 19886 2009-05-21 15:19:38Z vboxsync $ */
2/** @file
3 * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, Linux.
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/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include "the-linux-kernel.h"
36#include <iprt/semaphore.h>
37#include <iprt/alloc.h>
38#include <iprt/assert.h>
39#include <iprt/asm.h>
40#include <iprt/err.h>
41
42#include "internal/magics.h"
43
44
45/*******************************************************************************
46* Structures and Typedefs *
47*******************************************************************************/
48/**
49 * Linux event semaphore.
50 */
51typedef struct RTSEMEVENTMULTIINTERNAL
52{
53 /** Magic value (RTSEMEVENTMULTI_MAGIC). */
54 uint32_t volatile u32Magic;
55 /** The object status - !0 when signaled and 0 when reset. */
56 uint32_t volatile fState;
57 /** The wait queue. */
58 wait_queue_head_t Head;
59} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
60
61
62
63RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI pEventMultiSem)
64{
65 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
66 if (pThis)
67 {
68 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
69 pThis->fState = 0;
70 init_waitqueue_head(&pThis->Head);
71 *pEventMultiSem = pThis;
72 return VINF_SUCCESS;
73 }
74 return VERR_NO_MEMORY;
75}
76
77
78RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem)
79{
80 /*
81 * Validate input.
82 */
83 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
84 if (!pThis)
85 return VERR_INVALID_PARAMETER;
86 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
87 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
88
89 /*
90 * Invalidate it and signal the object just in case.
91 */
92 ASMAtomicIncU32(&pThis->u32Magic);
93 ASMAtomicXchgU32(&pThis->fState, 0);
94 Assert(!waitqueue_active(&pThis->Head));
95 wake_up_all(&pThis->Head);
96 RTMemFree(pThis);
97 return VINF_SUCCESS;
98}
99
100
101RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem)
102{
103 /*
104 * Validate input.
105 */
106 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
107 if (!pThis)
108 return VERR_INVALID_PARAMETER;
109 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
110 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
111
112 /*
113 * Signal the event object.
114 */
115 ASMAtomicXchgU32(&pThis->fState, 1);
116 wake_up_all(&pThis->Head);
117 return VINF_SUCCESS;
118}
119
120
121RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem)
122{
123 /*
124 * Validate input.
125 */
126 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
127 if (!pThis)
128 return VERR_INVALID_PARAMETER;
129 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
130 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
131
132 /*
133 * Reset it.
134 */
135 ASMAtomicXchgU32(&pThis->fState, 0);
136 return VINF_SUCCESS;
137}
138
139
140/**
141 * Worker for RTSemEventMulti and RTSemEventMultiNoResume.
142 *
143 * @returns VBox status code.
144 * @param pThis The event semaphore.
145 * @param cMillies The number of milliseconds to wait.
146 * @param fInterruptible Whether it's an interruptible wait or not.
147 */
148static int rtSemEventMultiWait(PRTSEMEVENTMULTIINTERNAL pThis, unsigned cMillies, bool fInterruptible)
149{
150 /*
151 * Ok wait for it.
152 */
153 DEFINE_WAIT(Wait);
154 int rc = VINF_SUCCESS;
155 long lTimeout = cMillies == RT_INDEFINITE_WAIT ? MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(cMillies);
156#ifdef IPRT_DEBUG_SEMS
157 snprintf(current->comm, TASK_COMM_LEN, "E%lx", IPRT_DEBUG_SEMS_ADDRESS(pThis));
158#endif
159 for (;;)
160 {
161 /* make everything thru schedule() atomic scheduling wise. */
162 prepare_to_wait(&pThis->Head, &Wait, fInterruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
163
164 /* check the condition. */
165 if (pThis->fState)
166 break;
167
168 /* check for pending signals. */
169 if (fInterruptible && signal_pending(current))
170 {
171 rc = VERR_INTERRUPTED;
172 break;
173 }
174
175 /* wait */
176 lTimeout = schedule_timeout(lTimeout);
177
178 /* Check if someone destroyed the semaphore while we were waiting. */
179 if (pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)
180 {
181 rc = VERR_SEM_DESTROYED;
182 break;
183 }
184
185 /* check for timeout. */
186 if (!lTimeout)
187 {
188 rc = VERR_TIMEOUT;
189 break;
190 }
191 }
192
193 finish_wait(&pThis->Head, &Wait);
194#ifdef IPRT_DEBUG_SEMS
195 snprintf(current->comm, TASK_COMM_LEN, "E%lx:%d", IPRT_DEBUG_SEMS_ADDRESS(pThis), rc);
196#endif
197 return rc;
198}
199
200
201RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies)
202{
203 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
204 if (!pThis)
205 return VERR_INVALID_PARAMETER;
206 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
207 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
208
209 if (pThis->fState)
210 return VINF_SUCCESS;
211 return rtSemEventMultiWait(pThis, cMillies, false /* fInterruptible */);
212}
213
214
215RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies)
216{
217 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
218 if (!pThis)
219 return VERR_INVALID_PARAMETER;
220 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
221 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
222
223 if (pThis->fState)
224 return VINF_SUCCESS;
225 return rtSemEventMultiWait(pThis, cMillies, true /* fInterruptible */);
226}
227
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