VirtualBox

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

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

semaphore-r0drv-lnx.c split.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.0 KB
Line 
1/* $Id: semevent-r0drv-linux.c 5225 2007-10-10 15:06:48Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Single 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 RTSEMEVENTINTERNAL
40{
41 /** Magic value (RTSEMEVENT_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} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
48
49
50
51RTDECL(int) RTSemEventCreate(PRTSEMEVENT pEventSem)
52{
53 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pEventInt));
54 if (pEventInt)
55 {
56 pEventInt->u32Magic = RTSEMEVENT_MAGIC;
57 init_waitqueue_head(&pEventInt->Head);
58 *pEventSem = pEventInt;
59 return VINF_SUCCESS;
60 }
61 return VERR_NO_MEMORY;
62}
63
64
65RTDECL(int) RTSemEventDestroy(RTSEMEVENT EventSem)
66{
67 /*
68 * Validate input.
69 */
70 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
71 if (!pEventInt)
72 return VERR_INVALID_PARAMETER;
73 if (pEventInt->u32Magic != RTSEMEVENT_MAGIC)
74 {
75 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt->u32Magic, pEventInt));
76 return VERR_INVALID_PARAMETER;
77 }
78
79 /*
80 * Invalidate it and signal the object just in case.
81 */
82 ASMAtomicIncU32(&pEventInt->u32Magic);
83 ASMAtomicXchgU32(&pEventInt->fState, 0);
84 Assert(!waitqueue_active(&pEventInt->Head));
85 wake_up_all(&pEventInt->Head);
86 RTMemFree(pEventInt);
87 return VINF_SUCCESS;
88}
89
90
91RTDECL(int) RTSemEventSignal(RTSEMEVENT EventSem)
92{
93 /*
94 * Validate input.
95 */
96 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
97 if (!pEventInt)
98 return VERR_INVALID_PARAMETER;
99 if ( !pEventInt
100 || pEventInt->u32Magic != RTSEMEVENT_MAGIC)
101 {
102 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt ? pEventInt->u32Magic : 0, pEventInt));
103 return VERR_INVALID_PARAMETER;
104 }
105
106 /*
107 * Signal the event object.
108 */
109 ASMAtomicXchgU32(&pEventInt->fState, 1);
110 wake_up(&pEventInt->Head);
111
112 return VINF_SUCCESS;
113}
114
115
116/**
117 * Worker for RTSemEvent and RTSemEventNoResume.
118 *
119 * @returns VBox status code.
120 * @param pEventInt The event semaphore.
121 * @param cMillies The number of milliseconds to wait.
122 * @param fInterruptible Whether it's an interruptible wait or not.
123 */
124static int rtSemEventWait(PRTSEMEVENTINTERNAL pEventInt, unsigned cMillies, bool fInterruptible)
125{
126 /*
127 * Ok wait for it.
128 */
129 DEFINE_WAIT(Wait);
130 int rc = VINF_SUCCESS;
131 long lTimeout = cMillies == RT_INDEFINITE_WAIT ? MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(cMillies);
132 for (;;)
133 {
134 /* make everything thru schedule() atomic scheduling wise. */
135 prepare_to_wait(&pEventInt->Head, &Wait, fInterruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
136
137 /* check the condition. */
138 if (ASMAtomicCmpXchgU32(&pEventInt->fState, 0, 1))
139 break;
140
141 /* check for pending signals. */
142 if (fInterruptible && signal_pending(current))
143 {
144 rc = VERR_INTERRUPTED;
145 break;
146 }
147
148 /* wait */
149 lTimeout = schedule_timeout(lTimeout);
150
151 /* Check if someone destroyed the semaphore while we were waiting. */
152 if (pEventInt->u32Magic != RTSEMEVENT_MAGIC)
153 {
154 rc = VERR_SEM_DESTROYED;
155 break;
156 }
157
158 /* check for timeout. */
159 if (!lTimeout)
160 {
161 rc = VERR_TIMEOUT;
162 break;
163 }
164 }
165
166 finish_wait(&pEventInt->Head, &Wait);
167 return rc;
168}
169
170
171RTDECL(int) RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies)
172{
173 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
174 if (!pEventInt)
175 return VERR_INVALID_PARAMETER;
176 if ( !pEventInt
177 || pEventInt->u32Magic != RTSEMEVENT_MAGIC)
178 {
179 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt ? pEventInt->u32Magic : 0, pEventInt));
180 return VERR_INVALID_PARAMETER;
181 }
182
183 if (ASMAtomicCmpXchgU32(&pEventInt->fState, 0, 1))
184 return VINF_SUCCESS;
185 return rtSemEventWait(pEventInt, cMillies, false /* fInterruptible */);
186}
187
188
189RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT EventSem, unsigned cMillies)
190{
191 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
192 if (!pEventInt)
193 return VERR_INVALID_PARAMETER;
194 if ( !pEventInt
195 || pEventInt->u32Magic != RTSEMEVENT_MAGIC)
196 {
197 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt ? pEventInt->u32Magic : 0, pEventInt));
198 return VERR_INVALID_PARAMETER;
199 }
200
201 if (ASMAtomicCmpXchgU32(&pEventInt->fState, 0, 1))
202 return VINF_SUCCESS;
203 return rtSemEventWait(pEventInt, cMillies, true /* fInterruptible */);
204}
205
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