summaryrefslogtreecommitdiff
path: root/src/VBox/Runtime/r3/linux
diff options
context:
space:
mode:
authorFelix Geyer <debfx-pkg@fobos.de>2010-05-02 13:24:51 +0200
committerFelix Geyer <debfx-pkg@fobos.de>2010-05-02 13:24:51 +0200
commit4749e3a0c5d3a159d3ae751e6780b537c860923a (patch)
tree28cd86e0a63ddac4224277df9ce83ef056629917 /src/VBox/Runtime/r3/linux
parent0429962c55c464036f613d707f26b91f252584e7 (diff)
downloadvirtualbox-4749e3a0c5d3a159d3ae751e6780b537c860923a.tar.gz
Imported Upstream version 3.1.51-dfsgupstream/3.1.51-dfsg
Diffstat (limited to 'src/VBox/Runtime/r3/linux')
-rw-r--r--src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp8
-rw-r--r--src/VBox/Runtime/r3/linux/RTSystemQueryDmiString-linux.cpp104
-rw-r--r--src/VBox/Runtime/r3/linux/RTThreadGetNativeState-linux.cpp111
-rw-r--r--src/VBox/Runtime/r3/linux/fileaio-linux.cpp28
-rw-r--r--src/VBox/Runtime/r3/linux/mp-linux.cpp10
-rw-r--r--src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp8
-rw-r--r--src/VBox/Runtime/r3/linux/sched-linux.cpp10
-rw-r--r--src/VBox/Runtime/r3/linux/semevent-linux.cpp157
-rw-r--r--src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp175
-rw-r--r--src/VBox/Runtime/r3/linux/semmutex-linux.cpp236
-rw-r--r--src/VBox/Runtime/r3/linux/sysfs.cpp49
-rw-r--r--src/VBox/Runtime/r3/linux/time-linux.cpp12
12 files changed, 730 insertions, 178 deletions
diff --git a/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp b/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp
index b0b2cd89a..065856c2e 100644
--- a/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp
@@ -1,10 +1,10 @@
-/* $Id: RTProcIsRunningByName-linux.cpp $ */
+/* $Id: RTProcIsRunningByName-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
/** @file
* IPRT - RTProcIsRunningByName, Linux implementation.
*/
/*
- * Copyright (C) 2009 Sun Microsystems, Inc.
+ * Copyright (C) 2009 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,10 +22,6 @@
*
* 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.
*/
/*******************************************************************************
diff --git a/src/VBox/Runtime/r3/linux/RTSystemQueryDmiString-linux.cpp b/src/VBox/Runtime/r3/linux/RTSystemQueryDmiString-linux.cpp
new file mode 100644
index 000000000..4c6ed2193
--- /dev/null
+++ b/src/VBox/Runtime/r3/linux/RTSystemQueryDmiString-linux.cpp
@@ -0,0 +1,104 @@
+/* $Id: RTSystemQueryDmiString-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
+/** @file
+ * IPRT - RTSystemQueryDmiString, linux ring-3.
+ */
+
+/*
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <iprt/system.h>
+#include "internal/iprt.h"
+
+#include <iprt/err.h>
+#include <iprt/assert.h>
+#include <iprt/linux/sysfs.h>
+
+#include <errno.h>
+
+
+RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t cbBuf)
+{
+ AssertPtrReturn(pszBuf, VERR_INVALID_POINTER);
+ AssertReturn(cbBuf > 0, VERR_INVALID_PARAMETER);
+ *pszBuf = '\0';
+ AssertReturn(enmString > RTSYSDMISTR_INVALID && enmString < RTSYSDMISTR_END, VERR_INVALID_PARAMETER);
+
+ const char *pszSysFsName;
+ switch (enmString)
+ {
+ case RTSYSDMISTR_PRODUCT_NAME: pszSysFsName = "id/product_name"; break;
+ case RTSYSDMISTR_PRODUCT_VERSION: pszSysFsName = "id/product_version"; break;
+ case RTSYSDMISTR_PRODUCT_UUID: pszSysFsName = "id/product_uuid"; break;
+ case RTSYSDMISTR_PRODUCT_SERIAL: pszSysFsName = "id/product_serial"; break;
+ default:
+ return VERR_NOT_SUPPORTED;
+ }
+
+ int rc;
+ int fd = RTLinuxSysFsOpen("devices/virtual/dmi/%s", pszSysFsName);
+ if (fd < 0)
+ fd = RTLinuxSysFsOpen("class/dmi/%s", pszSysFsName);
+ if (fd >= 0)
+ {
+ size_t cbRead;
+ rc = RTLinuxSysFsReadFile(fd, pszBuf, cbBuf, &cbRead);
+ if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
+ {
+ /* The file we're reading may end with a newline, remove it. */
+ if (cbRead == cbBuf)
+ pszBuf[cbRead - 1] = '\0';
+ else
+ {
+ AssertRC(rc);
+ pszBuf[cbRead] = '\0';
+ if (cbRead > 0 && pszBuf[cbRead - 1] == '\n')
+ pszBuf[cbRead - 1] = '\0';
+ }
+ }
+ RTLinuxSysFsClose(fd);
+ }
+ else
+ {
+ rc = RTErrConvertFromErrno(errno);
+ switch (rc)
+ {
+ case VINF_SUCCESS:
+ AssertFailed();
+ case VERR_FILE_NOT_FOUND:
+ case VERR_PATH_NOT_FOUND:
+ case VERR_IS_A_DIRECTORY:
+ rc = VERR_NOT_SUPPORTED;
+ break;
+ case VERR_PERMISSION_DENIED:
+ case VERR_ACCESS_DENIED:
+ rc = VERR_ACCESS_DENIED;
+ break;
+ }
+ }
+
+ return rc;
+}
+RT_EXPORT_SYMBOL(RTSystemQueryDmiString);
+
diff --git a/src/VBox/Runtime/r3/linux/RTThreadGetNativeState-linux.cpp b/src/VBox/Runtime/r3/linux/RTThreadGetNativeState-linux.cpp
new file mode 100644
index 000000000..ff65d2575
--- /dev/null
+++ b/src/VBox/Runtime/r3/linux/RTThreadGetNativeState-linux.cpp
@@ -0,0 +1,111 @@
+/* $Id: RTThreadGetNativeState-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
+/** @file
+ * IPRT - RTThreadGetNativeState, linux implementation.
+ */
+
+/*
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#define LOG_GROUP RTLOGGROUP_PROCESS
+#include <iprt/thread.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/ctype.h>
+#include <iprt/err.h>
+#include <iprt/string.h>
+
+#include "internal/thread.h"
+
+#include <unistd.h>
+#include <sys/fcntl.h>
+
+
+RTDECL(RTTHREADNATIVESTATE) RTThreadGetNativeState(RTTHREAD hThread)
+{
+ RTTHREADNATIVESTATE enmRet = RTTHREADNATIVESTATE_INVALID;
+ PRTTHREADINT pThread = rtThreadGet(hThread);
+ if (pThread)
+ {
+ enmRet = RTTHREADNATIVESTATE_UNKNOWN;
+
+ char szName[512];
+ RTStrPrintf(szName, sizeof(szName), "/proc/self/task/%u/stat", pThread->tid);
+ int fd = open(szName, O_RDONLY, 0);
+ if (fd >= 0)
+ {
+ ssize_t cch = read(fd, szName, sizeof(szName) - 1);
+ close(fd);
+ if (cch > 0)
+ {
+ szName[cch] = '\0';
+
+ /* skip the pid, the (comm name) and stop at the status char. */
+ const char *psz = szName;
+ while ( *psz
+ && ( *psz != ')'
+ || !RT_C_IS_SPACE(psz[1])
+ || !RT_C_IS_ALPHA(psz[2])
+ || !RT_C_IS_SPACE(psz[3])
+ )
+ )
+ psz++;
+ if (*psz == ')')
+ {
+ switch (psz[2])
+ {
+ case 'R': /* running */
+ enmRet = RTTHREADNATIVESTATE_RUNNING;
+ break;
+
+ case 'S': /* sleeping */
+ case 'D': /* disk sleeping */
+ enmRet = RTTHREADNATIVESTATE_BLOCKED;
+ break;
+
+ case 'T': /* stopped or tracking stop */
+ enmRet = RTTHREADNATIVESTATE_SUSPENDED;
+ break;
+
+ case 'Z': /* zombie */
+ case 'X': /* dead */
+ enmRet = RTTHREADNATIVESTATE_TERMINATED;
+ break;
+
+ default:
+ AssertMsgFailed(("state=%c\n", psz[2]));
+ enmRet = RTTHREADNATIVESTATE_UNKNOWN;
+ break;
+ }
+ }
+ else
+ AssertMsgFailed(("stat='%s'\n", szName));
+ }
+ }
+ rtThreadRelease(pThread);
+ }
+ return enmRet;
+}
+
diff --git a/src/VBox/Runtime/r3/linux/fileaio-linux.cpp b/src/VBox/Runtime/r3/linux/fileaio-linux.cpp
index 6ad01d405..e264fe2b5 100644
--- a/src/VBox/Runtime/r3/linux/fileaio-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/fileaio-linux.cpp
@@ -1,10 +1,10 @@
-/* $Id: fileaio-linux.cpp $ */
+/* $Id: fileaio-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
/** @file
* IPRT - File async I/O, native implementation for the Linux host platform.
*/
/*
- * Copyright (C) 2006-2007 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2007 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,10 +22,6 @@
*
* 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.
*/
/** @page pg_rtfileaio_linux RTFile Async I/O - Linux Implementation Notes
@@ -398,10 +394,10 @@ RTDECL(int) RTFileAioReqPrepareRead(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off,
RTDECL(int) RTFileAioReqPrepareWrite(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off,
- void *pvBuf, size_t cbWrite, void *pvUser)
+ void const *pvBuf, size_t cbWrite, void *pvUser)
{
return rtFileAioReqPrepareTransfer(hReq, hFile, LNXKAIO_IOCB_CMD_WRITE,
- off, pvBuf, cbWrite, pvUser);
+ off, (void *)pvBuf, cbWrite, pvUser);
}
@@ -646,7 +642,7 @@ RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size
}
-RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, unsigned cMillisTimeout,
+RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL cMillies,
PRTFILEAIOREQ pahReqs, size_t cReqs, uint32_t *pcReqs)
{
/*
@@ -672,10 +668,10 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, unsigned cMi
struct timespec *pTimeout = NULL;
struct timespec Timeout = {0,0};
uint64_t StartNanoTS = 0;
- if (cMillisTimeout != RT_INDEFINITE_WAIT)
+ if (cMillies != RT_INDEFINITE_WAIT)
{
- Timeout.tv_sec = cMillisTimeout / 1000;
- Timeout.tv_nsec = cMillisTimeout % 1000 * 1000000;
+ Timeout.tv_sec = cMillies / 1000;
+ Timeout.tv_nsec = cMillies % 1000 * 1000000;
pTimeout = &Timeout;
StartNanoTS = RTTimeNanoTS();
}
@@ -746,20 +742,20 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, unsigned cMi
cMinReqs -= cDone;
cReqs -= cDone;
- if (cMillisTimeout != RT_INDEFINITE_WAIT)
+ if (cMillies != RT_INDEFINITE_WAIT)
{
/* The API doesn't return ETIMEDOUT, so we have to fix that ourselves. */
uint64_t NanoTS = RTTimeNanoTS();
uint64_t cMilliesElapsed = (NanoTS - StartNanoTS) / 1000000;
- if (cMilliesElapsed >= cMillisTimeout)
+ if (cMilliesElapsed >= cMillies)
{
rc = VERR_TIMEOUT;
break;
}
/* The syscall supposedly updates it, but we're paranoid. :-) */
- Timeout.tv_sec = (cMillisTimeout - (unsigned)cMilliesElapsed) / 1000;
- Timeout.tv_nsec = (cMillisTimeout - (unsigned)cMilliesElapsed) % 1000 * 1000000;
+ Timeout.tv_sec = (cMillies - (RTMSINTERVAL)cMilliesElapsed) / 1000;
+ Timeout.tv_nsec = (cMillies - (RTMSINTERVAL)cMilliesElapsed) % 1000 * 1000000;
}
}
diff --git a/src/VBox/Runtime/r3/linux/mp-linux.cpp b/src/VBox/Runtime/r3/linux/mp-linux.cpp
index 7fcc9b73a..a8c6502ff 100644
--- a/src/VBox/Runtime/r3/linux/mp-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/mp-linux.cpp
@@ -1,10 +1,10 @@
-/* $Id: mp-linux.cpp $ */
+/* $Id: mp-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
/** @file
* IPRT - Multiprocessor, Linux.
*/
/*
- * Copyright (C) 2006-2008 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2008 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,10 +22,6 @@
*
* 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.
*/
@@ -120,7 +116,7 @@ static uint32_t rtMpLinuxGetFrequency(RTCPUID idCpu)
RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
{
- return idCpu < rtMpLinuxMaxCpus() ? idCpu : -1;
+ return idCpu < rtMpLinuxMaxCpus() ? (int)idCpu : -1;
}
diff --git a/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp b/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp
index 36a145a97..2f1151749 100644
--- a/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp
@@ -1,10 +1,10 @@
-/* $Id: rtProcInitExePath-linux.cpp $ */
+/* $Id: rtProcInitExePath-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
/** @file
* IPRT - rtProcInitName, Linux.
*/
/*
- * Copyright (C) 2006-2008 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2008 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,10 +22,6 @@
*
* 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.
*/
/*******************************************************************************
diff --git a/src/VBox/Runtime/r3/linux/sched-linux.cpp b/src/VBox/Runtime/r3/linux/sched-linux.cpp
index ffaf7caf6..ef66c272d 100644
--- a/src/VBox/Runtime/r3/linux/sched-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/sched-linux.cpp
@@ -1,10 +1,10 @@
-/* $Id: sched-linux.cpp $ */
+/* $Id: sched-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
/** @file
* IPRT - Scheduling, POSIX.
*/
/*
- * Copyright (C) 2006-2007 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2007 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,10 +22,6 @@
*
* 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.
*/
/*
@@ -46,7 +42,7 @@
* Be very careful with enabling this, it may cause deadlocks when combined
* with the 'thread' logging prefix.
*/
-#ifdef __DOXYGEN__
+#ifdef DOXYGEN_RUNNING
# define THREAD_LOGGING
#endif
diff --git a/src/VBox/Runtime/r3/linux/semevent-linux.cpp b/src/VBox/Runtime/r3/linux/semevent-linux.cpp
index 8a328454b..3bd51e977 100644
--- a/src/VBox/Runtime/r3/linux/semevent-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/semevent-linux.cpp
@@ -1,10 +1,10 @@
-/* $Id: semevent-linux.cpp $ */
+/* $Id: semevent-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
/** @file
* IPRT - Event Semaphore, Linux (2.6.x+).
*/
/*
- * Copyright (C) 2006-2007 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,10 +22,6 @@
*
* 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.
*/
#include <features.h>
@@ -49,12 +45,16 @@ asm volatile (".global epoll_pwait");
* Header Files *
*******************************************************************************/
#include <iprt/semaphore.h>
-#include <iprt/assert.h>
-#include <iprt/alloc.h>
+#include "internal/iprt.h"
+
#include <iprt/asm.h>
+#include <iprt/assert.h>
#include <iprt/err.h>
+#include <iprt/lockvalidator.h>
+#include <iprt/mem.h>
#include <iprt/time.h>
#include "internal/magics.h"
+#include "internal/strict.h"
#include <errno.h>
#include <limits.h>
@@ -86,6 +86,12 @@ struct RTSEMEVENTINTERNAL
uint32_t volatile fSignalled;
/** The number of waiting threads */
int32_t volatile cWaiters;
+#ifdef RTSEMEVENT_STRICT
+ /** Signallers. */
+ RTLOCKVALRECSHRD Signallers;
+ /** Indicates that lock validation should be performed. */
+ bool volatile fEverHadSignallers;
+#endif
};
@@ -106,8 +112,16 @@ static long sys_futex(uint32_t volatile *uaddr, int op, int val, struct timespec
-RTDECL(int) RTSemEventCreate(PRTSEMEVENT pEventSem)
+RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem)
{
+ return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
+}
+
+
+RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
+{
+ AssertReturn(!(fFlags & ~RTSEMEVENT_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
+
/*
* Allocate semaphore handle.
*/
@@ -117,21 +131,41 @@ RTDECL(int) RTSemEventCreate(PRTSEMEVENT pEventSem)
pThis->iMagic = RTSEMEVENT_MAGIC;
pThis->cWaiters = 0;
pThis->fSignalled = 0;
- *pEventSem = pThis;
+#ifdef RTSEMEVENT_STRICT
+ if (!pszNameFmt)
+ {
+ static uint32_t volatile s_iSemEventAnon = 0;
+ RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
+ true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
+ "RTSemEvent-%u", ASMAtomicIncU32(&s_iSemEventAnon) - 1);
+ }
+ else
+ {
+ va_list va;
+ va_start(va, pszNameFmt);
+ RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
+ true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
+ pszNameFmt, va);
+ va_end(va);
+ }
+ pThis->fEverHadSignallers = false;
+#endif
+
+ *phEventSem = pThis;
return VINF_SUCCESS;
}
return VERR_NO_MEMORY;
}
-RTDECL(int) RTSemEventDestroy(RTSEMEVENT EventSem)
+RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem)
{
/*
* Validate input.
*/
- if (EventSem == NIL_RTSEMEVENT) /* don't bitch */
- return VERR_INVALID_HANDLE;
- struct RTSEMEVENTINTERNAL *pThis = EventSem;
+ struct RTSEMEVENTINTERNAL *pThis = hEventSem;
+ if (pThis == NIL_RTSEMEVENT)
+ return VINF_SUCCESS;
AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
AssertReturn(pThis->iMagic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
@@ -148,19 +182,31 @@ RTDECL(int) RTSemEventDestroy(RTSEMEVENT EventSem)
/*
* Free the semaphore memory and be gone.
*/
+#ifdef RTSEMEVENT_STRICT
+ RTLockValidatorRecSharedDelete(&pThis->Signallers);
+#endif
RTMemFree(pThis);
return VINF_SUCCESS;
}
-RTDECL(int) RTSemEventSignal(RTSEMEVENT EventSem)
+RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
{
/*
* Validate input.
*/
- struct RTSEMEVENTINTERNAL *pThis = EventSem;
- AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENT_MAGIC,
- VERR_INVALID_HANDLE);
+ struct RTSEMEVENTINTERNAL *pThis = hEventSem;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->iMagic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
+
+#ifdef RTSEMEVENT_STRICT
+ if (pThis->fEverHadSignallers)
+ {
+ int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
+ if (RT_FAILURE(rc9))
+ return rc9;
+ }
+#endif
ASMAtomicWriteU32(&pThis->fSignalled, 1);
if (ASMAtomicReadS32(&pThis->cWaiters) < 1)
@@ -178,18 +224,23 @@ RTDECL(int) RTSemEventSignal(RTSEMEVENT EventSem)
}
-static int rtSemEventWait(RTSEMEVENT EventSem, unsigned cMillies, bool fAutoResume)
+static int rtSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies, bool fAutoResume)
{
+ PCRTLOCKVALSRCPOS pSrcPos = NULL;
+
/*
* Validate input.
*/
- struct RTSEMEVENTINTERNAL *pThis = EventSem;
- AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENT_MAGIC,
- VERR_INVALID_HANDLE);
+ struct RTSEMEVENTINTERNAL *pThis = hEventSem;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->iMagic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
/*
* Quickly check whether it's signaled.
*/
+ /** @todo this isn't fair if someone is already waiting on it. They should
+ * have the first go at it!
+ * (ASMAtomicReadS32(&pThis->cWaiters) == 0 || !cMillies) && ... */
if (ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
return VINF_SUCCESS;
@@ -214,10 +265,26 @@ static int rtSemEventWait(RTSEMEVENT EventSem, unsigned cMillies, bool fAutoResu
/*
* The wait loop.
*/
+#ifdef RTSEMEVENT_STRICT
+ RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
+#else
+ RTTHREAD hThreadSelf = RTThreadSelf();
+#endif
int rc = VINF_SUCCESS;
for (;;)
{
+#ifdef RTSEMEVENT_STRICT
+ if (pThis->fEverHadSignallers)
+ {
+ rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
+ cMillies, RTTHREADSTATE_EVENT, true);
+ if (RT_FAILURE(rc))
+ break;
+ }
+#endif
+ RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true);
long lrc = sys_futex(&pThis->fSignalled, FUTEX_WAIT, 0, pTimeout, NULL, 0);
+ RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT);
if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENT_MAGIC))
{
rc = VERR_SEM_DESTROYED;
@@ -269,18 +336,56 @@ static int rtSemEventWait(RTSEMEVENT EventSem, unsigned cMillies, bool fAutoResu
}
-RTDECL(int) RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies)
+RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
{
- int rc = rtSemEventWait(EventSem, cMillies, true);
+ int rc = rtSemEventWait(hEventSem, cMillies, true);
Assert(rc != VERR_INTERRUPTED);
Assert(rc != VERR_TIMEOUT || cMillies != RT_INDEFINITE_WAIT);
return rc;
}
-RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT EventSem, unsigned cMillies)
+RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
+{
+ return rtSemEventWait(hEventSem, cMillies, false);
+}
+
+
+RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
+{
+#ifdef RTSEMEVENT_STRICT
+ struct RTSEMEVENTINTERNAL *pThis = hEventSem;
+ AssertPtrReturnVoid(pThis);
+ AssertReturnVoid(pThis->iMagic == RTSEMEVENT_MAGIC);
+
+ ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
+ RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
+#endif
+}
+
+
+RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
{
- return rtSemEventWait(EventSem, cMillies, false);
+#ifdef RTSEMEVENT_STRICT
+ struct RTSEMEVENTINTERNAL *pThis = hEventSem;
+ AssertPtrReturnVoid(pThis);
+ AssertReturnVoid(pThis->iMagic == RTSEMEVENT_MAGIC);
+
+ ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
+ RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
+#endif
+}
+
+
+RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
+{
+#ifdef RTSEMEVENT_STRICT
+ struct RTSEMEVENTINTERNAL *pThis = hEventSem;
+ AssertPtrReturnVoid(pThis);
+ AssertReturnVoid(pThis->iMagic == RTSEMEVENT_MAGIC);
+
+ RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
+#endif
}
#endif /* glibc < 2.6 || IPRT_WITH_FUTEX_BASED_SEMS */
diff --git a/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp b/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp
index 711a12673..059f3facb 100644
--- a/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp
@@ -1,10 +1,10 @@
-/* $Id: semeventmulti-linux.cpp $ */
+/* $Id: semeventmulti-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
/** @file
* IPRT - Multiple Release Event Semaphore, Linux (2.6.x+).
*/
/*
- * Copyright (C) 2006-2007 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2007 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,10 +22,6 @@
*
* 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.
*/
@@ -51,12 +47,17 @@ asm volatile (".global epoll_pwait");
* Header Files *
*******************************************************************************/
#include <iprt/semaphore.h>
+#include "internal/iprt.h"
+
#include <iprt/assert.h>
-#include <iprt/alloc.h>
#include <iprt/asm.h>
#include <iprt/err.h>
+#include <iprt/lockvalidator.h>
+#include <iprt/mem.h>
#include <iprt/time.h>
#include "internal/magics.h"
+#include "internal/strict.h"
+
#include <errno.h>
#include <limits.h>
@@ -81,13 +82,19 @@ asm volatile (".global epoll_pwait");
struct RTSEMEVENTMULTIINTERNAL
{
/** Magic value. */
- intptr_t volatile iMagic;
+ uint32_t volatile u32Magic;
/** The futex state variable.
* -1 means signaled.
* 0 means not signaled, no waiters.
* 1 means not signaled and that someone is waiting.
*/
int32_t volatile iState;
+#ifdef RTSEMEVENTMULTI_STRICT
+ /** Signallers. */
+ RTLOCKVALRECSHRD Signallers;
+ /** Indicates that lock validation should be performed. */
+ bool volatile fEverHadSignallers;
+#endif
};
@@ -107,36 +114,67 @@ static long sys_futex(int32_t volatile *uaddr, int op, int val, struct timespec
}
-RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI pEventMultiSem)
+RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
+{
+ return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
+}
+
+
+RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
+ const char *pszNameFmt, ...)
{
+ AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
+
/*
* Allocate semaphore handle.
*/
struct RTSEMEVENTMULTIINTERNAL *pThis = (struct RTSEMEVENTMULTIINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTMULTIINTERNAL));
if (pThis)
{
- pThis->iMagic = RTSEMEVENTMULTI_MAGIC;
- pThis->iState = 0;
- *pEventMultiSem = pThis;
+ pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
+ pThis->iState = 0;
+#ifdef RTSEMEVENTMULTI_STRICT
+ if (!pszNameFmt)
+ {
+ static uint32_t volatile s_iSemEventMultiAnon = 0;
+ RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
+ true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
+ "RTSemEventMulti-%u", ASMAtomicIncU32(&s_iSemEventMultiAnon) - 1);
+ }
+ else
+ {
+ va_list va;
+ va_start(va, pszNameFmt);
+ RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
+ true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
+ pszNameFmt, va);
+ va_end(va);
+ }
+ pThis->fEverHadSignallers = false;
+#endif
+
+ *phEventMultiSem = pThis;
return VINF_SUCCESS;
}
return VERR_NO_MEMORY;
}
-RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem)
+RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
{
/*
* Validate input.
*/
- struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
- AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
- VERR_INVALID_HANDLE);
+ struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
+ if (pThis == NIL_RTSEMEVENTMULTI)
+ return VINF_SUCCESS;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
/*
* Invalidate the semaphore and wake up anyone waiting on it.
*/
- ASMAtomicWriteSize(&pThis->iMagic, RTSEMEVENTMULTI_MAGIC + 1);
+ ASMAtomicWriteSize(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC + 1);
if (ASMAtomicXchgS32(&pThis->iState, -1) == 1)
{
sys_futex(&pThis->iState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
@@ -146,19 +184,33 @@ RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem)
/*
* Free the semaphore memory and be gone.
*/
+#ifdef RTSEMEVENTMULTI_STRICT
+ RTLockValidatorRecSharedDelete(&pThis->Signallers);
+#endif
RTMemFree(pThis);
return VINF_SUCCESS;
}
-RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem)
+RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
{
/*
* Validate input.
*/
- struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
- AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
+ struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
+ AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
VERR_INVALID_HANDLE);
+
+#ifdef RTSEMEVENTMULTI_STRICT
+ if (pThis->fEverHadSignallers)
+ {
+ int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
+ if (RT_FAILURE(rc9))
+ return rc9;
+ }
+#endif
+
+
/*
* Signal it.
*/
@@ -174,13 +226,13 @@ RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem)
}
-RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem)
+RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
{
/*
* Validate input.
*/
- struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
- AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
+ struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
+ AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
VERR_INVALID_HANDLE);
#ifdef RT_STRICT
int32_t i = pThis->iState;
@@ -195,13 +247,15 @@ RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem)
}
-static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, bool fAutoResume)
+static int rtSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies, bool fAutoResume)
{
+ PCRTLOCKVALSRCPOS pSrcPos = NULL;
+
/*
* Validate input.
*/
- struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
- AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
+ struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
+ AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
VERR_INVALID_HANDLE);
/*
@@ -220,6 +274,7 @@ static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies,
uint64_t u64End = 0; /* shut up gcc */
if (cMillies != RT_INDEFINITE_WAIT)
{
+ /* If the timeout is zero, then we're done. */
if (!cMillies)
return VERR_TIMEOUT;
ts.tv_sec = cMillies / 1000;
@@ -231,6 +286,11 @@ static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies,
/*
* The wait loop.
*/
+#ifdef RTSEMEVENTMULTI_STRICT
+ RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
+#else
+ RTTHREAD hThreadSelf = RTThreadSelf();
+#endif
for (unsigned i = 0;; i++)
{
/*
@@ -251,8 +311,19 @@ static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies,
ts.tv_sec = (uint64_t)i64Diff / UINT32_C(1000000000);
ts.tv_nsec = (uint64_t)i64Diff % UINT32_C(1000000000);
}
+#ifdef RTSEMEVENTMULTI_STRICT
+ if (pThis->fEverHadSignallers)
+ {
+ int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
+ cMillies, RTTHREADSTATE_EVENT_MULTI, true);
+ if (RT_FAILURE(rc9))
+ return rc9;
+ }
+#endif
+ RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
long rc = sys_futex(&pThis->iState, FUTEX_WAIT, 1, pTimeout, NULL, 0);
- if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENTMULTI_MAGIC))
+ RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
+ if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
return VERR_SEM_DESTROYED;
if (rc == 0)
return VINF_SUCCESS;
@@ -262,7 +333,9 @@ static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies,
*/
if (rc == -ETIMEDOUT)
{
-/** @something is broken here. shows up every now and again in the ata code. Should try to run the timeout against RTTimeMilliTS to check that it's doing the right thing... */
+/** @todo something is broken here. shows up every now and again in the ata
+ * code. Should try to run the timeout against RTTimeMilliTS to
+ * check that it's doing the right thing... */
Assert(pTimeout);
return VERR_TIMEOUT;
}
@@ -286,17 +359,55 @@ static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies,
}
-RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies)
+RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
{
- int rc = rtSemEventMultiWait(EventMultiSem, cMillies, true);
+ int rc = rtSemEventMultiWait(hEventMultiSem, cMillies, true);
Assert(rc != VERR_INTERRUPTED);
return rc;
}
-RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies)
+RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
+{
+ return rtSemEventMultiWait(hEventMultiSem, cMillies, false);
+}
+
+
+RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
+{
+#ifdef RTSEMEVENTMULTI_STRICT
+ struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
+ AssertPtrReturnVoid(pThis);
+ AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
+
+ ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
+ RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
+#endif
+}
+
+
+RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
+{
+#ifdef RTSEMEVENTMULTI_STRICT
+ struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
+ AssertPtrReturnVoid(pThis);
+ AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
+
+ ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
+ RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
+#endif
+}
+
+
+RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
{
- return rtSemEventMultiWait(EventMultiSem, cMillies, false);
+#ifdef RTSEMEVENTMULTI_STRICT
+ struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
+ AssertPtrReturnVoid(pThis);
+ AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
+
+ RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
+#endif
}
#endif /* glibc < 2.6 || IPRT_WITH_FUTEX_BASED_SEMS */
diff --git a/src/VBox/Runtime/r3/linux/semmutex-linux.cpp b/src/VBox/Runtime/r3/linux/semmutex-linux.cpp
index 36d781a6d..16a28270f 100644
--- a/src/VBox/Runtime/r3/linux/semmutex-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/semmutex-linux.cpp
@@ -1,10 +1,10 @@
-/* $Id: semmutex-linux.cpp $ */
+/* $Id: semmutex-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
/** @file
* IPRT - Mutex Semaphore, Linux (2.6.x+).
*/
/*
- * Copyright (C) 2006-2007 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2007 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,21 +22,20 @@
*
* 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/assert.h>
+#include "internal/iprt.h"
+
#include <iprt/alloc.h>
-#include <iprt/thread.h>
#include <iprt/asm.h>
+#include <iprt/assert.h>
#include <iprt/err.h>
+#include <iprt/lockvalidator.h>
+#include <iprt/thread.h>
#include <iprt/time.h>
#include "internal/magics.h"
#include "internal/strict.h"
@@ -70,14 +69,19 @@ struct RTSEMMUTEXINTERNAL
*/
int32_t volatile iState;
/** Nesting count. */
- uint32_t volatile cNesting;
+ uint32_t volatile cNestings;
/** The owner of the mutex. */
pthread_t volatile Owner;
- /** Magic value. */
- intptr_t volatile iMagic;
+ /** Magic value (RTSEMMUTEX_MAGIC). */
+ uint32_t volatile u32Magic;
+#ifdef RTSEMMUTEX_STRICT
+ /** Lock validator record associated with this mutex. */
+ RTLOCKVALRECEXCL ValidatorRec;
+#endif
};
+
/**
* Wrapper for the futex syscall.
*/
@@ -94,20 +98,47 @@ static long sys_futex(int32_t volatile *uaddr, int op, int val, struct timespec
}
-RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
+#undef RTSemMutexCreate
+RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem)
{
+ return RTSemMutexCreateEx(phMutexSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
+}
+
+
+RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags,
+ RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
+{
+ AssertReturn(!(fFlags & ~RTSEMMUTEX_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
+
/*
* Allocate semaphore handle.
*/
struct RTSEMMUTEXINTERNAL *pThis = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL));
if (pThis)
{
- pThis->iMagic = RTSEMMUTEX_MAGIC;
- pThis->iState = 0;
- pThis->Owner = (pthread_t)~0;
- pThis->cNesting = 0;
+ pThis->u32Magic = RTSEMMUTEX_MAGIC;
+ pThis->iState = 0;
+ pThis->Owner = (pthread_t)~0;
+ pThis->cNestings = 0;
+#ifdef RTSEMMUTEX_STRICT
+ if (!pszNameFmt)
+ {
+ static uint32_t volatile s_iMutexAnon = 0;
+ RTLockValidatorRecExclInit(&pThis->ValidatorRec, hClass, uSubClass, pThis,
+ !(fFlags & RTSEMMUTEX_FLAGS_NO_LOCK_VAL),
+ "RTSemMutex-%u", ASMAtomicIncU32(&s_iMutexAnon) - 1);
+ }
+ else
+ {
+ va_list va;
+ va_start(va, pszNameFmt);
+ RTLockValidatorRecExclInitV(&pThis->ValidatorRec, hClass, uSubClass, pThis,
+ !(fFlags & RTSEMMUTEX_FLAGS_NO_LOCK_VAL), pszNameFmt, va);
+ va_end(va);
+ }
+#endif
- *pMutexSem = pThis;
+ *phMutexSem = pThis;
return VINF_SUCCESS;
}
@@ -115,30 +146,33 @@ RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
}
-RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)
+RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem)
{
/*
* Validate input.
*/
- if (MutexSem == NIL_RTSEMMUTEX)
- return VERR_INVALID_HANDLE;
- struct RTSEMMUTEXINTERNAL *pThis = MutexSem;
+ if (hMutexSem == NIL_RTSEMMUTEX)
+ return VINF_SUCCESS;
+ struct RTSEMMUTEXINTERNAL *pThis = hMutexSem;
AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
- AssertMsgReturn(pThis->iMagic == RTSEMMUTEX_MAGIC,
- ("MutexSem=%p iMagic=%#x\n", pThis, pThis->iMagic),
+ AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC,
+ ("hMutexSem=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
VERR_INVALID_HANDLE);
/*
* Invalidate the semaphore and wake up anyone waiting on it.
*/
- ASMAtomicXchgSize(&pThis->iMagic, RTSEMMUTEX_MAGIC + 1);
+ ASMAtomicWriteU32(&pThis->u32Magic, RTSEMMUTEX_MAGIC_DEAD);
if (ASMAtomicXchgS32(&pThis->iState, 0) > 0)
{
sys_futex(&pThis->iState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
usleep(1000);
}
- pThis->Owner = (pthread_t)~0;
- pThis->cNesting = 0;
+ pThis->Owner = (pthread_t)~0;
+ pThis->cNestings = 0;
+#ifdef RTSEMMUTEX_STRICT
+ RTLockValidatorRecExclDelete(&pThis->ValidatorRec);
+#endif
/*
* Free the semaphore memory and be gone.
@@ -148,26 +182,60 @@ RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)
}
-static int rtsemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies, bool fAutoResume)
+RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass)
+{
+#ifdef RTSEMMUTEX_STRICT
+ /*
+ * Validate.
+ */
+ RTSEMMUTEXINTERNAL *pThis = hMutexSem;
+ AssertPtrReturn(pThis, RTLOCKVAL_SUB_CLASS_INVALID);
+ AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
+
+ return RTLockValidatorRecExclSetSubClass(&pThis->ValidatorRec, uSubClass);
+#else
+ return RTLOCKVAL_SUB_CLASS_INVALID;
+#endif
+}
+
+
+DECL_FORCE_INLINE(int) rtSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, bool fAutoResume, PCRTLOCKVALSRCPOS pSrcPos)
{
/*
* Validate input.
*/
- struct RTSEMMUTEXINTERNAL *pThis = MutexSem;
- AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMMUTEX_MAGIC,
- VERR_INVALID_HANDLE);
+ struct RTSEMMUTEXINTERNAL *pThis = hMutexSem;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
/*
* Check if nested request.
*/
pthread_t Self = pthread_self();
if ( pThis->Owner == Self
- && pThis->cNesting > 0)
+ && pThis->cNestings > 0)
{
- pThis->cNesting++;
+#ifdef RTSEMMUTEX_STRICT
+ int rc9 = RTLockValidatorRecExclRecursion(&pThis->ValidatorRec, pSrcPos);
+ if (RT_FAILURE(rc9))
+ return rc9;
+#endif
+ ASMAtomicIncU32(&pThis->cNestings);
return VINF_SUCCESS;
}
+#ifdef RTSEMMUTEX_STRICT
+ RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
+ if (cMillies)
+ {
+ int rc9 = RTLockValidatorRecExclCheckOrder(&pThis->ValidatorRec, hThreadSelf, pSrcPos, cMillies);
+ if (RT_FAILURE(rc9))
+ return rc9;
+ }
+#else
+ RTTHREAD hThreadSelf = RTThreadSelf();
+#endif
+
/*
* Convert timeout value.
*/
@@ -201,8 +269,22 @@ static int rtsemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies, bool fAutoR
/*
* Go to sleep.
*/
+ if (pTimeout && ( pTimeout->tv_sec || pTimeout->tv_nsec ))
+ {
+#ifdef RTSEMMUTEX_STRICT
+ int rc9 = RTLockValidatorRecExclCheckBlocking(&pThis->ValidatorRec, hThreadSelf, pSrcPos, true,
+ cMillies, RTTHREADSTATE_MUTEX, true);
+ if (RT_FAILURE(rc9))
+ return rc9;
+#else
+ RTThreadBlocking(hThreadSelf, RTTHREADSTATE_MUTEX, true);
+#endif
+ }
+
long rc = sys_futex(&pThis->iState, FUTEX_WAIT, 2, pTimeout, NULL, 0);
- if (RT_UNLIKELY(pThis->iMagic != RTSEMMUTEX_MAGIC))
+
+ RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_MUTEX);
+ if (RT_UNLIKELY(pThis->u32Magic != RTSEMMUTEX_MAGIC))
return VERR_SEM_DESTROYED;
/*
@@ -257,70 +339,97 @@ static int rtsemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies, bool fAutoR
* Set the owner and nesting.
*/
pThis->Owner = Self;
- ASMAtomicXchgU32(&pThis->cNesting, 1);
+ ASMAtomicWriteU32(&pThis->cNestings, 1);
#ifdef RTSEMMUTEX_STRICT
- RTTHREAD Thread = RTThreadSelf();
- if (Thread != NIL_RTTHREAD)
- RTThreadWriteLockInc(Thread);
+ RTLockValidatorRecExclSetOwner(&pThis->ValidatorRec, hThreadSelf, pSrcPos, true);
#endif
return VINF_SUCCESS;
}
-RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
+#undef RTSemMutexRequest
+RTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
+{
+#ifndef RTSEMMUTEX_STRICT
+ int rc = rtSemMutexRequest(hMutexSem, cMillies, true, NULL);
+#else
+ RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
+ int rc = rtSemMutexRequest(hMutexSem, cMillies, true, &SrcPos);
+#endif
+ Assert(rc != VERR_INTERRUPTED);
+ return rc;
+}
+
+
+RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
{
- int rc = rtsemMutexRequest(MutexSem, cMillies, true);
+ RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
+ int rc = rtSemMutexRequest(hMutexSem, cMillies, true, &SrcPos);
Assert(rc != VERR_INTERRUPTED);
return rc;
}
-RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
+#undef RTSemMutexRequestNoResume
+RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
{
- return rtsemMutexRequest(MutexSem, cMillies, false);
+#ifndef RTSEMMUTEX_STRICT
+ return rtSemMutexRequest(hMutexSem, cMillies, false, NULL);
+#else
+ RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
+ return rtSemMutexRequest(hMutexSem, cMillies, false, &SrcPos);
+#endif
+}
+
+
+RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
+ return rtSemMutexRequest(hMutexSem, cMillies, false, &SrcPos);
}
-RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)
+RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem)
{
/*
* Validate input.
*/
- struct RTSEMMUTEXINTERNAL *pThis = MutexSem;
- AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMMUTEX_MAGIC,
- VERR_INVALID_HANDLE);
+ struct RTSEMMUTEXINTERNAL *pThis = hMutexSem;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
+
+#ifdef RTSEMMUTEX_STRICT
+ int rc9 = RTLockValidatorRecExclReleaseOwner(&pThis->ValidatorRec, pThis->cNestings == 1);
+ if (RT_FAILURE(rc9))
+ return rc9;
+#endif
/*
* Check if nested.
*/
pthread_t Self = pthread_self();
if (RT_UNLIKELY( pThis->Owner != Self
- || pThis->cNesting == 0))
+ || pThis->cNestings == 0))
{
- AssertMsgFailed(("Not owner of mutex %p!! Self=%08x Owner=%08x cNesting=%d\n",
- pThis, Self, pThis->Owner, pThis->cNesting));
+ AssertMsgFailed(("Not owner of mutex %p!! Self=%08x Owner=%08x cNestings=%d\n",
+ pThis, Self, pThis->Owner, pThis->cNestings));
return VERR_NOT_OWNER;
}
/*
* If nested we'll just pop a nesting.
*/
- if (pThis->cNesting > 1)
+ if (pThis->cNestings > 1)
{
- pThis->cNesting--;
+ ASMAtomicDecU32(&pThis->cNestings);
return VINF_SUCCESS;
}
/*
- * Clear the state. (cNesting == 1)
+ * Clear the state. (cNestings == 1)
*/
-#ifdef RTSEMMUTEX_STRICT
- RTTHREAD Thread = RTThreadSelf();
- if (Thread != NIL_RTTHREAD)
- RTThreadWriteLockDec(Thread);
-#endif
pThis->Owner = (pthread_t)~0;
- ASMAtomicXchgU32(&pThis->cNesting, 0);
+ ASMAtomicWriteU32(&pThis->cNestings, 0);
/*
* Release the mutex.
@@ -335,3 +444,16 @@ RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)
return VINF_SUCCESS;
}
+
+RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem)
+{
+ /*
+ * Validate.
+ */
+ RTSEMMUTEXINTERNAL *pThis = hMutexSem;
+ AssertPtrReturn(pThis, false);
+ AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, false);
+
+ return pThis->Owner != (pthread_t)~0;
+}
+
diff --git a/src/VBox/Runtime/r3/linux/sysfs.cpp b/src/VBox/Runtime/r3/linux/sysfs.cpp
index b2cc56a5f..5b099fb6a 100644
--- a/src/VBox/Runtime/r3/linux/sysfs.cpp
+++ b/src/VBox/Runtime/r3/linux/sysfs.cpp
@@ -1,10 +1,10 @@
-/* $Id: sysfs.cpp $ */
+/* $Id: sysfs.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
/** @file
* IPRT - Linux sysfs access.
*/
/*
- * Copyright (C) 2006-2008 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2008 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,10 +22,6 @@
*
* 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.
*/
@@ -210,6 +206,39 @@ RTDECL(ssize_t) RTLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf)
}
+RTDECL(int) RTLinuxSysFsReadFile(int fd, void *pvBuf, size_t cbBuf, size_t *pcbRead)
+{
+ int rc;
+ ssize_t cbRead = read(fd, pvBuf, cbBuf);
+ if (cbRead >= 0)
+ {
+ if (pcbRead)
+ *pcbRead = cbRead;
+ if ((size_t)cbRead < cbBuf)
+ rc = VINF_SUCCESS;
+ else
+ {
+ /* Check for EOF */
+ char ch;
+ off_t off = lseek(fd, 0, SEEK_CUR);
+ ssize_t cbRead2 = read(fd, &ch, 1);
+ if (cbRead2 == 0)
+ rc = VINF_SUCCESS;
+ else if (cbRead2 > 0)
+ {
+ lseek(fd, off, SEEK_SET);
+ rc = VERR_BUFFER_OVERFLOW;
+ }
+ else
+ rc = RTErrConvertFromErrno(errno);
+ }
+ }
+ else
+ rc = RTErrConvertFromErrno(errno);
+ return rc;
+}
+
+
RTDECL(int64_t) RTLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va)
{
int fd = RTLinuxSysFsOpenV(pszFormat, va);
@@ -412,7 +441,7 @@ static ssize_t rtLinuxFindDevicePathRecursive(dev_t DevNum, RTFMODE fMode, const
rcRet = -1;
break;
}
- if (RTFS_IS_SYMLINK(Entry.Info.Attr.fMode)) /* paranoia. @todo RTDirReadEx now returns symlinks, see also #if 1 below. */
+ if (RTFS_IS_SYMLINK(Entry.Info.Attr.fMode))
continue;
/* Do the matching. */
@@ -437,12 +466,6 @@ static ssize_t rtLinuxFindDevicePathRecursive(dev_t DevNum, RTFMODE fMode, const
rcRet = -1;
break;
}
-#if 1 /** @todo This is a temporary hack, as RTDirReadEx in 3.0 doesn't know about symbolic links. */
- struct stat Stat = { 0 };
- if ( lstat(szPath, &Stat) < 0
- || S_ISLNK(Stat.st_mode))
- continue;
-#endif
strcat(&szPath[cchBasePath], "/");
rcRet = rtLinuxFindDevicePathRecursive(DevNum, fMode, szPath, pszBuf, cchBuf);
if (rcRet >= 0 || errno != ENOENT)
diff --git a/src/VBox/Runtime/r3/linux/time-linux.cpp b/src/VBox/Runtime/r3/linux/time-linux.cpp
index 8dfe73d5c..b9be9e532 100644
--- a/src/VBox/Runtime/r3/linux/time-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/time-linux.cpp
@@ -1,10 +1,10 @@
-/* $Id: time-linux.cpp $ */
+/* $Id: time-linux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
/** @file
* IPRT - Time, POSIX.
*/
/*
- * Copyright (C) 2006-2007 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2007 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,10 +22,6 @@
*
* 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.
*/
@@ -39,8 +35,8 @@
#include <sys/syscall.h>
#include <unistd.h>
#ifndef __NR_clock_gettime
-# define __NR_timer_create 259
-# define __NR_clock_gettime (__NR_timer_create+6)
+# define __NR_timer_create 259
+# define __NR_clock_gettime (__NR_timer_create+6)
#endif
#include <iprt/time.h>