diff options
| author | Felix Geyer <debfx-pkg@fobos.de> | 2010-05-02 13:24:51 +0200 |
|---|---|---|
| committer | Felix Geyer <debfx-pkg@fobos.de> | 2010-05-02 13:24:51 +0200 |
| commit | 4749e3a0c5d3a159d3ae751e6780b537c860923a (patch) | |
| tree | 28cd86e0a63ddac4224277df9ce83ef056629917 /src/VBox/Runtime/r3/linux | |
| parent | 0429962c55c464036f613d707f26b91f252584e7 (diff) | |
| download | virtualbox-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.cpp | 8 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/RTSystemQueryDmiString-linux.cpp | 104 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/RTThreadGetNativeState-linux.cpp | 111 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/fileaio-linux.cpp | 28 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/mp-linux.cpp | 10 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp | 8 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/sched-linux.cpp | 10 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/semevent-linux.cpp | 157 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp | 175 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/semmutex-linux.cpp | 236 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/sysfs.cpp | 49 | ||||
| -rw-r--r-- | src/VBox/Runtime/r3/linux/time-linux.cpp | 12 |
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> |
