semsrw-generic.cpp revision aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32
/* $Id$ */
/** @file
* IPRT - Read-Write Semaphore, Generic.
*
* This is a generic implementation for OSes which don't have
* native RW semaphores.
*/
/*
* Copyright (C) 2006-2009 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <iprt/semaphore.h>
#include <iprt/critsect.h>
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/** Internal representation of a Read-Write semaphore for the
* Generic implementation. */
struct RTSEMRWINTERNAL
{
/** The usual magic. (RTSEMRW_MAGIC) */
/* Alignment padding. */
/** This critical section serializes the access to and updating of the structure members. */
/** The current number of reads. (pure read recursion counts too) */
/** The current number of writes. (recursion counts too) */
/** Number of read recursions by the writer. */
/** Number of writers waiting. */
/** The write owner of the lock. */
/** The handle of the event object on which the waiting readers block. (manual reset). */
/** The handle of the event object on which the waiting writers block. (automatic reset). */
};
/**
* Validate a read-write semaphore handle passed to one of the interface.
*
* @returns true if valid.
* @returns false if invalid.
* @param pThis Pointer to the read-write semaphore to validate.
*/
{
return false;
return false;
return true;
}
{
int rc;
/*
* Allocate memory.
*/
struct RTSEMRWINTERNAL *pThis = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL));
if (pThis)
{
/*
* Create the semaphores.
*/
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/*
* Signal the read semaphore and initialize other variables.
*/
if (RT_SUCCESS(rc))
{
pThis->cWriterReads = 0;
pThis->cWritesWaiting = 0;
return VINF_SUCCESS;
}
}
}
}
}
else
rc = VERR_NO_MEMORY;
return rc;
}
{
/*
* Validate handle.
*/
if (!rtsemRWValid(pThis))
{
return VERR_INVALID_HANDLE;
}
/*
* Check if busy.
*/
if (RT_SUCCESS(rc))
{
{
/*
* Make it invalid and unusable.
*/
/*
* Do actual cleanup. None of these can now fail.
*/
rc = VINF_SUCCESS;
}
else
{
rc = VERR_SEM_BUSY;
}
}
else
{
rc = VERR_SEM_BUSY;
}
return rc;
}
{
/*
* Validate handle.
*/
if (!rtsemRWValid(pThis))
{
return VERR_INVALID_HANDLE;
}
unsigned cMilliesInitial = cMillies;
if (cMillies != RT_INDEFINITE_WAIT)
tsStart = RTTimeNanoTS();
/*
* Take critsect.
*/
if (RT_FAILURE(rc))
{
return rc;
}
for (;;)
{
/*
* Check if the state of affairs allows read access.
* Do not block further readers if there is a writer waiting, as
*/
{
return VINF_SUCCESS;
}
{
pThis->cWriterReads++;
return VINF_SUCCESS;
}
/*
* Wait till it's ready for reading.
*/
if (cMillies != RT_INDEFINITE_WAIT)
{
if (tsDelta >= 1000000)
{
if (cMillies > cMilliesInitial)
}
}
{
break;
}
{
break;
}
/*
* Re-take critsect.
*/
if (RT_FAILURE(rc))
{
break;
}
}
return rc;
}
{
}
{
/*
* Validate handle.
*/
if (!rtsemRWValid(pThis))
{
return VERR_INVALID_HANDLE;
}
/*
* Take critsect.
*/
if (RT_SUCCESS(rc))
{
{
pThis->cWriterReads--;
}
else
{
/* Kick off a writer if appropriate. */
if ( pThis->cWritesWaiting > 0
{
}
}
return VINF_SUCCESS;
}
else
return rc;
}
{
/*
* Validate handle.
*/
if (!rtsemRWValid(pThis))
{
return VERR_INVALID_HANDLE;
}
unsigned cMilliesInitial = cMillies;
if (cMillies != RT_INDEFINITE_WAIT)
tsStart = RTTimeNanoTS();
/*
* Take critsect.
*/
if (RT_FAILURE(rc))
{
return rc;
}
/*
* Signal writer presence.
*/
pThis->cWritesWaiting++;
for (;;)
{
/*
* Check if the state of affairs allows write access.
*/
{
/*
* Reset the reader event semaphore. For write recursion this
* is redundant, but does not hurt.
*/
/* We're not waiting, so decrease counter. */
pThis->cWritesWaiting--;
return VINF_SUCCESS;
}
/*
* Wait till it's ready for writing.
*/
if (cMillies != RT_INDEFINITE_WAIT)
{
if (tsDelta >= 1000000)
{
if (cMillies > cMilliesInitial)
}
}
{
break;
}
{
break;
}
/*
* Re-take critsect.
*/
if (RT_FAILURE(rc))
{
break;
}
// AssertMsg(!pThis->cReads, ("We woke up and there are readers around!\n"));
}
/*
*/
{
/* Adjust this counter, whether we got the critsect or not. */
pThis->cWritesWaiting--;
}
return rc;
}
{
}
{
/*
* Validate handle.
*/
if (!rtsemRWValid(pThis))
{
return VERR_INVALID_HANDLE;
}
/*
* Take critsect.
*/
if (RT_FAILURE(rc))
{
return rc;
}
/*
* Check if owner.
*/
{
return VERR_NOT_OWNER;
}
/*
* Release ownership and remove ourselves from the writers count.
*/
/*
* Release the readers if no more writers waiting, otherwise the writers.
*/
if (!pThis->cWritesWaiting)
{
}
else
{
}
return rc;
}
{
/*
* Validate handle.
*/
if (!rtsemRWValid(pThis))
{
return false;
}
/*
* Check ownership.
*/
}
{
/*
* Validate handle.
*/
if (!rtsemRWValid(pThis))
{
return 0;
}
/*
* Return the requested data.
*/
}
{
/*
* Validate handle.
*/
if (!rtsemRWValid(pThis))
{
return 0;
}
/*
* Return the requested data.
*/
return pThis->cWriterReads;
}