VirtualBox

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

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

rtSemEventWait -> rtSemEventMultiWait.

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