VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/linux/semmutex-r0drv-linux.c@ 5999

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

The Giant CDDL Dual-License Header Change.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.5 KB
Line 
1/* $Id: semmutex-r0drv-linux.c 5999 2007-12-07 15:05:06Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Mutex 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 (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/*******************************************************************************
30* Header Files *
31*******************************************************************************/
32#include "the-linux-kernel.h"
33#include <iprt/semaphore.h>
34#include <iprt/alloc.h>
35#include <iprt/assert.h>
36#include <iprt/asm.h>
37#include <iprt/err.h>
38
39#include "internal/magics.h"
40
41
42/*******************************************************************************
43* Structures and Typedefs *
44*******************************************************************************/
45/**
46 * Linux mutex semaphore.
47 */
48typedef struct RTSEMMUTEXINTERNAL
49{
50 /** Magic value (RTSEMMUTEX_MAGIC). */
51 uint32_t volatile u32Magic;
52 /** Number of recursive locks - 0 if not owned by anyone, > 0 if owned. */
53 uint32_t volatile cRecursion;
54 /** The wait queue. */
55 wait_queue_head_t Head;
56 /** The current owner. */
57 void * volatile pOwner;
58} RTSEMMUTEXINTERNAL, *PRTSEMMUTEXINTERNAL;
59
60
61
62RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
63{
64 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pMutexInt));
65 if (pMutexInt)
66 {
67 pMutexInt->u32Magic = RTSEMMUTEX_MAGIC;
68 init_waitqueue_head(&pMutexInt->Head);
69 *pMutexSem = pMutexInt;
70AssertReleaseMsgFailed(("This mutex implementation is buggy, fix it!\n"));
71 return VINF_SUCCESS;
72 }
73 return VERR_NO_MEMORY;
74}
75
76
77RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)
78{
79 /*
80 * Validate input.
81 */
82 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
83 if (!pMutexInt)
84 return VERR_INVALID_PARAMETER;
85 if (pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
86 {
87 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt->u32Magic, pMutexInt));
88 return VERR_INVALID_PARAMETER;
89 }
90
91 /*
92 * Invalidate it and signal the object just in case.
93 */
94 ASMAtomicIncU32(&pMutexInt->u32Magic);
95 ASMAtomicXchgU32(&pMutexInt->cRecursion, 0);
96 Assert(!waitqueue_active(&pMutexInt->Head));
97 wake_up_all(&pMutexInt->Head);
98 RTMemFree(pMutexInt);
99 return VINF_SUCCESS;
100}
101
102
103RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
104{
105 /*
106 * Validate input.
107 */
108 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
109 if (!pMutexInt)
110 return VERR_INVALID_PARAMETER;
111 if ( !pMutexInt
112 || pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
113 {
114 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt ? pMutexInt->u32Magic : 0, pMutexInt));
115 return VERR_INVALID_PARAMETER;
116 }
117
118 /*
119 * Check for recursive request.
120 */
121 if (pMutexInt->pOwner == current)
122 {
123 Assert(pMutexInt->cRecursion < 1000);
124 ASMAtomicIncU32(&pMutexInt->cRecursion);
125 return VINF_SUCCESS;
126 }
127
128 /*
129 * Try aquire it.
130 */
131 if (ASMAtomicCmpXchgU32(&pMutexInt->cRecursion, 1, 0))
132 {
133 ASMAtomicXchgPtr(&pMutexInt->pOwner, current);
134 return VINF_SUCCESS;
135 }
136 else
137 {
138 /*
139 * Ok wait for it.
140 */
141 DEFINE_WAIT(Wait);
142 int rc = VINF_SUCCESS;
143 long lTimeout = cMillies == RT_INDEFINITE_WAIT ? MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(cMillies);
144 for (;;)
145 {
146 /* make everything thru schedule() atomic scheduling wise. */
147 prepare_to_wait(&pMutexInt->Head, &Wait, TASK_INTERRUPTIBLE);
148
149 /* check the condition. */
150 if (ASMAtomicCmpXchgU32(&pMutexInt->cRecursion, 1, 0))
151 {
152 ASMAtomicXchgPtr(&pMutexInt->pOwner, current);
153 break;
154 }
155
156 /* check for pending signals. */
157 if (signal_pending(current))
158 {
159 rc = VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
160 break;
161 }
162
163 /* wait */
164 lTimeout = schedule_timeout(lTimeout);
165
166 /* Check if someone destroyed the semaphore while we was waiting. */
167 if (pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
168 {
169 rc = VERR_SEM_DESTROYED;
170 break;
171 }
172
173 /* check for timeout. */
174 if (!lTimeout)
175 {
176 rc = VERR_TIMEOUT;
177 break;
178 }
179 }
180 finish_wait(&pMutexInt->Head, &Wait);
181 return rc;
182 }
183 return VINF_SUCCESS;
184}
185
186
187RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)
188{
189 /*
190 * Validate input.
191 */
192 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
193 if (!pMutexInt)
194 return VERR_INVALID_PARAMETER;
195 if ( !pMutexInt
196 || pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
197 {
198 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt ? pMutexInt->u32Magic : 0, pMutexInt));
199 return VERR_INVALID_PARAMETER;
200 }
201 if (pMutexInt->pOwner != current)
202 {
203 AssertMsgFailed(("Not owner, pOwner=%p current=%p\n", (void *)pMutexInt->pOwner, (void *)current));
204 return VERR_NOT_OWNER;
205 }
206
207 /*
208 * Release the mutex.
209 */
210 if (pMutexInt->cRecursion == 1)
211 {
212 ASMAtomicXchgPtr(&pMutexInt->pOwner, NULL);
213 ASMAtomicXchgU32(&pMutexInt->cRecursion, 0);
214 }
215 else
216 ASMAtomicDecU32(&pMutexInt->cRecursion);
217
218 return VINF_SUCCESS;
219}
220
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