diff options
| author | Michael Meskes <meskes@debian.org> | 2009-07-01 09:47:13 +0200 |
|---|---|---|
| committer | Michael Meskes <meskes@debian.org> | 2009-07-01 09:47:13 +0200 |
| commit | 519cfe73fc8bfbb621340d6e1665edf7cc7c42e3 (patch) | |
| tree | f8fcff39649e098ff27fa02c49815ca9fd6bb300 /src/VBox/Runtime/r3 | |
| parent | ffd803c5f75d470a7bd301d9fc899703546bedfb (diff) | |
| download | virtualbox-519cfe73fc8bfbb621340d6e1665edf7cc7c42e3.tar.gz | |
Imported Upstream version 3.0.0-dfsgupstream/3.0.0-dfsg
Diffstat (limited to 'src/VBox/Runtime/r3')
97 files changed, 7014 insertions, 187 deletions
diff --git a/src/VBox/Runtime/r3/alloc-ef-cpp.cpp b/src/VBox/Runtime/r3/alloc-ef-cpp.cpp index 481cc9ba5..bb8e0e667 100644 --- a/src/VBox/Runtime/r3/alloc-ef-cpp.cpp +++ b/src/VBox/Runtime/r3/alloc-ef-cpp.cpp @@ -1,4 +1,4 @@ -/* $Id: alloc-ef-cpp.cpp $ */ +/* $Id: alloc-ef-cpp.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - Memory Allocation, C++ electric fence. */ diff --git a/src/VBox/Runtime/r3/alloc-ef.cpp b/src/VBox/Runtime/r3/alloc-ef.cpp index e5cd84ab6..760ee43b2 100644 --- a/src/VBox/Runtime/r3/alloc-ef.cpp +++ b/src/VBox/Runtime/r3/alloc-ef.cpp @@ -1,4 +1,4 @@ -/* $Id: alloc-ef.cpp $ */ +/* $Id: alloc-ef.cpp 19547 2009-05-08 20:39:39Z vboxsync $ */ /** @file * IPRT - Memory Allocation, electric fence. */ @@ -271,7 +271,7 @@ static inline PRTMEMBLOCK rtmemBlockDelayRemove(void) /** * Internal allocator. */ -RTDECL(void *) rtMemAlloc(const char *pszOp, RTMEMTYPE enmType, size_t cb, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction) +void *rtMemAlloc(const char *pszOp, RTMEMTYPE enmType, size_t cb, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction) { /* * Sanity. @@ -354,7 +354,7 @@ RTDECL(void *) rtMemAlloc(const char *pszOp, RTMEMTYPE enmType, size_t cb, void /** * Internal free. */ -RTDECL(void) rtMemFree(const char *pszOp, RTMEMTYPE enmType, void *pv, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction) +void rtMemFree(const char *pszOp, RTMEMTYPE enmType, void *pv, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction) { /* * Simple case. @@ -459,7 +459,7 @@ RTDECL(void) rtMemFree(const char *pszOp, RTMEMTYPE enmType, void *pv, void *pvC /** * Internal realloc. */ -RTDECL(void *) rtMemRealloc(const char *pszOp, RTMEMTYPE enmType, void *pvOld, size_t cbNew, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction) +void *rtMemRealloc(const char *pszOp, RTMEMTYPE enmType, void *pvOld, size_t cbNew, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction) { /* * Allocate new and copy. diff --git a/src/VBox/Runtime/r3/alloc-ef.h b/src/VBox/Runtime/r3/alloc-ef.h index 6e83bc868..fa0ff03b1 100644 --- a/src/VBox/Runtime/r3/alloc-ef.h +++ b/src/VBox/Runtime/r3/alloc-ef.h @@ -1,4 +1,4 @@ -/* $Id: alloc-ef.h $ */ +/* $Id: alloc-ef.h 20374 2009-06-08 00:43:21Z vboxsync $ */ /** @file * IPRT - Memory Allocation, electric fence. */ @@ -157,12 +157,12 @@ typedef struct RTMEMBLOCK /******************************************************************************* * Internal Functions * -*******************************************************************************/ -__BEGIN_DECLS -RTDECL(void *) rtMemAlloc(const char *pszOp, RTMEMTYPE enmType, size_t cb, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction); -RTDECL(void *) rtMemRealloc(const char *pszOp, RTMEMTYPE enmType, void *pvOld, size_t cbNew, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction); -RTDECL(void) rtMemFree(const char *pszOp, RTMEMTYPE enmType, void *pv, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction); -__END_DECLS +******************************************************************************/ +RT_C_DECLS_BEGIN +void * rtMemAlloc(const char *pszOp, RTMEMTYPE enmType, size_t cb, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction); +void * rtMemRealloc(const char *pszOp, RTMEMTYPE enmType, void *pvOld, size_t cbNew, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction); +void rtMemFree(const char *pszOp, RTMEMTYPE enmType, void *pv, void *pvCaller, unsigned iLine, const char *pszFile, const char *pszFunction); +RT_C_DECLS_END #endif diff --git a/src/VBox/Runtime/r3/alloc.cpp b/src/VBox/Runtime/r3/alloc.cpp index 40d85813f..43b48f4bb 100644 --- a/src/VBox/Runtime/r3/alloc.cpp +++ b/src/VBox/Runtime/r3/alloc.cpp @@ -1,4 +1,4 @@ -/* $Id: alloc.cpp $ */ +/* $Id: alloc.cpp 11019 2008-07-30 22:47:04Z vboxsync $ */ /** @file * IPRT - Memory Allocation. */ diff --git a/src/VBox/Runtime/r3/darwin/alloc-darwin.cpp b/src/VBox/Runtime/r3/darwin/alloc-darwin.cpp index 3343146fa..b3c691a64 100644 --- a/src/VBox/Runtime/r3/darwin/alloc-darwin.cpp +++ b/src/VBox/Runtime/r3/darwin/alloc-darwin.cpp @@ -1,4 +1,4 @@ -/* $Id: alloc-darwin.cpp $ */ +/* $Id: alloc-darwin.cpp 11019 2008-07-30 22:47:04Z vboxsync $ */ /** @file * IPRT - Memory Allocation, POSIX. */ diff --git a/src/VBox/Runtime/r3/darwin/filelock-darwin.cpp b/src/VBox/Runtime/r3/darwin/filelock-darwin.cpp index 05ecbbd62..bfe5be0db 100644 --- a/src/VBox/Runtime/r3/darwin/filelock-darwin.cpp +++ b/src/VBox/Runtime/r3/darwin/filelock-darwin.cpp @@ -1,4 +1,4 @@ -/* $Id: filelock-darwin.cpp $ */ +/* $Id: filelock-darwin.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - File Locking, POSIX. */ diff --git a/src/VBox/Runtime/r3/darwin/mp-darwin.cpp b/src/VBox/Runtime/r3/darwin/mp-darwin.cpp index 67e0a2a6b..fe083c4de 100644 --- a/src/VBox/Runtime/r3/darwin/mp-darwin.cpp +++ b/src/VBox/Runtime/r3/darwin/mp-darwin.cpp @@ -1,4 +1,4 @@ -/* $Id: mp-darwin.cpp $ */ +/* $Id: mp-darwin.cpp 13836 2008-11-05 02:42:54Z vboxsync $ */ /** @file * IPRT - Multiprocessor, Darwin. */ diff --git a/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp b/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp index 9835384b9..f6259aade 100644 --- a/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp +++ b/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp @@ -1,4 +1,4 @@ -/* $Id: rtProcInitExePath-darwin.cpp $ */ +/* $Id: rtProcInitExePath-darwin.cpp 11838 2008-08-29 17:14:02Z vboxsync $ */ /** @file * IPRT - rtProcInitName, Darwin. */ diff --git a/src/VBox/Runtime/r3/darwin/sched-darwin.cpp b/src/VBox/Runtime/r3/darwin/sched-darwin.cpp index e48089642..cf9275570 100644 --- a/src/VBox/Runtime/r3/darwin/sched-darwin.cpp +++ b/src/VBox/Runtime/r3/darwin/sched-darwin.cpp @@ -1,4 +1,4 @@ -/* $Id: sched-darwin.cpp $ */ +/* $Id: sched-darwin.cpp 15881 2009-01-08 18:46:52Z vboxsync $ */ /** @file * IPRT - Scheduling, Darwin. */ diff --git a/src/VBox/Runtime/r3/darwin/time-darwin.cpp b/src/VBox/Runtime/r3/darwin/time-darwin.cpp index 6fcfbb57c..3fab3ea6c 100644 --- a/src/VBox/Runtime/r3/darwin/time-darwin.cpp +++ b/src/VBox/Runtime/r3/darwin/time-darwin.cpp @@ -1,4 +1,4 @@ -/* $Id: time-darwin.cpp $ */ +/* $Id: time-darwin.cpp 15870 2009-01-08 15:08:24Z vboxsync $ */ /** @file * IPRT - Time, Darwin. */ diff --git a/src/VBox/Runtime/r3/dir.cpp b/src/VBox/Runtime/r3/dir.cpp index 893a6f4fb..81644f080 100644 --- a/src/VBox/Runtime/r3/dir.cpp +++ b/src/VBox/Runtime/r3/dir.cpp @@ -1,4 +1,4 @@ -/* $Id: dir.cpp $ */ +/* $Id: dir.cpp 19212 2009-04-27 13:56:45Z vboxsync $ */ /** @file * IPRT - Directory Manipulation. */ diff --git a/src/VBox/Runtime/r3/fileio.cpp b/src/VBox/Runtime/r3/fileio.cpp index aeaed6df8..99798c445 100644 --- a/src/VBox/Runtime/r3/fileio.cpp +++ b/src/VBox/Runtime/r3/fileio.cpp @@ -1,4 +1,4 @@ -/* $Id: fileio.cpp $ */ +/* $Id: fileio.cpp 8913 2008-05-19 11:34:46Z vboxsync $ */ /** @file * IPRT - File I/O. */ diff --git a/src/VBox/Runtime/r3/freebsd/alloc-freebsd.cpp b/src/VBox/Runtime/r3/freebsd/alloc-freebsd.cpp index aca20a43d..8409fce3e 100644 --- a/src/VBox/Runtime/r3/freebsd/alloc-freebsd.cpp +++ b/src/VBox/Runtime/r3/freebsd/alloc-freebsd.cpp @@ -1,4 +1,4 @@ -/* $Id: alloc-freebsd.cpp $ */ +/* $Id: alloc-freebsd.cpp 11020 2008-07-30 22:48:35Z vboxsync $ */ /** @file * IPRT - Memory Allocation, POSIX. */ diff --git a/src/VBox/Runtime/r3/freebsd/fileaio-freebsd.cpp b/src/VBox/Runtime/r3/freebsd/fileaio-freebsd.cpp new file mode 100644 index 000000000..03e9170c7 --- /dev/null +++ b/src/VBox/Runtime/r3/freebsd/fileaio-freebsd.cpp @@ -0,0 +1,655 @@ +/* $Id: fileaio-freebsd.cpp 19562 2009-05-10 21:44:16Z vboxsync $ */ +/** @file + * IPRT - File async I/O, native implementation for the FreeBSD host platform. + */ + +/* + * Copyright (C) 2006-2007 Sun Microsystems, Inc. + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * 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. + * + * 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 * +*******************************************************************************/ +#define LOG_GROUP RTLOGGROUP_FILE +#include <iprt/asm.h> +#include <iprt/file.h> +#include <iprt/mem.h> +#include <iprt/assert.h> +#include <iprt/string.h> +#include <iprt/err.h> +#include <iprt/log.h> +#include <iprt/thread.h> +#include "internal/fileaio.h" + +#include <sys/types.h> +#include <sys/event.h> +#include <sys/time.h> +#include <sys/sysctl.h> +#include <aio.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * Async I/O completion context state. + */ +typedef struct RTFILEAIOCTXINTERNAL +{ + /** Handle to the kernel queue. */ + int iKQueue; + /** Current number of requests active on this context. */ + volatile int32_t cRequests; + /** The ID of the thread which is currently waiting for requests. */ + volatile RTTHREAD hThreadWait; + /** Flag whether the thread was woken up. */ + volatile bool fWokenUp; + /** Flag whether the thread is currently waiting in the syscall. */ + volatile bool fWaiting; + /** Magic value (RTFILEAIOCTX_MAGIC). */ + uint32_t u32Magic; +} RTFILEAIOCTXINTERNAL; +/** Pointer to an internal context structure. */ +typedef RTFILEAIOCTXINTERNAL *PRTFILEAIOCTXINTERNAL; + +/** + * Async I/O request state. + */ +typedef struct RTFILEAIOREQINTERNAL +{ + /** The aio control block. Must be the FIRST + * element. */ + struct aiocb AioCB; + /** Current state the request is in. */ + RTFILEAIOREQSTATE enmState; + /** Flag whether this is a flush request. */ + bool fFlush; + /** Opaque user data. */ + void *pvUser; + /** Completion context we are assigned to. */ + PRTFILEAIOCTXINTERNAL pCtxInt; + /** Number of bytes actually transfered. */ + size_t cbTransfered; + /** Status code. */ + int Rc; + /** Magic value (RTFILEAIOREQ_MAGIC). */ + uint32_t u32Magic; +} RTFILEAIOREQINTERNAL; +/** Pointer to an internal request structure. */ +typedef RTFILEAIOREQINTERNAL *PRTFILEAIOREQINTERNAL; + + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +/** The max number of events to get in one call. */ +#define AIO_MAXIMUM_REQUESTS_PER_CONTEXT 64 + +RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits) +{ + int rcBSD = 0; + AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER); + + /* + * The AIO API is implemented in a kernel module which is not + * loaded by default. + * If it is loaded there are additional sysctl parameters. + */ + int cReqsOutstandingMax = 0; + size_t cbParameter = sizeof(int); + + rcBSD = sysctlbyname("vfs.aio.max_aio_per_proc", /* name */ + &cReqsOutstandingMax, /* Where to store the old value. */ + &cbParameter, /* Size of the memory pointed to. */ + NULL, /* Where the new value is located. */ + NULL); /* Where the size of the new value is stored. */ + if (rcBSD == -1) + { + /* ENOENT means the value is unknown thus the module is not loaded. */ + if (errno == ENOENT) + return VERR_NOT_SUPPORTED; + else + return RTErrConvertFromErrno(errno); + } + + pAioLimits->cReqsOutstandingMax = cReqsOutstandingMax; + pAioLimits->cbBufferAlignment = 0; + + return VINF_SUCCESS; +} + +RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq) +{ + AssertPtrReturn(phReq, VERR_INVALID_POINTER); + + PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)RTMemAllocZ(sizeof(RTFILEAIOREQINTERNAL)); + if (RT_UNLIKELY(!pReqInt)) + return VERR_NO_MEMORY; + + /* Ininitialize static parts. */ + pReqInt->AioCB.aio_sigevent.sigev_notify = SIGEV_KEVENT; + pReqInt->AioCB.aio_sigevent.sigev_value.sival_ptr = pReqInt; + pReqInt->pCtxInt = NULL; + pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + + *phReq = (RTFILEAIOREQ)pReqInt; + + return VINF_SUCCESS; +} + +RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq) +{ + /* + * Validate the handle and ignore nil. + */ + if (hReq == NIL_RTFILEAIOREQ) + return VINF_SUCCESS; + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + + /* + * Trash the magic and free it. + */ + ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC); + RTMemFree(pReqInt); + return VINF_SUCCESS; +} + +/** + * Worker setting up the request. + */ +DECLINLINE(int) rtFileAioReqPrepareTransfer(RTFILEAIOREQ hReq, RTFILE hFile, + unsigned uTransferDirection, + RTFOFF off, void *pvBuf, size_t cbTransfer, + void *pvUser) +{ + /* + * Validate the input. + */ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + Assert(hFile != NIL_RTFILE); + AssertPtr(pvBuf); + Assert(off >= 0); + Assert(cbTransfer > 0); + + pReqInt->AioCB.aio_sigevent.sigev_notify = SIGEV_KEVENT; + pReqInt->AioCB.aio_sigevent.sigev_value.sival_ptr = pReqInt; + pReqInt->AioCB.aio_lio_opcode = uTransferDirection; + pReqInt->AioCB.aio_fildes = (int)hFile; + pReqInt->AioCB.aio_offset = off; + pReqInt->AioCB.aio_nbytes = cbTransfer; + pReqInt->AioCB.aio_buf = pvBuf; + pReqInt->pvUser = pvUser; + pReqInt->pCtxInt = NULL; + pReqInt->Rc = VERR_FILE_AIO_IN_PROGRESS; + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + + return VINF_SUCCESS; +} + +RTDECL(int) RTFileAioReqPrepareRead(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off, + void *pvBuf, size_t cbRead, void *pvUser) +{ + return rtFileAioReqPrepareTransfer(hReq, hFile, LIO_READ, + off, pvBuf, cbRead, pvUser); +} + +RTDECL(int) RTFileAioReqPrepareWrite(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off, + void *pvBuf, size_t cbWrite, void *pvUser) +{ + return rtFileAioReqPrepareTransfer(hReq, hFile, LIO_WRITE, + off, pvBuf, cbWrite, pvUser); +} + +RTDECL(int) RTFileAioReqPrepareFlush(RTFILEAIOREQ hReq, RTFILE hFile, void *pvUser) +{ + PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)hReq; + + RTFILEAIOREQ_VALID_RETURN(pReqInt); + Assert(hFile != NIL_RTFILE); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + + pReqInt->fFlush = true; + pReqInt->AioCB.aio_fildes = (int)hFile; + pReqInt->pvUser = pvUser; + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + + return VINF_SUCCESS; +} + +RTDECL(void *) RTFileAioReqGetUser(RTFILEAIOREQ hReq) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN_RC(pReqInt, NULL); + + return pReqInt->pvUser; +} + +RTDECL(int) RTFileAioReqCancel(RTFILEAIOREQ hReq) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED); + + + int rcBSD = aio_cancel(pReqInt->AioCB.aio_fildes, &pReqInt->AioCB); + + if (rcBSD == AIO_CANCELED) + { + /* + * Decrement request count because the request will never arrive at the + * completion port. + */ + AssertMsg(VALID_PTR(pReqInt->pCtxInt), + ("Invalid state. Request was canceled but wasn't submitted\n")); + + ASMAtomicDecS32(&pReqInt->pCtxInt->cRequests); + pReqInt->Rc = VERR_FILE_AIO_CANCELED; + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + return VINF_SUCCESS; + } + else if (rcBSD == AIO_ALLDONE) + return VERR_FILE_AIO_COMPLETED; + else if (rcBSD == AIO_NOTCANCELED) + return VERR_FILE_AIO_IN_PROGRESS; + else + return RTErrConvertFromErrno(errno); +} + +RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + AssertPtrNull(pcbTransfered); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); + + if ( (RT_SUCCESS(pReqInt->Rc)) + && (pcbTransfered)) + *pcbTransfered = pReqInt->cbTransfered; + + return pReqInt->Rc; +} + +RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax) +{ + int rc = VINF_SUCCESS; + PRTFILEAIOCTXINTERNAL pCtxInt; + AssertPtrReturn(phAioCtx, VERR_INVALID_POINTER); + + pCtxInt = (PRTFILEAIOCTXINTERNAL)RTMemAllocZ(sizeof(RTFILEAIOCTXINTERNAL)); + if (RT_UNLIKELY(!pCtxInt)) + return VERR_NO_MEMORY; + + /* Init the event handle. */ + pCtxInt->iKQueue = kqueue(); + if (RT_LIKELY(pCtxInt->iKQueue > 0)) + { + pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC; + *phAioCtx = (RTFILEAIOCTX)pCtxInt; + } + else + { + RTMemFree(pCtxInt); + rc = RTErrConvertFromErrno(errno); + } + + return rc; +} + +RTDECL(int) RTFileAioCtxDestroy(RTFILEAIOCTX hAioCtx) +{ + /* Validate the handle and ignore nil. */ + if (hAioCtx == NIL_RTFILEAIOCTX) + return VINF_SUCCESS; + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + + /* Cannot destroy a busy context. */ + if (RT_UNLIKELY(pCtxInt->cRequests)) + return VERR_FILE_AIO_BUSY; + + close(pCtxInt->iKQueue); + ASMAtomicUoWriteU32(&pCtxInt->u32Magic, RTFILEAIOCTX_MAGIC_DEAD); + RTMemFree(pCtxInt); + + return VINF_SUCCESS; +} + +RTDECL(uint32_t) RTFileAioCtxGetMaxReqCount(RTFILEAIOCTX hAioCtx) +{ + return RTFILEAIO_UNLIMITED_REQS; +} + +RTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTX hAioCtx, RTFILE hFile) +{ + return VINF_SUCCESS; +} + +RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) +{ + /* + * Parameter validation. + */ + int rc = VINF_SUCCESS; + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + AssertReturn(cReqs > 0, VERR_INVALID_PARAMETER); + AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); + uint32_t i = cReqs; + + do + { + int rcBSD = 0; + size_t cReqsSubmit = 0; + size_t i = 0; + PRTFILEAIOREQINTERNAL pReqInt; + + while ( (i < cReqs) + && (i < AIO_LISTIO_MAX)) + { + pReqInt = pahReqs[i]; + if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt)) + { + /* Undo everything and stop submitting. */ + for (size_t iUndo = 0; iUndo < i; iUndo++) + { + pReqInt = pahReqs[iUndo]; + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + pReqInt->pCtxInt = NULL; + pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = 0; + } + rc = VERR_INVALID_HANDLE; + break; + } + + pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = pCtxInt->iKQueue; + pReqInt->pCtxInt = pCtxInt; + RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); + + if (pReqInt->fFlush) + break; + + cReqsSubmit++; + i++; + } + + if (cReqsSubmit) + { + rcBSD = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL); + if (RT_UNLIKELY(rcBSD < 0)) + { + if (rcBSD == EAGAIN) + rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; + else + rc = RTErrConvertFromErrno(errno); + + /* Check which requests got actually submitted and which not. */ + for (i = 0; i < cReqs; i++) + { + pReqInt = pahReqs[i]; + rcBSD = aio_error(&pReqInt->AioCB); + if (rcBSD == EINVAL) + { + /* Was not submitted. */ + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + pReqInt->pCtxInt = NULL; + } + else if (rcBSD != EINPROGRESS) + { + /* The request encountered an error. */ + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + pReqInt->Rc = RTErrConvertFromErrno(rcBSD); + pReqInt->pCtxInt = NULL; + pReqInt->cbTransfered = 0; + } + } + break; + } + + ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit); + cReqs -= cReqsSubmit; + pahReqs += cReqsSubmit; + } + + /* Check if we have a flush request now. */ + if (cReqs) + { + pReqInt = pahReqs[0]; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + + if (pReqInt->fFlush) + { + /* + * lio_listio does not work with flush requests so + * we have to use aio_fsync directly. + */ + rcBSD = aio_fsync(O_SYNC, &pReqInt->AioCB); + if (RT_UNLIKELY(rcBSD < 0)) + { + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + pReqInt->Rc = RTErrConvertFromErrno(errno); + pReqInt->cbTransfered = 0; + return pReqInt->Rc; + } + + ASMAtomicIncS32(&pCtxInt->cRequests); + cReqs--; + pahReqs++; + } + } + } while (cReqs); + + return rc; +} + +RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, unsigned cMillisTimeout, + PRTFILEAIOREQ pahReqs, size_t cReqs, uint32_t *pcReqs) +{ + int rc = VINF_SUCCESS; + int cRequestsCompleted = 0; + + /* + * Validate the parameters, making sure to always set pcReqs. + */ + AssertPtrReturn(pcReqs, VERR_INVALID_POINTER); + *pcReqs = 0; /* always set */ + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); + AssertReturn(cReqs != 0, VERR_INVALID_PARAMETER); + AssertReturn(cReqs >= cMinReqs, VERR_OUT_OF_RANGE); + + if (RT_UNLIKELY(ASMAtomicReadS32(&pCtxInt->cRequests) == 0)) + return VERR_FILE_AIO_NO_REQUEST; + + /* + * Convert the timeout if specified. + */ + struct timespec *pTimeout = NULL; + struct timespec Timeout = {0,0}; + uint64_t StartNanoTS = 0; + if (cMillisTimeout != RT_INDEFINITE_WAIT) + { + Timeout.tv_sec = cMillisTimeout / 1000; + Timeout.tv_nsec = cMillisTimeout % 1000 * 1000000; + pTimeout = &Timeout; + StartNanoTS = RTTimeNanoTS(); + } + + /* Wait for at least one. */ + if (!cMinReqs) + cMinReqs = 1; + + /* For the wakeup call. */ + Assert(pCtxInt->hThreadWait == NIL_RTTHREAD); + ASMAtomicWriteHandle(&pCtxInt->hThreadWait, RTThreadSelf()); + + while ( cMinReqs + && RT_SUCCESS_NP(rc)) + { + struct kevent aKEvents[AIO_MAXIMUM_REQUESTS_PER_CONTEXT]; + int cRequestsToWait = cMinReqs < AIO_MAXIMUM_REQUESTS_PER_CONTEXT ? cReqs : AIO_MAXIMUM_REQUESTS_PER_CONTEXT; + int rcBSD; + uint64_t StartTime; + + ASMAtomicXchgBool(&pCtxInt->fWaiting, true); + rcBSD = kevent(pCtxInt->iKQueue, NULL, 0, aKEvents, cRequestsToWait, pTimeout); + ASMAtomicXchgBool(&pCtxInt->fWaiting, false); + + if (RT_UNLIKELY(rcBSD < 0)) + { + rc = RTErrConvertFromErrno(errno); + break; + } + + uint32_t const cDone = rcBSD; + + /* Process received events. */ + for (uint32_t i = 0; i < cDone; i++) + { + PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)aKEvents[i].udata; + AssertPtr(pReqInt); + Assert(pReqInt->u32Magic == RTFILEAIOREQ_MAGIC); + + /* + * Retrieve the status code here already because the + * user may omit the RTFileAioReqGetRC() call and + * we will leak kernel ressources then. + * This will result in errors during submission + * of other requests as soon as the max_aio_queue_per_proc + * limit is reached. + */ + int cbTransfered = aio_return(&pReqInt->AioCB); + + if (cbTransfered < 0) + { + pReqInt->Rc = RTErrConvertFromErrno(cbTransfered); + pReqInt->cbTransfered = 0; + } + else + { + pReqInt->Rc = VINF_SUCCESS; + pReqInt->cbTransfered = cbTransfered; + } + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + pahReqs[cRequestsCompleted++] = (RTFILEAIOREQ)pReqInt; + } + + /* + * Done Yet? If not advance and try again. + */ + if (cDone >= cMinReqs) + break; + cMinReqs -= cDone; + cReqs -= cDone; + + if (cMillisTimeout != 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) + { + 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; + } + } + + /* + * Update the context state and set the return value. + */ + *pcReqs = cRequestsCompleted; + ASMAtomicSubS32(&pCtxInt->cRequests, cRequestsCompleted); + Assert(pCtxInt->hThreadWait == RTThreadSelf()); + ASMAtomicWriteHandle(&pCtxInt->hThreadWait, NIL_RTTHREAD); + + /* + * Clear the wakeup flag and set rc. + */ + if ( pCtxInt->fWokenUp + && RT_SUCCESS(rc)) + { + ASMAtomicXchgBool(&pCtxInt->fWokenUp, false); + rc = VERR_INTERRUPTED; + } + + return rc; +} + +RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx) +{ + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + + /** @todo r=bird: Define the protocol for how to resume work after calling + * this function. */ + + bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true); + + /* + * Read the thread handle before the status flag. + * If we read the handle after the flag we might + * end up with an invalid handle because the thread + * waiting in RTFileAioCtxWakeup() might get scheduled + * before we read the flag and returns. + * We can ensure that the handle is valid if fWaiting is true + * when reading the handle before the status flag. + */ + RTTHREAD hThread; + ASMAtomicReadHandle(&pCtxInt->hThreadWait, &hThread); + bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting); + if ( !fWokenUp + && fWaiting) + { + /* + * If a thread waits the handle must be valid. + * It is possible that the thread returns from + * kevent() before the signal is send. + * This is no problem because we already set fWokenUp + * to true which will let the thread return VERR_INTERRUPTED + * and the next call to RTFileAioCtxWait() will not + * return VERR_INTERRUPTED because signals are not saved + * and will simply vanish if the destination thread can't + * receive it. + */ + Assert(hThread != NIL_RTTHREAD); + RTThreadPoke(hThread); + } + + return VINF_SUCCESS; +} + diff --git a/src/VBox/Runtime/r3/freebsd/mp-freebsd.cpp b/src/VBox/Runtime/r3/freebsd/mp-freebsd.cpp new file mode 100644 index 000000000..7e413299c --- /dev/null +++ b/src/VBox/Runtime/r3/freebsd/mp-freebsd.cpp @@ -0,0 +1,105 @@ +/* $Id: mp-freebsd.cpp 20449 2009-06-09 22:23:42Z vboxsync $ */ +/** @file + * IPRT - Multiprocessor, FreeBSD. + */ + +/* + * Copyright (C) 2008 Sun Microsystems, Inc. + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * 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. + * + * 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 * +*******************************************************************************/ +#define LOG_GROUP RTLOGGROUP_DEFAULT +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <sys/sysctl.h> + +#include <iprt/mp.h> +#include <iprt/cpuset.h> +#include <iprt/assert.h> +#include <iprt/string.h> +#include <iprt/alloc.h> +#include <iprt/log.h> +#include <iprt/once.h> +#include <iprt/critsect.h> + + +RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu) +{ + int uFreqCurr = 0; + size_t cbParameter = sizeof(uFreqCurr); + + /* CPU's have a common frequency. */ + int rc = sysctlbyname("dev.cpu.0.freq", &uFreqCurr, &cbParameter, NULL, NULL); + if (rc) + return 0; + + return (uint32_t)uFreqCurr; +} + + +RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu) +{ + char szFreqLevels[20]; /* Should be enough to get the highest level which is always the first. */ + size_t cbFreqLevels = sizeof(szFreqLevels); + + memset(szFreqLevels, 0, sizeof(szFreqLevels)); + + /* + * CPU 0 has the freq levels entry. ENOMEM is ok as we don't need all supported + * levels but only the first one. + */ + int rc = sysctlbyname("dev.cpu.0.freq_levels", szFreqLevels, &cbFreqLevels, NULL, NULL); + if ( (rc && (errno != ENOMEM)) + || (cbFreqLevels == 0)) + return 0; + + /* Clear everything starting from the '/' */ + unsigned i = 0; + + do + { + if (szFreqLevels[i] == '/') + { + memset(&szFreqLevels[i], 0, sizeof(szFreqLevels) - i); + break; + } + i++; + } while (i < sizeof(szFreqLevels)); + + /* Returns 0 on failure. */ + return RTStrToUInt32(szFreqLevels); +} + +RTDECL(RTCPUID) RTMpGetOnlineCount(void) +{ + /* + * FreeBSD has sysconf. + */ + return sysconf(_SC_NPROCESSORS_ONLN); +} + + diff --git a/src/VBox/Runtime/r3/freebsd/rtProcInitExePath-freebsd.cpp b/src/VBox/Runtime/r3/freebsd/rtProcInitExePath-freebsd.cpp index 602f284aa..84eb0700f 100644 --- a/src/VBox/Runtime/r3/freebsd/rtProcInitExePath-freebsd.cpp +++ b/src/VBox/Runtime/r3/freebsd/rtProcInitExePath-freebsd.cpp @@ -1,4 +1,4 @@ -/* $Id: rtProcInitExePath-freebsd.cpp $ */ +/* $Id: rtProcInitExePath-freebsd.cpp 16024 2009-01-19 04:45:55Z vboxsync $ */ /** @file * IPRT - rtProcInitName, FreeBSD. */ diff --git a/src/VBox/Runtime/r3/fs.cpp b/src/VBox/Runtime/r3/fs.cpp index 74a9d64f1..d26ae5f3e 100644 --- a/src/VBox/Runtime/r3/fs.cpp +++ b/src/VBox/Runtime/r3/fs.cpp @@ -1,4 +1,4 @@ -/* $Id: fs.cpp $ */ +/* $Id: fs.cpp 19171 2009-04-24 15:35:54Z vboxsync $ */ /** @file * IPRT - File System. */ diff --git a/src/VBox/Runtime/r3/init.cpp b/src/VBox/Runtime/r3/init.cpp index 763aa148f..4d5f88d65 100644 --- a/src/VBox/Runtime/r3/init.cpp +++ b/src/VBox/Runtime/r3/init.cpp @@ -1,4 +1,4 @@ -/* $Id: init.cpp $ */ +/* $Id: init.cpp 20911 2009-06-24 23:46:10Z vboxsync $ */ /** @file * IPRT - Init Ring-3. */ @@ -33,6 +33,8 @@ * Header Files * *******************************************************************************/ #define LOG_GROUP RTLOGGROUP_DEFAULT +#include <iprt/types.h> /* darwin: UINT32_C and others. */ + #ifdef RT_OS_WINDOWS # include <process.h> #else @@ -58,9 +60,10 @@ #if !defined(IN_GUEST) && !defined(RT_NO_GIP) # include <iprt/file.h> # include <VBox/sup.h> -# include <stdlib.h> #endif +#include <stdlib.h> +#include "internal/alignmentchecks.h" #include "internal/path.h" #include "internal/process.h" #include "internal/thread.h" @@ -77,7 +80,7 @@ static int32_t volatile g_cUsers = 0; static bool volatile g_fInitializing = false; /** The process path. - * This is used by RTPathProgram and RTProcGetExecutableName and set by rtProcInitName. */ + * This is used by RTPathExecDir and RTProcGetExecutableName and set by rtProcInitName. */ char g_szrtProcExePath[RTPATH_MAX]; /** The length of g_szrtProcExePath. */ size_t g_cchrtProcExePath; @@ -111,6 +114,15 @@ RTPROCESS g_ProcessSelf = NIL_RTPROCESS; */ RTPROCPRIORITY g_enmProcessPriority = RTPROCPRIORITY_DEFAULT; +#ifdef IPRT_WITH_ALIGNMENT_CHECKS +/** + * Whether alignment checks are enabled. + * This is set if the environment variable IPRT_ALIGNMENT_CHECKS is 1. + */ +RTDATADECL(bool) g_fRTAlignmentChecks = false; +#endif + + #ifndef RT_OS_WINDOWS /** @@ -194,7 +206,7 @@ static int rtR3InitBody(bool fInitSUPLib, const char *pszProgramPath) */ const char *pszDisableHostCache = getenv("VBOX_DISABLE_HOST_DISK_CACHE"); if ( pszDisableHostCache != NULL - && strlen(pszDisableHostCache) > 0 + && *pszDisableHostCache && strcmp(pszDisableHostCache, "0") != 0) { RTFileSetForceFlags(RTFILE_O_WRITE, RTFILE_O_WRITE_THROUGH, 0); @@ -262,6 +274,18 @@ static int rtR3InitBody(bool fInitSUPLib, const char *pszProgramPath) AssertMsg(rc == 0, ("%d\n", rc)); #endif +#ifdef IPRT_WITH_ALIGNMENT_CHECKS + /* + * Enable alignment checks. + */ + const char *pszAlignmentChecks = getenv("IPRT_ALIGNMENT_CHECKS"); + g_fRTAlignmentChecks = pszAlignmentChecks != NULL + && pszAlignmentChecks[0] == '1' + && pszAlignmentChecks[1] == '\0'; + if (g_fRTAlignmentChecks) + IPRT_ALIGNMENT_CHECKS_ENABLE(); +#endif + return VINF_SUCCESS; } diff --git a/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp b/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp index b0b2cd89a..2ab4cd69f 100644 --- a/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp +++ b/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp @@ -1,4 +1,4 @@ -/* $Id: RTProcIsRunningByName-linux.cpp $ */ +/* $Id: RTProcIsRunningByName-linux.cpp 17018 2009-02-23 13:27:43Z vboxsync $ */ /** @file * IPRT - RTProcIsRunningByName, Linux implementation. */ diff --git a/src/VBox/Runtime/r3/linux/fileaio-linux.cpp b/src/VBox/Runtime/r3/linux/fileaio-linux.cpp new file mode 100644 index 000000000..37f783383 --- /dev/null +++ b/src/VBox/Runtime/r3/linux/fileaio-linux.cpp @@ -0,0 +1,821 @@ +/* $Id: fileaio-linux.cpp 19562 2009-05-10 21:44:16Z vboxsync $ */ +/** @file + * IPRT - File async I/O, native implementation for the Linux host platform. + */ + +/* + * Copyright (C) 2006-2007 Sun Microsystems, Inc. + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * 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. + * + * 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 + * @internal + * + * Linux implements the kernel async I/O API through the io_* syscalls. They are + * not exposed in the glibc (the aio_* API uses userspace threads and blocking + * I/O operations to simulate async behavior). There is an external library + * called libaio which implements these syscalls but because we don't want to + * have another dependency and this library is not installed by default and the + * interface is really simple we use the kernel interface directly using wrapper + * functions. + * + * The interface has some limitations. The first one is that the file must be + * opened with O_DIRECT. This disables caching done by the kernel which can be + * compensated if the user of this API implements caching itself. The next + * limitation is that data buffers must be aligned at a 512 byte boundary or the + * request will fail. + */ +/** @todo r=bird: What's this about "must be opened with O_DIRECT"? An + * explanation would be nice, esp. seeing what Linus is quoted saying + * about it in the open man page... */ + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#define LOG_GROUP RTLOGGROUP_FILE +#include <iprt/asm.h> +#include <iprt/mem.h> +#include <iprt/assert.h> +#include <iprt/string.h> +#include <iprt/err.h> +#include <iprt/log.h> +#include <iprt/thread.h> +#include "internal/fileaio.h" + +#define _LINUX_BYTEORDER_SWABB_H +#include <linux/aio_abi.h> +#include <unistd.h> +#include <sys/syscall.h> +#include <errno.h> + +#include <iprt/file.h> + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * The iocb structure of a request which is passed to the kernel. + * + * We redefined this here because the version in the header lacks padding + * for 32bit. + */ +typedef struct LNXKAIOIOCB +{ + /** Opaque pointer to data which is returned on an I/O event. */ + void *pvUser; +#ifdef RT_ARCH_X86 + uint32_t u32Padding0; +#endif + /** Contains the request number and is set by the kernel. */ + uint32_t u32Key; + /** Reserved. */ + uint32_t u32Reserved0; + /** The I/O opcode. */ + uint16_t u16IoOpCode; + /** Request priority. */ + int16_t i16Priority; + /** The file descriptor. */ + uint32_t File; + /** The userspace pointer to the buffer containing/receiving the data. */ + void *pvBuf; +#ifdef RT_ARCH_X86 + uint32_t u32Padding1; +#endif + /** How many bytes to transfer. */ +#ifdef RT_ARCH_X86 + uint32_t cbTransfer; + uint32_t u32Padding2; +#elif defined(RT_ARCH_AMD64) + uint64_t cbTransfer; +#else +# error "Unknown architecture" +#endif + /** At which offset to start the transfer. */ + int64_t off; + /** Reserved. */ + uint64_t u64Reserved1; + /** Flags */ + uint32_t fFlags; + /** Readyness signal file descriptor. */ + uint32_t u32ResFd; +} LNXKAIOIOCB, *PLNXKAIOIOCB; + +/** + * I/O event structure to notify about completed requests. + * Redefined here too because of the padding. + */ +typedef struct LNXKAIOIOEVENT +{ + /** The pvUser field from the iocb. */ + void *pvUser; +#ifdef RT_ARCH_X86 + uint32_t u32Padding0; +#endif + /** The LNXKAIOIOCB object this event is for. */ + PLNXKAIOIOCB *pIoCB; +#ifdef RT_ARCH_X86 + uint32_t u32Padding1; +#endif + /** The result code of the operation .*/ +#ifdef RT_ARCH_X86 + int32_t rc; + uint32_t u32Padding2; +#elif defined(RT_ARCH_AMD64) + int64_t rc; +#else +# error "Unknown architecture" +#endif + /** Secondary result code. */ +#ifdef RT_ARCH_X86 + int32_t rc2; + uint32_t u32Padding3; +#elif defined(RT_ARCH_AMD64) + int64_t rc2; +#else +# error "Unknown architecture" +#endif +} LNXKAIOIOEVENT, *PLNXKAIOIOEVENT; + + +/** + * Async I/O completion context state. + */ +typedef struct RTFILEAIOCTXINTERNAL +{ + /** Handle to the async I/O context. */ + aio_context_t AioContext; + /** Maximum number of requests this context can handle. */ + int cRequestsMax; + /** Current number of requests active on this context. */ + volatile int32_t cRequests; + /** The ID of the thread which is currently waiting for requests. */ + volatile RTTHREAD hThreadWait; + /** Flag whether the thread was woken up. */ + volatile bool fWokenUp; + /** Flag whether the thread is currently waiting in the syscall. */ + volatile bool fWaiting; + /** Magic value (RTFILEAIOCTX_MAGIC). */ + uint32_t u32Magic; +} RTFILEAIOCTXINTERNAL; +/** Pointer to an internal context structure. */ +typedef RTFILEAIOCTXINTERNAL *PRTFILEAIOCTXINTERNAL; + +/** + * Async I/O request state. + */ +typedef struct RTFILEAIOREQINTERNAL +{ + /** The aio control block. This must be the FIRST elment in + * the structure! (see notes below) */ + LNXKAIOIOCB AioCB; + /** Current state the request is in. */ + RTFILEAIOREQSTATE enmState; + /** The I/O context this request is associated with. */ + aio_context_t AioContext; + /** Return code the request completed with. */ + int Rc; + /** Number of bytes actually trasnfered. */ + size_t cbTransfered; + /** Completion context we are assigned to. */ + PRTFILEAIOCTXINTERNAL pCtxInt; + /** Magic value (RTFILEAIOREQ_MAGIC). */ + uint32_t u32Magic; +} RTFILEAIOREQINTERNAL; +/** Pointer to an internal request structure. */ +typedef RTFILEAIOREQINTERNAL *PRTFILEAIOREQINTERNAL; + + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +/** The max number of events to get in one call. */ +#define AIO_MAXIMUM_REQUESTS_PER_CONTEXT 64 + + +/** + * Creates a new async I/O context. + */ +DECLINLINE(int) rtFileAsyncIoLinuxCreate(unsigned cEvents, aio_context_t *pAioContext) +{ + int rc = syscall(__NR_io_setup, cEvents, pAioContext); + if (RT_UNLIKELY(rc == -1)) + return RTErrConvertFromErrno(errno); + + return VINF_SUCCESS; +} + +/** + * Destroys a async I/O context. + */ +DECLINLINE(int) rtFileAsyncIoLinuxDestroy(aio_context_t AioContext) +{ + int rc = syscall(__NR_io_destroy, AioContext); + if (RT_UNLIKELY(rc == -1)) + return RTErrConvertFromErrno(errno); + + return VINF_SUCCESS; +} + +/** + * Submits an array of I/O requests to the kernel. + */ +DECLINLINE(int) rtFileAsyncIoLinuxSubmit(aio_context_t AioContext, long cReqs, LNXKAIOIOCB **ppIoCB, int *pcSubmitted) +{ + int rc = syscall(__NR_io_submit, AioContext, cReqs, ppIoCB); + if (RT_UNLIKELY(rc == -1)) + return RTErrConvertFromErrno(errno); + + *pcSubmitted = rc; + + return VINF_SUCCESS; +} + +/** + * Cancels a I/O request. + */ +DECLINLINE(int) rtFileAsyncIoLinuxCancel(aio_context_t AioContext, PLNXKAIOIOCB pIoCB, PLNXKAIOIOEVENT pIoResult) +{ + int rc = syscall(__NR_io_cancel, AioContext, pIoCB, pIoResult); + if (RT_UNLIKELY(rc == -1)) + return RTErrConvertFromErrno(errno); + + return VINF_SUCCESS; +} + +/** + * Waits for I/O events. + * @returns Number of events (natural number w/ 0), IPRT error code (negative). + */ +DECLINLINE(int) rtFileAsyncIoLinuxGetEvents(aio_context_t AioContext, long cReqsMin, long cReqs, + PLNXKAIOIOEVENT paIoResults, struct timespec *pTimeout) +{ + int rc = syscall(__NR_io_getevents, AioContext, cReqsMin, cReqs, paIoResults, pTimeout); + if (RT_UNLIKELY(rc == -1)) + return RTErrConvertFromErrno(errno); + + return rc; +} + +RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits) +{ + int rc = VINF_SUCCESS; + AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER); + + /* + * Check if the API is implemented by creating a + * completion port. + */ + aio_context_t AioContext = 0; + rc = rtFileAsyncIoLinuxCreate(1, &AioContext); + if (RT_FAILURE(rc)) + return rc; + + rc = rtFileAsyncIoLinuxDestroy(AioContext); + if (RT_FAILURE(rc)) + return rc; + + /* Supported - fill in the limits. The alignment is the only restriction. */ + pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS; + pAioLimits->cbBufferAlignment = 512; + + return VINF_SUCCESS; +} + + +RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq) +{ + AssertPtrReturn(phReq, VERR_INVALID_POINTER); + + /* + * Allocate a new request and initialize it. + */ + PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)RTMemAllocZ(sizeof(*pReqInt)); + if (RT_UNLIKELY(!pReqInt)) + return VERR_NO_MEMORY; + + pReqInt->pCtxInt = NULL; + pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + + *phReq = (RTFILEAIOREQ)pReqInt; + return VINF_SUCCESS; +} + + +RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq) +{ + /* + * Validate the handle and ignore nil. + */ + if (hReq == NIL_RTFILEAIOREQ) + return VINF_SUCCESS; + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + + /* + * Trash the magic and free it. + */ + ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC); + RTMemFree(pReqInt); + return VINF_SUCCESS; +} + + +/** + * Worker setting up the request. + */ +DECLINLINE(int) rtFileAioReqPrepareTransfer(RTFILEAIOREQ hReq, RTFILE hFile, + uint16_t uTransferDirection, + RTFOFF off, void *pvBuf, size_t cbTransfer, + void *pvUser) +{ + /* + * Validate the input. + */ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + Assert(hFile != NIL_RTFILE); + AssertPtr(pvBuf); + Assert(off >= 0); + Assert(cbTransfer > 0); + + /* + * Setup the control block and clear the finished flag. + */ + pReqInt->AioCB.u16IoOpCode = uTransferDirection; + pReqInt->AioCB.File = (uint32_t)hFile; + pReqInt->AioCB.off = off; + pReqInt->AioCB.cbTransfer = cbTransfer; + pReqInt->AioCB.pvBuf = pvBuf; + pReqInt->AioCB.pvUser = pvUser; + + pReqInt->pCtxInt = NULL; + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + + return VINF_SUCCESS; +} + + +RTDECL(int) RTFileAioReqPrepareRead(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off, + void *pvBuf, size_t cbRead, void *pvUser) +{ + return rtFileAioReqPrepareTransfer(hReq, hFile, IOCB_CMD_PREAD, + off, pvBuf, cbRead, pvUser); +} + + +RTDECL(int) RTFileAioReqPrepareWrite(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off, + void *pvBuf, size_t cbWrite, void *pvUser) +{ + return rtFileAioReqPrepareTransfer(hReq, hFile, IOCB_CMD_PWRITE, + off, pvBuf, cbWrite, pvUser); +} + + +RTDECL(int) RTFileAioReqPrepareFlush(RTFILEAIOREQ hReq, RTFILE hFile, void *pvUser) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + + /** @todo: Flushing is not neccessary on Linux because O_DIRECT is mandatory + * which disables caching. + * We could setup a fake request which isn't really executed + * to avoid platform dependent code in the caller. + */ +#if 0 + return rtFileAsyncPrepareTransfer(pRequest, File, TRANSFERDIRECTION_FLUSH, + 0, NULL, 0, pvUser); +#endif + return VERR_NOT_IMPLEMENTED; +} + + +RTDECL(void *) RTFileAioReqGetUser(RTFILEAIOREQ hReq) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN_RC(pReqInt, NULL); + + return pReqInt->AioCB.pvUser; +} + + +RTDECL(int) RTFileAioReqCancel(RTFILEAIOREQ hReq) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED); + + LNXKAIOIOEVENT AioEvent; + int rc = rtFileAsyncIoLinuxCancel(pReqInt->AioContext, &pReqInt->AioCB, &AioEvent); + if (RT_SUCCESS(rc)) + { + /* + * Decrement request count because the request will never arrive at the + * completion port. + */ + AssertMsg(VALID_PTR(pReqInt->pCtxInt), + ("Invalid state. Request was canceled but wasn't submitted\n")); + + ASMAtomicDecS32(&pReqInt->pCtxInt->cRequests); + pReqInt->Rc = VERR_FILE_AIO_CANCELED; + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + return VINF_SUCCESS; + } + if (rc == VERR_TRY_AGAIN) + return VERR_FILE_AIO_IN_PROGRESS; + return rc; +} + + +RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + AssertPtrNull(pcbTransfered); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); + + if ( pcbTransfered + && RT_SUCCESS(pReqInt->Rc)) + *pcbTransfered = pReqInt->cbTransfered; + + return pReqInt->Rc; +} + + +RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax) +{ + PRTFILEAIOCTXINTERNAL pCtxInt; + AssertPtrReturn(phAioCtx, VERR_INVALID_POINTER); + + /* The kernel interface needs a maximum. */ + if (cAioReqsMax == RTFILEAIO_UNLIMITED_REQS) + return VERR_OUT_OF_RANGE; + + pCtxInt = (PRTFILEAIOCTXINTERNAL)RTMemAllocZ(sizeof(RTFILEAIOCTXINTERNAL)); + if (RT_UNLIKELY(!pCtxInt)) + return VERR_NO_MEMORY; + + /* Init the event handle. */ + int rc = rtFileAsyncIoLinuxCreate(cAioReqsMax, &pCtxInt->AioContext); + if (RT_SUCCESS(rc)) + { + pCtxInt->fWokenUp = false; + pCtxInt->fWaiting = false; + pCtxInt->hThreadWait = NIL_RTTHREAD; + pCtxInt->cRequestsMax = cAioReqsMax; + pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC; + *phAioCtx = (RTFILEAIOCTX)pCtxInt; + } + else + RTMemFree(pCtxInt); + + return rc; +} + + +RTDECL(int) RTFileAioCtxDestroy(RTFILEAIOCTX hAioCtx) +{ + /* Validate the handle and ignore nil. */ + if (hAioCtx == NIL_RTFILEAIOCTX) + return VINF_SUCCESS; + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + + /* Cannot destroy a busy context. */ + if (RT_UNLIKELY(pCtxInt->cRequests)) + return VERR_FILE_AIO_BUSY; + + /* The native bit first, then mark it as dead and free it. */ + int rc = rtFileAsyncIoLinuxDestroy(pCtxInt->AioContext); + if (RT_FAILURE(rc)) + return rc; + ASMAtomicUoWriteU32(&pCtxInt->u32Magic, RTFILEAIOCTX_MAGIC_DEAD); + RTMemFree(pCtxInt); + + return VINF_SUCCESS; +} + + +RTDECL(uint32_t) RTFileAioCtxGetMaxReqCount(RTFILEAIOCTX hAioCtx) +{ + /* Nil means global here. */ + if (hAioCtx == NIL_RTFILEAIOCTX) + return RTFILEAIO_UNLIMITED_REQS; /** @todo r=bird: I'm a bit puzzled by this return value since it + * is completely useless in RTFileAioCtxCreate. */ + + /* Return 0 if the handle is invalid, it's better than garbage I think... */ + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN_RC(pCtxInt, 0); + + return pCtxInt->cRequestsMax; +} + +RTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTX hAioCtx, RTFILE hFile) +{ + /* Nothing to do. */ + return VINF_SUCCESS; +} + +RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) +{ + int rc = VINF_SUCCESS; + + /* + * Parameter validation. + */ + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + AssertReturn(cReqs > 0, VERR_INVALID_PARAMETER); + AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); + uint32_t i = cReqs; + PRTFILEAIOREQINTERNAL pReqInt = NULL; + + /* + * Vaildate requests and associate with the context. + */ + while (i-- > 0) + { + pReqInt = pahReqs[i]; + if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt)) + { + /* Undo everything and stop submitting. */ + size_t iUndo = cReqs; + while (iUndo-- > i) + { + pReqInt = pahReqs[iUndo]; + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + pReqInt->pCtxInt = NULL; + } + return VERR_INVALID_HANDLE; + } + + pReqInt->AioContext = pCtxInt->AioContext; + pReqInt->pCtxInt = pCtxInt; + RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); + } + + do + { + /* + * We cast pahReqs to the Linux iocb structure to avoid copying the requests + * into a temporary array. This is possible because the iocb structure is + * the first element in the request structure (see PRTFILEAIOCTXINTERNAL). + */ + int cReqsSubmitted = 0; + rc = rtFileAsyncIoLinuxSubmit(pCtxInt->AioContext, cReqs, + (PLNXKAIOIOCB *)pahReqs, + &cReqsSubmitted); + if (RT_FAILURE(rc)) + { + /* + * We encountered an error. + * This means that the first IoCB + * is not correctly initialized + * (invalid buffer alignment or bad file descriptor). + * Revert every request into the prepared state except + * the first one which will switch to completed. + * Another reason could be insuffidient ressources. + */ + i = cReqs; + while (i-- > 0) + { + /* Already validated. */ + pReqInt = pahReqs[i]; + pReqInt->pCtxInt = NULL; + pReqInt->AioContext = 0; + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + } + + if (rc == VERR_TRY_AGAIN) + return VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; + else + { + /* The first request failed. */ + pReqInt = pahReqs[0]; + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + pReqInt->Rc = rc; + pReqInt->cbTransfered = 0; + return rc; + } + } + + /* Advance. */ + cReqs -= cReqsSubmitted; + pahReqs += cReqsSubmitted; + ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmitted); + + } while (cReqs); + + return rc; +} + + +RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, unsigned cMillisTimeout, + PRTFILEAIOREQ pahReqs, size_t cReqs, uint32_t *pcReqs) +{ + /* + * Validate the parameters, making sure to always set pcReqs. + */ + AssertPtrReturn(pcReqs, VERR_INVALID_POINTER); + *pcReqs = 0; /* always set */ + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); + AssertReturn(cReqs != 0, VERR_INVALID_PARAMETER); + AssertReturn(cReqs >= cMinReqs, VERR_OUT_OF_RANGE); + + /* + * Can't wait if there are not requests around. + */ + if (RT_UNLIKELY(ASMAtomicUoReadS32(&pCtxInt->cRequests) == 0)) + return VERR_FILE_AIO_NO_REQUEST; + + /* + * Convert the timeout if specified. + */ + struct timespec *pTimeout = NULL; + struct timespec Timeout = {0,0}; + uint64_t StartNanoTS = 0; + if (cMillisTimeout != RT_INDEFINITE_WAIT) + { + Timeout.tv_sec = cMillisTimeout / 1000; + Timeout.tv_nsec = cMillisTimeout % 1000 * 1000000; + pTimeout = &Timeout; + StartNanoTS = RTTimeNanoTS(); + } + + /* Wait for at least one. */ + if (!cMinReqs) + cMinReqs = 1; + + /* For the wakeup call. */ + Assert(pCtxInt->hThreadWait == NIL_RTTHREAD); + ASMAtomicWriteHandle(&pCtxInt->hThreadWait, RTThreadSelf()); + + /* + * Loop until we're woken up, hit an error (incl timeout), or + * have collected the desired number of requests. + */ + int rc = VINF_SUCCESS; + int cRequestsCompleted = 0; + while (!pCtxInt->fWokenUp) + { + LNXKAIOIOEVENT aPortEvents[AIO_MAXIMUM_REQUESTS_PER_CONTEXT]; + int cRequestsToWait = RT_MIN(cReqs, AIO_MAXIMUM_REQUESTS_PER_CONTEXT); + ASMAtomicXchgBool(&pCtxInt->fWaiting, true); + rc = rtFileAsyncIoLinuxGetEvents(pCtxInt->AioContext, cMinReqs, cRequestsToWait, &aPortEvents[0], pTimeout); + ASMAtomicXchgBool(&pCtxInt->fWaiting, false); + if (RT_FAILURE(rc)) + break; + uint32_t const cDone = rc; + rc = VINF_SUCCESS; + + /* + * Process received events / requests. + */ + for (uint32_t i = 0; i < cDone; i++) + { + /* + * The iocb is the first element in our request structure. + * So we can safely cast it directly to the handle (see above) + */ + PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)aPortEvents[i].pIoCB; + AssertPtr(pReqInt); + Assert(pReqInt->u32Magic == RTFILEAIOREQ_MAGIC); + + /** @todo aeichner: The rc field contains the result code + * like you can find in errno for the normal read/write ops. + * But there is a second field called rc2. I don't know the + * purpose for it yet. + */ + if (RT_UNLIKELY(aPortEvents[i].rc < 0)) + pReqInt->Rc = RTErrConvertFromErrno(aPortEvents[i].rc); + else + { + pReqInt->Rc = VINF_SUCCESS; + pReqInt->cbTransfered = aPortEvents[i].rc; + } + + /* Mark the request as finished. */ + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + + pahReqs[cRequestsCompleted++] = (RTFILEAIOREQ)pReqInt; + } + + /* + * Done Yet? If not advance and try again. + */ + if (cDone >= cMinReqs) + break; + cMinReqs -= cDone; + cReqs -= cDone; + + if (cMillisTimeout != 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) + { + 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; + } + } + + /* + * Update the context state and set the return value. + */ + *pcReqs = cRequestsCompleted; + ASMAtomicSubS32(&pCtxInt->cRequests, cRequestsCompleted); + Assert(pCtxInt->hThreadWait == RTThreadSelf()); + ASMAtomicWriteHandle(&pCtxInt->hThreadWait, NIL_RTTHREAD); + + /* + * Clear the wakeup flag and set rc. + */ + if ( pCtxInt->fWokenUp + && RT_SUCCESS(rc)) + { + ASMAtomicXchgBool(&pCtxInt->fWokenUp, false); + rc = VERR_INTERRUPTED; + } + + return rc; +} + + +RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx) +{ + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + + /** @todo r=bird: Define the protocol for how to resume work after calling + * this function. */ + + bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true); + + /* + * Read the thread handle before the status flag. + * If we read the handle after the flag we might + * end up with an invalid handle because the thread + * waiting in RTFileAioCtxWakeup() might get scheduled + * before we read the flag and returns. + * We can ensure that the handle is valid if fWaiting is true + * when reading the handle before the status flag. + */ + RTTHREAD hThread; + ASMAtomicReadHandle(&pCtxInt->hThreadWait, &hThread); + bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting); + if ( !fWokenUp + && fWaiting) + { + /* + * If a thread waits the handle must be valid. + * It is possible that the thread returns from + * rtFileAsyncIoLinuxGetEvents() before the signal + * is send. + * This is no problem because we already set fWokenUp + * to true which will let the thread return VERR_INTERRUPTED + * and the next call to RTFileAioCtxWait() will not + * return VERR_INTERRUPTED because signals are not saved + * and will simply vanish if the destination thread can't + * receive it. + */ + Assert(hThread != NIL_RTTHREAD); + RTThreadPoke(hThread); + } + + return VINF_SUCCESS; +} + diff --git a/src/VBox/Runtime/r3/linux/mp-linux.cpp b/src/VBox/Runtime/r3/linux/mp-linux.cpp index 7fcc9b73a..6eed83dff 100644 --- a/src/VBox/Runtime/r3/linux/mp-linux.cpp +++ b/src/VBox/Runtime/r3/linux/mp-linux.cpp @@ -1,4 +1,4 @@ -/* $Id: mp-linux.cpp $ */ +/* $Id: mp-linux.cpp 15399 2008-12-12 22:02:14Z vboxsync $ */ /** @file * IPRT - Multiprocessor, Linux. */ diff --git a/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp b/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp index 36a145a97..22b254d59 100644 --- a/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp +++ b/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp @@ -1,4 +1,4 @@ -/* $Id: rtProcInitExePath-linux.cpp $ */ +/* $Id: rtProcInitExePath-linux.cpp 11838 2008-08-29 17:14:02Z vboxsync $ */ /** @file * IPRT - rtProcInitName, Linux. */ diff --git a/src/VBox/Runtime/r3/linux/sched-linux.cpp b/src/VBox/Runtime/r3/linux/sched-linux.cpp index ffaf7caf6..d4e2957a8 100644 --- a/src/VBox/Runtime/r3/linux/sched-linux.cpp +++ b/src/VBox/Runtime/r3/linux/sched-linux.cpp @@ -1,4 +1,4 @@ -/* $Id: sched-linux.cpp $ */ +/* $Id: sched-linux.cpp 13837 2008-11-05 02:54:02Z vboxsync $ */ /** @file * IPRT - Scheduling, POSIX. */ diff --git a/src/VBox/Runtime/r3/linux/semevent-linux.cpp b/src/VBox/Runtime/r3/linux/semevent-linux.cpp index f1595c436..556715746 100644 --- a/src/VBox/Runtime/r3/linux/semevent-linux.cpp +++ b/src/VBox/Runtime/r3/linux/semevent-linux.cpp @@ -1,4 +1,4 @@ -/* $Id: semevent-linux.cpp $ */ +/* $Id: semevent-linux.cpp 14468 2008-11-21 15:44:27Z vboxsync $ */ /** @file * IPRT - Event Semaphore, Linux (2.6.x+). */ diff --git a/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp b/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp index b7e883a0b..3464c90a8 100644 --- a/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp +++ b/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp @@ -1,4 +1,4 @@ -/* $Id: semeventmulti-linux.cpp $ */ +/* $Id: semeventmulti-linux.cpp 14468 2008-11-21 15:44:27Z vboxsync $ */ /** @file * IPRT - Multiple Release Event Semaphore, Linux (2.6.x+). */ diff --git a/src/VBox/Runtime/r3/linux/semmutex-linux.cpp b/src/VBox/Runtime/r3/linux/semmutex-linux.cpp index 003789398..271f77b9d 100644 --- a/src/VBox/Runtime/r3/linux/semmutex-linux.cpp +++ b/src/VBox/Runtime/r3/linux/semmutex-linux.cpp @@ -1,4 +1,4 @@ -/* $Id: semmutex-linux.cpp $ */ +/* $Id: semmutex-linux.cpp 8651 2008-05-07 12:16:29Z vboxsync $ */ /** @file * IPRT - Mutex Semaphore, Linux (2.6.x+). */ diff --git a/src/VBox/Runtime/r3/linux/sysfs.cpp b/src/VBox/Runtime/r3/linux/sysfs.cpp index 6d0fd58c4..526a89227 100644 --- a/src/VBox/Runtime/r3/linux/sysfs.cpp +++ b/src/VBox/Runtime/r3/linux/sysfs.cpp @@ -1,4 +1,4 @@ -/* $Id: sysfs.cpp $ */ +/* $Id: sysfs.cpp 15644 2008-12-18 11:16:58Z vboxsync $ */ /** @file * IPRT - Linux sysfs access. */ diff --git a/src/VBox/Runtime/r3/linux/time-linux.cpp b/src/VBox/Runtime/r3/linux/time-linux.cpp index 8dfe73d5c..102e500b0 100644 --- a/src/VBox/Runtime/r3/linux/time-linux.cpp +++ b/src/VBox/Runtime/r3/linux/time-linux.cpp @@ -1,4 +1,4 @@ -/* $Id: time-linux.cpp $ */ +/* $Id: time-linux.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - Time, POSIX. */ diff --git a/src/VBox/Runtime/r3/os2/filelock-os2.cpp b/src/VBox/Runtime/r3/os2/filelock-os2.cpp index 63930a9d3..b6e33cfce 100644 --- a/src/VBox/Runtime/r3/os2/filelock-os2.cpp +++ b/src/VBox/Runtime/r3/os2/filelock-os2.cpp @@ -1,4 +1,4 @@ -/* $Id: filelock-os2.cpp $ */ +/* $Id: filelock-os2.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - File Locking, OS/2. */ diff --git a/src/VBox/Runtime/r3/os2/mp-os2.cpp b/src/VBox/Runtime/r3/os2/mp-os2.cpp index 15569b465..f3a12a5d0 100644 --- a/src/VBox/Runtime/r3/os2/mp-os2.cpp +++ b/src/VBox/Runtime/r3/os2/mp-os2.cpp @@ -1,4 +1,4 @@ -/* $Id: mp-os2.cpp $ */ +/* $Id: mp-os2.cpp 13908 2008-11-06 11:53:47Z vboxsync $ */ /** @file * IPRT - Multiprocessor, OS/2. */ diff --git a/src/VBox/Runtime/r3/os2/rtProcInitExePath-os2.cpp b/src/VBox/Runtime/r3/os2/rtProcInitExePath-os2.cpp index 32332b190..16064dfde 100644 --- a/src/VBox/Runtime/r3/os2/rtProcInitExePath-os2.cpp +++ b/src/VBox/Runtime/r3/os2/rtProcInitExePath-os2.cpp @@ -1,4 +1,4 @@ -/* $Id: rtProcInitExePath-os2.cpp $ */ +/* $Id: rtProcInitExePath-os2.cpp 13908 2008-11-06 11:53:47Z vboxsync $ */ /** @file * IPRT - rtProcInitName, OS/2. */ diff --git a/src/VBox/Runtime/r3/os2/sched-os2.cpp b/src/VBox/Runtime/r3/os2/sched-os2.cpp index c826d53a0..ea64a4135 100644 --- a/src/VBox/Runtime/r3/os2/sched-os2.cpp +++ b/src/VBox/Runtime/r3/os2/sched-os2.cpp @@ -1,4 +1,4 @@ -/* $Id: sched-os2.cpp $ */ +/* $Id: sched-os2.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - Scheduling, OS/2 */ diff --git a/src/VBox/Runtime/r3/os2/sems-os2.cpp b/src/VBox/Runtime/r3/os2/sems-os2.cpp index 57b27ae2f..a08d68b2c 100644 --- a/src/VBox/Runtime/r3/os2/sems-os2.cpp +++ b/src/VBox/Runtime/r3/os2/sems-os2.cpp @@ -1,4 +1,4 @@ -/* $Id: sems-os2.cpp $ */ +/* $Id: sems-os2.cpp 10839 2008-07-23 19:48:51Z vboxsync $ */ /** @file * IPRT - Semaphores, OS/2. */ diff --git a/src/VBox/Runtime/r3/os2/thread-os2.cpp b/src/VBox/Runtime/r3/os2/thread-os2.cpp index 8567638b4..5228fd751 100644 --- a/src/VBox/Runtime/r3/os2/thread-os2.cpp +++ b/src/VBox/Runtime/r3/os2/thread-os2.cpp @@ -1,4 +1,4 @@ -/* $Id: thread-os2.cpp $ */ +/* $Id: thread-os2.cpp 16311 2009-01-28 13:46:41Z vboxsync $ */ /** @file * IPRT - Threads, OS/2. */ diff --git a/src/VBox/Runtime/r3/os2/time-os2.cpp b/src/VBox/Runtime/r3/os2/time-os2.cpp index 13fcad048..d39e1fc24 100644 --- a/src/VBox/Runtime/r3/os2/time-os2.cpp +++ b/src/VBox/Runtime/r3/os2/time-os2.cpp @@ -1,4 +1,4 @@ -/* $Id: time-os2.cpp $ */ +/* $Id: time-os2.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - Time, POSIX. */ diff --git a/src/VBox/Runtime/r3/path.cpp b/src/VBox/Runtime/r3/path.cpp index b983781cd..71f61a70b 100644 --- a/src/VBox/Runtime/r3/path.cpp +++ b/src/VBox/Runtime/r3/path.cpp @@ -1,4 +1,4 @@ -/* $Id: path.cpp $ */ +/* $Id: path.cpp 20101 2009-05-27 16:43:08Z vboxsync $ */ /** @file * IPRT - Path Manipulation. */ @@ -41,6 +41,7 @@ #include <iprt/ctype.h> #include <iprt/err.h> #include <iprt/uni.h> +#include <iprt/env.h> #include "internal/fs.h" #include "internal/path.h" #include "internal/process.h" @@ -447,25 +448,24 @@ static int rtPathCompare(const char *pszPath1, const char *pszPath2, bool fLimit * The comparison takes platform-dependent details into account, * such as: * <ul> - * <li>On DOS-like platforms, both |\| and |/| separator chars are considered + * <li>On DOS-like platforms, both separator chars (|\| and |/|) are considered * to be equal. * <li>On platforms with case-insensitive file systems, mismatching characters * are uppercased and compared again. * </ul> * - * @remark - * - * File system details are currently ignored. This means that you won't get - * case-insentive compares on unix systems when a path goes into a case-insensitive - * filesystem like FAT, HPFS, HFS, NTFS, JFS, or similar. For NT, OS/2 and similar - * you'll won't get case-sensitve compares on a case-sensitive file system. + * @returns @< 0 if the first path less than the second path. + * @returns 0 if the first path identical to the second path. + * @returns @> 0 if the first path greater than the second path. * * @param pszPath1 Path to compare (must be an absolute path). * @param pszPath2 Path to compare (must be an absolute path). * - * @returns @< 0 if the first path less than the second path. - * @returns 0 if the first path identical to the second path. - * @returns @> 0 if the first path greater than the second path. + * @remarks File system details are currently ignored. This means that you won't + * get case-insentive compares on unix systems when a path goes into a + * case-insensitive filesystem like FAT, HPFS, HFS, NTFS, JFS, or + * similar. For NT, OS/2 and similar you'll won't get case-sensitve + * compares on a case-sensitive file system. */ RTDECL(int) RTPathCompare(const char *pszPath1, const char *pszPath2) { @@ -476,23 +476,23 @@ RTDECL(int) RTPathCompare(const char *pszPath1, const char *pszPath2) /** * Checks if a path starts with the given parent path. * - * This means that either the path and the parent path matches completely, or that - * the path is to some file or directory residing in the tree given by the parent - * directory. + * This means that either the path and the parent path matches completely, or + * that the path is to some file or directory residing in the tree given by the + * parent directory. * * The path comparison takes platform-dependent details into account, * see RTPathCompare() for details. * + * @returns |true| when \a pszPath starts with \a pszParentPath (or when they + * are identical), or |false| otherwise. + * * @param pszPath Path to check, must be an absolute path. * @param pszParentPath Parent path, must be an absolute path. * No trailing directory slash! * - * @returns |true| when \a pszPath starts with \a pszParentPath (or when they - * are identical), or |false| otherwise. - * - * @remark This API doesn't currently handle root directory compares in a manner - * consistant with the other APIs. RTPathStartsWith(pszSomePath, "/") will - * not work if pszSomePath isn't "/". + * @remarks This API doesn't currently handle root directory compares in a + * manner consistant with the other APIs. RTPathStartsWith(pszSomePath, + * "/") will not work if pszSomePath isn't "/". */ RTDECL(bool) RTPathStartsWith(const char *pszPath, const char *pszParentPath) { @@ -545,6 +545,72 @@ RTDECL(char *) RTPathAbsDup(const char *pszPath) /** + * Figures the length of the root part of the path. + * + * @returns length of the root specifier. + * @retval 0 if none. + * + * @param pszPath The path to investigate. + * + * @remarks Unnecessary root slashes will not be counted. The caller will have + * to deal with it where it matters. + */ +static size_t rtPathRootSpecLen(const char *pszPath) +{ + /* fend of wildlife. */ + if (!pszPath) + return 0; + + /* Root slash? */ + if (RTPATH_IS_SLASH(pszPath[0])) + { +#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS) + /* UNC? */ + if ( RTPATH_IS_SLASH(pszPath[1]) + && pszPath[2] != '\0' + && !RTPATH_IS_SLASH(pszPath[2])) + { + /* Find the end of the server name. */ + const char *pszEnd = pszPath + 2; + pszEnd += 2; + while ( *pszEnd != '\0' + && !RTPATH_IS_SLASH(*pszEnd)) + pszEnd++; + if (RTPATH_IS_SLASH(*pszEnd)) + { + pszEnd++; + while (RTPATH_IS_SLASH(*pszEnd)) + pszEnd++; + + /* Find the end of the share name */ + while ( *pszEnd != '\0' + && !RTPATH_IS_SLASH(*pszEnd)) + pszEnd++; + if (RTPATH_IS_SLASH(*pszEnd)) + pszEnd++; + return pszPath - pszEnd; + } + } +#endif + return 1; + } + +#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS) + /* Drive specifier? */ + if ( pszPath[0] != '\0' + && pszPath[1] == ':' + && RT_C_IS_ALPHA(pszPath[0])) + { + if (RTPATH_IS_SLASH(pszPath[2])) + return 3; + return 2; + } +#endif + return 0; +} + + +/** * Returns the length of the volume name specifier of the given path. * If no such specifier zero is returned. */ @@ -663,9 +729,89 @@ RTDECL(char *) RTPathAbsExDup(const char *pszBase, const char *pszPath) } +RTDECL(int) RTPathAppend(char *pszPath, size_t cbPathDst, const char *pszAppend) +{ + char *pszPathEnd = (char *)memchr(pszPath, '\0', cbPathDst); + AssertReturn(pszPathEnd, VERR_INVALID_PARAMETER); + + /* + * Special cases. + */ + if (!pszAppend) + return VINF_SUCCESS; + size_t cchAppend = strlen(pszAppend); + if (!cchAppend) + return VINF_SUCCESS; + if (pszPathEnd == pszPath) + { + if (cchAppend >= cbPathDst) + return VERR_BUFFER_OVERFLOW; + memcpy(pszPath, pszAppend, cchAppend + 1); + return VINF_SUCCESS; + } + + /* + * Balance slashes and check for buffer overflow. + */ + bool fAddSlash = false; + if (!RTPATH_IS_SLASH(pszPathEnd[-1])) + { + if (!RTPATH_IS_SLASH(pszAppend[0])) + { +#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS) + if ( (size_t)(pszPathEnd - pszPath) == 2 + && pszPath[1] == ':' + && RT_C_IS_ALPHA(pszPath[0])) + { + if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst) + return VERR_BUFFER_OVERFLOW; + } + else +#endif + { + if ((size_t)(pszPathEnd - pszPath) + 1 + cchAppend >= cbPathDst) + return VERR_BUFFER_OVERFLOW; + *pszPathEnd++ = '/'; + } + } + else + { + /* One slash is sufficient at this point. */ + while (RTPATH_IS_SLASH(pszAppend[1])) + pszAppend++, cchAppend--; + + if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst) + return VERR_BUFFER_OVERFLOW; + } + } + else + { + /* No slashes needed in the appended bit. */ + while (RTPATH_IS_SLASH(*pszAppend)) + pszAppend++, cchAppend--; + + /* In the leading path we can skip unnecessary trailing slashes, but + be sure to leave one. */ + size_t const cchRoot = rtPathRootSpecLen(pszPath); + while ( (size_t)(pszPathEnd - pszPath) > RT_MAX(1, cchRoot) + && RTPATH_IS_SLASH(pszPathEnd[-2])) + pszPathEnd--; + + if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst) + return VERR_BUFFER_OVERFLOW; + } + + /* + * What remains now is the just the copying. + */ + memcpy(pszPathEnd, pszAppend, cchAppend + 1); + return VINF_SUCCESS; +} + + #ifndef RT_MINI -RTDECL(int) RTPathProgram(char *pszPath, size_t cchPath) +RTDECL(int) RTPathExecDir(char *pszPath, size_t cchPath) { AssertReturn(g_szrtProcExePath[0], VERR_WRONG_ORDER); @@ -691,7 +837,7 @@ RTDECL(int) RTPathProgram(char *pszPath, size_t cchPath) * * Linux: /usr/shared/@<application@> * Windows: @<program files directory@>/@<application@> - * Old path: same as RTPathProgram() + * Old path: same as RTPathExecDir() * */ RTDECL(int) RTPathAppPrivateNoArch(char *pszPath, size_t cchPath) @@ -711,7 +857,7 @@ RTDECL(int) RTPathAppPrivateNoArch(char *pszPath, size_t cchPath) } return rc; #else - return RTPathProgram(pszPath, cchPath); + return RTPathExecDir(pszPath, cchPath); #endif } @@ -722,7 +868,7 @@ RTDECL(int) RTPathAppPrivateNoArch(char *pszPath, size_t cchPath) * * Linux: /usr/lib/@<application@> * Windows: @<program files directory@>/@<application@> - * Old path: same as RTPathProgram() + * Old path: same as RTPathExecDir() * * @returns iprt status code. * @param pszPath Buffer where to store the path. @@ -745,7 +891,7 @@ RTDECL(int) RTPathAppPrivateArch(char *pszPath, size_t cchPath) } return rc; #else - return RTPathProgram(pszPath, cchPath); + return RTPathExecDir(pszPath, cchPath); #endif } @@ -757,7 +903,7 @@ RTDECL(int) RTPathAppPrivateArch(char *pszPath, size_t cchPath) * * Linux: /usr/lib * Windows: @<program files directory@>/@<application@> - * Old path: same as RTPathProgram() + * Old path: same as RTPathExecDir() * * @returns iprt status code. * @param pszPath Buffer where to store the path. @@ -780,7 +926,7 @@ RTDECL(int) RTPathSharedLibs(char *pszPath, size_t cchPath) } return rc; #else - return RTPathProgram(pszPath, cchPath); + return RTPathExecDir(pszPath, cchPath); #endif } @@ -790,7 +936,7 @@ RTDECL(int) RTPathSharedLibs(char *pszPath, size_t cchPath) * * Linux: /usr/share/doc/@<application@> * Windows: @<program files directory@>/@<application@> - * Old path: same as RTPathProgram() + * Old path: same as RTPathExecDir() * * @returns iprt status code. * @param pszPath Buffer where to store the path. @@ -813,8 +959,53 @@ RTDECL(int) RTPathAppDocs(char *pszPath, size_t cchPath) } return rc; #else - return RTPathProgram(pszPath, cchPath); + return RTPathExecDir(pszPath, cchPath); +#endif +} + + +/** + * Gets the temporary directory path. + * + * @returns iprt status code. + * + * @param pszPath Buffer where to store the path. + * @param cchPath Buffer size in bytes. + */ +RTDECL(int) RTPathTemp(char *pszPath, size_t cchPath) +{ + /* + * Try get it from the environment first. + */ + static const char * const s_apszVars[] = + { + "IPRT_TMPDIR" +#if defined(RT_OS_WINDOWS) + , "TMP", "TEMP", "USERPROFILE" +#elif defined(RT_OS_OS2) + , "TMP", "TEMP", "TMPDIR" +#else + , "TMPDIR" #endif + }; + for (size_t iVar = 0; iVar < RT_ELEMENTS(s_apszVars); iVar++) + { + int rc = RTEnvGetEx(RTENV_DEFAULT, s_apszVars[iVar], pszPath, cchPath, NULL); + if (rc != VERR_ENV_VAR_NOT_FOUND) + return rc; + } + + /* + * Here we should use some sane system default, instead we just use + * the typical unix temp dir for now. + */ + /** @todo Windows should default to the windows directory, see GetTempPath. + * Some unixes has path.h and _PATH_TMP. There is also a question about + * whether /var/tmp wouldn't be a better place... */ + if (cchPath < sizeof("/tmp") ) + return VERR_BUFFER_OVERFLOW; + memcpy(pszPath, "/tmp", sizeof("/tmp")); + return VINF_SUCCESS; } #endif /* !RT_MINI */ diff --git a/src/VBox/Runtime/r3/posix/RTMpGetCount-posix.cpp b/src/VBox/Runtime/r3/posix/RTMpGetCount-posix.cpp index 6518ef890..9beb4446e 100644 --- a/src/VBox/Runtime/r3/posix/RTMpGetCount-posix.cpp +++ b/src/VBox/Runtime/r3/posix/RTMpGetCount-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: RTMpGetCount-posix.cpp $ */ +/* $Id: RTMpGetCount-posix.cpp 11243 2008-08-08 13:19:14Z vboxsync $ */ /** @file * IPRT - RTMpGetCount, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/RTSystemQueryOSInfo-posix.cpp b/src/VBox/Runtime/r3/posix/RTSystemQueryOSInfo-posix.cpp index 8ff6ead0e..2e2d501f6 100644 --- a/src/VBox/Runtime/r3/posix/RTSystemQueryOSInfo-posix.cpp +++ b/src/VBox/Runtime/r3/posix/RTSystemQueryOSInfo-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: RTSystemQueryOSInfo-posix.cpp $ */ +/* $Id: RTSystemQueryOSInfo-posix.cpp 15850 2009-01-08 10:16:09Z vboxsync $ */ /** @file * IPRT - RTSystemQueryOSInfo, POSIX implementation. */ diff --git a/src/VBox/Runtime/r3/posix/RTTimeNow-posix.cpp b/src/VBox/Runtime/r3/posix/RTTimeNow-posix.cpp index 7c5e9acc2..74ee305cf 100644 --- a/src/VBox/Runtime/r3/posix/RTTimeNow-posix.cpp +++ b/src/VBox/Runtime/r3/posix/RTTimeNow-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: RTTimeNow-posix.cpp $ */ +/* $Id: RTTimeNow-posix.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - RTTimeNow, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/alloc-posix.cpp b/src/VBox/Runtime/r3/posix/alloc-posix.cpp index 3e18b4ec5..be5efcc1b 100644 --- a/src/VBox/Runtime/r3/posix/alloc-posix.cpp +++ b/src/VBox/Runtime/r3/posix/alloc-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: alloc-posix.cpp $ */ +/* $Id: alloc-posix.cpp 11020 2008-07-30 22:48:35Z vboxsync $ */ /** @file * IPRT - Memory Allocation, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/dir-posix.cpp b/src/VBox/Runtime/r3/posix/dir-posix.cpp index 9ffd82225..4ecfcdd3a 100644 --- a/src/VBox/Runtime/r3/posix/dir-posix.cpp +++ b/src/VBox/Runtime/r3/posix/dir-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: dir-posix.cpp $ */ +/* $Id: dir-posix.cpp 20111 2009-05-28 00:34:52Z vboxsync $ */ /** @file * IPRT - Directory manipulation, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/env-posix.cpp b/src/VBox/Runtime/r3/posix/env-posix.cpp index 5c671edfc..75e7a9a83 100644 --- a/src/VBox/Runtime/r3/posix/env-posix.cpp +++ b/src/VBox/Runtime/r3/posix/env-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: env-posix.cpp $ */ +/* $Id: env-posix.cpp 20821 2009-06-23 12:42:19Z vboxsync $ */ /** @file * IPRT - Environment, Posix. */ @@ -40,20 +40,28 @@ #include <iprt/string.h> #include <iprt/alloca.h> #include <iprt/assert.h> +#if defined(DEBUG) && defined(RT_OS_LINUX) +# include <iprt/asm.h> +#endif #include <stdlib.h> #include <errno.h> +#include "internal/alignmentchecks.h" + RTDECL(bool) RTEnvExist(const char *pszVar) { - return getenv(pszVar) != NULL; + return RTEnvGet(pszVar) != NULL; } RTDECL(const char *) RTEnvGet(const char *pszVar) { - return getenv(pszVar); + IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc causes trouble */ + const char *pszValue = getenv(pszVar); + IPRT_ALIGNMENT_CHECKS_ENABLE(); + return pszValue; } @@ -85,12 +93,12 @@ RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue) if (!putenv(pszTmp)) return 0; return RTErrConvertFromErrno(errno); - + #else if (!setenv(pszVar, pszValue, 1)) return VINF_SUCCESS; return RTErrConvertFromErrno(errno); -#endif +#endif } diff --git a/src/VBox/Runtime/r3/posix/fileaio-posix.cpp b/src/VBox/Runtime/r3/posix/fileaio-posix.cpp new file mode 100644 index 000000000..655685991 --- /dev/null +++ b/src/VBox/Runtime/r3/posix/fileaio-posix.cpp @@ -0,0 +1,813 @@ +/* $Id: fileaio-posix.cpp 20961 2009-06-26 08:45:18Z vboxsync $ */ +/** @file + * IPRT - File async I/O, native implementation for POSIX compliant host platforms. + */ + +/* + * Copyright (C) 2006-2007 Sun Microsystems, Inc. + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * 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. + * + * 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 * +*******************************************************************************/ +#define LOG_GROUP RTLOGGROUP_DIR +#include <iprt/asm.h> +#include <iprt/file.h> +#include <iprt/mem.h> +#include <iprt/assert.h> +#include <iprt/string.h> +#include <iprt/err.h> +#include <iprt/log.h> +#include <iprt/thread.h> +#include <iprt/semaphore.h> +#include "internal/fileaio.h" + +#if defined(RT_OS_DARWIN) +# include <sys/types.h> +# include <sys/sysctl.h> /* for sysctlbyname */ +#endif +#include <aio.h> +#include <errno.h> +#include <time.h> + +/* + * Linux does not define this value. + * Just define it with really big + * value. + */ +#ifndef AIO_LISTIO_MAX +# define AIO_LISTIO_MAX UINT32_MAX +#endif + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * Async I/O request state. + */ +typedef struct RTFILEAIOREQINTERNAL +{ + /** The aio control block. FIRST ELEMENT! */ + struct aiocb AioCB; + /** Next element in the chain. */ + struct RTFILEAIOREQINTERNAL *pNext; + /** Previous element in the chain. */ + struct RTFILEAIOREQINTERNAL *pPrev; + /** Current state the request is in. */ + RTFILEAIOREQSTATE enmState; + /** Flag whether this is a flush request. */ + bool fFlush; + /** Flag indicating if the request was canceled. */ + volatile bool fCanceled; + /** Opaque user data. */ + void *pvUser; + /** Number of bytes actually transfered. */ + size_t cbTransfered; + /** Status code. */ + int Rc; + /** Completion context we are assigned to. */ + struct RTFILEAIOCTXINTERNAL *pCtxInt; + /** Entry in the waiting list the request is in. */ + unsigned iWaitingList; + /** Magic value (RTFILEAIOREQ_MAGIC). */ + uint32_t u32Magic; +} RTFILEAIOREQINTERNAL, *PRTFILEAIOREQINTERNAL; + +/** + * Async I/O completion context state. + */ +typedef struct RTFILEAIOCTXINTERNAL +{ + /** Current number of requests active on this context. */ + volatile int32_t cRequests; + /** Maximum number of requests this context can handle. */ + uint32_t cMaxRequests; + /** The ID of the thread which is currently waiting for requests. */ + volatile RTTHREAD hThreadWait; + /** Flag whether the thread was woken up. */ + volatile bool fWokenUp; + /** Flag whether the thread is currently waiting in the syscall. */ + volatile bool fWaiting; + /** Magic value (RTFILEAIOCTX_MAGIC). */ + uint32_t u32Magic; + /** Flag whether the thread was woken up due to a internal event. */ + volatile bool fWokenUpInternal; + /** List of new requests which needs to be inserted into apReqs by the + * waiting thread. */ + volatile PRTFILEAIOREQINTERNAL apReqsNewHead[5]; + /** Special entry for requests which are canceled. Because only one + * request can be canceled at a time and the thread canceling the request + * has to wait we need only one entry. */ + volatile PRTFILEAIOREQINTERNAL pReqToCancel; + /** Event semaphore the canceling thread is waiting for completion of + * the operation. */ + RTSEMEVENT SemEventCancel; + /** Number of elements in the waiting list. */ + unsigned cReqsWait; + /** First free slot in the waiting list. */ + unsigned iFirstFree; + /** List of requests we are currently waiting on. + * Size depends on cMaxRequests. */ + volatile PRTFILEAIOREQINTERNAL apReqs[1]; +} RTFILEAIOCTXINTERNAL, *PRTFILEAIOCTXINTERNAL; + +/** + * Internal worker for waking up the waiting thread. + */ +static void rtFileAioCtxWakeup(PRTFILEAIOCTXINTERNAL pCtxInt) +{ + /* + * Read the thread handle before the status flag. + * If we read the handle after the flag we might + * end up with an invalid handle because the thread + * waiting in RTFileAioCtxWakeup() might get scheduled + * before we read the flag and returns. + * We can ensure that the handle is valid if fWaiting is true + * when reading the handle before the status flag. + */ + RTTHREAD hThread; + ASMAtomicReadHandle(&pCtxInt->hThreadWait, &hThread); + bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting); + if (fWaiting) + { + /* + * If a thread waits the handle must be valid. + * It is possible that the thread returns from + * aio_suspend() before the signal is send. + * This is no problem because we already set fWokenUp + * to true which will let the thread return VERR_INTERRUPTED + * and the next call to RTFileAioCtxWait() will not + * return VERR_INTERRUPTED because signals are not saved + * and will simply vanish if the destination thread can't + * receive it. + */ + Assert(hThread != NIL_RTTHREAD); + RTThreadPoke(hThread); + } +} + +/** + * Internal worker processing events and inserting new requests into the waiting list. + */ +static int rtFileAioCtxProcessEvents(PRTFILEAIOCTXINTERNAL pCtxInt) +{ + int rc = VINF_SUCCESS; + + /* Process new requests first. */ + bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUpInternal, false); + if (fWokenUp) + { + for (unsigned iSlot = 0; iSlot < RT_ELEMENTS(pCtxInt->apReqsNewHead); iSlot++) + { + PRTFILEAIOREQINTERNAL pReqHead = (PRTFILEAIOREQINTERNAL)ASMAtomicXchgPtr((void* volatile*)&pCtxInt->apReqsNewHead[iSlot], + NULL); + + while (pReqHead) + { + pCtxInt->apReqs[pCtxInt->iFirstFree] = pReqHead; + pReqHead->iWaitingList = pCtxInt->iFirstFree; + pReqHead = pReqHead->pNext; + + /* Clear pointer to next and previous element just for safety. */ + pCtxInt->apReqs[pCtxInt->iFirstFree]->pNext = NULL; + pCtxInt->apReqs[pCtxInt->iFirstFree]->pPrev = NULL; + pCtxInt->iFirstFree++; + Assert(pCtxInt->iFirstFree <= pCtxInt->cMaxRequests); + } + } + + /* Check if a request needs to be canceled. */ + PRTFILEAIOREQINTERNAL pReqToCancel = (PRTFILEAIOREQINTERNAL)ASMAtomicReadPtr((void* volatile*)&pCtxInt->pReqToCancel); + if (pReqToCancel) + { + /* Put it out of the waiting list. */ + pCtxInt->apReqs[pReqToCancel->iWaitingList] = pCtxInt->apReqs[--pCtxInt->iFirstFree]; + pCtxInt->apReqs[pReqToCancel->iWaitingList]->iWaitingList = pReqToCancel->iWaitingList; + ASMAtomicDecS32(&pCtxInt->cRequests); + RTSemEventSignal(pCtxInt->SemEventCancel); + } + } + else + { + if (ASMAtomicXchgBool(&pCtxInt->fWokenUp, false)) + rc = VERR_INTERRUPTED; + } + + return rc; +} + +RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits) +{ + int rcBSD = 0; + AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER); + +#if defined(RT_OS_DARWIN) + int cReqsOutstandingMax = 0; + size_t cbParameter = sizeof(int); + + rcBSD = sysctlbyname("kern.aioprocmax", /* name */ + &cReqsOutstandingMax, /* Where to store the old value. */ + &cbParameter, /* Size of the memory pointed to. */ + NULL, /* Where the new value is located. */ + NULL); /* Where the size of the new value is stored. */ + if (rcBSD == -1) + return RTErrConvertFromErrno(errno); + + pAioLimits->cReqsOutstandingMax = cReqsOutstandingMax; + pAioLimits->cbBufferAlignment = 0; +#else + pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS; + pAioLimits->cbBufferAlignment = 0; +#endif + + return VINF_SUCCESS; +} + +RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq) +{ + AssertPtrReturn(phReq, VERR_INVALID_POINTER); + + PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)RTMemAllocZ(sizeof(RTFILEAIOREQINTERNAL)); + if (RT_UNLIKELY(!pReqInt)) + return VERR_NO_MEMORY; + + pReqInt->pCtxInt = NULL; + pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + + *phReq = (RTFILEAIOREQ)pReqInt; + + return VINF_SUCCESS; +} + + +RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq) +{ + /* + * Validate the handle and ignore nil. + */ + if (hReq == NIL_RTFILEAIOREQ) + return VINF_SUCCESS; + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + + /* + * Trash the magic and free it. + */ + ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC); + RTMemFree(pReqInt); + return VINF_SUCCESS; +} + +/** + * Worker setting up the request. + */ +DECLINLINE(int) rtFileAioReqPrepareTransfer(RTFILEAIOREQ hReq, RTFILE hFile, + unsigned uTransferDirection, + RTFOFF off, void *pvBuf, size_t cbTransfer, + void *pvUser) +{ + /* + * Validate the input. + */ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + Assert(hFile != NIL_RTFILE); + AssertPtr(pvBuf); + Assert(off >= 0); + Assert(cbTransfer > 0); + + memset(&pReqInt->AioCB, 0, sizeof(struct aiocb)); + pReqInt->AioCB.aio_lio_opcode = uTransferDirection; + pReqInt->AioCB.aio_fildes = (int)hFile; + pReqInt->AioCB.aio_offset = off; + pReqInt->AioCB.aio_nbytes = cbTransfer; + pReqInt->AioCB.aio_buf = pvBuf; + pReqInt->pvUser = pvUser; + pReqInt->pCtxInt = NULL; + pReqInt->Rc = VERR_FILE_AIO_IN_PROGRESS; + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + + return VINF_SUCCESS; +} + + +RTDECL(int) RTFileAioReqPrepareRead(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off, + void *pvBuf, size_t cbRead, void *pvUser) +{ + return rtFileAioReqPrepareTransfer(hReq, hFile, LIO_READ, + off, pvBuf, cbRead, pvUser); +} + + +RTDECL(int) RTFileAioReqPrepareWrite(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off, + void *pvBuf, size_t cbWrite, void *pvUser) +{ + return rtFileAioReqPrepareTransfer(hReq, hFile, LIO_WRITE, + off, pvBuf, cbWrite, pvUser); +} + + +RTDECL(int) RTFileAioReqPrepareFlush(RTFILEAIOREQ hReq, RTFILE hFile, void *pvUser) +{ + PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)hReq; + + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + Assert(hFile != NIL_RTFILE); + + pReqInt->fFlush = true; + pReqInt->AioCB.aio_fildes = (int)hFile; + pReqInt->pvUser = pvUser; + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + + return VINF_SUCCESS; +} + + +RTDECL(void *) RTFileAioReqGetUser(RTFILEAIOREQ hReq) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN_RC(pReqInt, NULL); + + return pReqInt->pvUser; +} + + +RTDECL(int) RTFileAioReqCancel(RTFILEAIOREQ hReq) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED); + + ASMAtomicXchgBool(&pReqInt->fCanceled, true); + + int rcPosix = aio_cancel(pReqInt->AioCB.aio_fildes, &pReqInt->AioCB); + + if (rcPosix == AIO_CANCELED) + { + PRTFILEAIOCTXINTERNAL pCtxInt = pReqInt->pCtxInt; + /* + * Notify the waiting thread that the request was canceled. + */ + AssertMsg(VALID_PTR(pCtxInt), + ("Invalid state. Request was canceled but wasn't submitted\n")); + + Assert(!pCtxInt->pReqToCancel); + ASMAtomicWritePtr((void* volatile*)&pCtxInt->pReqToCancel, pReqInt); + rtFileAioCtxWakeup(pCtxInt); + + /* Wait for acknowledge. */ + int rc = RTSemEventWait(pCtxInt->SemEventCancel, RT_INDEFINITE_WAIT); + AssertRC(rc); + + ASMAtomicWritePtr((void* volatile*)&pCtxInt->pReqToCancel, NULL); + pReqInt->Rc = VERR_FILE_AIO_CANCELED; + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + return VINF_SUCCESS; + } + else if (rcPosix == AIO_ALLDONE) + return VERR_FILE_AIO_COMPLETED; + else if (rcPosix == AIO_NOTCANCELED) + return VERR_FILE_AIO_IN_PROGRESS; + else + return RTErrConvertFromErrno(errno); +} + + +RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); + AssertPtrNull(pcbTransfered); + + if ( (RT_SUCCESS(pReqInt->Rc)) + && (pcbTransfered)) + *pcbTransfered = pReqInt->cbTransfered; + + return pReqInt->Rc; +} + + +RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax) +{ + PRTFILEAIOCTXINTERNAL pCtxInt; + AssertPtrReturn(phAioCtx, VERR_INVALID_POINTER); + + pCtxInt = (PRTFILEAIOCTXINTERNAL)RTMemAllocZ( sizeof(RTFILEAIOCTXINTERNAL) + + cAioReqsMax * sizeof(PRTFILEAIOREQINTERNAL)); + if (RT_UNLIKELY(!pCtxInt)) + return VERR_NO_MEMORY; + + /* Create event semaphore. */ + int rc = RTSemEventCreate(&pCtxInt->SemEventCancel); + if (RT_FAILURE(rc)) + { + RTMemFree(pCtxInt); + return rc; + } + + pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC; + pCtxInt->cMaxRequests = cAioReqsMax; + *phAioCtx = (RTFILEAIOCTX)pCtxInt; + + return VINF_SUCCESS; +} + + +RTDECL(int) RTFileAioCtxDestroy(RTFILEAIOCTX hAioCtx) +{ + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + + AssertPtrReturn(pCtxInt, VERR_INVALID_HANDLE); + + if (RT_UNLIKELY(pCtxInt->cRequests)) + return VERR_FILE_AIO_BUSY; + + RTSemEventDestroy(pCtxInt->SemEventCancel); + RTMemFree(pCtxInt); + + return VINF_SUCCESS; +} + + +RTDECL(uint32_t) RTFileAioCtxGetMaxReqCount(RTFILEAIOCTX hAioCtx) +{ + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + + if (hAioCtx == NIL_RTFILEAIOCTX) + return RTFILEAIO_UNLIMITED_REQS; + else + return pCtxInt->cMaxRequests; +} + +RTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTX hAioCtx, RTFILE hFile) +{ + return VINF_SUCCESS; +} + +RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) +{ + int rc = VINF_SUCCESS; + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + + /* Parameter checks */ + AssertPtrReturn(pCtxInt, VERR_INVALID_HANDLE); + AssertReturn(cReqs != 0, VERR_INVALID_POINTER); + AssertPtrReturn(pahReqs, VERR_INVALID_PARAMETER); + + /* Check that we don't exceed the limit */ + if (ASMAtomicUoReadS32(&pCtxInt->cRequests) + cReqs > pCtxInt->cMaxRequests) + return VERR_FILE_AIO_LIMIT_EXCEEDED; + + PRTFILEAIOREQINTERNAL pHead = NULL; + + do + { + int rcPosix = 0; + size_t cReqsSubmit = 0; + size_t i = 0; + PRTFILEAIOREQINTERNAL pReqInt; + + while ( (i < cReqs) + && (i < AIO_LISTIO_MAX)) + { + pReqInt = pahReqs[i]; + if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt)) + { + /* Undo everything and stop submitting. */ + for (size_t iUndo = 0; iUndo < i; iUndo++) + { + pReqInt = pahReqs[iUndo]; + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + pReqInt->pCtxInt = NULL; + + /* Unlink from the list again. */ + PRTFILEAIOREQINTERNAL pNext, pPrev; + pNext = pReqInt->pNext; + pPrev = pReqInt->pPrev; + if (pNext) + pNext->pPrev = pPrev; + if (pPrev) + pPrev->pNext = pNext; + else + pHead = pNext; + } + rc = VERR_INVALID_HANDLE; + break; + } + + pReqInt->pCtxInt = pCtxInt; + + /* Link them together. */ + pReqInt->pNext = pHead; + if (pHead) + pHead->pPrev = pReqInt; + pReqInt->pPrev = NULL; + pHead = pReqInt; + RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); + + if (pReqInt->fFlush) + break; + + cReqsSubmit++; + i++; + } + + if (cReqsSubmit) + { + rcPosix = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL); + if (RT_UNLIKELY(rcPosix < 0)) + { + if (rcPosix == EAGAIN) + rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; + else + rc = RTErrConvertFromErrno(errno); + + /* Check which ones were not submitted. */ + for (i = 0; i < cReqs; i++) + { + pReqInt = pahReqs[i]; + rcPosix = aio_error(&pReqInt->AioCB); + if (rcPosix != EINPROGRESS) + { + if (rcPosix == EINVAL) + { + /* Was not submitted. */ + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + } + else + { + /* An error occurred. */ + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + pReqInt->Rc = RTErrConvertFromErrno(rcPosix); + pReqInt->cbTransfered = 0; + } + /* Unlink from the list. */ + PRTFILEAIOREQINTERNAL pNext, pPrev; + pNext = pReqInt->pNext; + pPrev = pReqInt->pPrev; + if (pNext) + pNext->pPrev = pPrev; + if (pPrev) + pPrev->pNext = pNext; + else + pHead = pNext; + } + } + + break; + } + + ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit); + cReqs -= cReqsSubmit; + pahReqs += cReqsSubmit; + } + + /* Check if we have a flush request now. */ + if (cReqs) + { + pReqInt = pahReqs[0]; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + + Assert(pReqInt->fFlush); + + /* + * lio_listio does not work with flush requests so + * we have to use aio_fsync directly. + */ + rcPosix = aio_fsync(O_SYNC, &pReqInt->AioCB); + if (RT_UNLIKELY(rcPosix < 0)) + { + rc = RTErrConvertFromErrno(errno); + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + pReqInt->Rc = rc; + pReqInt->cbTransfered = 0; + + /* Unlink from the list. */ + PRTFILEAIOREQINTERNAL pNext, pPrev; + pNext = pReqInt->pNext; + pPrev = pReqInt->pPrev; + if (pNext) + pNext->pPrev = pPrev; + if (pPrev) + pPrev->pNext = pNext; + else + pHead = pNext; + break; + } + + ASMAtomicIncS32(&pCtxInt->cRequests); + cReqs--; + pahReqs++; + } + } while (cReqs); + + if (pHead) + { + /* + * Forward successfully submitted requests to the thread waiting for requests. + * We search for a free slot first and if we don't find one + * we will grab the first one and append our list to the existing entries. + */ + unsigned iSlot = 0; + while ( (iSlot < RT_ELEMENTS(pCtxInt->apReqsNewHead)) + && !ASMAtomicCmpXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[iSlot], pHead, NULL)) + iSlot++; + + if (iSlot == RT_ELEMENTS(pCtxInt->apReqsNewHead)) + { + /* Nothing found. */ + PRTFILEAIOREQINTERNAL pOldHead = (PRTFILEAIOREQINTERNAL)ASMAtomicXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[0], + NULL); + + /* Find the end of the current head and link the old list to the current. */ + PRTFILEAIOREQINTERNAL pTail = pHead; + while (pTail->pNext) + pTail = pTail->pNext; + + pTail->pNext = pOldHead; + + ASMAtomicXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[0], pHead); + } + + /* Set the internal wakeup flag and wakeup the thread if possible. */ + bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUpInternal, true); + if (!fWokenUp) + rtFileAioCtxWakeup(pCtxInt); + } + + return rc; +} + + +RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, unsigned cMillisTimeout, + PRTFILEAIOREQ pahReqs, size_t cReqs, uint32_t *pcReqs) +{ + int rc = VINF_SUCCESS; + int cRequestsCompleted = 0; + PRTFILEAIOCTXINTERNAL pCtxInt = (PRTFILEAIOCTXINTERNAL)hAioCtx; + struct timespec Timeout; + struct timespec *pTimeout = NULL; + uint64_t StartNanoTS = 0; + + /* Check parameters. */ + AssertPtrReturn(pCtxInt, VERR_INVALID_HANDLE); + AssertPtrReturn(pcReqs, VERR_INVALID_POINTER); + AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); + AssertReturn(cReqs != 0, VERR_INVALID_PARAMETER); + AssertReturn(cReqs >= cMinReqs, VERR_OUT_OF_RANGE); + + if (RT_UNLIKELY(ASMAtomicReadS32(&pCtxInt->cRequests) == 0)) + return VERR_FILE_AIO_NO_REQUEST; + + if (cMillisTimeout != RT_INDEFINITE_WAIT) + { + Timeout.tv_sec = cMillisTimeout / 1000; + Timeout.tv_nsec = (cMillisTimeout % 1000) * 1000000; + pTimeout = &Timeout; + StartNanoTS = RTTimeNanoTS(); + } + + /* Wait for at least one. */ + if (!cMinReqs) + cMinReqs = 1; + + /* For the wakeup call. */ + Assert(pCtxInt->hThreadWait == NIL_RTTHREAD); + ASMAtomicWriteHandle(&pCtxInt->hThreadWait, RTThreadSelf()); + + /* Update the waiting list once before we enter the loop. */ + rc = rtFileAioCtxProcessEvents(pCtxInt); + + while ( cMinReqs + && RT_SUCCESS_NP(rc)) + { + ASMAtomicXchgBool(&pCtxInt->fWaiting, true); + int rcPosix = aio_suspend((const struct aiocb * const *)pCtxInt->apReqs, + pCtxInt->iFirstFree, pTimeout); + ASMAtomicXchgBool(&pCtxInt->fWaiting, false); + if (rcPosix < 0) + { + /* Check that this is an external wakeup event. */ + if (errno == EINTR) + rc = rtFileAioCtxProcessEvents(pCtxInt); + else + rc = RTErrConvertFromErrno(errno); + } + else + { + /* Requests finished. */ + unsigned iReqCurr = 0; + int cDone = 0; + + /* Remove completed requests from the waiting list. */ + while (iReqCurr < pCtxInt->iFirstFree) + { + PRTFILEAIOREQINTERNAL pReq = pCtxInt->apReqs[iReqCurr]; + int rcReq = aio_error(&pReq->AioCB); + + if (rcReq != EINPROGRESS) + { + /* Completed store the return code. */ + if (rcReq == 0) + { + pReq->Rc = VINF_SUCCESS; + /* Call aio_return() to free ressources. */ + pReq->cbTransfered = aio_return(&pReq->AioCB); + } + else + pReq->Rc = RTErrConvertFromErrno(rcReq); + + /* Mark the request as finished. */ + RTFILEAIOREQ_SET_STATE(pReq, COMPLETED); + cDone++; + + /* + * Move the last entry into the current position to avoid holes + * but only if it is not the last element already. + */ + if (pReq->iWaitingList < pCtxInt->iFirstFree - 1) + { + pCtxInt->apReqs[pReq->iWaitingList] = pCtxInt->apReqs[--pCtxInt->iFirstFree]; + pCtxInt->apReqs[pReq->iWaitingList]->iWaitingList = pReq->iWaitingList; + pCtxInt->apReqs[pCtxInt->iFirstFree] = NULL; + } + else + pCtxInt->iFirstFree--; + + /* Put the request into the completed list. */ + pahReqs[cRequestsCompleted++] = pReq; + } + else + iReqCurr++; + } + + cReqs -= cDone; + cMinReqs -= cDone; + ASMAtomicSubS32(&pCtxInt->cRequests, cDone); + + if ((cMillisTimeout != RT_INDEFINITE_WAIT) && (cMinReqs > 0)) + { + uint64_t TimeDiff; + + /* Recalculate the timeout. */ + TimeDiff = RTTimeSystemNanoTS() - StartNanoTS; + Timeout.tv_sec = Timeout.tv_sec - (TimeDiff / 1000000); + Timeout.tv_nsec = Timeout.tv_nsec - (TimeDiff % 1000000); + } + + /* Check for new elements. */ + rc = rtFileAioCtxProcessEvents(pCtxInt); + } + } + + *pcReqs = cRequestsCompleted; + Assert(pCtxInt->hThreadWait == RTThreadSelf()); + ASMAtomicWriteHandle(&pCtxInt->hThreadWait, NIL_RTTHREAD); + + return rc; +} + + +RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx) +{ + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + + /** @todo r=bird: Define the protocol for how to resume work after calling + * this function. */ + + bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true); + if (!fWokenUp) + rtFileAioCtxWakeup(pCtxInt); + + return VINF_SUCCESS; +} + diff --git a/src/VBox/Runtime/r3/posix/fileio-posix.cpp b/src/VBox/Runtime/r3/posix/fileio-posix.cpp index 47173ead9..51857dadb 100644 --- a/src/VBox/Runtime/r3/posix/fileio-posix.cpp +++ b/src/VBox/Runtime/r3/posix/fileio-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: fileio-posix.cpp $ */ +/* $Id: fileio-posix.cpp 19346 2009-05-05 00:39:14Z vboxsync $ */ /** @file * IPRT - File I/O, POSIX. */ @@ -142,6 +142,11 @@ RTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, unsigned fOpen if (fOpen & RTFILE_O_WRITE_THROUGH) fOpenMode |= O_SYNC; #endif +#if defined(O_DIRECT) && defined(RT_OS_LINUX) + /* O_DIRECT is mandatory to get async I/O working on Linux. */ + if (fOpen & RTFILE_O_ASYNC_IO) + fOpenMode |= O_DIRECT; +#endif /* create/truncate file */ switch (fOpen & RTFILE_O_ACTION_MASK) diff --git a/src/VBox/Runtime/r3/posix/filelock-posix.cpp b/src/VBox/Runtime/r3/posix/filelock-posix.cpp index 17bcb97c3..41c7cfcb3 100644 --- a/src/VBox/Runtime/r3/posix/filelock-posix.cpp +++ b/src/VBox/Runtime/r3/posix/filelock-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: filelock-posix.cpp $ */ +/* $Id: filelock-posix.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - File Locking, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/fs-posix.cpp b/src/VBox/Runtime/r3/posix/fs-posix.cpp index c1e20287c..0dbdc93d0 100644 --- a/src/VBox/Runtime/r3/posix/fs-posix.cpp +++ b/src/VBox/Runtime/r3/posix/fs-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: fs-posix.cpp $ */ +/* $Id: fs-posix.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - File System, Linux. */ diff --git a/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp b/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp index 9e9739f49..b879eef7b 100644 --- a/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp +++ b/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: ldrNative-posix.cpp $ */ +/* $Id: ldrNative-posix.cpp 12146 2008-09-05 16:27:28Z vboxsync $ */ /** @file * IPRT - Binary Image Loader, POSIX native. */ diff --git a/src/VBox/Runtime/r3/posix/path-posix.cpp b/src/VBox/Runtime/r3/posix/path-posix.cpp index 726b5ee55..abcfde53c 100644 --- a/src/VBox/Runtime/r3/posix/path-posix.cpp +++ b/src/VBox/Runtime/r3/posix/path-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: path-posix.cpp $ */ +/* $Id: path-posix.cpp 20819 2009-06-23 12:15:07Z vboxsync $ */ /** @file * IPRT - Path Manipulation, POSIX. */ @@ -44,6 +44,7 @@ #include <pwd.h> #include <iprt/path.h> +#include <iprt/env.h> #include <iprt/assert.h> #include <iprt/string.h> #include <iprt/err.h> @@ -392,7 +393,7 @@ static int rtPathUserHomeByEnv(char *pszPath, size_t cchPath) * Get HOME env. var it and validate it's existance. */ int rc = VERR_PATH_NOT_FOUND; - const char *pszHome = getenv("HOME"); + const char *pszHome = RTEnvGet("HOME"); if (pszHome) { diff --git a/src/VBox/Runtime/r3/posix/process-posix.cpp b/src/VBox/Runtime/r3/posix/process-posix.cpp index eed1ee369..777a4ebb3 100644 --- a/src/VBox/Runtime/r3/posix/process-posix.cpp +++ b/src/VBox/Runtime/r3/posix/process-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: process-posix.cpp $ */ +/* $Id: process-posix.cpp 20498 2009-06-12 11:05:46Z vboxsync $ */ /** @file * IPRT - Process, POSIX. */ @@ -74,6 +74,7 @@ RTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, AssertReturn(Env != NIL_RTENV, VERR_INVALID_PARAMETER); const char * const *papszEnv = RTEnvGetExecEnvP(Env); AssertPtrReturn(papszEnv, VERR_INVALID_HANDLE); + AssertPtrReturn(papszArgs, VERR_INVALID_PARAMETER); /* later: path searching. */ diff --git a/src/VBox/Runtime/r3/posix/rand-posix.cpp b/src/VBox/Runtime/r3/posix/rand-posix.cpp index ac706d689..b53c5957e 100644 --- a/src/VBox/Runtime/r3/posix/rand-posix.cpp +++ b/src/VBox/Runtime/r3/posix/rand-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: rand-posix.cpp $ */ +/* $Id: rand-posix.cpp 11557 2008-08-21 21:47:31Z vboxsync $ */ /** @file * IPRT - Random Numbers and Byte Streams, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/sched-posix.cpp b/src/VBox/Runtime/r3/posix/sched-posix.cpp index e8f90e864..86f67e381 100644 --- a/src/VBox/Runtime/r3/posix/sched-posix.cpp +++ b/src/VBox/Runtime/r3/posix/sched-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: sched-posix.cpp $ */ +/* $Id: sched-posix.cpp 13837 2008-11-05 02:54:02Z vboxsync $ */ /** @file * IPRT - Scheduling, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/semevent-posix.cpp b/src/VBox/Runtime/r3/posix/semevent-posix.cpp index c89b90280..c2789133b 100644 --- a/src/VBox/Runtime/r3/posix/semevent-posix.cpp +++ b/src/VBox/Runtime/r3/posix/semevent-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: semevent-posix.cpp $ */ +/* $Id: semevent-posix.cpp 14318 2008-11-18 16:56:53Z vboxsync $ */ /** @file * IPRT - Event Semaphore, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp b/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp index cf446f83c..d2df8af2f 100644 --- a/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp +++ b/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: semeventmulti-posix.cpp $ */ +/* $Id: semeventmulti-posix.cpp 14318 2008-11-18 16:56:53Z vboxsync $ */ /** @file * IPRT - Multiple Release Event Semaphore, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/semmutex-posix.cpp b/src/VBox/Runtime/r3/posix/semmutex-posix.cpp index 9050f9496..217dee87e 100644 --- a/src/VBox/Runtime/r3/posix/semmutex-posix.cpp +++ b/src/VBox/Runtime/r3/posix/semmutex-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: semmutex-posix.cpp $ */ +/* $Id: semmutex-posix.cpp 8651 2008-05-07 12:16:29Z vboxsync $ */ /** @file * IPRT - Mutex Semaphore, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/semrw-posix.cpp b/src/VBox/Runtime/r3/posix/semrw-posix.cpp index 03336d346..bbd4da38c 100644 --- a/src/VBox/Runtime/r3/posix/semrw-posix.cpp +++ b/src/VBox/Runtime/r3/posix/semrw-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: semrw-posix.cpp $ */ +/* $Id: semrw-posix.cpp 8653 2008-05-07 12:31:30Z vboxsync $ */ /** @file * IPRT - Read-Write Semaphore, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/thread-posix.cpp b/src/VBox/Runtime/r3/posix/thread-posix.cpp index d76682db9..de36ed092 100644 --- a/src/VBox/Runtime/r3/posix/thread-posix.cpp +++ b/src/VBox/Runtime/r3/posix/thread-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: thread-posix.cpp $ */ +/* $Id: thread-posix.cpp 13837 2008-11-05 02:54:02Z vboxsync $ */ /** @file * IPRT - Threads, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/time-posix.cpp b/src/VBox/Runtime/r3/posix/time-posix.cpp index 34f538a20..7191e4966 100644 --- a/src/VBox/Runtime/r3/posix/time-posix.cpp +++ b/src/VBox/Runtime/r3/posix/time-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: time-posix.cpp $ */ +/* $Id: time-posix.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - Time, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/timer-posix.cpp b/src/VBox/Runtime/r3/posix/timer-posix.cpp index 92cb17e19..2393aeb9f 100644 --- a/src/VBox/Runtime/r3/posix/timer-posix.cpp +++ b/src/VBox/Runtime/r3/posix/timer-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: timer-posix.cpp $ */ +/* $Id: timer-posix.cpp 14298 2008-11-18 12:47:26Z vboxsync $ */ /** @file * IPRT - Timer, POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/tls-posix.cpp b/src/VBox/Runtime/r3/posix/tls-posix.cpp index 4a6ab3a38..a32140540 100644 --- a/src/VBox/Runtime/r3/posix/tls-posix.cpp +++ b/src/VBox/Runtime/r3/posix/tls-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: tls-posix.cpp $ */ +/* $Id: tls-posix.cpp 16311 2009-01-28 13:46:41Z vboxsync $ */ /** @file * IPRT - Thread Local Storage (TLS), POSIX. */ diff --git a/src/VBox/Runtime/r3/posix/utf8-posix.cpp b/src/VBox/Runtime/r3/posix/utf8-posix.cpp index a7e878182..a0b1d10e1 100644 --- a/src/VBox/Runtime/r3/posix/utf8-posix.cpp +++ b/src/VBox/Runtime/r3/posix/utf8-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: utf8-posix.cpp $ */ +/* $Id: utf8-posix.cpp 20822 2009-06-23 12:44:05Z vboxsync $ */ /** @file * IPRT - UTF-8 helpers, POSIX. */ @@ -44,9 +44,12 @@ #include <wctype.h> #ifdef RT_OS_SOLARIS -#include <langinfo.h> +# include <langinfo.h> #endif +#include "internal/alignmentchecks.h" + + /******************************************************************************* * Internal Functions * *******************************************************************************/ @@ -72,6 +75,7 @@ static int rtstrConvert(const void *pvInput, size_t cbInput, const char *pszInpu /* * Allocate buffer */ + bool fUcs2Term; void *pvOutput; size_t cbOutput2; if (!cbOutput) @@ -80,11 +84,13 @@ static int rtstrConvert(const void *pvInput, size_t cbInput, const char *pszInpu pvOutput = RTMemTmpAlloc(cbOutput2 + sizeof(RTUTF16)); if (!pvOutput) return VERR_NO_TMP_MEMORY; + fUcs2Term = true; } else { pvOutput = *ppvOutput; - cbOutput2 = cbOutput - (!strcmp(pszOutputCS, "UCS-2") ? sizeof(RTUTF16) : 1); + fUcs2Term = !strcmp(pszOutputCS, "UCS-2"); + cbOutput2 = cbOutput - (fUcs2Term ? sizeof(RTUTF16) : 1); if (cbOutput2 > cbOutput) return VERR_BUFFER_OVERFLOW; } @@ -104,7 +110,9 @@ static int rtstrConvert(const void *pvInput, size_t cbInput, const char *pszInpu if (!*pszOutputCS) pszOutputCS = nl_langinfo(CODESET); #endif + IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc causes trouble */ iconv_t icHandle = iconv_open(pszOutputCS, pszInputCS); + IPRT_ALIGNMENT_CHECKS_ENABLE(); if (icHandle != (iconv_t)-1) { /* @@ -127,15 +135,13 @@ static int rtstrConvert(const void *pvInput, size_t cbInput, const char *pszInpu * (Two terminators to support UCS-2 output, too.) */ iconv_close(icHandle); - if (!cbOutput || !strcmp(pszOutputCS, "UCS-2")) - *(PRTUTF16)pvOutputLeft = '\0'; - else - *(char *)pvOutputLeft = '\0'; + ((char *)pvOutputLeft)[0] = '\0'; + if (fUcs2Term) + ((char *)pvOutputLeft)[1] = '\0'; *ppvOutput = pvOutput; return VINF_SUCCESS; } - else - errno = E2BIG; + errno = E2BIG; } iconv_close(icHandle); @@ -149,7 +155,7 @@ static int rtstrConvert(const void *pvInput, size_t cbInput, const char *pszInpu { RTMemTmpFree(pvOutput); cbOutput2 *= 2; - pvOutput = RTMemTmpAlloc(cbOutput2); + pvOutput = RTMemTmpAlloc(cbOutput2 + sizeof(RTUTF16)); if (!pvOutput) return VERR_NO_TMP_MEMORY; continue; diff --git a/src/VBox/Runtime/r3/process.cpp b/src/VBox/Runtime/r3/process.cpp index d7c2fee58..59ba81e9f 100644 --- a/src/VBox/Runtime/r3/process.cpp +++ b/src/VBox/Runtime/r3/process.cpp @@ -1,4 +1,4 @@ -/* $Id: process.cpp $ */ +/* $Id: process.cpp 18997 2009-04-17 15:22:25Z vboxsync $ */ /** @file * IPRT - Process, Common. */ diff --git a/src/VBox/Runtime/r3/solaris/alloc-solaris.cpp b/src/VBox/Runtime/r3/solaris/alloc-solaris.cpp index ee97b8309..0293f8c9f 100644 --- a/src/VBox/Runtime/r3/solaris/alloc-solaris.cpp +++ b/src/VBox/Runtime/r3/solaris/alloc-solaris.cpp @@ -1,4 +1,4 @@ -/* $Id: alloc-solaris.cpp $ */ +/* $Id: alloc-solaris.cpp 11020 2008-07-30 22:48:35Z vboxsync $ */ /** @file * IPRT - Memory Allocation, POSIX. */ diff --git a/src/VBox/Runtime/r3/solaris/mp-solaris.cpp b/src/VBox/Runtime/r3/solaris/mp-solaris.cpp index f6bf56e13..282509712 100644 --- a/src/VBox/Runtime/r3/solaris/mp-solaris.cpp +++ b/src/VBox/Runtime/r3/solaris/mp-solaris.cpp @@ -1,4 +1,4 @@ -/* $Id: mp-solaris.cpp $ */ +/* $Id: mp-solaris.cpp 12108 2008-09-04 20:17:24Z vboxsync $ */ /** @file * IPRT - Multiprocessor, Solaris. */ diff --git a/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp b/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp index d154b361e..49813cf04 100644 --- a/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp +++ b/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp @@ -1,4 +1,4 @@ -/* $Id: rtProcInitExePath-solaris.cpp $ */ +/* $Id: rtProcInitExePath-solaris.cpp 11840 2008-08-29 17:49:10Z vboxsync $ */ /** @file * IPRT - rtProcInitName, Solaris. */ diff --git a/src/VBox/Runtime/r3/stream.cpp b/src/VBox/Runtime/r3/stream.cpp index f2d9de349..b96a8e78f 100644 --- a/src/VBox/Runtime/r3/stream.cpp +++ b/src/VBox/Runtime/r3/stream.cpp @@ -1,4 +1,4 @@ -/* $Id: stream.cpp $ */ +/* $Id: stream.cpp 21045 2009-06-30 01:09:19Z vboxsync $ */ /** @file * IPRT - I/O Stream. */ @@ -41,6 +41,8 @@ #include <iprt/err.h> #include <iprt/param.h> #include <iprt/string.h> + +#include "internal/alignmentchecks.h" #include "internal/magics.h" #include <stdio.h> @@ -296,6 +298,7 @@ RTR3DECL(int) RTStrmClearError(PRTSTREAM pStream) int rc; if (pStream && pStream->u32Magic == RTSTREAM_MAGIC) { + clearerr(pStream->pFile); ASMAtomicXchgS32(&pStream->i32Error, VINF_SUCCESS); rc = VINF_SUCCESS; } @@ -309,6 +312,41 @@ RTR3DECL(int) RTStrmClearError(PRTSTREAM pStream) /** + * Rewinds the stream. + * + * Stream errors will be reset on success. + * + * @returns IPRT status code. + * + * @param pStream The stream. + * + * @remarks Not all streams are rewindable and that behavior is currently + * undefined for those. + */ +RTR3DECL(int) RTStrmRewind(PRTSTREAM pStream) +{ + AssertPtrReturn(pStream, VERR_INVALID_HANDLE); + AssertReturn(pStream->u32Magic == RTSTREAM_MAGIC, VERR_INVALID_HANDLE); + + int rc; + clearerr(pStream->pFile); + errno = 0; + if (!fseek(pStream->pFile, 0, SEEK_SET)) + { + ASMAtomicXchgS32(&pStream->i32Error, VINF_SUCCESS); + rc = VINF_SUCCESS; + } + else + { + rc = RTErrConvertFromErrno(errno); + ASMAtomicXchgS32(&pStream->i32Error, rc); + } + + return rc; +} + + +/** * Reads from a file stream. * * @returns iprt status code. @@ -401,7 +439,9 @@ RTR3DECL(int) RTStrmWriteEx(PRTSTREAM pStream, const void *pvBuf, size_t cbWrite { if (pcbWritten) { + IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ *pcbWritten = fwrite(pvBuf, 1, cbWrite, pStream->pFile); + IPRT_ALIGNMENT_CHECKS_ENABLE(); if ( *pcbWritten == cbWrite || !ferror(pStream->pFile)) return VINF_SUCCESS; @@ -410,9 +450,12 @@ RTR3DECL(int) RTStrmWriteEx(PRTSTREAM pStream, const void *pvBuf, size_t cbWrite else { /* - * Must read it all! + * Must write it all! */ - if (fwrite(pvBuf, cbWrite, 1, pStream->pFile) == 1) + IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ + size_t cbWritten = fwrite(pvBuf, cbWrite, 1, pStream->pFile); + IPRT_ALIGNMENT_CHECKS_ENABLE(); + if (cbWritten == 1) return VINF_SUCCESS; if (!ferror(pStream->pFile)) return VINF_SUCCESS; /* WEIRD! But anyway... */ @@ -499,32 +542,32 @@ RTR3DECL(int) RTStrmGetLine(PRTSTREAM pStream, char *pszString, size_t cchString if (RT_SUCCESS(rc)) { cchString--; /* save space for the terminator. */ - #ifdef HAVE_FWRITE_UNLOCKED +#ifdef HAVE_FWRITE_UNLOCKED flockfile(pStream->pFile); - #endif +#endif for (;;) { - #ifdef HAVE_FWRITE_UNLOCKED +#ifdef HAVE_FWRITE_UNLOCKED int ch = fgetc_unlocked(pStream->pFile); - #else +#else int ch = fgetc(pStream->pFile); - #endif +#endif if (ch == EOF) { - #ifdef HAVE_FWRITE_UNLOCKED +#ifdef HAVE_FWRITE_UNLOCKED if (feof_unlocked(pStream->pFile)) - #else +#else if (feof(pStream->pFile)) - #endif +#endif { rc = VERR_EOF; break; } - #ifdef HAVE_FWRITE_UNLOCKED +#ifdef HAVE_FWRITE_UNLOCKED if (ferror_unlocked(pStream->pFile)) - #else +#else if (ferror(pStream->pFile)) - #endif +#endif rc = VERR_READ_ERROR; else { @@ -542,9 +585,9 @@ RTR3DECL(int) RTStrmGetLine(PRTSTREAM pStream, char *pszString, size_t cchString break; } } - #ifdef HAVE_FWRITE_UNLOCKED +#ifdef HAVE_FWRITE_UNLOCKED funlockfile(pStream->pFile); - #endif +#endif *pszString = '\0'; if (RT_FAILURE(rc)) @@ -596,12 +639,14 @@ static DECLCALLBACK(size_t) rtstrmOutput(void *pvArg, const char *pachChars, siz int rc = pStream->i32Error; if (RT_SUCCESS(rc)) { - #ifdef HAVE_FWRITE_UNLOCKED + IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ +#ifdef HAVE_FWRITE_UNLOCKED if (fwrite_unlocked(pachChars, cchChars, 1, pStream->pFile) != 1) - #else +#else if (fwrite(pachChars, cchChars, 1, pStream->pFile) != 1) - #endif +#endif ASMAtomicXchgS32(&pStream->i32Error, VERR_WRITE_ERROR); + IPRT_ALIGNMENT_CHECKS_ENABLE(); } } /* else: ignore termination call. */ @@ -626,13 +671,13 @@ RTR3DECL(int) RTStrmPrintfV(PRTSTREAM pStream, const char *pszFormat, va_list ar if (RT_SUCCESS(rc)) { /** @todo consider making this thread safe... */ - #ifdef HAVE_FWRITE_UNLOCKED +#ifdef HAVE_FWRITE_UNLOCKED flockfile(pStream->pFile); rc = (int)RTStrFormatV(rtstrmOutput, pStream, NULL, NULL, pszFormat, args); funlockfile(pStream->pFile); - #else +#else rc = (int)RTStrFormatV(rtstrmOutput, pStream, NULL, NULL, pszFormat, args); - #endif +#endif Assert(rc >= 0); } else diff --git a/src/VBox/Runtime/r3/tcp.cpp b/src/VBox/Runtime/r3/tcp.cpp index af3d23af1..27313bf86 100644 --- a/src/VBox/Runtime/r3/tcp.cpp +++ b/src/VBox/Runtime/r3/tcp.cpp @@ -1,4 +1,4 @@ -/* $Id: tcp.cpp $ */ +/* $Id: tcp.cpp 15655 2008-12-18 13:28:02Z vboxsync $ */ /** @file * IPRT - TCP/IP. */ diff --git a/src/VBox/Runtime/r3/test.cpp b/src/VBox/Runtime/r3/test.cpp index c3da350f0..c165148b9 100644 --- a/src/VBox/Runtime/r3/test.cpp +++ b/src/VBox/Runtime/r3/test.cpp @@ -1,4 +1,4 @@ -/* $Id: test.cpp $ */ +/* $Id: test.cpp 20605 2009-06-15 20:49:41Z vboxsync $ */ /** @file * IPRT - Testcase Framework. */ @@ -33,14 +33,17 @@ * Header Files * *******************************************************************************/ #include <iprt/test.h> + +#include <iprt/asm.h> +#include <iprt/critsect.h> +#include <iprt/env.h> +#include <iprt/err.h> +#include <iprt/initterm.h> #include <iprt/mem.h> +#include <iprt/once.h> #include <iprt/param.h> #include <iprt/string.h> #include <iprt/stream.h> -#include <iprt/critsect.h> -#include <iprt/once.h> -#include <iprt/err.h> -#include <iprt/asm.h> #include "internal/magics.h" @@ -163,6 +166,7 @@ typedef RTTESTINT *PRTTESTINT; * Internal Functions * *******************************************************************************/ static void rtTestGuardedFreeOne(PRTTESTGUARDEDMEM pMem); +static int rtTestPrintf(PRTTESTINT pTest, const char *pszFormat, ...); /******************************************************************************* @@ -246,6 +250,28 @@ RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest) rc = RTTlsSet(g_iTestTls, pTest); if (RT_SUCCESS(rc)) { + /* + * Finally, pick up overrides from the environment. + */ + char szMaxLevel[80]; + rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_MAX_LEVEL", szMaxLevel, sizeof(szMaxLevel), NULL); + if (RT_SUCCESS(rc)) + { + char *pszMaxLevel = RTStrStrip(szMaxLevel); + if (!strcmp(pszMaxLevel, "all")) + pTest->enmMaxLevel = RTTESTLVL_DEBUG; + if (!strcmp(pszMaxLevel, "quiet")) + pTest->enmMaxLevel = RTTESTLVL_FAILURE; + else if (!strcmp(pszMaxLevel, "debug")) + pTest->enmMaxLevel = RTTESTLVL_DEBUG; + else if (!strcmp(pszMaxLevel, "info")) + pTest->enmMaxLevel = RTTESTLVL_INFO; + else if (!strcmp(pszMaxLevel, "sub_test")) + pTest->enmMaxLevel = RTTESTLVL_SUB_TEST; + else if (!strcmp(pszMaxLevel, "failure")) + pTest->enmMaxLevel = RTTESTLVL_FAILURE; + } + *phTest = pTest; return VINF_SUCCESS; } @@ -262,6 +288,24 @@ RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest) } +RTR3DECL(int) RTTestInitAndCreate(const char *pszTest, PRTTEST phTest) +{ + int rc = RTR3Init(); + if (RT_FAILURE(rc)) + { + RTStrmPrintf(g_pStdErr, "%s: fatal error: RTR3Init failed with rc=%Rrc\n", pszTest, rc); + return 16; + } + rc = RTTestCreate(pszTest, phTest); + if (RT_FAILURE(rc)) + { + RTStrmPrintf(g_pStdErr, "%s: fatal error: RTTestCreate failed with rc=%Rrc\n", pszTest, rc); + return 17; + } + return 0; +} + + /** * Destroys a test instance previously created by RTTestCreate. * @@ -279,6 +323,12 @@ RTR3DECL(int) RTTestDestroy(RTTEST hTest) RTTEST_VALID_RETURN(pTest); /* + * Make sure we end with a new line. + */ + if (!pTest->fNewLine) + rtTestPrintf(pTest, "\n"); + + /* * Clean up. */ if ((RTTESTINT *)RTTlsGet(g_iTestTls) == pTest) @@ -307,6 +357,21 @@ RTR3DECL(int) RTTestDestroy(RTTEST hTest) } +/** + * Changes the default test instance for the calling thread. + * + * @returns IPRT status code. + * + * @param hNewDefaultTest The new default test. NIL_RTTEST is fine. + * @param phOldTest Where to store the old test handle. Optional. + */ +RTR3DECL(int) RTTestSetDefault(RTTEST hNewDefaultTest, PRTTEST phOldTest) +{ + if (phOldTest) + *phOldTest = (RTTEST)RTTlsGet(g_iTestTls); + return RTTlsSet(g_iTestTls, hNewDefaultTest); +} + /** * Allocate a block of guarded memory. @@ -698,12 +763,12 @@ static int rtTestSubTestReport(PRTTESTINT pTest) pTest->fSubTestReported = true; uint32_t cErrors = ASMAtomicUoReadU32(&pTest->cErrors) - pTest->cSubTestAtErrors; if (!cErrors) - cch += RTTestPrintf(pTest, RTTESTLVL_SUB_TEST, "%-50s: PASSED\n", pTest->pszSubTest); + cch += RTTestPrintfNl(pTest, RTTESTLVL_SUB_TEST, "%-50s: PASSED\n", pTest->pszSubTest); else { pTest->cSubTestsFailed++; - cch += RTTestPrintf(pTest, RTTESTLVL_SUB_TEST, "%-50s: FAILED (%u errors)\n", - pTest->pszSubTest, cErrors); + cch += RTTestPrintfNl(pTest, RTTESTLVL_SUB_TEST, "%-50s: FAILED (%u errors)\n", + pTest->pszSubTest, cErrors); } } return cch; @@ -761,12 +826,49 @@ RTR3DECL(int) RTTestSummaryAndDestroy(RTTEST hTest) rc = 1; } + RTTestDestroy(pTest); + return rc; +} + + +RTR3DECL(int) RTTestSkipAndDestroyV(RTTEST hTest, const char *pszReason, va_list va) +{ + PRTTESTINT pTest = hTest; + RTTEST_GET_VALID_RETURN_RC(pTest, 2); + + RTCritSectEnter(&pTest->Lock); + rtTestSubTestReport(pTest); + RTCritSectLeave(&pTest->Lock); + + int rc; + if (!pTest->cErrors) + { + if (pszReason) + RTTestPrintfNlV(hTest, RTTESTLVL_FAILURE, pszReason, va); + RTTestPrintfNl(hTest, RTTESTLVL_ALWAYS, "SKIPPED\n", pTest->cErrors); + rc = 2; + } + else + { + RTTestPrintfNl(hTest, RTTESTLVL_ALWAYS, "FAILURE - %u errors\n", pTest->cErrors); + rc = 1; + } RTTestDestroy(pTest); return rc; } +RTR3DECL(int) RTTestSkipAndDestroy(RTTEST hTest, const char *pszReason, ...) +{ + va_list va; + va_start(va, pszReason); + int rc = RTTestSkipAndDestroyV(hTest, pszReason, va); + va_end(va); + return rc; +} + + /** * Starts a sub-test. * @@ -806,6 +908,52 @@ RTR3DECL(int) RTTestSub(RTTEST hTest, const char *pszSubTest) /** + * Format string version of RTTestSub. + * + * See RTTestSub for details. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszSubTestFmt The sub-test name format string. + * @param ... Arguments. + */ +RTR3DECL(int) RTTestSubF(RTTEST hTest, const char *pszSubTestFmt, ...) +{ + va_list va; + va_start(va, pszSubTestFmt); + int cch = RTTestSubV(hTest, pszSubTestFmt, va); + va_end(va); + return cch; +} + + +/** + * Format string version of RTTestSub. + * + * See RTTestSub for details. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszSubTestFmt The sub-test name format string. + * @param ... Arguments. + */ +RTR3DECL(int) RTTestSubV(RTTEST hTest, const char *pszSubTestFmt, va_list va) +{ + char *pszSubTest; + RTStrAPrintfV(&pszSubTest, pszSubTestFmt, va); + if (pszSubTest) + { + int cch = RTTestSub(hTest, pszSubTest); + RTStrFree(pszSubTest); + return cch; + } + return 0; +} + + +/** * Completes a sub-test. * * @returns Number of chars printed. @@ -922,8 +1070,12 @@ RTR3DECL(int) RTTestFailedV(RTTEST hTest, const char *pszFormat, va_list va) va_list va2; va_copy(va2, va); + const char *pszEnd = strchr(pszFormat, '\0'); + bool fHasNewLine = pszFormat != pszEnd + && pszEnd[-1] == '\n'; + RTCritSectEnter(&pTest->OutputLock); - cch += rtTestPrintf(pTest, "%N\n", pszFormat, &va2); + cch += rtTestPrintf(pTest, fHasNewLine ? "%N" : "%N\n", pszFormat, &va2); RTCritSectLeave(&pTest->OutputLock); va_end(va2); diff --git a/src/VBox/Runtime/r3/testi.cpp b/src/VBox/Runtime/r3/testi.cpp index 241867159..8fc2de346 100644 --- a/src/VBox/Runtime/r3/testi.cpp +++ b/src/VBox/Runtime/r3/testi.cpp @@ -1,4 +1,4 @@ -/* $Id: testi.cpp $ */ +/* $Id: testi.cpp 19944 2009-05-23 21:48:08Z vboxsync $ */ /** @file * IPRT - Testcase Framework, the implicit test handle API variation. */ @@ -52,6 +52,34 @@ RTR3DECL(int) RTTestIPrintf(RTTESTLVL enmLevel, const char *pszFormat, ...) } +RTR3DECL(int) RTTestISub(const char *pszSubTest) +{ + return RTTestSub(NIL_RTTEST, pszSubTest); +} + + +RTR3DECL(int) RTTestISubF(const char *pszSubTestFmt, ...) +{ + va_list va; + va_start(va, pszSubTestFmt); + int cch = RTTestSubV(NIL_RTTEST, pszSubTestFmt, va); + va_end(va); + return cch; +} + + +RTR3DECL(int) RTTestISubV(const char *pszSubTestFmt, va_list va) +{ + return RTTestSubV(NIL_RTTEST, pszSubTestFmt, va); +} + + +RTR3DECL(int) RTTestISubDone(void) +{ + return RTTestSubDone(NIL_RTTEST); +} + + RTR3DECL(int) RTTestIPassedV(const char *pszFormat, va_list va) { return RTTestPassedV(NIL_RTTEST, pszFormat, va); diff --git a/src/VBox/Runtime/r3/win/RTLogWriteDebugger-win.cpp b/src/VBox/Runtime/r3/win/RTLogWriteDebugger-win.cpp index 34dec02cb..216a40891 100644 --- a/src/VBox/Runtime/r3/win/RTLogWriteDebugger-win.cpp +++ b/src/VBox/Runtime/r3/win/RTLogWriteDebugger-win.cpp @@ -1,4 +1,4 @@ -/* $Id: RTLogWriteDebugger-win.cpp $ */ +/* $Id: RTLogWriteDebugger-win.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - Log To Debugger, Win32. */ diff --git a/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp b/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp index 3cf4ff980..be558cd85 100644 --- a/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp +++ b/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp @@ -1,4 +1,4 @@ -/* $Id: RTSystemQueryOSInfo-win.cpp $ */ +/* $Id: RTSystemQueryOSInfo-win.cpp 15954 2009-01-14 19:46:17Z vboxsync $ */ /** @file * IPRT - RTSystemQueryOSInfo, generic stub. */ diff --git a/src/VBox/Runtime/r3/win/RTUuidCreate-win.cpp b/src/VBox/Runtime/r3/win/RTUuidCreate-win.cpp index ba4f9722e..4690203be 100644 --- a/src/VBox/Runtime/r3/win/RTUuidCreate-win.cpp +++ b/src/VBox/Runtime/r3/win/RTUuidCreate-win.cpp @@ -1,4 +1,4 @@ -/* $Id: RTUuidCreate-win.cpp $ */ +/* $Id: RTUuidCreate-win.cpp 9749 2008-06-17 08:42:50Z vboxsync $ */ /** @file * IPRT - UUID, Windows RTUuidCreate implementation. */ diff --git a/src/VBox/Runtime/r3/win/VBoxRT-openssl-ose.def b/src/VBox/Runtime/r3/win/VBoxRT-openssl-ose.def new file mode 100644 index 000000000..dfcfdcb92 --- /dev/null +++ b/src/VBox/Runtime/r3/win/VBoxRT-openssl-ose.def @@ -0,0 +1,1656 @@ +; $Id: VBoxRT-openssl-ose.def 20238 2009-06-03 17:05:51Z vboxsync $ +;; @file +; IPRT - Windows OpenSSL exports. +; +; This file is appended to the architecture specific .def file. +; +; E:\coding\vbox\svn\trunk\tools\win.x86\vcc\v8sp1\bin\x86_amd64\dumpbin.exe \coding\vbox\svn\trunk\out\win.amd64\debug\lib\VBox-libcrypto.lib /symbols /OUT:foo.lst +; grep " External " foo.lst | grep -v " UNDEF " | grep -v " ??_" | grep -v " notype " | sort | cut -d "|" -f 2 +; + +; +; Copyright (C) 2009 Sun Microsystems, Inc. +; +; This file is part of VirtualBox Open Source Edition (OSE), as +; available from http://www.virtualbox.org. This file is free software; +; 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. +; +; 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. +; + + ; + ; OpenSSL symbols + ; + ACCESS_DESCRIPTION_free + ACCESS_DESCRIPTION_new + ASN1_BIT_STRING_free + ASN1_BIT_STRING_get_bit + ASN1_BIT_STRING_new + ASN1_BIT_STRING_set + ASN1_BIT_STRING_set_bit + ASN1_BMPSTRING_free + ASN1_BMPSTRING_new + ASN1_ENUMERATED_free + ASN1_ENUMERATED_get + ASN1_ENUMERATED_new + ASN1_ENUMERATED_set + ASN1_ENUMERATED_to_BN + ASN1_GENERALIZEDTIME_check + ASN1_GENERALIZEDTIME_free + ASN1_GENERALIZEDTIME_new + ASN1_GENERALIZEDTIME_print + ASN1_GENERALIZEDTIME_set + ASN1_GENERALIZEDTIME_set_string + ASN1_GENERALSTRING_free + ASN1_GENERALSTRING_new + ASN1_IA5STRING_free + ASN1_IA5STRING_new + ASN1_INTEGER_cmp + ASN1_INTEGER_dup + ASN1_INTEGER_free + ASN1_INTEGER_get + ASN1_INTEGER_new + ASN1_INTEGER_set + ASN1_INTEGER_to_BN + ASN1_NULL_free + ASN1_NULL_new + ASN1_OBJECT_create + ASN1_OBJECT_free + ASN1_OBJECT_new + ASN1_OCTET_STRING_cmp + ASN1_OCTET_STRING_dup + ASN1_OCTET_STRING_free + ASN1_OCTET_STRING_new + ASN1_OCTET_STRING_set + ASN1_PRINTABLESTRING_free + ASN1_PRINTABLESTRING_new + ASN1_PRINTABLE_free + ASN1_PRINTABLE_new + ASN1_PRINTABLE_type + ASN1_STRING_TABLE_add + ASN1_STRING_TABLE_cleanup + ASN1_STRING_TABLE_get + ASN1_STRING_cmp + ASN1_STRING_data + ASN1_STRING_dup + ASN1_STRING_free + ASN1_STRING_get_default_mask + ASN1_STRING_length + ASN1_STRING_length_set + ASN1_STRING_new + ASN1_STRING_print + ASN1_STRING_print_ex + ASN1_STRING_print_ex_fp + ASN1_STRING_set + ASN1_STRING_set0 + ASN1_STRING_set_by_NID + ASN1_STRING_set_default_mask + ASN1_STRING_set_default_mask_asc + ASN1_STRING_to_UTF8 + ASN1_STRING_type + ASN1_STRING_type_new + ASN1_T61STRING_free + ASN1_T61STRING_new + ASN1_TIME_check + ASN1_TIME_free + ASN1_TIME_new + ASN1_TIME_print + ASN1_TIME_set + ASN1_TIME_to_generalizedtime + ASN1_TYPE_free + ASN1_TYPE_get + ASN1_TYPE_get_int_octetstring + ASN1_TYPE_get_octetstring + ASN1_TYPE_new + ASN1_TYPE_set + ASN1_TYPE_set1 + ASN1_TYPE_set_int_octetstring + ASN1_TYPE_set_octetstring + ASN1_UNIVERSALSTRING_free + ASN1_UNIVERSALSTRING_new + ASN1_UNIVERSALSTRING_to_string + ASN1_UTCTIME_check + ASN1_UTCTIME_cmp_time_t + ASN1_UTCTIME_free + ASN1_UTCTIME_new + ASN1_UTCTIME_print + ASN1_UTCTIME_set + ASN1_UTCTIME_set_string + ASN1_UTF8STRING_free + ASN1_UTF8STRING_new + ASN1_VISIBLESTRING_free + ASN1_VISIBLESTRING_new + ASN1_check_infinite_end + ASN1_const_check_infinite_end + ASN1_d2i_bio + ASN1_d2i_fp + ASN1_digest + ASN1_dup + ASN1_generate_nconf + ASN1_generate_v3 + ASN1_get_object + ASN1_i2d_bio + ASN1_i2d_fp + ASN1_item_d2i + ASN1_item_d2i_bio + ASN1_item_d2i_fp + ASN1_item_digest + ASN1_item_dup + ASN1_item_ex_d2i + ASN1_item_ex_free + ASN1_item_ex_i2d + ASN1_item_ex_new + ASN1_item_free + ASN1_item_i2d + ASN1_item_i2d_bio + ASN1_item_i2d_fp + ASN1_item_ndef_i2d + ASN1_item_new + ASN1_item_pack + ASN1_item_sign + ASN1_item_unpack + ASN1_item_verify + ASN1_mbstring_copy + ASN1_mbstring_ncopy + ASN1_object_size + ASN1_pack_string + ASN1_parse + ASN1_parse_dump + ASN1_primitive_free + ASN1_primitive_new + ASN1_put_eoc + ASN1_put_object + ASN1_seq_pack + ASN1_seq_unpack + ASN1_sign + ASN1_tag2bit + ASN1_tag2str + ASN1_template_d2i + ASN1_template_free + ASN1_template_i2d + ASN1_template_new + ASN1_unpack_string + ASN1_verify + AUTHORITY_INFO_ACCESS_free + AUTHORITY_INFO_ACCESS_new + AUTHORITY_KEYID_free + AUTHORITY_KEYID_new + BASIC_CONSTRAINTS_free + BASIC_CONSTRAINTS_new + BIO_callback_ctrl + BIO_clear_flags + BIO_copy_next_retry + BIO_ctrl + BIO_ctrl_pending + BIO_ctrl_wpending + BIO_dump + BIO_dump_cb + BIO_dump_fp + BIO_dump_indent + BIO_dump_indent_cb + BIO_dump_indent_fp + BIO_dup_chain + BIO_find_type + BIO_free + BIO_free_all + BIO_get_callback + BIO_get_callback_arg + BIO_get_ex_data + BIO_get_ex_new_index + BIO_get_retry_BIO + BIO_get_retry_reason + BIO_gets + BIO_indent + BIO_int_ctrl + BIO_method_name + BIO_method_type + BIO_new + BIO_new_file + BIO_new_fp + BIO_next + BIO_number_read + BIO_number_written + BIO_pop + BIO_ptr_ctrl + BIO_push + BIO_puts + BIO_read + BIO_s_file + BIO_set + BIO_set_callback + BIO_set_callback_arg + BIO_set_ex_data + BIO_set_flags + BIO_test_flags + BIO_vfree + BIO_write + BN_BLINDING_convert + BN_BLINDING_convert_ex + BN_BLINDING_create_param + BN_BLINDING_free + BN_BLINDING_get_flags + BN_BLINDING_get_thread_id + BN_BLINDING_invert + BN_BLINDING_invert_ex + BN_BLINDING_new + BN_BLINDING_set_flags + BN_BLINDING_set_thread_id + BN_BLINDING_update + BN_CTX_end + BN_CTX_free + BN_CTX_get + BN_CTX_init + BN_CTX_new + BN_CTX_start + BN_GENCB_call + BN_GF2m_add + BN_GF2m_arr2poly + BN_GF2m_mod + BN_GF2m_mod_arr + BN_GF2m_mod_div + BN_GF2m_mod_div_arr + BN_GF2m_mod_exp + BN_GF2m_mod_exp_arr + BN_GF2m_mod_inv + BN_GF2m_mod_inv_arr + BN_GF2m_mod_mul + BN_GF2m_mod_mul_arr + BN_GF2m_mod_solve_quad + BN_GF2m_mod_solve_quad_arr + BN_GF2m_mod_sqr + BN_GF2m_mod_sqr_arr + BN_GF2m_mod_sqrt + BN_GF2m_mod_sqrt_arr + BN_GF2m_poly2arr + BN_MONT_CTX_copy + BN_MONT_CTX_free + BN_MONT_CTX_init + BN_MONT_CTX_new + BN_MONT_CTX_set + BN_MONT_CTX_set_locked + BN_RECP_CTX_free + BN_RECP_CTX_init + BN_RECP_CTX_new + BN_RECP_CTX_set + BN_add + BN_add_word + BN_bin2bn + BN_bn2bin + BN_bn2dec + BN_bn2hex + BN_bntest_rand + BN_clear + BN_clear_bit + BN_clear_free + BN_cmp + BN_copy + BN_dec2bn + BN_div + BN_div_recp + BN_div_word + BN_dup + BN_exp + BN_free + BN_from_montgomery + BN_gcd + BN_generate_prime_ex + BN_get0_nist_prime_192 + BN_get0_nist_prime_224 + BN_get0_nist_prime_256 + BN_get0_nist_prime_384 + BN_get0_nist_prime_521 + BN_get_params + BN_get_word + BN_hex2bn + BN_init + BN_is_bit_set + BN_is_prime_ex + BN_is_prime_fasttest_ex + BN_kronecker + BN_lshift + BN_lshift1 + BN_mask_bits + BN_mod_add + BN_mod_add_quick + BN_mod_exp + BN_mod_exp_mont + BN_mod_exp_mont_consttime + BN_mod_exp_mont_word + BN_mod_exp_recp + BN_mod_exp_simple + BN_mod_inverse + BN_mod_lshift + BN_mod_lshift1 + BN_mod_lshift1_quick + BN_mod_lshift_quick + BN_mod_mul + BN_mod_mul_montgomery + BN_mod_mul_reciprocal + BN_mod_sqr + BN_mod_sqrt + BN_mod_sub + BN_mod_sub_quick + BN_mod_word + BN_mul + BN_mul_word + BN_new + BN_nist_mod_192 + BN_nist_mod_224 + BN_nist_mod_256 + BN_nist_mod_384 + BN_nist_mod_521 + BN_nnmod + BN_num_bits + BN_num_bits_word + BN_print + BN_pseudo_rand + BN_pseudo_rand_range + BN_rand + BN_rand_range + BN_reciprocal + BN_rshift + BN_rshift1 + BN_set_bit + BN_set_negative + BN_set_params + BN_set_word + BN_sqr + BN_sub + BN_sub_word + BN_swap + BN_to_ASN1_ENUMERATED + BN_to_ASN1_INTEGER + BN_uadd + BN_ucmp + BN_usub + BN_value_one + BUF_MEM_free + BUF_MEM_grow + BUF_MEM_grow_clean + BUF_MEM_new + BUF_memdup + BUF_strdup + BUF_strlcat + BUF_strlcpy + BUF_strndup + CERTIFICATEPOLICIES_free + CERTIFICATEPOLICIES_new + CONF_dump_bio + CONF_dump_fp + CONF_free + CONF_get_number + CONF_get_section + CONF_get_string + CONF_load + CONF_load_bio + CONF_load_fp + CONF_parse_list + CONF_set_default_method + CONF_set_nconf + CRL_DIST_POINTS_free + CRL_DIST_POINTS_new + CRYPTO_add_lock + CRYPTO_cleanup_all_ex_data + CRYPTO_dbg_free + CRYPTO_dbg_get_options + CRYPTO_dbg_malloc + CRYPTO_dbg_pop_info + CRYPTO_dbg_push_info + CRYPTO_dbg_realloc + CRYPTO_dbg_remove_all_info + CRYPTO_dbg_set_options + CRYPTO_destroy_dynlockid + CRYPTO_dup_ex_data + CRYPTO_ex_data_new_class + CRYPTO_free + CRYPTO_free_ex_data + CRYPTO_free_locked + CRYPTO_get_add_lock_callback + CRYPTO_get_dynlock_create_callback + CRYPTO_get_dynlock_destroy_callback + CRYPTO_get_dynlock_lock_callback + CRYPTO_get_dynlock_value + CRYPTO_get_ex_data + CRYPTO_get_ex_data_implementation + CRYPTO_get_ex_new_index + CRYPTO_get_id_callback + CRYPTO_get_locked_mem_ex_functions + CRYPTO_get_locked_mem_functions + CRYPTO_get_locking_callback + CRYPTO_get_mem_debug_functions + CRYPTO_get_mem_debug_options + CRYPTO_get_mem_ex_functions + CRYPTO_get_mem_functions + CRYPTO_get_new_dynlockid + CRYPTO_get_new_lockid + CRYPTO_is_mem_check_on + CRYPTO_lock + CRYPTO_malloc + CRYPTO_malloc_debug_init + CRYPTO_malloc_locked + CRYPTO_mem_ctrl + CRYPTO_mem_leaks + CRYPTO_mem_leaks_cb + CRYPTO_mem_leaks_fp + CRYPTO_new_ex_data + CRYPTO_num_locks + CRYPTO_pop_info + CRYPTO_push_info_ + CRYPTO_realloc + CRYPTO_realloc_clean + CRYPTO_remalloc + CRYPTO_remove_all_info + CRYPTO_set_add_lock_callback + CRYPTO_set_dynlock_create_callback + CRYPTO_set_dynlock_destroy_callback + CRYPTO_set_dynlock_lock_callback + CRYPTO_set_ex_data + CRYPTO_set_ex_data_implementation + CRYPTO_set_id_callback + CRYPTO_set_locked_mem_ex_functions + CRYPTO_set_locked_mem_functions + CRYPTO_set_locking_callback + CRYPTO_set_mem_debug_functions + CRYPTO_set_mem_debug_options + CRYPTO_set_mem_ex_functions + CRYPTO_set_mem_functions + CRYPTO_set_mem_info_functions + CRYPTO_strdup + CRYPTO_thread_id + DH_OpenSSL + DH_check + DH_check_pub_key + DH_compute_key + DH_free + DH_generate_key + DH_get_default_method + DH_get_ex_data + DH_get_ex_new_index + DH_new + DH_new_method + DH_set_default_method + DH_set_ex_data + DH_set_method + DH_size + DH_up_ref + DHparams_print + DHparams_print_fp + DIRECTORYSTRING_free + DIRECTORYSTRING_new + DISPLAYTEXT_free + DISPLAYTEXT_new + DIST_POINT_NAME_free + DIST_POINT_NAME_new + DIST_POINT_free + DIST_POINT_new + ECDSA_OpenSSL + ECDSA_SIG_free + ECDSA_SIG_new + ECDSA_do_sign + ECDSA_do_sign_ex + ECDSA_get_default_method + ECDSA_get_ex_data + ECDSA_get_ex_new_index + ECDSA_set_default_method + ECDSA_set_ex_data + ECDSA_set_method + ECDSA_sign + ECDSA_sign_ex + ECDSA_sign_setup + ECDSA_size + ECPKParameters_print + ECPKParameters_print_fp + ECParameters_print + ECParameters_print_fp + EC_GF2m_simple_method + EC_GFp_mont_method + EC_GFp_nist_method + EC_GFp_simple_method + EC_GROUP_check_discriminant + EC_GROUP_clear_free + EC_GROUP_cmp + EC_GROUP_copy + EC_GROUP_dup + EC_GROUP_free + EC_GROUP_get0_generator + EC_GROUP_get0_seed + EC_GROUP_get_asn1_flag + EC_GROUP_get_basis_type + EC_GROUP_get_cofactor + EC_GROUP_get_curve_GF2m + EC_GROUP_get_curve_GFp + EC_GROUP_get_curve_name + EC_GROUP_get_degree + EC_GROUP_get_order + EC_GROUP_get_pentanomial_basis + EC_GROUP_get_point_conversion_form + EC_GROUP_get_seed_len + EC_GROUP_get_trinomial_basis + EC_GROUP_have_precompute_mult + EC_GROUP_method_of + EC_GROUP_new + EC_GROUP_new_by_curve_name + EC_GROUP_new_curve_GF2m + EC_GROUP_new_curve_GFp + EC_GROUP_precompute_mult + EC_GROUP_set_asn1_flag + EC_GROUP_set_curve_GF2m + EC_GROUP_set_curve_GFp + EC_GROUP_set_curve_name + EC_GROUP_set_generator + EC_GROUP_set_point_conversion_form + EC_GROUP_set_seed + EC_KEY_check_key + EC_KEY_copy + EC_KEY_dup + EC_KEY_free + EC_KEY_generate_key + EC_KEY_get0_group + EC_KEY_get0_private_key + EC_KEY_get0_public_key + EC_KEY_get_conv_form + EC_KEY_get_enc_flags + EC_KEY_get_key_method_data + EC_KEY_insert_key_method_data + EC_KEY_new + EC_KEY_new_by_curve_name + EC_KEY_precompute_mult + EC_KEY_print + EC_KEY_print_fp + EC_KEY_set_asn1_flag + EC_KEY_set_conv_form + EC_KEY_set_enc_flags + EC_KEY_set_group + EC_KEY_set_private_key + EC_KEY_set_public_key + EC_KEY_up_ref + EC_METHOD_get_field_type + EC_POINT_add + EC_POINT_bn2point + EC_POINT_clear_free + EC_POINT_cmp + EC_POINT_copy + EC_POINT_dbl + EC_POINT_dup + EC_POINT_free + EC_POINT_get_Jprojective_coordinates_GFp + EC_POINT_get_affine_coordinates_GF2m + EC_POINT_get_affine_coordinates_GFp + EC_POINT_hex2point + EC_POINT_invert + EC_POINT_is_at_infinity + EC_POINT_is_on_curve + EC_POINT_make_affine + EC_POINT_method_of + EC_POINT_mul + EC_POINT_new + EC_POINT_oct2point + EC_POINT_point2bn + EC_POINT_point2hex + EC_POINT_point2oct + EC_POINT_set_Jprojective_coordinates_GFp + EC_POINT_set_affine_coordinates_GF2m + EC_POINT_set_affine_coordinates_GFp + EC_POINT_set_compressed_coordinates_GF2m + EC_POINT_set_compressed_coordinates_GFp + EC_POINT_set_to_infinity + EC_POINTs_make_affine + EC_POINTs_mul + EC_get_builtin_curves + EDIPARTYNAME_free + EDIPARTYNAME_new + ERR_add_error_data + ERR_clear_error + ERR_error_string + ERR_error_string_n + ERR_free_strings + ERR_func_error_string + ERR_get_err_state_table + ERR_get_error + ERR_get_error_line + ERR_get_error_line_data + ERR_get_implementation + ERR_get_next_error_library + ERR_get_state + ERR_get_string_table + ERR_lib_error_string + ERR_load_ERR_strings + ERR_load_strings + ERR_peek_error + ERR_peek_error_line + ERR_peek_error_line_data + ERR_peek_last_error + ERR_peek_last_error_line + ERR_peek_last_error_line_data + ERR_print_errors + ERR_print_errors_cb + ERR_put_error + ERR_reason_error_string + ERR_release_err_state_table + ERR_remove_state + ERR_set_error_data + ERR_set_implementation + ERR_unload_strings + EVP_BytesToKey + EVP_CIPHER_CTX_block_size + EVP_CIPHER_CTX_cipher + EVP_CIPHER_CTX_cleanup + EVP_CIPHER_CTX_clear_flags + EVP_CIPHER_CTX_ctrl + EVP_CIPHER_CTX_flags + EVP_CIPHER_CTX_free + EVP_CIPHER_CTX_get_app_data + EVP_CIPHER_CTX_init + EVP_CIPHER_CTX_iv_length + EVP_CIPHER_CTX_key_length + EVP_CIPHER_CTX_new + EVP_CIPHER_CTX_nid + EVP_CIPHER_CTX_rand_key + EVP_CIPHER_CTX_set_app_data + EVP_CIPHER_CTX_set_flags + EVP_CIPHER_CTX_set_key_length + EVP_CIPHER_CTX_set_padding + EVP_CIPHER_CTX_test_flags + EVP_CIPHER_asn1_to_param + EVP_CIPHER_block_size + EVP_CIPHER_flags + EVP_CIPHER_get_asn1_iv + EVP_CIPHER_iv_length + EVP_CIPHER_key_length + EVP_CIPHER_nid + EVP_CIPHER_param_to_asn1 + EVP_CIPHER_set_asn1_iv + EVP_CIPHER_type + EVP_Cipher + EVP_CipherFinal + EVP_CipherFinal_ex + EVP_CipherInit + EVP_CipherInit_ex + EVP_CipherUpdate + EVP_DecodeBlock + EVP_DecodeFinal + EVP_DecodeInit + EVP_DecodeUpdate + EVP_DecryptFinal + EVP_DecryptFinal_ex + EVP_DecryptInit + EVP_DecryptInit_ex + EVP_DecryptUpdate + EVP_Digest + EVP_DigestFinal + EVP_DigestFinal_ex + EVP_DigestInit + EVP_DigestInit_ex + EVP_DigestUpdate + EVP_EncodeBlock + EVP_EncodeFinal + EVP_EncodeInit + EVP_EncodeUpdate + EVP_EncryptFinal + EVP_EncryptFinal_ex + EVP_EncryptInit + EVP_EncryptInit_ex + EVP_EncryptUpdate + EVP_MD_CTX_cleanup + EVP_MD_CTX_clear_flags + EVP_MD_CTX_copy + EVP_MD_CTX_copy_ex + EVP_MD_CTX_create + EVP_MD_CTX_destroy + EVP_MD_CTX_init + EVP_MD_CTX_md + EVP_MD_CTX_set_flags + EVP_MD_CTX_test_flags + EVP_MD_block_size + EVP_MD_pkey_type + EVP_MD_size + EVP_MD_type + EVP_PBE_CipherInit + EVP_PBE_alg_add + EVP_PBE_cleanup + EVP_PKCS82PKEY + EVP_PKEY2PKCS8 + EVP_PKEY2PKCS8_broken + EVP_PKEY_add1_attr + EVP_PKEY_add1_attr_by_NID + EVP_PKEY_add1_attr_by_OBJ + EVP_PKEY_add1_attr_by_txt + EVP_PKEY_assign + EVP_PKEY_bits + EVP_PKEY_cmp + EVP_PKEY_cmp_parameters + EVP_PKEY_copy_parameters + EVP_PKEY_delete_attr + EVP_PKEY_free + EVP_PKEY_get1_DH + EVP_PKEY_get1_EC_KEY + EVP_PKEY_get1_RSA + EVP_PKEY_get_attr + EVP_PKEY_get_attr_by_NID + EVP_PKEY_get_attr_by_OBJ + EVP_PKEY_get_attr_count + EVP_PKEY_missing_parameters + EVP_PKEY_new + EVP_PKEY_save_parameters + EVP_PKEY_set1_DH + EVP_PKEY_set1_EC_KEY + EVP_PKEY_set1_RSA + EVP_PKEY_size + EVP_PKEY_type + EVP_SignFinal + EVP_VerifyFinal + EVP_add_cipher + EVP_add_digest + EVP_cleanup + EVP_get_cipherbyname + EVP_get_digestbyname + EVP_get_pw_prompt + EVP_md5 + EVP_read_pw_string + EVP_set_pw_prompt + EVP_sha1 + EVP_sha224 + EVP_sha256 + EVP_sha384 + EVP_sha512 + EXTENDED_KEY_USAGE_free + EXTENDED_KEY_USAGE_new + GENERAL_NAMES_free + GENERAL_NAMES_new + GENERAL_NAME_free + GENERAL_NAME_new + GENERAL_NAME_print + GENERAL_SUBTREE_free + GENERAL_SUBTREE_new + HMAC + HMAC_CTX_cleanup + HMAC_CTX_init + HMAC_CTX_set_flags + HMAC_Final + HMAC_Init + HMAC_Init_ex + HMAC_Update + MD5_Final + MD5_Init + MD5_Transform + MD5_Update + NAME_CONSTRAINTS_free + NAME_CONSTRAINTS_new + NCONF_WIN32 + NCONF_default + NCONF_dump_bio + NCONF_dump_fp + NCONF_free + NCONF_free_data + NCONF_get_number_e + NCONF_get_section + NCONF_get_string + NCONF_load + NCONF_load_bio + NCONF_load_fp + NCONF_new + NETSCAPE_SPKAC_free + NETSCAPE_SPKAC_new + NETSCAPE_SPKI_free + NETSCAPE_SPKI_new + NETSCAPE_SPKI_sign + NETSCAPE_SPKI_verify + NOTICEREF_free + NOTICEREF_new + OBJ_NAME_add + OBJ_NAME_cleanup + OBJ_NAME_do_all + OBJ_NAME_do_all_sorted + OBJ_NAME_get + OBJ_NAME_init + OBJ_NAME_new_index + OBJ_NAME_remove + OBJ_add_object + OBJ_bsearch + OBJ_bsearch_ex + OBJ_cleanup + OBJ_cmp + OBJ_create + OBJ_create_objects + OBJ_dup + OBJ_ln2nid + OBJ_new_nid + OBJ_nid2ln + OBJ_nid2obj + OBJ_nid2sn + OBJ_obj2nid + OBJ_obj2txt + OBJ_sn2nid + OBJ_txt2nid + OBJ_txt2obj + OCSP_BASICRESP_free + OCSP_BASICRESP_new + OCSP_CERTID_free + OCSP_CERTID_new + OCSP_CERTSTATUS_free + OCSP_CERTSTATUS_new + OCSP_CRLID_free + OCSP_CRLID_new + OCSP_ONEREQ_free + OCSP_ONEREQ_new + OCSP_REQINFO_free + OCSP_REQINFO_new + OCSP_REQUEST_free + OCSP_REQUEST_new + OCSP_RESPBYTES_free + OCSP_RESPBYTES_new + OCSP_RESPDATA_free + OCSP_RESPDATA_new + OCSP_RESPID_free + OCSP_RESPID_new + OCSP_RESPONSE_free + OCSP_RESPONSE_new + OCSP_REVOKEDINFO_free + OCSP_REVOKEDINFO_new + OCSP_SERVICELOC_free + OCSP_SERVICELOC_new + OCSP_SIGNATURE_free + OCSP_SIGNATURE_new + OCSP_SINGLERESP_free + OCSP_SINGLERESP_new + OPENSSL_cleanse + OPENSSL_isservice + OTHERNAME_free + OTHERNAME_new + OpenSSLDie + PEM_ASN1_read_bio + PEM_ASN1_write_bio + PEM_bytes_read_bio + PEM_def_callback + PEM_dek_info + PEM_do_header + PEM_get_EVP_CIPHER_INFO + PEM_proc_type + PEM_read_bio + PEM_read_bio_PrivateKey + PEM_read_bio_X509 + PEM_write_bio + PEM_write_bio_X509 + PKCS7_DIGEST_free + PKCS7_DIGEST_new + PKCS7_ENCRYPT_free + PKCS7_ENCRYPT_new + PKCS7_ENC_CONTENT_free + PKCS7_ENC_CONTENT_new + PKCS7_ENVELOPE_free + PKCS7_ENVELOPE_new + PKCS7_ISSUER_AND_SERIAL_digest + PKCS7_ISSUER_AND_SERIAL_free + PKCS7_ISSUER_AND_SERIAL_new + PKCS7_RECIP_INFO_free + PKCS7_RECIP_INFO_new + PKCS7_SIGNED_free + PKCS7_SIGNED_new + PKCS7_SIGNER_INFO_free + PKCS7_SIGNER_INFO_new + PKCS7_SIGN_ENVELOPE_free + PKCS7_SIGN_ENVELOPE_new + PKCS7_dup + PKCS7_free + PKCS7_new + PKCS8_PRIV_KEY_INFO_free + PKCS8_PRIV_KEY_INFO_new + PKCS8_set_broken + PKEY_USAGE_PERIOD_free + PKEY_USAGE_PERIOD_new + POLICYINFO_free + POLICYINFO_new + POLICYQUALINFO_free + POLICYQUALINFO_new + POLICY_CONSTRAINTS_free + POLICY_CONSTRAINTS_new + POLICY_MAPPING_free + POLICY_MAPPING_new + PROXY_CERT_INFO_EXTENSION_free + PROXY_CERT_INFO_EXTENSION_new + PROXY_POLICY_free + PROXY_POLICY_new + RAND_SSLeay + RAND_add + RAND_bytes + RAND_cleanup + RAND_egd + RAND_egd_bytes + RAND_event + RAND_get_rand_method + RAND_poll + RAND_pseudo_bytes + RAND_query_egd_bytes + RAND_screen + RAND_seed + RAND_set_rand_method + RAND_status + RC4 + RC4_options + RC4_set_key + RSAPrivateKey_asn1_meth + RSAPrivateKey_dup + RSAPublicKey_dup + RSA_blinding_off + RSA_blinding_on + RSA_flags + RSA_free + RSA_generate_key + RSA_generate_key_ex + RSA_get_default_method + RSA_get_ex_data + RSA_get_ex_new_index + RSA_get_method + RSA_memory_lock + RSA_new + RSA_new_method + RSA_null_method + RSA_print + RSA_print_fp + RSA_private_decrypt + RSA_private_encrypt + RSA_public_decrypt + RSA_public_encrypt + RSA_set_default_method + RSA_set_ex_data + RSA_set_method + RSA_setup_blinding + RSA_sign + RSA_size + RSA_up_ref + RSA_verify + SHA1_Final + SHA1_Init + SHA1_Transform + SHA1_Update + SHA224 + SHA224_Final + SHA224_Init + SHA224_Update + SHA256 + SHA256_Final + SHA256_Init + SHA256_Transform + SHA256_Update + SHA384 + SHA384_Final + SHA384_Init + SHA384_Update + SHA512 + SHA512_Final + SHA512_Init + SHA512_Transform + SHA512_Update + SSLeay + SSLeay_version + SXNETID_free + SXNETID_new + SXNET_add_id_INTEGER + SXNET_add_id_asc + SXNET_add_id_ulong + SXNET_free + SXNET_get_id_INTEGER + SXNET_get_id_asc + SXNET_get_id_ulong + SXNET_new + UI_OpenSSL + UI_add_error_string + UI_add_info_string + UI_add_input_boolean + UI_add_input_string + UI_add_user_data + UI_add_verify_string + UI_construct_prompt + UI_create_method + UI_ctrl + UI_destroy_method + UI_dup_error_string + UI_dup_info_string + UI_dup_input_boolean + UI_dup_input_string + UI_dup_verify_string + UI_free + UI_get0_action_string + UI_get0_output_string + UI_get0_result + UI_get0_result_string + UI_get0_test_string + UI_get0_user_data + UI_get_default_method + UI_get_ex_data + UI_get_ex_new_index + UI_get_input_flags + UI_get_method + UI_get_result_maxsize + UI_get_result_minsize + UI_get_string_type + UI_method_get_closer + UI_method_get_flusher + UI_method_get_opener + UI_method_get_reader + UI_method_get_writer + UI_method_set_closer + UI_method_set_flusher + UI_method_set_opener + UI_method_set_reader + UI_method_set_writer + UI_new + UI_new_method + UI_process + UI_set_default_method + UI_set_ex_data + UI_set_method + UI_set_result + USERNOTICE_free + USERNOTICE_new + UTF8_getc + UTF8_putc + X509V3_EXT_CRL_add_conf + X509V3_EXT_CRL_add_nconf + X509V3_EXT_REQ_add_conf + X509V3_EXT_REQ_add_nconf + X509V3_EXT_add + X509V3_EXT_add_alias + X509V3_EXT_add_conf + X509V3_EXT_add_list + X509V3_EXT_add_nconf + X509V3_EXT_add_nconf_sk + X509V3_EXT_cleanup + X509V3_EXT_conf + X509V3_EXT_conf_nid + X509V3_EXT_d2i + X509V3_EXT_get + X509V3_EXT_get_nid + X509V3_EXT_i2d + X509V3_EXT_nconf + X509V3_EXT_nconf_nid + X509V3_EXT_print + X509V3_EXT_print_fp + X509V3_EXT_val_prn + X509V3_NAME_from_section + X509V3_add1_i2d + X509V3_add_standard_extensions + X509V3_add_value + X509V3_add_value_bool + X509V3_add_value_bool_nf + X509V3_add_value_int + X509V3_add_value_uchar + X509V3_conf_free + X509V3_extensions_print + X509V3_get_d2i + X509V3_get_section + X509V3_get_string + X509V3_get_value_bool + X509V3_get_value_int + X509V3_parse_list + X509V3_section_free + X509V3_set_conf_lhash + X509V3_set_ctx + X509V3_set_nconf + X509V3_string_free + X509_ALGOR_dup + X509_ALGOR_free + X509_ALGOR_get0 + X509_ALGOR_new + X509_ALGOR_set0 + X509_ATTRIBUTE_count + X509_ATTRIBUTE_create + X509_ATTRIBUTE_create_by_NID + X509_ATTRIBUTE_create_by_OBJ + X509_ATTRIBUTE_create_by_txt + X509_ATTRIBUTE_dup + X509_ATTRIBUTE_free + X509_ATTRIBUTE_get0_data + X509_ATTRIBUTE_get0_object + X509_ATTRIBUTE_get0_type + X509_ATTRIBUTE_new + X509_ATTRIBUTE_set1_data + X509_ATTRIBUTE_set1_object + X509_CERT_AUX_free + X509_CERT_AUX_new + X509_CERT_AUX_print + X509_CERT_PAIR_free + X509_CERT_PAIR_new + X509_CINF_free + X509_CINF_new + X509_CRL_INFO_free + X509_CRL_INFO_new + X509_CRL_add0_revoked + X509_CRL_add1_ext_i2d + X509_CRL_add_ext + X509_CRL_cmp + X509_CRL_delete_ext + X509_CRL_digest + X509_CRL_dup + X509_CRL_free + X509_CRL_get_ext + X509_CRL_get_ext_by_NID + X509_CRL_get_ext_by_OBJ + X509_CRL_get_ext_by_critical + X509_CRL_get_ext_count + X509_CRL_get_ext_d2i + X509_CRL_new + X509_CRL_sign + X509_CRL_verify + X509_EXTENSION_create_by_NID + X509_EXTENSION_create_by_OBJ + X509_EXTENSION_dup + X509_EXTENSION_free + X509_EXTENSION_get_critical + X509_EXTENSION_get_data + X509_EXTENSION_get_object + X509_EXTENSION_new + X509_EXTENSION_set_critical + X509_EXTENSION_set_data + X509_EXTENSION_set_object + X509_NAME_ENTRY_create_by_NID + X509_NAME_ENTRY_create_by_OBJ + X509_NAME_ENTRY_create_by_txt + X509_NAME_ENTRY_dup + X509_NAME_ENTRY_free + X509_NAME_ENTRY_get_data + X509_NAME_ENTRY_get_object + X509_NAME_ENTRY_new + X509_NAME_ENTRY_set_data + X509_NAME_ENTRY_set_object + X509_NAME_add_entry + X509_NAME_add_entry_by_NID + X509_NAME_add_entry_by_OBJ + X509_NAME_add_entry_by_txt + X509_NAME_cmp + X509_NAME_delete_entry + X509_NAME_digest + X509_NAME_dup + X509_NAME_entry_count + X509_NAME_free + X509_NAME_get_entry + X509_NAME_get_index_by_NID + X509_NAME_get_index_by_OBJ + X509_NAME_get_text_by_NID + X509_NAME_get_text_by_OBJ + X509_NAME_hash + X509_NAME_new + X509_NAME_oneline + X509_NAME_print + X509_NAME_print_ex + X509_NAME_print_ex_fp + X509_NAME_set + X509_POLICY_NODE_print + X509_PUBKEY_free + X509_PUBKEY_get + X509_PUBKEY_new + X509_PUBKEY_set + X509_PURPOSE_add + X509_PURPOSE_cleanup + X509_PURPOSE_get0 + X509_PURPOSE_get0_name + X509_PURPOSE_get0_sname + X509_PURPOSE_get_by_id + X509_PURPOSE_get_by_sname + X509_PURPOSE_get_count + X509_PURPOSE_get_id + X509_PURPOSE_get_trust + X509_PURPOSE_set + X509_REQ_INFO_free + X509_REQ_INFO_new + X509_REQ_add1_attr + X509_REQ_add1_attr_by_NID + X509_REQ_add1_attr_by_OBJ + X509_REQ_add1_attr_by_txt + X509_REQ_add_extensions + X509_REQ_add_extensions_nid + X509_REQ_check_private_key + X509_REQ_delete_attr + X509_REQ_digest + X509_REQ_dup + X509_REQ_extension_nid + X509_REQ_free + X509_REQ_get1_email + X509_REQ_get_attr + X509_REQ_get_attr_by_NID + X509_REQ_get_attr_by_OBJ + X509_REQ_get_attr_count + X509_REQ_get_extension_nids + X509_REQ_get_extensions + X509_REQ_get_pubkey + X509_REQ_new + X509_REQ_set_extension_nids + X509_REQ_set_pubkey + X509_REQ_set_subject_name + X509_REQ_set_version + X509_REQ_sign + X509_REQ_verify + X509_REVOKED_add1_ext_i2d + X509_REVOKED_add_ext + X509_REVOKED_delete_ext + X509_REVOKED_free + X509_REVOKED_get_ext + X509_REVOKED_get_ext_by_NID + X509_REVOKED_get_ext_by_OBJ + X509_REVOKED_get_ext_by_critical + X509_REVOKED_get_ext_count + X509_REVOKED_get_ext_d2i + X509_REVOKED_new + X509_SIG_free + X509_SIG_new + X509_VAL_free + X509_VAL_new + X509_add1_ext_i2d + X509_add1_reject_object + X509_add1_trust_object + X509_add_ext + X509_alias_get0 + X509_alias_set1 + X509_asn1_meth + X509_check_ca + X509_check_issued + X509_check_private_key + X509_check_purpose + X509_cmp + X509_delete_ext + X509_digest + X509_dup + X509_email_free + X509_find_by_issuer_and_serial + X509_find_by_subject + X509_free + X509_get0_pubkey_bitstr + X509_get1_email + X509_get1_ocsp + X509_get_ex_data + X509_get_ex_new_index + X509_get_ext + X509_get_ext_by_NID + X509_get_ext_by_OBJ + X509_get_ext_by_critical + X509_get_ext_count + X509_get_ext_d2i + X509_get_issuer_name + X509_get_pubkey + X509_get_serialNumber + X509_get_subject_name + X509_issuer_and_serial_cmp + X509_issuer_and_serial_hash + X509_issuer_name_cmp + X509_issuer_name_hash + X509_keyid_get0 + X509_keyid_set1 + X509_new + X509_ocspid_print + X509_print + X509_print_ex + X509_print_ex_fp + X509_print_fp + X509_pubkey_digest + X509_reject_clear + X509_set_ex_data + X509_sign + X509_signature_print + X509_subject_name_cmp + X509_subject_name_hash + X509_supported_extension + X509_to_X509_REQ + X509_trust_clear + X509_verify + X509at_add1_attr + X509at_add1_attr_by_NID + X509at_add1_attr_by_OBJ + X509at_add1_attr_by_txt + X509at_delete_attr + X509at_get0_data_by_OBJ + X509at_get_attr + X509at_get_attr_by_NID + X509at_get_attr_by_OBJ + X509at_get_attr_count + X509v3_add_ext + X509v3_delete_ext + X509v3_get_ext + X509v3_get_ext_by_NID + X509v3_get_ext_by_OBJ + X509v3_get_ext_by_critical + X509v3_get_ext_count + _CONF_get_section + _CONF_get_string + a2d_ASN1_OBJECT + a2i_ASN1_INTEGER + a2i_ASN1_STRING + a2i_IPADDRESS + a2i_IPADDRESS_NC + a2i_ipadd + asn1_Finish + asn1_GetSequence + asn1_add_error + asn1_const_Finish + asn1_do_adb + asn1_do_lock + asn1_enc_free + asn1_enc_init + asn1_enc_restore + asn1_enc_save + asn1_ex_c2i + asn1_ex_i2c + asn1_get_choice_selector + asn1_get_field_ptr + asn1_set_choice_selector + bn_add_words + bn_div_words + bn_dup_expand + bn_expand2 + bn_mul_add_words + bn_mul_words + bn_sqr_words + bn_sub_words + c2i_ASN1_BIT_STRING + c2i_ASN1_INTEGER + c2i_ASN1_OBJECT + d2i_ACCESS_DESCRIPTION + d2i_ASN1_BIT_STRING + d2i_ASN1_BMPSTRING + d2i_ASN1_BOOLEAN + d2i_ASN1_ENUMERATED + d2i_ASN1_GENERALIZEDTIME + d2i_ASN1_GENERALSTRING + d2i_ASN1_IA5STRING + d2i_ASN1_INTEGER + d2i_ASN1_NULL + d2i_ASN1_OBJECT + d2i_ASN1_OCTET_STRING + d2i_ASN1_PRINTABLE + d2i_ASN1_PRINTABLESTRING + d2i_ASN1_SET + d2i_ASN1_T61STRING + d2i_ASN1_TIME + d2i_ASN1_TYPE + d2i_ASN1_UINTEGER + d2i_ASN1_UNIVERSALSTRING + d2i_ASN1_UTCTIME + d2i_ASN1_UTF8STRING + d2i_ASN1_VISIBLESTRING + d2i_ASN1_bytes + d2i_ASN1_type_bytes + d2i_AUTHORITY_INFO_ACCESS + d2i_AUTHORITY_KEYID + d2i_AutoPrivateKey + d2i_BASIC_CONSTRAINTS + d2i_CERTIFICATEPOLICIES + d2i_CRL_DIST_POINTS + d2i_DIRECTORYSTRING + d2i_DISPLAYTEXT + d2i_DIST_POINT + d2i_DIST_POINT_NAME + d2i_ECDSA_SIG + d2i_ECPKParameters + d2i_ECParameters + d2i_ECPrivateKey + d2i_ECPrivateKey_bio + d2i_EC_PUBKEY + d2i_EC_PUBKEY_bio + d2i_EDIPARTYNAME + d2i_EXTENDED_KEY_USAGE + d2i_GENERAL_NAME + d2i_GENERAL_NAMES + d2i_NETSCAPE_SPKAC + d2i_NETSCAPE_SPKI + d2i_NOTICEREF + d2i_OCSP_BASICRESP + d2i_OCSP_CERTID + d2i_OCSP_CERTSTATUS + d2i_OCSP_CRLID + d2i_OCSP_ONEREQ + d2i_OCSP_REQINFO + d2i_OCSP_REQUEST + d2i_OCSP_RESPBYTES + d2i_OCSP_RESPDATA + d2i_OCSP_RESPID + d2i_OCSP_RESPONSE + d2i_OCSP_REVOKEDINFO + d2i_OCSP_SERVICELOC + d2i_OCSP_SIGNATURE + d2i_OCSP_SINGLERESP + d2i_OTHERNAME + d2i_PKCS7 + d2i_PKCS7_DIGEST + d2i_PKCS7_ENCRYPT + d2i_PKCS7_ENC_CONTENT + d2i_PKCS7_ENVELOPE + d2i_PKCS7_ISSUER_AND_SERIAL + d2i_PKCS7_RECIP_INFO + d2i_PKCS7_SIGNED + d2i_PKCS7_SIGNER_INFO + d2i_PKCS7_SIGN_ENVELOPE + d2i_PKCS7_bio + d2i_PKCS8_PRIV_KEY_INFO + d2i_PKCS8_PRIV_KEY_INFO_bio + d2i_PKCS8_bio + d2i_PKEY_USAGE_PERIOD + d2i_POLICYINFO + d2i_POLICYQUALINFO + d2i_PROXY_CERT_INFO_EXTENSION + d2i_PROXY_POLICY + d2i_PUBKEY + d2i_PUBKEY_bio + d2i_PrivateKey + d2i_PrivateKey_bio + d2i_PublicKey + d2i_RSAPrivateKey + d2i_RSAPrivateKey_bio + d2i_RSAPublicKey + d2i_RSAPublicKey_bio + d2i_RSA_PUBKEY + d2i_RSA_PUBKEY_bio + d2i_SXNET + d2i_SXNETID + d2i_USERNOTICE + d2i_X509 + d2i_X509_ALGOR + d2i_X509_ALGORS + d2i_X509_ATTRIBUTE + d2i_X509_AUX + d2i_X509_CERT_AUX + d2i_X509_CERT_PAIR + d2i_X509_CINF + d2i_X509_CRL + d2i_X509_CRL_INFO + d2i_X509_CRL_bio + d2i_X509_EXTENSION + d2i_X509_EXTENSIONS + d2i_X509_NAME + d2i_X509_NAME_ENTRY + d2i_X509_PUBKEY + d2i_X509_REQ + d2i_X509_REQ_INFO + d2i_X509_REQ_bio + d2i_X509_REVOKED + d2i_X509_SIG + d2i_X509_VAL + d2i_X509_bio + hex_to_string + i2a_ACCESS_DESCRIPTION + i2a_ASN1_INTEGER + i2a_ASN1_OBJECT + i2a_ASN1_STRING + i2c_ASN1_BIT_STRING + i2c_ASN1_INTEGER + i2d_ACCESS_DESCRIPTION + i2d_ASN1_BIT_STRING + i2d_ASN1_BMPSTRING + i2d_ASN1_BOOLEAN + i2d_ASN1_ENUMERATED + i2d_ASN1_GENERALIZEDTIME + i2d_ASN1_GENERALSTRING + i2d_ASN1_IA5STRING + i2d_ASN1_INTEGER + i2d_ASN1_NULL + i2d_ASN1_OBJECT + i2d_ASN1_OCTET_STRING + i2d_ASN1_PRINTABLE + i2d_ASN1_PRINTABLESTRING + i2d_ASN1_SET + i2d_ASN1_T61STRING + i2d_ASN1_TIME + i2d_ASN1_TYPE + i2d_ASN1_UNIVERSALSTRING + i2d_ASN1_UTCTIME + i2d_ASN1_UTF8STRING + i2d_ASN1_VISIBLESTRING + i2d_ASN1_bytes + i2d_AUTHORITY_INFO_ACCESS + i2d_AUTHORITY_KEYID + i2d_BASIC_CONSTRAINTS + i2d_CERTIFICATEPOLICIES + i2d_CRL_DIST_POINTS + i2d_DIRECTORYSTRING + i2d_DISPLAYTEXT + i2d_DIST_POINT + i2d_DIST_POINT_NAME + i2d_ECDSA_SIG + i2d_ECPKParameters + i2d_ECParameters + i2d_ECPrivateKey + i2d_ECPrivateKey_bio + i2d_EC_PUBKEY + i2d_EC_PUBKEY_bio + i2d_EDIPARTYNAME + i2d_EXTENDED_KEY_USAGE + i2d_GENERAL_NAME + i2d_GENERAL_NAMES + i2d_NETSCAPE_SPKAC + i2d_NETSCAPE_SPKI + i2d_NOTICEREF + i2d_OCSP_BASICRESP + i2d_OCSP_CERTID + i2d_OCSP_CERTSTATUS + i2d_OCSP_CRLID + i2d_OCSP_ONEREQ + i2d_OCSP_REQINFO + i2d_OCSP_REQUEST + i2d_OCSP_RESPBYTES + i2d_OCSP_RESPDATA + i2d_OCSP_RESPID + i2d_OCSP_RESPONSE + i2d_OCSP_REVOKEDINFO + i2d_OCSP_SERVICELOC + i2d_OCSP_SIGNATURE + i2d_OCSP_SINGLERESP + i2d_OTHERNAME + i2d_PKCS7 + i2d_PKCS7_DIGEST + i2d_PKCS7_ENCRYPT + i2d_PKCS7_ENC_CONTENT + i2d_PKCS7_ENVELOPE + i2d_PKCS7_ISSUER_AND_SERIAL + i2d_PKCS7_NDEF + i2d_PKCS7_RECIP_INFO + i2d_PKCS7_SIGNED + i2d_PKCS7_SIGNER_INFO + i2d_PKCS7_SIGN_ENVELOPE + i2d_PKCS7_bio + i2d_PKCS8PrivateKeyInfo_bio + i2d_PKCS8_PRIV_KEY_INFO + i2d_PKCS8_PRIV_KEY_INFO_bio + i2d_PKCS8_bio + i2d_PKEY_USAGE_PERIOD + i2d_POLICYINFO + i2d_POLICYQUALINFO + i2d_PROXY_CERT_INFO_EXTENSION + i2d_PROXY_POLICY + i2d_PUBKEY + i2d_PUBKEY_bio + i2d_PrivateKey + i2d_PrivateKey_bio + i2d_PublicKey + i2d_RSAPrivateKey + i2d_RSAPrivateKey_bio + i2d_RSAPublicKey + i2d_RSAPublicKey_bio + i2d_RSA_PUBKEY + i2d_RSA_PUBKEY_bio + i2d_SXNET + i2d_SXNETID + i2d_USERNOTICE + i2d_X509 + i2d_X509_ALGOR + i2d_X509_ALGORS + i2d_X509_ATTRIBUTE + i2d_X509_AUX + i2d_X509_CERT_AUX + i2d_X509_CERT_PAIR + i2d_X509_CINF + i2d_X509_CRL + i2d_X509_CRL_INFO + i2d_X509_CRL_bio + i2d_X509_EXTENSION + i2d_X509_EXTENSIONS + i2d_X509_NAME + i2d_X509_NAME_ENTRY + i2d_X509_PUBKEY + i2d_X509_REQ + i2d_X509_REQ_INFO + i2d_X509_REQ_bio + i2d_X509_REVOKED + i2d_X509_SIG + i2d_X509_VAL + i2d_X509_bio + i2o_ECPublicKey + i2s_ASN1_ENUMERATED + i2s_ASN1_ENUMERATED_TABLE + i2s_ASN1_INTEGER + i2s_ASN1_OCTET_STRING + i2t_ASN1_OBJECT + i2v_ASN1_BIT_STRING + i2v_GENERAL_NAME + i2v_GENERAL_NAMES + lh_delete + lh_doall + lh_doall_arg + lh_free + lh_insert + lh_new + lh_num_items + lh_retrieve + lh_strhash + name_cmp + o2i_ECPublicKey + s2i_ASN1_INTEGER + s2i_ASN1_OCTET_STRING + sk_delete + sk_delete_ptr + sk_dup + sk_find + sk_find_ex + sk_free + sk_insert + sk_is_sorted + sk_new + sk_new_null + sk_num + sk_pop + sk_pop_free + sk_push + sk_set + sk_set_cmp_func + sk_shift + sk_sort + sk_unshift + sk_value + sk_zero + string_to_hex + v2i_ASN1_BIT_STRING + v2i_GENERAL_NAME + v2i_GENERAL_NAMES + v2i_GENERAL_NAME_ex diff --git a/src/VBox/Runtime/r3/win/VBoxRT-openssl.def b/src/VBox/Runtime/r3/win/VBoxRT-openssl.def new file mode 100644 index 000000000..f6c2a8960 --- /dev/null +++ b/src/VBox/Runtime/r3/win/VBoxRT-openssl.def @@ -0,0 +1,1788 @@ +; $Id: VBoxRT-openssl.def 19554 2009-05-08 22:10:24Z vboxsync $ +;; @file +; IPRT - Windows OpenSSL exports. +; +; This file is appended to the architecture specific .def file. +; +; E:\coding\vbox\svn\trunk\tools\win.x86\vcc\v8sp1\bin\x86_amd64\dumpbin.exe \coding\vbox\svn\trunk\out\win.amd64\debug\lib\VBox-libcrypto.lib /symbols /OUT:foo.lst +; grep " External " foo.lst | grep -v " UNDEF " | grep -v " ??_" | grep -v " notype " | sort | cut -d "|" -f 2 +; + +; +; Copyright (C) 2009 Sun Microsystems, Inc. +; +; This file is part of VirtualBox Open Source Edition (OSE), as +; available from http://www.virtualbox.org. This file is free software; +; 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. +; +; 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. +; + + ; + ; OpenSSL symbols + ; + _CONF_get_section + ASN1_BIT_STRING_set + ASN1_d2i_fp + ASN1_digest + ASN1_dup + ASN1_ENUMERATED_set + asn1_get_choice_selector + ASN1_i2d_fp + ASN1_INTEGER_dup + ASN1_item_free + ASN1_item_ndef_i2d + ASN1_item_new + ASN1_mbstring_copy + ASN1_OCTET_STRING_dup + ASN1_PRINTABLE_type + ASN1_seq_unpack + ASN1_sign + ASN1_TYPE_get + ASN1_TYPE_set_octetstring + ASN1_verify + BIO_dump_cb + BIO_new + BN_add + BN_BLINDING_new + BN_CTX_init + BN_div + BN_exp + BN_gcd + BN_lshift1 + BN_mod_mul_montgomery + BN_mod_sqrt + BN_mod_word + bn_mul_add_words + BN_nnmod + BN_rand + BN_RECP_CTX_init + BN_sqr + bn_sub_part_words + BUF_MEM_new + BUF_strdup + d2i_ASN1_type_bytes + d2i_PrivateKey + d2i_PublicKey + DH_check + ec_GF2m_simple_mul + EC_GROUP_new_curve_GFp + EC_KEY_new + ec_wNAF_mul + ECDSA_do_sign + EVP_add_cipher + EVP_CIPHER_CTX_init + EVP_CIPHER_param_to_asn1 + EVP_MD_CTX_init + EVP_PBE_CipherInit + EVP_PKCS82PKEY + EVP_PKEY_bits + EVP_set_pw_prompt + EVP_SignFinal + EVP_VerifyFinal + HMAC_Init_ex + i2d_ASN1_BOOLEAN + i2d_ASN1_OBJECT + i2d_ASN1_SET + i2d_PrivateKey + i2d_PublicKey + OBJ_dup + OPENSSL_gmtime + PEM_ASN1_read_bio + PEM_read_bio_PrivateKey + PEM_read_bio_X509 + policy_cache_free + policy_cache_set_mapping + policy_data_free + RAND_query_egd_bytes + RC4 + RSA_generate_key + RSA_generate_key_ex + RSA_public_encrypt + RSA_sign + SSLeay_version + UTF8_getc + X509_CERT_AUX_print + X509_CRL_get_ext_count + X509_issuer_and_serial_cmp + X509_NAME_get_text_by_NID + X509_REQ_set_version + X509_verify + X509at_get_attr_count + X509V3_EXT_val_prn + X509v3_get_ext_count + ASN1_check_infinite_end + ASN1_tag2bit + BN_bn2hex + BN_GENCB_call + BN_GF2m_add + BN_kronecker + EC_GFp_simple_method + EC_GROUP_new + EVP_CIPHER_CTX_new + lh_new + MD5_Update + OPENSSL_cleanse + RAND_poll + RAND_set_rand_method + RC4_options + SHA1_Update + sk_set_cmp_func + UI_new + X509_NAME_oneline + X509V3_add_value + ASN1_GENERALIZEDTIME_check + ASN1_UTCTIME_check + EVP_EncodeInit + i2s_ASN1_OCTET_STRING + i2v_GENERAL_NAMES + PEM_def_callback + SHA224_Init + SHA384_Init + X509_to_X509_REQ + X509V3_EXT_nconf + EC_GF2m_simple_method + BIO_new_file + CONF_set_nconf + d2i_ASN1_TIME + DH_generate_key + DH_set_default_method + EC_POINT_point2bn + ECDSA_OpenSSL + ECDSA_set_default_method + i2a_ASN1_INTEGER + i2a_ASN1_STRING + OBJ_NAME_init + RSA_new + RSA_null_method + UI_OpenSSL + ASN1_STRING_set_default_mask + X509_NAME_print_ex + CRYPTO_get_ex_data_implementation + CRYPTO_mem_ctrl + d2i_EXTENDED_KEY_USAGE + d2i_ECDSA_SIG + d2i_X509_VAL + RSA_print_fp + d2i_PKEY_USAGE_PERIOD + d2i_X509_SIG + NCONF_default + POLICY_CONSTRAINTS_new + RAND_SSLeay + d2i_BASIC_CONSTRAINTS + RAND_egd + ASN1_TYPE_set + ASN1_item_ex_free + asn1_set_choice_selector + ASN1_item_i2d + BIO_dump_indent_cb + ECDSA_do_sign_ex + ASN1_mbstring_ncopy + BN_CTX_new + RSA_private_encrypt + EVP_CIPHER_asn1_to_param + BN_div_word + ASN1_UNIVERSALSTRING_to_string + UTF8_putc + ASN1_INTEGER_cmp + ASN1_OCTET_STRING_cmp + X509_CRL_get_ext_by_NID + X509at_get_attr_by_NID + EVP_CipherInit_ex + EVP_MD_CTX_create + i2c_ASN1_BIT_STRING + X509v3_get_ext_by_NID + X509_REQ_set_subject_name + BN_RECP_CTX_new + X509_NAME_get_text_by_OBJ + X509_issuer_and_serial_hash + BN_uadd + BN_rshift1 + bn_add_part_words + BN_set_params + X509_REQ_verify + d2i_AUTHORITY_KEYID + ec_GFp_simple_group_init + RAND_get_rand_method + ASN1_item_d2i + UI_new_method + sk_dup + policy_cache_set + ASN1_TYPE_get_octetstring + EVP_add_digest + BN_mod_add + BN_generate_prime_ex + BUF_strndup + d2i_X509_ATTRIBUTE + POLICY_MAPPING_new + RAND_egd_bytes + EVP_EncodeUpdate + EVP_get_pw_prompt + policy_data_new + SHA256_Init + asn1_do_lock + RSA_private_decrypt + SHA512_Init + EVP_CIPHER_get_asn1_iv + BN_GF2m_mod_arr + stub_VBOX_BIO_printf + s2i_ASN1_OCTET_STRING + PEM_write_bio_X509 + PEM_proc_type + BUF_MEM_free + ASN1_d2i_bio + ASN1_i2d_bio + ASN1_TYPE_set1 + EC_KEY_new_by_curve_name + ECDSA_sign + MD5_Transform + SHA1_Transform + ASN1_UTCTIME_set_string + ASN1_GENERALIZEDTIME_set_string + BN_get0_nist_prime_192 + ec_GF2m_simple_group_init + DH_get_default_method + ECDSA_get_default_method + RSA_set_default_method + DH_compute_key + ASN1_item_ex_new + ASN1_OCTET_STRING_set + X509_CRL_get_ext_by_OBJ + BIO_set + X509at_get_attr_by_OBJ + X509v3_get_ext_by_OBJ + ASN1_const_check_infinite_end + X509_REQ_set_pubkey + EVP_PKEY_size + i2c_ASN1_INTEGER + BN_from_montgomery + X509_NAME_entry_count + c2i_ASN1_BIT_STRING + BN_lshift + bn_mul_recursive + d2i_X509_ALGOR + ASN1_STRING_get_default_mask + i2d_ASN1_TIME + CONF_set_default_method + _CONF_get_section_values + i2v_GENERAL_NAME + X509_CRL_verify + BN_mod_add_quick + EC_GROUP_new_curve_GF2m + EVP_get_cipherbyname + d2i_AutoPrivateKey + BN_add_word + BN_usub + EVP_CipherInit + RAND_cleanup + EVP_read_pw_string + OBJ_NAME_new_index + ec_GFp_simple_group_finish + ASN1_seq_pack + d2i_ASN1_BOOLEAN + RSA_public_decrypt + SHA224 + BN_BLINDING_free + SHA512_Final + DH_check_pub_key + d2i_ACCESS_DESCRIPTION + RC4_set_key + EVP_DigestInit + BN_RECP_CTX_free + a2d_ASN1_OBJECT + BN_CTX_free + ASN1_TYPE_set_int_octetstring + ECDSA_sign_ex + BN_bn2dec + MD5_Final + SHA1_Final + BN_GF2m_mod + EC_GFp_mont_method + RSA_get_default_method + DH_OpenSSL + ASN1_get_object + EC_KEY_free + EC_GROUP_free + d2i_PROXY_POLICY + d2i_SXNETID + d2i_X509_EXTENSION + ASN1_STRING_set_default_mask_asc + i2d_EXTENDED_KEY_USAGE + DH_set_method + ECDSA_set_method + ec_GF2m_simple_group_finish + CONF_load + _CONF_add_string + X509_CRL_get_ext_by_critical + BUF_MEM_grow + X509_NAME_get_index_by_NID + BN_mod_exp + lh_free + c2i_ASN1_INTEGER + BN_rshift + ASN1_TIME_new + RAND_seed + ASN1_template_d2i + NETSCAPE_SPKI_verify + EVP_PKEY_save_parameters + X509at_get_attr + BUF_memdup + X509v3_get_ext_by_critical + asn1_enc_init + RSA_size + EVP_get_digestbyname + BIO_free + OBJ_cmp + BN_sub + bn_mul_words + EC_GFp_nist_method + EVP_CipherUpdate + EVP_md5 + EVP_DigestInit_ex + ASN1_item_digest + ec_GFp_simple_group_clear_finish + X509V3_EXT_nconf_nid + ASN1_item_dup + UI_free + EC_POINT_bn2point + sk_new_null + X509V3_add_value_uchar + BN_mod_inverse + BN_sub_word + SHA384_Final + MD5_Init + SHA1_Init + GENERAL_SUBTREE_new + BN_CTX_start + BN_mod_sub + BN_BLINDING_update + d2i_NETSCAPE_SPKAC + NCONF_WIN32 + i2d_ECDSA_SIG + i2d_X509_VAL + RSA_get_method + CRYPTO_set_ex_data_implementation + ecdsa_check + DH_new + BN_RECP_CTX_set + CRYPTO_is_mem_check_on + ECDSA_sign_setup + X509_NAME_get_index_by_OBJ + EC_GROUP_clear_free + lh_insert + BN_mod_exp_recp + bn_sqr_normal + BN_is_prime_ex + BN_MONT_CTX_new + POLICY_CONSTRAINTS_free + d2i_X509_PUBKEY + i2d_PKEY_USAGE_PERIOD + i2d_X509_SIG + EXTENDED_KEY_USAGE_new + ec_GF2m_simple_group_clear_finish + RAND_add + X509_CRL_get_ext + EVP_PKEY_copy_parameters + X509at_delete_attr + ASN1_ENUMERATED_get + EVP_cleanup + X509v3_get_ext + BUF_MEM_grow_clean + EVP_EncodeFinal + i2d_BASIC_CONSTRAINTS + EVP_sha1 + ASN1_TIME_free + EVP_CipherFinal_ex + X509_sign + sk_new + X509V3_conf_free + ASN1_item_ex_i2d + RSA_blinding_off + BUF_strlcpy + BIO_vfree + SHA512_Update + md5_block_data_order + BN_get_params + X509_REQ_get_pubkey + ec_GFp_simple_group_copy + ASN1_item_d2i_bio + EVP_DigestUpdate + BN_CTX_end + BN_mod_sub_quick + EVP_CIPHER_set_asn1_iv + EVP_CIPHER_CTX_cleanup + BN_mul_word + RSA_print + RSA_set_method + DH_new_method + ASN1_item_ex_d2i + _CONF_get_string + CRYPTO_dbg_set_options + asn1_enc_free + ASN1_UTCTIME_set + ASN1_GENERALIZEDTIME_set + ASN1_BIT_STRING_set_bit + BN_is_prime_fasttest_ex + X509V3_EXT_add + d2i_X509_NAME_ENTRY + i2d_AUTHORITY_KEYID + ECDSA_SIG_new + X509_VAL_new + a2i_ASN1_STRING + SHA256 + ASN1_unpack_string + X509v3_delete_ext + BN_to_ASN1_ENUMERATED + EVP_EncodeBlock + BN_BLINDING_convert + ERR_print_errors + POLICY_MAPPING_free + i2d_X509_ATTRIBUTE + PKEY_USAGE_PERIOD_new + X509_SIG_new + i2d_X509_PUBKEY + EXTENDED_KEY_USAGE_free + CONF_load_fp + RAND_bytes + X509_CRL_delete_ext + ec_GF2m_simple_group_copy + EVP_CipherFinal + ASN1_item_i2d_fp + EC_KEY_copy + X509at_add1_attr + X509V3_add_value_bool + BUF_strlcat + X509_NAME_get_entry + BIO_clear_flags + EC_GROUP_copy + RSA_verify + ASN1_template_free + BN_GF2m_mod_mul_arr + d2i_X509_CERT_AUX + BN_get0_nist_prime_224 + BASIC_CONSTRAINTS_new + ASN1_TIME_set + BN_value_one + X509V3_EXT_print + BN_mod_mul_reciprocal + EVP_DigestFinal + X509_REQ_sign + EC_POINT_point2hex + RSA_blinding_on + BN_mod_mul + i2d_ASN1_bytes + BN_CTX_get + d2i_ASN1_SET + SHA384_Update + X509_print_fp + RSA_new_method + X509_REQ_check_private_key + a2i_ASN1_INTEGER + UI_add_input_string + ec_GFp_simple_group_set_curve + ASN1_item_verify + CRYPTO_dbg_get_options + lh_delete + bn_sqr_recursive + BN_MONT_CTX_init + bn_mul_part_recursive + i2d_X509_ALGOR + d2i_PKCS8_PRIV_KEY_INFO + BIO_new_fp + sk_insert + asn1_enc_save + BN_BLINDING_convert_ex + EVP_Cipher + ASN1_put_object + EVP_DecodeInit + d2i_ASN1_UINTEGER + AUTHORITY_KEYID_new + ECDSA_SIG_free + X509_VAL_free + RAND_pseudo_bytes + EVP_EncryptInit + EVP_PKEY_missing_parameters + ASN1_item_i2d_bio + X509v3_add_ext + X509_NAME_delete_entry + BIO_test_flags + ASN1_BIT_STRING_get_bit + bn_sqr_words + ec_GFp_mont_group_init + BN_get0_nist_prime_256 + i2d_ACCESS_DESCRIPTION + X509_ATTRIBUTE_new + PKEY_USAGE_PERIOD_free + X509_SIG_free + X509_PUBKEY_new + BN_num_bits_word + CONF_load_bio + X509_CRL_get_ext_d2i + X509_issuer_name_cmp + EVP_DigestFinal_ex + X509_CRL_sign + EVP_CIPHER_type + HMAC_Init + EC_POINT_hex2point + ASN1_item_sign + BN_hex2bn + SHA512_Transform + BASIC_CONSTRAINTS_free + EVP_BytesToKey + CRYPTO_dbg_push_info + ASN1_pack_string + RSA_setup_blinding + ec_GF2m_simple_group_set_curve + EC_GROUP_dup + i2d_PROXY_POLICY + i2d_SXNETID + i2d_X509_EXTENSION + PEM_dek_info + ASN1_item_d2i_fp + SHA224_Update + X509_REQ_extension_nid + BN_pseudo_rand + sk_delete_ptr + EVP_CIPHER_CTX_ctrl + EVP_DecodeUpdate + BN_MONT_CTX_free + RSAPrivateKey_asn1_meth + ec_GFp_nist_group_copy + ERR_print_errors_cb + X509_ALGOR_new + i2d_PKCS8_PRIV_KEY_INFO + BIO_s_file + RAND_status + EVP_PBE_alg_add + EVP_EncryptInit_ex + EVP_PKEY_cmp_parameters + BIO_set_flags + BN_BLINDING_invert + bn_div_words + BN_get0_nist_prime_384 + CRYPTO_set_mem_functions + AUTHORITY_KEYID_free + X509_subject_name_cmp + BN_num_bits + NETSCAPE_SPKI_sign + OBJ_NAME_get + asn1_enc_restore + HMAC_Update + ASN1_ENUMERATED_to_BN + X509_NAME_add_entry_by_OBJ + lh_retrieve + SHA384 + GENERAL_SUBTREE_free + ec_GFp_mont_group_finish + ACCESS_DESCRIPTION_new + X509_ATTRIBUTE_free + X509_PUBKEY_free + X509_CRL_add1_ext_i2d + X509V3_add_value_bool_nf + DH_free + ASN1_put_eoc + i2d_NETSCAPE_SPKAC + BN_div_recp + SHA224_Final + ASN1_TYPE_get_int_octetstring + BN_mod_sqr + X509_REQ_get_extension_nids + d2i_ASN1_bytes + BN_bntest_rand + sk_delete + EVP_CIPHER_CTX_flags + EC_GROUP_method_of + BN_mod_exp_mont + PROXY_POLICY_new + SXNETID_new + X509_EXTENSION_new + SSLeay + EVP_DecryptInit + X509at_add1_attr_by_OBJ + BIO_get_callback + EC_KEY_dup + BN_BLINDING_invert_ex + BN_get0_nist_prime_521 + ec_GFp_nist_group_set_curve + X509_ALGOR_free + PKCS8_PRIV_KEY_INFO_new + CRYPTO_set_mem_ex_functions + ASN1_TIME_check + CONF_get_section + _CONF_new_data + X509_CRL_cmp + EVP_MD_CTX_copy + EVP_PKEY_cmp + BN_clear_free + d2i_X509_bio + HMAC_Final + asn1_get_field_ptr + ASN1_template_new + ASN1_primitive_free + BN_MONT_CTX_set + ec_GF2m_precompute_mult + bn_add_words + i2s_ASN1_ENUMERATED + RSA_free + ASN1_item_pack + X509_NAME_add_entry_by_NID + ec_GF2m_simple_group_get_curve + BN_dec2bn + bn_mul_low_recursive + NAME_CONSTRAINTS_new + ACCESS_DESCRIPTION_free + X509_ATTRIBUTE_dup + X509_PUBKEY_set + X509_CRL_add_ext + SHA256_Update + X509_REQ_set_extension_nids + BN_mod_lshift1 + BN_rand_range + sk_find + EVP_CIPHER_CTX_iv_length + EC_METHOD_get_field_type + i2t_ASN1_OBJECT + EVP_DecodeBlock + i2d_X509_NAME_ENTRY + NETSCAPE_SPKAC_new + EVP_sha224 + EVP_DecryptInit_ex + BIO_set_callback + X509at_add1_attr_by_NID + DH_up_ref + X509_EXTENSION_create_by_NID + EC_KEY_up_ref + BN_BLINDING_get_thread_id + lh_doall + BN_nist_mod_192 + PROXY_POLICY_free + SXNETID_free + X509_EXTENSION_free + ec_GFp_mont_group_clear_finish + CRYPTO_set_locked_mem_functions + X509_get_issuer_name + EVP_MD_CTX_copy_ex + asn1_do_adb + UI_dup_input_string + policy_cache_find_data + ASN1_UTCTIME_cmp_time_t + ASN1_object_size + bn_sub_words + i2s_ASN1_ENUMERATED_TABLE + X509_check_purpose + X509_print_ex_fp + i2d_X509_CERT_AUX + d2i_X509_ALGORS + ASN1_STRING_set_by_NID + PKCS8_PRIV_KEY_INFO_free + _CONF_free_data + ec_GFp_simple_group_get_curve + X509_NAME_add_entry_by_txt + ASN1_INTEGER_set + ec_GF2m_have_precompute_mult + bn_mul_high + NAME_CONSTRAINTS_free + ASN1_TIME_to_generalizedtime + X509_REQ_get_extensions + i2d_X509_bio + BN_free + EVP_CIPHER_nid + ec_GF2m_simple_group_get_degree + EC_GROUP_set_generator + ASN1_template_i2d + EVP_DecodeFinal + d2i_X509_REQ_INFO + d2i_AUTHORITY_INFO_ACCESS + X509_ATTRIBUTE_create + EVP_sha256 + CONF_get_string + PEM_bytes_read_bio + X509_get_ext_count + EVP_EncryptUpdate + BIO_set_callback_arg + BN_mod_lshift1_quick + X509at_add1_attr_by_txt + OBJ_NAME_add + DH_get_ex_new_index + EVP_PKEY_new + ASN1_item_unpack + EC_KEY_generate_key + BN_BLINDING_set_thread_id + i2a_ASN1_OBJECT + X509_NAME_ENTRY_new + X509V3_EXT_get_nid + NETSCAPE_SPKAC_free + CRYPTO_set_locked_mem_ex_functions + ECDSA_size + X509_issuer_name_hash + EVP_PBE_cleanup + i2s_ASN1_INTEGER + X509V3_extensions_print + CRYPTO_dbg_pop_info + X509_EXTENSION_create_by_OBJ + HMAC_CTX_init + SHA256_Transform + BN_reciprocal + asn1_Finish + bn_mul_comba8 + d2i_X509_CINF + d2i_PROXY_CERT_INFO_EXTENSION + d2i_SXNET + d2i_X509_EXTENSIONS + i2d_X509_ALGORS + RSA_up_ref + BIO_dump_fp + UI_add_verify_string + X509_NAME_add_entry + BN_print + X509_CERT_AUX_new + ec_GFp_mont_group_copy + BN_init + EVP_Digest + ec_GFp_simple_group_get_degree + sk_find_ex + lh_doall_arg + i2d_AUTHORITY_INFO_ACCESS + X509_get_ext_by_NID + BIO_get_callback_arg + d2i_X509_CRL_bio + X509at_get0_data_by_OBJ + EVP_CIPHER_block_size + BN_BLINDING_get_flags + ec_GF2m_simple_group_check_discriminant + EC_GROUP_get0_generator + SHA512 + ec_wNAF_precompute_mult + i2d_X509_REQ_INFO + CRYPTO_set_mem_debug_functions + X509_get_subject_name + BN_mod_lshift + DH_set_ex_data + SHA256_Final + EVP_PKEY2PKCS8 + BN_GF2m_mod_mul + X509_NAME_ENTRY_free + d2i_NETSCAPE_SPKI + i2d_PROXY_CERT_INFO_EXTENSION + i2d_SXNET + i2d_X509_EXTENSIONS + X509_ALGOR_dup + s2i_ASN1_INTEGER + RSA_get_ex_new_index + HMAC_CTX_cleanup + OBJ_NAME_remove + UI_dup_verify_string + BN_pseudo_rand_range + BN_mod_exp_mont_consttime + d2i_RSAPrivateKey + X509_print + ASN1_STRING_TABLE_get + CONF_get_number + X509_EXTENSION_set_object + ec_GFp_simple_group_check_discriminant + sk_push + X509_CERT_AUX_free + AUTHORITY_INFO_ACCESS_new + X509_get_ext_by_OBJ + BIO_method_name + BN_new + EVP_CIPHER_CTX_block_size + EVP_PKEY_assign + X509_ATTRIBUTE_create_by_NID + BN_BLINDING_set_flags + EC_GROUP_get_order + asn1_const_Finish + bn_mul_comba4 + d2i_CERTIFICATEPOLICIES + CRYPTO_set_mem_info_functions + X509_get_serialNumber + i2d_X509_CRL_bio + X509V3_EXT_i2d + EVP_PKEY2PKCS8_broken + EVP_EncryptFinal + ASN1_INTEGER_get + X509_REQ_INFO_new + i2d_NETSCAPE_SPKI + PROXY_CERT_INFO_EXTENSION_new + SXNET_new + X509_EXTENSION_dup + DH_get_ex_data + BIO_dump_indent_fp + UI_add_input_boolean + ASN1_primitive_new + X509_NAME_ENTRY_create_by_txt + BN_GF2m_mod_sqr_arr + X509_NAME_ENTRY_dup + X509_print_ex + X509_ALGOR_set0 + BN_mod_lshift_quick + RSA_set_ex_data + HMAC + sk_unshift + EC_KEY_check_key + BN_mul + i2d_RSAPrivateKey + AUTHORITY_INFO_ACCESS_free + ec_GFp_mont_group_set_curve + X509_get_ext_by_critical + BIO_method_type + EVP_CIPHER_CTX_cipher + EVP_PKEY_set1_RSA + BN_BLINDING_create_param + X509_EXTENSION_set_critical + EC_GROUP_get_cofactor + asn1_GetSequence + BN_MONT_CTX_copy + X509_alias_set1 + ec_GFp_nist_field_mul + CRYPTO_get_mem_functions + X509_subject_name_hash + d2i_PKCS7_bio + EVP_MD_CTX_destroy + X509_ATTRIBUTE_create_by_OBJ + EVP_EncryptFinal_ex + BN_to_ASN1_INTEGER + d2i_OTHERNAME + NETSCAPE_SPKI_new + PROXY_CERT_INFO_EXTENSION_free + SXNET_free + X509_REQ_add_extensions_nid + OBJ_NAME_do_all + BIO_dump + ec_GF2m_simple_point_init + d2i_ASN1_OBJECT + X509_REQ_INFO_free + X509V3_EXT_get + ERR_get_implementation + DH_size + CRYPTO_dbg_remove_all_info + sk_shift + BN_GF2m_mod_sqr + bn_sqr_comba8 + d2i_X509_NAME + CONF_free + X509_get_ext + BIO_read + EVP_CIPHER_flags + RSA_get_ex_data + X509_EXTENSION_set_data + asn1_primitive_clear + EC_GROUP_set_curve_name + ASN1_STRING_dup + BN_MONT_CTX_set_locked + d2i_X509_REVOKED + d2i_RSAPublicKey + X509_cmp + CRYPTO_get_mem_ex_functions + ECDSA_get_ex_new_index + bn_dup_expand + EVP_MD_CTX_cleanup + EVP_PKEY_get1_RSA + ec_GFp_simple_point_init + lh_strhash + X509_PURPOSE_set + NETSCAPE_SPKI_free + i2d_PKCS7_bio + X509V3_add_value_int + ec_GF2m_simple_point_finish + UI_dup_input_boolean + ec_wNAF_have_precompute_mult + i2d_X509_CINF + X509_ALGOR_get0 + ec_GFp_nist_field_sqr + CRYPTO_dbg_malloc + X509_ATTRIBUTE_create_by_txt + sk_pop + d2i_X509_REQ + i2d_X509_NAME + X509V3_EXT_add_list + d2i_DIST_POINT_NAME + EVP_sha384 + ASN1_STRING_TABLE_add + X509_delete_ext + BIO_write + EVP_CIPHER_CTX_get_app_data + BN_nist_mod_224 + X509_NAME_ENTRY_create_by_NID + EC_GROUP_get_curve_name + EC_KEY_get0_group + ASN1_STRING_set + BN_GF2m_mod_inv + i2d_RSAPublicKey + CRYPTO_get_locked_mem_functions + RSA_flags + EVP_PKEY_set1_EC_KEY + HMAC_CTX_set_flags + X509_EXTENSION_get_object + EVP_DecryptUpdate + ec_GFp_simple_point_finish + lh_num_items + ASN1_INTEGER_to_BN + i2d_X509_REVOKED + ECDSA_set_ex_data + d2i_X509_REQ_bio + X509_PUBKEY_get + X509V3_get_value_bool + BIO_dump_indent + ec_GF2m_simple_point_clear_finish + X509_PURPOSE_get_count + X509_keyid_set1 + CONF_dump_fp + X509_NAME_cmp + sk_zero + PKCS8_set_broken + UI_add_info_string + bn_sqr_comba4 + X509_CINF_new + i2d_X509_REQ + X509_NAME_new + X509V3_EXT_add_alias + EVP_sha512 + X509_add_ext + EVP_CIPHER_CTX_set_app_data + BIO_puts + bn_expand2 + EC_GROUP_set_asn1_flag + X509_NAME_ENTRY_create_by_OBJ + EC_KEY_set_group + bn_mul_normal + RSAPublicKey_dup + i2d_DIST_POINT_NAME + ERR_set_implementation + ec_GFp_mont_field_mul + CRYPTO_get_locked_mem_ex_functions + RSA_memory_lock + X509_EXTENSION_get_data + ec_GFp_simple_point_clear_finish + i2d_CERTIFICATEPOLICIES + EVP_PKEY_get1_EC_KEY + ec_GF2m_simple_point_copy + c2i_ASN1_OBJECT + X509_REVOKED_new + CONF_dump_bio + ECDSA_get_ex_data + i2d_X509_REQ_bio + _CONF_new_section + UI_dup_info_string + BN_mod_exp_mont_word + BN_GF2m_mod_inv_arr + X509_PURPOSE_get0 + X509_REQ_new + X509_NAME_free + X509_get_ext_d2i + EVP_CIPHER_iv_length + OBJ_NAME_do_all_sorted + X509_ATTRIBUTE_set1_object + BIO_gets + sk_pop_free + BN_dup + EC_GROUP_get_asn1_flag + EVP_DecryptFinal + X509_CINF_free + X509_alias_get0 + ec_GFp_mont_field_sqr + CRYPTO_get_mem_debug_functions + X509_EXTENSION_get_critical + EC_KEY_get0_private_key + ec_GFp_simple_point_copy + RSAPrivateKey_dup + DIST_POINT_NAME_new + X509V3_EXT_print_fp + EVP_PKEY_set1_DH + ec_GF2m_simple_point_set_to_infinity + X509_NAME_ENTRY_set_object + BN_nist_mod_256 + bn_mul_low_normal + i2d_OTHERNAME + CERTIFICATEPOLICIES_new + d2i_RSAPrivateKey_bio + ASN1_OBJECT_new + UI_add_error_string + X509_REVOKED_free + X509_REQ_free + X509_NAME_dup + X509V3_EXT_cleanup + X509_add1_ext_i2d + EVP_CIPHER_key_length + sk_free + BN_copy + BIO_indent + EC_GROUP_set_point_conversion_form + EVP_DecryptFinal_ex + asn1_ex_i2c + BN_GF2m_mod_div + X509_PURPOSE_get_by_sname + X509_keyid_get0 + ec_GFp_mont_field_encode + CRYPTO_malloc_locked + X509_REQ_add_extensions + X509_ATTRIBUTE_set1_data + EC_KEY_set_private_key + ec_GFp_simple_point_set_to_infinity + ASN1_STRING_set0 + BN_mod_exp_simple + ASN1_STRING_TABLE_cleanup + NCONF_new + DIST_POINT_NAME_free + ECPKParameters_print_fp + EVP_PKEY_get1_DH + ec_GF2m_simple_point_set_affine_coordinates + X509_NAME_ENTRY_set_data + ASN1_OBJECT_free + UI_dup_error_string + OTHERNAME_new + CERTIFICATEPOLICIES_free + X509_REQ_dup + X509_REVOKED_get_ext_count + i2d_RSAPrivateKey_bio + EVP_CIPHER_CTX_key_length + sk_num + EC_GROUP_get_point_conversion_form + BN_swap + EVP_CIPHER_CTX_free + d2i_X509_CRL_INFO + GENERAL_NAME_print + X509_add1_trust_object + ec_GFp_mont_field_decode + X509_REQ_get_attr_count + BN_GF2m_mod_div_arr + X509_PURPOSE_get_by_id + NCONF_free + CRYPTO_free_locked + CRYPTO_dbg_free + EC_KEY_get0_public_key + ec_GFp_simple_set_Jprojective_coordinates_GFp + ASN1_STRING_new + EC_KEY_print_fp + EVP_PKEY_type + BIO_int_ctrl + UI_construct_prompt + ASN1_OBJECT_create + d2i_DIST_POINT + X509_REVOKED_get_ext_by_NID + EVP_CIPHER_CTX_nid + d2i_RSAPublicKey_bio + sk_value + EC_GROUP_set_seed + BN_clear + BN_nist_mod_384 + OTHERNAME_free + d2i_POLICYINFO + i2d_X509_CRL_INFO + X509V3_add_standard_extensions + NCONF_free_data + ec_GFp_mont_field_set_to_one + CRYPTO_malloc + X509_REQ_get_attr_by_NID + EC_KEY_set_public_key + ec_GF2m_simple_point_get_affine_coordinates + EVP_CIPHER_CTX_set_key_length + ASN1_STRING_type_new + BN_GF2m_mod_exp_arr + ASN1_parse + ECPKParameters_print + EVP_PKEY_free + OBJ_NAME_cleanup + d2i_PUBKEY + X509_NAME_hash + ec_GFp_simple_get_Jprojective_coordinates_GFp + SXNET_add_id_asc + i2d_DIST_POINT + X509_add1_reject_object + EVP_MD_block_size + X509_REVOKED_get_ext_by_OBJ + sk_set + EC_GROUP_get0_seed + BN_get_word + d2i_ASN1_INTEGER + i2d_POLICYINFO + X509_CRL_INFO_new + d2i_X509 + X509V3_EXT_d2i + d2i_RSA_PUBKEY_bio + X509_ATTRIBUTE_count + CRYPTO_ex_data_new_class + d2i_EDIPARTYNAME + NCONF_load + X509_NAME_ENTRY_get_object + ASN1_STRING_free + X509_REQ_get_attr_by_OBJ + CRYPTO_realloc + i2d_PUBKEY + EC_KEY_get_enc_flags + EVP_CIPHER_CTX_set_padding + DIST_POINT_new + X509_trust_clear + EVP_MD_type + X509_REVOKED_get_ext_by_critical + sk_sort + EC_GROUP_get_seed_len + CRYPTO_dbg_realloc + BN_set_word + ec_GFp_simple_point_set_affine_coordinates + BN_GF2m_mod_exp + POLICYINFO_new + X509_CRL_INFO_free + i2d_X509 + X509_PURPOSE_add + X509_ATTRIBUTE_get0_object + BIO_ptr_ctrl + ec_GF2m_simple_set_compressed_coordinates + CRYPTO_cleanup_all_ex_data + i2d_EDIPARTYNAME + SXNET_add_id_ulong + NCONF_load_fp + X509_NAME_ENTRY_get_data + EVP_PKEY_get_attr_count + ASN1_STRING_cmp + BN_nist_mod_521 + CRYPTO_realloc_clean + EC_KEY_set_enc_flags + EVP_CIPHER_CTX_rand_key + DIST_POINT_free + EVP_MD_pkey_type + i2d_RSAPublicKey_bio + X509_REVOKED_get_ext + X509_REQ_get_attr + EC_GROUP_set_curve_GFp + BN_bin2bn + POLICYINFO_free + d2i_X509_CRL + X509_new + X509V3_get_d2i + X509_ATTRIBUTE_get0_data + sk_is_sorted + X509_find_by_issuer_and_serial + ec_GF2m_simple_point2oct + CRYPTO_get_ex_new_index + BN_GF2m_mod_sqrt_arr + i2v_ASN1_BIT_STRING + EDIPARTYNAME_new + X509_reject_clear + NCONF_load_bio + d2i_RSA_PUBKEY + ec_GFp_simple_point_get_affine_coordinates + EC_KEY_get_conv_form + CRYPTO_mem_leaks + EVP_PKEY_get_attr_by_NID + asn1_add_error + d2i_CRL_DIST_POINTS + EVP_MD_size + i2d_RSA_PUBKEY_bio + X509_REVOKED_delete_ext + BIO_ctrl + EC_GROUP_get_curve_GFp + BN_bn2bin + d2i_POLICYQUALINFO + i2d_X509_CRL + X509_free + SXNET_add_id_INTEGER + X509_REQ_delete_attr + CRYPTO_free + CRYPTO_new_ex_data + EDIPARTYNAME_free + d2i_X509_CERT_PAIR + NCONF_get_section + X509V3_EXT_add_nconf_sk + X509_ATTRIBUTE_get0_type + asn1_ex_c2i + ASN1_parse_dump + X509V3_add1_i2d + EC_KEY_set_conv_form + BN_GF2m_mod_sqrt + i2d_CRL_DIST_POINTS + EVP_MD_CTX_md + X509_REVOKED_add_ext + EC_GROUP_set_curve_GF2m + BIO_callback_ctrl + EVP_PKEY_get_attr_by_OBJ + BN_ucmp + i2d_POLICYQUALINFO + X509_CRL_new + X509_dup + X509_PURPOSE_cleanup + CRYPTO_remalloc + X509_find_by_subject + CRYPTO_dup_ex_data + ec_GF2m_simple_oct2point + ec_GFp_simple_set_compressed_coordinates + i2d_ASN1_INTEGER + d2i_GENERAL_NAME + i2d_X509_CERT_PAIR + i2a_ACCESS_DESCRIPTION + d2i_EC_PUBKEY_bio + X509_REQ_add1_attr + NCONF_get_string + i2d_RSA_PUBKEY + CRL_DIST_POINTS_new + EVP_MD_CTX_set_flags + X509_REVOKED_get_ext_d2i + EC_KEY_get_key_method_data + EC_GROUP_get_curve_GF2m + BIO_ctrl_pending + BN_cmp + BN_GF2m_mod_solve_quad_arr + POLICYQUALINFO_new + X509_CRL_free + PEM_ASN1_write_bio + X509V3_EXT_add_nconf + X509_get_pubkey + CRYPTO_free_ex_data + EVP_PKEY_get_attr + i2d_GENERAL_NAME + X509_asn1_meth + X509_CERT_PAIR_new + ASN1_INTEGER_new + SXNET_get_id_asc + X509_REQ_add1_attr_by_OBJ + CRL_DIST_POINTS_free + EVP_MD_CTX_clear_flags + i2d_EC_PUBKEY_bio + X509V3_get_value_int + X509_REVOKED_add1_ext_i2d + CRYPTO_set_mem_debug_options + d2i_EC_PUBKEY + EC_GROUP_get_degree + BIO_ctrl_wpending + UI_add_user_data + BN_set_bit + POLICYQUALINFO_free + X509_CRL_dup + X509_PURPOSE_get_id + X509V3_EXT_CRL_add_nconf + EC_KEY_insert_key_method_data + CRYPTO_set_ex_data + GENERAL_NAME_new + X509_get_ex_new_index + X509_CERT_PAIR_free + X509_get0_pubkey_bitstr + EVP_PKEY_delete_attr + SXNET_get_id_ulong + BN_GF2m_mod_solve_quad + v2i_ASN1_BIT_STRING + ASN1_INTEGER_free + EVP_MD_CTX_test_flags + X509V3_parse_list + X509_REQ_add1_attr_by_NID + CRYPTO_get_mem_debug_options + EC_GROUP_check_discriminant + BIO_push + UI_get0_user_data + BN_clear_bit + ec_GF2m_simple_add + d2i_USERNOTICE + X509_PURPOSE_get0_name + d2i_ECPrivateKey_bio + X509V3_EXT_REQ_add_nconf + CRYPTO_get_ex_data + EC_GROUP_get_basis_type + GENERAL_NAME_free + EC_KEY_set_asn1_flag + X509_check_private_key + X509_set_ex_data + SXNET_get_id_INTEGER + NCONF_get_number_e + EVP_PKEY_add1_attr + ec_GFp_simple_point2oct + EVP_CIPHER_CTX_set_flags + CRYPTO_push_info_ + EC_GROUP_cmp + BIO_pop + UI_get0_result + BN_is_bit_set + BN_GF2m_poly2arr + d2i_ASN1_ENUMERATED + i2d_USERNOTICE + X509_PURPOSE_get0_sname + X509_REQ_add1_attr_by_txt + i2d_EC_PUBKEY + d2i_GENERAL_NAMES + X509_CRL_add0_revoked + i2d_ECPrivateKey_bio + NCONF_dump_fp + EC_KEY_precompute_mult + ec_GF2m_simple_dbl + X509_get_ex_data + EVP_CIPHER_CTX_clear_flags + CRYPTO_pop_info + BIO_get_retry_BIO + EVP_PKEY_add1_attr_by_OBJ + ASN1_STRING_length + BN_mask_bits + BN_GF2m_arr2poly + i2d_ASN1_ENUMERATED + USERNOTICE_new + X509_PURPOSE_get_trust + X509V3_get_string + i2d_GENERAL_NAMES + UI_process + ec_GFp_simple_oct2point + X509_pubkey_digest + NCONF_dump_bio + ec_GF2m_simple_invert + EVP_CIPHER_CTX_test_flags + CRYPTO_remove_all_info + BIO_get_retry_reason + ASN1_STRING_length_set + BN_set_negative + ASN1_ENUMERATED_new + USERNOTICE_free + d2i_X509_AUX + X509_supported_extension + X509_NAME_set + X509V3_get_section + EVP_PKEY_add1_attr_by_NID + GENERAL_NAMES_new + EC_EX_DATA_set_data + ASN1_generate_nconf + hex_to_string + BIO_find_type + ASN1_STRING_type + bn_cmp_words + ec_GF2m_simple_is_at_infinity + ASN1_ENUMERATED_free + d2i_NOTICEREF + X509_digest + ERR_load_ERR_strings + X509V3_string_free + X509_NAME_print_ex_fp + GENERAL_NAMES_free + EVP_PKEY_add1_attr_by_txt + EC_EX_DATA_get_data + i2d_X509_AUX + EC_GROUP_get_trinomial_basis + string_to_hex + BIO_next + ASN1_STRING_data + bn_cmp_part_words + ec_GF2m_simple_is_on_curve + ec_GFp_simple_add + d2i_ASN1_BIT_STRING + i2d_NOTICEREF + ERR_load_strings + X509V3_section_free + X509_CRL_digest + EC_EX_DATA_free_data + UI_ctrl + BIO_free_all + i2d_ASN1_BIT_STRING + NOTICEREF_new + ec_GF2m_simple_cmp + EC_GROUP_get_pentanomial_basis + X509_REQ_digest + EC_EX_DATA_clear_free_data + EC_KEY_print + ASN1_STRING_print_ex + UI_get_ex_new_index + ERR_unload_strings + name_cmp + BIO_dup_chain + ASN1_BIT_STRING_new + NOTICEREF_free + ec_GFp_simple_dbl + X9_62_PENTANOMIAL_new + RAND_event + X509_NAME_digest + EC_EX_DATA_free_all_data + ec_GF2m_simple_make_affine + PEM_do_header + ASN1_STRING_print_ex_fp + ERR_free_strings + X509V3_set_nconf + UI_set_ex_data + ASN1_BIT_STRING_free + X509_get1_email + BIO_copy_next_retry + EC_EX_DATA_clear_free_all_data + X9_62_PENTANOMIAL_free + X509_ocspid_print + PKCS7_ISSUER_AND_SERIAL_digest + ASN1_STRING_to_UTF8 + ec_GF2m_simple_points_make_affine + ec_GFp_simple_invert + ERR_put_error + X509V3_set_ctx + d2i_ASN1_OCTET_STRING + UI_get_ex_data + ASN1_generate_v3 + BIO_get_ex_new_index + EC_POINT_new + CRYPTO_mem_leaks_fp + ec_GF2m_simple_field_mul + ec_GFp_simple_is_at_infinity + X9_62_CHARACTERISTIC_TWO_new + d2i_PKCS8_bio + ERR_clear_error + X509V3_EXT_conf + X509_get1_ocsp + d2i_PKCS7 + i2d_ASN1_OCTET_STRING + UI_set_default_method + EC_POINT_free + BIO_set_ex_data + ec_GFp_simple_is_on_curve + X9_62_CHARACTERISTIC_TWO_free + ERR_get_error + ec_GF2m_simple_field_sqr + ASN1_OCTET_STRING_new + PEM_get_EVP_CIPHER_INFO + i2d_PKCS8_bio + UI_get_default_method + EC_POINT_clear_free + CRYPTO_mem_leaks_cb + ECPARAMETERS_new + RAND_screen + ERR_get_error_line + X509V3_EXT_conf_nid + BIO_get_ex_data + ec_GFp_simple_cmp + ASN1_OCTET_STRING_free + ec_GF2m_simple_field_div + EC_POINT_copy + d2i_PKCS8_PRIV_KEY_INFO_bio + X509_REQ_get1_email + UI_get_method + ECPARAMETERS_free + ERR_get_error_line_data + d2i_ASN1_NULL + BIO_number_read + ec_GFp_simple_make_affine + EC_POINT_dup + UI_set_method + d2i_ECPKPARAMETERS + X509_check_ca + ERR_peek_error + i2d_ASN1_NULL + i2d_PKCS8_PRIV_KEY_INFO_bio + BIO_number_written + CRYPTO_malloc_debug_init + i2d_PKCS7 + PEM_write_bio + EC_POINT_method_of + ec_GFp_simple_points_make_affine + v2i_GENERAL_NAMES + UI_create_method + ERR_peek_error_line + i2d_ECPKPARAMETERS + ASN1_NULL_new + i2d_PKCS8PrivateKeyInfo_bio + EC_POINT_set_to_infinity + PKCS7_new + X509V3_set_conf_lhash + CRYPTO_strdup + UI_destroy_method + v2i_GENERAL_NAME + ERR_peek_error_line_data + ASN1_NULL_free + ECPKPARAMETERS_new + X509_signature_print + EC_POINT_set_Jprojective_coordinates_GFp + X509V3_EXT_add_conf + UI_method_set_opener + PKCS7_free + i2d_PrivateKey_bio + v2i_GENERAL_NAME_ex + ERR_peek_last_error + d2i_ASN1_UTF8STRING + ec_GFp_simple_field_mul + ECPKPARAMETERS_free + EC_POINT_get_Jprojective_coordinates_GFp + UI_method_set_writer + ERR_peek_last_error_line + i2d_PKCS7_NDEF + i2d_ASN1_UTF8STRING + d2i_PrivateKey_bio + ec_GFp_simple_field_sqr + d2i_EC_PRIVATEKEY + X509V3_EXT_CRL_add_conf + EC_POINT_set_affine_coordinates_GFp + X509_email_free + UI_method_set_flusher + ERR_peek_last_error_line_data + ASN1_UTF8STRING_new + PKCS7_dup + i2d_EC_PRIVATEKEY + EC_POINT_set_affine_coordinates_GF2m + i2d_PUBKEY_bio + UI_method_set_reader + PEM_read_bio + ASN1_UTF8STRING_free + X509V3_EXT_REQ_add_conf + EC_PRIVATEKEY_new + ASN1_STRING_print + a2i_IPADDRESS + DHparams_print_fp + EC_POINT_get_affine_coordinates_GFp + d2i_PKCS7_SIGNED + UI_method_set_closer + d2i_PUBKEY_bio + d2i_OCSP_SIGNATURE + d2i_ASN1_PRINTABLESTRING + EC_PRIVATEKEY_free + ERR_error_string_n + DHparams_print + EC_POINT_get_affine_coordinates_GF2m + i2d_PKCS7_SIGNED + UI_method_get_opener + i2d_ASN1_PRINTABLESTRING + ASN1_TIME_print + d2i_ECPKParameters + EC_POINT_set_compressed_coordinates_GFp + PKCS7_SIGNED_new + UI_method_get_writer + ASN1_PRINTABLESTRING_new + X509_check_issued + ASN1_tag2str + EC_POINT_set_compressed_coordinates_GF2m + PKCS7_SIGNED_free + a2i_IPADDRESS_NC + UI_method_get_flusher + ASN1_GENERALIZEDTIME_print + ASN1_PRINTABLESTRING_free + EC_POINT_point2oct + UI_method_get_reader + d2i_ASN1_T61STRING + i2d_OCSP_SIGNATURE + EC_POINT_oct2point + d2i_PKCS7_SIGNER_INFO + UI_method_get_closer + ECParameters_print_fp + a2i_ipadd + i2d_ASN1_T61STRING + EC_POINT_add + OCSP_SIGNATURE_new + i2d_PKCS7_SIGNER_INFO + ASN1_UTCTIME_print + UI_get_string_type + ECParameters_print + ERR_error_string + ASN1_T61STRING_new + EC_POINT_dbl + PKCS7_SIGNER_INFO_new + UI_get_input_flags + OCSP_SIGNATURE_free + X509_NAME_print + ASN1_T61STRING_free + ERR_get_string_table + EC_POINT_invert + PKCS7_SIGNER_INFO_free + UI_get0_output_string + d2i_OCSP_CERTID + d2i_ASN1_IA5STRING + ERR_get_err_state_table + EC_POINT_is_at_infinity + d2i_PKCS7_ISSUER_AND_SERIAL + UI_get0_action_string + i2d_OCSP_CERTID + i2d_ASN1_IA5STRING + ERR_release_err_state_table + EC_POINT_is_on_curve + i2d_PKCS7_ISSUER_AND_SERIAL + UI_get0_result_string + OCSP_CERTID_new + ASN1_IA5STRING_new + i2d_ECPKParameters + ERR_lib_error_string + EC_POINT_cmp + PKCS7_ISSUER_AND_SERIAL_new + UI_get0_test_string + OCSP_CERTID_free + ASN1_IA5STRING_free + EC_POINT_make_affine + PKCS7_ISSUER_AND_SERIAL_free + UI_get_result_minsize + ERR_func_error_string + d2i_OCSP_ONEREQ + d2i_ASN1_GENERALSTRING + EC_POINTs_make_affine + d2i_PKCS7_ENVELOPE + UI_get_result_maxsize + X509V3_NAME_from_section + i2d_OCSP_ONEREQ + i2d_ASN1_GENERALSTRING + EC_POINTs_mul + i2d_PKCS7_ENVELOPE + ERR_reason_error_string + UI_set_result + OCSP_ONEREQ_new + ASN1_GENERALSTRING_new + PKCS7_ENVELOPE_new + EC_POINT_mul + OCSP_ONEREQ_free + ASN1_GENERALSTRING_free + PKCS7_ENVELOPE_free + d2i_OCSP_REQINFO + d2i_ASN1_UTCTIME + X509_POLICY_NODE_print + EC_GROUP_precompute_mult + i2d_OCSP_REQINFO + i2d_ASN1_UTCTIME + d2i_PKCS7_RECIP_INFO + OCSP_REQINFO_new + ASN1_UTCTIME_new + EC_GROUP_have_precompute_mult + ERR_remove_state + i2d_PKCS7_RECIP_INFO + OCSP_REQINFO_free + ASN1_UTCTIME_free + PKCS7_RECIP_INFO_new + d2i_OCSP_REQUEST + d2i_ASN1_GENERALIZEDTIME + ERR_get_state + PKCS7_RECIP_INFO_free + i2d_OCSP_REQUEST + i2d_ASN1_GENERALIZEDTIME + d2i_PKCS7_ENC_CONTENT + OCSP_REQUEST_new + ASN1_GENERALIZEDTIME_new + ERR_get_next_error_library + i2d_PKCS7_ENC_CONTENT + OCSP_REQUEST_free + ASN1_GENERALIZEDTIME_free + ERR_set_error_data + d2i_ECPrivateKey + PKCS7_ENC_CONTENT_new + d2i_OCSP_RESPBYTES + d2i_ASN1_VISIBLESTRING + ERR_add_error_data + PKCS7_ENC_CONTENT_free + i2d_OCSP_RESPBYTES + i2d_ASN1_VISIBLESTRING + d2i_PKCS7_SIGN_ENVELOPE + OCSP_RESPBYTES_new + ASN1_VISIBLESTRING_new + i2d_ECPrivateKey + i2d_PKCS7_SIGN_ENVELOPE + OpenSSLDie + OCSP_RESPBYTES_free + ASN1_VISIBLESTRING_free + PKCS7_SIGN_ENVELOPE_new + CRYPTO_get_new_lockid + i2d_ECParameters + d2i_OCSP_RESPONSE + d2i_ASN1_UNIVERSALSTRING + PKCS7_SIGN_ENVELOPE_free + d2i_ECParameters + i2d_OCSP_RESPONSE + i2d_ASN1_UNIVERSALSTRING + d2i_PKCS7_ENCRYPT + CRYPTO_num_locks + o2i_ECPublicKey + OCSP_RESPONSE_new + ASN1_UNIVERSALSTRING_new + i2d_PKCS7_ENCRYPT + CRYPTO_get_new_dynlockid + i2o_ECPublicKey + OCSP_RESPONSE_free + ASN1_UNIVERSALSTRING_free + PKCS7_ENCRYPT_new + d2i_OCSP_RESPID + d2i_ASN1_BMPSTRING + CRYPTO_destroy_dynlockid + PKCS7_ENCRYPT_free + i2d_OCSP_RESPID + i2d_ASN1_BMPSTRING + d2i_PKCS7_DIGEST + CRYPTO_get_dynlock_value + OCSP_RESPID_new + ASN1_BMPSTRING_new + i2d_PKCS7_DIGEST + CRYPTO_get_dynlock_create_callback + OCSP_RESPID_free + ASN1_BMPSTRING_free + PKCS7_DIGEST_new + CRYPTO_get_dynlock_lock_callback + d2i_OCSP_REVOKEDINFO + d2i_ASN1_TYPE + PKCS7_DIGEST_free + CRYPTO_get_dynlock_destroy_callback + i2d_OCSP_REVOKEDINFO + i2d_ASN1_TYPE + CRYPTO_set_dynlock_create_callback + OCSP_REVOKEDINFO_new + ASN1_TYPE_new + CRYPTO_set_dynlock_lock_callback + OCSP_REVOKEDINFO_free + ASN1_TYPE_free + CRYPTO_set_dynlock_destroy_callback + d2i_OCSP_CERTSTATUS + d2i_ASN1_PRINTABLE + CRYPTO_get_locking_callback + i2d_OCSP_CERTSTATUS + i2d_ASN1_PRINTABLE + CRYPTO_get_add_lock_callback + OCSP_CERTSTATUS_new + ASN1_PRINTABLE_new + CRYPTO_set_locking_callback + OCSP_CERTSTATUS_free + ASN1_PRINTABLE_free + CRYPTO_set_add_lock_callback + d2i_OCSP_SINGLERESP + d2i_DISPLAYTEXT + CRYPTO_get_id_callback + i2d_OCSP_SINGLERESP + i2d_DISPLAYTEXT + CRYPTO_set_id_callback + OCSP_SINGLERESP_new + DISPLAYTEXT_new + CRYPTO_thread_id + OCSP_SINGLERESP_free + DISPLAYTEXT_free + d2i_OCSP_RESPDATA + d2i_DIRECTORYSTRING + CRYPTO_lock + i2d_OCSP_RESPDATA + i2d_DIRECTORYSTRING + CRYPTO_add_lock + OCSP_RESPDATA_new + DIRECTORYSTRING_new + OPENSSL_isservice + OCSP_RESPDATA_free + DIRECTORYSTRING_free + d2i_OCSP_BASICRESP + i2d_OCSP_BASICRESP + OCSP_BASICRESP_new + OCSP_BASICRESP_free + CONF_parse_list + d2i_OCSP_CRLID + i2d_OCSP_CRLID + OCSP_CRLID_new + OCSP_CRLID_free + d2i_OCSP_SERVICELOC + i2d_OCSP_SERVICELOC + OCSP_SERVICELOC_new + OCSP_SERVICELOC_free + EC_GROUP_new_by_curve_name + EC_get_builtin_curves + OBJ_cleanup + OBJ_new_nid + OBJ_add_object + OBJ_nid2obj + OBJ_nid2sn + OBJ_nid2ln + OBJ_obj2nid + OBJ_txt2obj + OBJ_obj2txt + OBJ_txt2nid + OBJ_ln2nid + OBJ_sn2nid + OBJ_bsearch + OBJ_bsearch_ex + OBJ_create_objects + OBJ_create + diff --git a/src/VBox/Runtime/r3/win/VBoxRT-win32.def b/src/VBox/Runtime/r3/win/VBoxRT-win32.def index 71168dcb4..01e105ea3 100644 --- a/src/VBox/Runtime/r3/win/VBoxRT-win32.def +++ b/src/VBox/Runtime/r3/win/VBoxRT-win32.def @@ -1,4 +1,4 @@ -; $Id: $
+; $Id: $
;; @file
; IPRT - Win32 ASM exports.
;
diff --git a/src/VBox/Runtime/r3/win/VBoxRT-win64.def b/src/VBox/Runtime/r3/win/VBoxRT-win64.def index 0db5426e8..3ea841b6d 100644 --- a/src/VBox/Runtime/r3/win/VBoxRT-win64.def +++ b/src/VBox/Runtime/r3/win/VBoxRT-win64.def @@ -1,4 +1,4 @@ -; $Id: $
+; $Id: $
;; @file
; IPRT - Win64 ASM exports.
;
diff --git a/src/VBox/Runtime/r3/win/alloc-win.cpp b/src/VBox/Runtime/r3/win/alloc-win.cpp index 96fa83420..28169107e 100644 --- a/src/VBox/Runtime/r3/win/alloc-win.cpp +++ b/src/VBox/Runtime/r3/win/alloc-win.cpp @@ -1,4 +1,4 @@ -/* $Id: alloc-win.cpp $ */ +/* $Id: alloc-win.cpp 11020 2008-07-30 22:48:35Z vboxsync $ */ /** @file * IPRT - Memory Allocation, Win32. */ diff --git a/src/VBox/Runtime/r3/win/dir-win.cpp b/src/VBox/Runtime/r3/win/dir-win.cpp index 450bedc16..7f32f4d31 100644 --- a/src/VBox/Runtime/r3/win/dir-win.cpp +++ b/src/VBox/Runtime/r3/win/dir-win.cpp @@ -1,4 +1,4 @@ -/* $Id: dir-win.cpp $ */ +/* $Id: dir-win.cpp 20111 2009-05-28 00:34:52Z vboxsync $ */ /** @file * IPRT - Directory, win32. */ @@ -34,6 +34,7 @@ *******************************************************************************/ #define LOG_GROUP RTLOGGROUP_DIR #include <Windows.h> +#include <io.h> #include <iprt/dir.h> #include <iprt/path.h> diff --git a/src/VBox/Runtime/r3/win/dllmain-win.cpp b/src/VBox/Runtime/r3/win/dllmain-win.cpp index 9ae8ee197..841b33fef 100644 --- a/src/VBox/Runtime/r3/win/dllmain-win.cpp +++ b/src/VBox/Runtime/r3/win/dllmain-win.cpp @@ -1,4 +1,4 @@ -/* $Id: dllmain-win.cpp $ */ +/* $Id: dllmain-win.cpp 8155 2008-04-18 15:16:47Z vboxsync $ */ /** @file * IPRT - Win32 DllMain (Ring-3). */ diff --git a/src/VBox/Runtime/r3/win/fileaio-win.cpp b/src/VBox/Runtime/r3/win/fileaio-win.cpp new file mode 100644 index 000000000..6d7399be0 --- /dev/null +++ b/src/VBox/Runtime/r3/win/fileaio-win.cpp @@ -0,0 +1,523 @@ +/* $Id: fileaio-win.cpp 19562 2009-05-10 21:44:16Z vboxsync $ */ +/** @file + * IPRT - File async I/O, native implementation for the Windows host platform. + */ + +/* + * Copyright (C) 2006-2007 Sun Microsystems, Inc. + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * 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. + * + * 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 * +*******************************************************************************/ +#define LOG_GROUP RTLOGGROUP_DIR + +#include <iprt/asm.h> +#include <iprt/file.h> +#include <iprt/mem.h> +#include <iprt/assert.h> +#include <iprt/string.h> +#include <iprt/err.h> +#include <iprt/log.h> +#include "internal/fileaio.h" + +#include <Windows.h> + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ + +/** + * Transfer direction. + */ +typedef enum TRANSFERDIRECTION +{ + TRANSFERDIRECTION_INVALID = 0, + /** Read. */ + TRANSFERDIRECTION_READ, + /** Write. */ + TRANSFERDIRECTION_WRITE, + /** The usual 32-bit hack. */ + TRANSFERDIRECTION_32BIT_HACK = 0x7fffffff +} TRANSFERDIRECTION; + +/** + * Async I/O completion context state. + */ +typedef struct RTFILEAIOCTXINTERNAL +{ + /** handle to I/O completion port. */ + HANDLE hIoCompletionPort; + /** Current number of requests pending. */ + volatile int32_t cRequests; + /** Flag whether the thread was woken up. */ + volatile bool fWokenUp; + /** Flag whether the thread is currently waiting. */ + volatile bool fWaiting; + /** Magic value (RTFILEAIOCTX_MAGIC). */ + uint32_t u32Magic; +} RTFILEAIOCTXINTERNAL; +/** Pointer to an internal context structure. */ +typedef RTFILEAIOCTXINTERNAL *PRTFILEAIOCTXINTERNAL; + +/** + * Async I/O request state. + */ +typedef struct RTFILEAIOREQINTERNAL +{ + /** Overlapped structure. */ + OVERLAPPED Overlapped; + /** Current state the request is in. */ + RTFILEAIOREQSTATE enmState; + /** The file handle. */ + HANDLE hFile; + /** Kind of transfer Read/Write. */ + TRANSFERDIRECTION enmTransferDirection; + /** Number of bytes to transfer. */ + size_t cbTransfer; + /** Pointer to the buffer. */ + void *pvBuf; + /** Opaque user data. */ + void *pvUser; + /** Flag whether the request completed. */ + bool fCompleted; + /** Number of bytes transfered successfully. */ + size_t cbTransfered; + /** Error code of the completed request. */ + int Rc; + /** Completion context we are assigned to. */ + PRTFILEAIOCTXINTERNAL pCtxInt; + /** Magic value (RTFILEAIOREQ_MAGIC). */ + uint32_t u32Magic; +} RTFILEAIOREQINTERNAL; +/** Pointer to an internal request structure. */ +typedef RTFILEAIOREQINTERNAL *PRTFILEAIOREQINTERNAL; + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +/** Id for the wakeup event. */ +#define AIO_CONTEXT_WAKEUP_EVENT 1 +/** Converts a pointer to an OVERLAPPED structure to a internal request. */ +#define OVERLAPPED_2_RTFILEAIOREQINTERNAL(pOverlapped) ( (PRTFILEAIOREQINTERNAL)((uintptr_t)(pOverlapped) - RT_OFFSETOF(RTFILEAIOREQINTERNAL, Overlapped)) ) + +RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits) +{ + int rcBSD = 0; + AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER); + + /* No limits known. */ + pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS; + pAioLimits->cbBufferAlignment = 0; + + return VINF_SUCCESS; +} + +RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq) +{ + AssertPtrReturn(phReq, VERR_INVALID_POINTER); + + PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)RTMemAllocZ(sizeof(RTFILEAIOREQINTERNAL)); + if (RT_UNLIKELY(!pReqInt)) + return VERR_NO_MEMORY; + + pReqInt->pCtxInt = NULL; + pReqInt->fCompleted = false; + pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + + *phReq = (RTFILEAIOREQ)pReqInt; + + return VINF_SUCCESS; +} + +RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq) +{ + /* + * Validate the handle and ignore nil. + */ + if (hReq == NIL_RTFILEAIOREQ) + return VINF_SUCCESS; + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + + /* + * Trash the magic and free it. + */ + ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC); + RTMemFree(pReqInt); + return VINF_SUCCESS; +} + +/** + * Worker setting up the request. + */ +DECLINLINE(int) rtFileAioReqPrepareTransfer(RTFILEAIOREQ hReq, RTFILE hFile, + TRANSFERDIRECTION enmTransferDirection, + RTFOFF off, void *pvBuf, size_t cbTransfer, + void *pvUser) +{ + /* + * Validate the input. + */ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + Assert(hFile != NIL_RTFILE); + AssertPtr(pvBuf); + Assert(off >= 0); + Assert(cbTransfer > 0); + + pReqInt->enmTransferDirection = enmTransferDirection; + pReqInt->hFile = (HANDLE)hFile; + pReqInt->Overlapped.Offset = (DWORD)(off & 0xffffffff); + pReqInt->Overlapped.OffsetHigh = (DWORD)(off >> 32); + pReqInt->cbTransfer = cbTransfer; + pReqInt->pvBuf = pvBuf; + pReqInt->pvUser = pvUser; + pReqInt->fCompleted = false; + + return VINF_SUCCESS; +} + +RTDECL(int) RTFileAioReqPrepareRead(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off, + void *pvBuf, size_t cbRead, void *pvUser) +{ + return rtFileAioReqPrepareTransfer(hReq, hFile, TRANSFERDIRECTION_READ, + off, pvBuf, cbRead, pvUser); +} + +RTDECL(int) RTFileAioReqPrepareWrite(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off, + void *pvBuf, size_t cbWrite, void *pvUser) +{ + return rtFileAioReqPrepareTransfer(hReq, hFile, TRANSFERDIRECTION_WRITE, + off, pvBuf, cbWrite, pvUser); +} + +RTDECL(int) RTFileAioReqPrepareFlush(RTFILEAIOREQ hReq, RTFILE hFile, void *pvUser) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE); + + /** @todo: Flushing is not available */ +#if 0 + return rtFileAsyncPrepareTransfer(pRequest, File, TRANSFERDIRECTION_FLUSH, + 0, NULL, 0, pvUser); +#endif + return VERR_NOT_IMPLEMENTED; +} + +RTDECL(void *) RTFileAioReqGetUser(RTFILEAIOREQ hReq) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN_RC(pReqInt, NULL); + + return pReqInt->pvUser; +} + +RTDECL(int) RTFileAioReqCancel(RTFILEAIOREQ hReq) +{ + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED); + + /** + * @todo r=aeichner It is not possible to cancel specific + * requests on Windows before Vista. + * CancelIo cancels all requests for a file issued by the + * calling thread and CancelIoEx which does what we need + * is only available from Vista and up. + * The solution is to return VERR_FILE_AIO_IN_PROGRESS + * if the request didn't completed yet (checked above). + * Shouldn't be a big issue because a request is normally + * only canceled if it exceeds a timeout which is quite huge. + */ + return VERR_FILE_AIO_COMPLETED; +} + +RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered) +{ + int rc = VINF_SUCCESS; + PRTFILEAIOREQINTERNAL pReqInt = hReq; + RTFILEAIOREQ_VALID_RETURN(pReqInt); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); + RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); + + rc = pReqInt->Rc; + if (pcbTransfered && RT_SUCCESS(rc)) + *pcbTransfered = pReqInt->cbTransfered; + + return rc; +} + +RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax) +{ + PRTFILEAIOCTXINTERNAL pCtxInt; + AssertPtrReturn(phAioCtx, VERR_INVALID_POINTER); + + pCtxInt = (PRTFILEAIOCTXINTERNAL)RTMemAllocZ(sizeof(RTFILEAIOCTXINTERNAL)); + if (RT_UNLIKELY(!pCtxInt)) + return VERR_NO_MEMORY; + + pCtxInt->hIoCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, + NULL, + 0, + 0); + if (RT_UNLIKELY(!pCtxInt->hIoCompletionPort)) + { + RTMemFree(pCtxInt); + return VERR_NO_MEMORY; + } + + pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC; + + *phAioCtx = (RTFILEAIOCTX)pCtxInt; + + return VINF_SUCCESS; +} + +RTDECL(int) RTFileAioCtxDestroy(RTFILEAIOCTX hAioCtx) +{ + /* Validate the handle and ignore nil. */ + if (hAioCtx == NIL_RTFILEAIOCTX) + return VINF_SUCCESS; + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + + /* Cannot destroy a busy context. */ + if (RT_UNLIKELY(pCtxInt->cRequests)) + return VERR_FILE_AIO_BUSY; + + CloseHandle(pCtxInt->hIoCompletionPort); + ASMAtomicUoWriteU32(&pCtxInt->u32Magic, RTFILEAIOCTX_MAGIC_DEAD); + RTMemFree(pCtxInt); + + return VINF_SUCCESS; +} + +RTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTX hAioCtx, RTFILE hFile) +{ + int rc = VINF_SUCCESS; + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + + HANDLE hTemp = CreateIoCompletionPort((HANDLE)hFile, pCtxInt->hIoCompletionPort, 0, 1); + if (hTemp != pCtxInt->hIoCompletionPort) + rc = RTErrConvertFromWin32(GetLastError()); + + return rc; +} + +RTDECL(uint32_t) RTFileAioCtxGetMaxReqCount(RTFILEAIOCTX hAioCtx) +{ + return RTFILEAIO_UNLIMITED_REQS; +} + +RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) +{ + /* + * Parameter validation. + */ + int rc = VINF_SUCCESS; + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + AssertReturn(cReqs > 0, VERR_INVALID_PARAMETER); + AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); + int i; + + for (i = 0; i < cReqs; i++) + { + PRTFILEAIOREQINTERNAL pReqInt = pahReqs[i]; + BOOL fSucceeded; + + if (pReqInt->enmTransferDirection == TRANSFERDIRECTION_READ) + { + fSucceeded = ReadFile(pReqInt->hFile, pReqInt->pvBuf, + pReqInt->cbTransfer, NULL, + &pReqInt->Overlapped); + } + else if (pReqInt->enmTransferDirection == TRANSFERDIRECTION_WRITE) + { + fSucceeded = WriteFile(pReqInt->hFile, pReqInt->pvBuf, + pReqInt->cbTransfer, NULL, + &pReqInt->Overlapped); + } + else + AssertMsgFailed(("Invalid transfer direction\n")); + + if (RT_UNLIKELY(!fSucceeded && GetLastError() != ERROR_IO_PENDING)) + { + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + rc = RTErrConvertFromWin32(GetLastError()); + pReqInt->Rc = rc; + break; + } + RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); + } + + ASMAtomicAddS32(&pCtxInt->cRequests, i); + + return rc; +} + +RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, unsigned cMillisTimeout, + PRTFILEAIOREQ pahReqs, size_t cReqs, uint32_t *pcReqs) +{ + /* + * Validate the parameters, making sure to always set pcReqs. + */ + AssertPtrReturn(pcReqs, VERR_INVALID_POINTER); + *pcReqs = 0; /* always set */ + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); + AssertReturn(cReqs != 0, VERR_INVALID_PARAMETER); + AssertReturn(cReqs >= cMinReqs, VERR_OUT_OF_RANGE); + + /* + * Can't wait if there are no requests around. + */ + if (RT_UNLIKELY(ASMAtomicUoReadS32(&pCtxInt->cRequests) == 0)) + return VERR_FILE_AIO_NO_REQUEST; + + /* Wait for at least one. */ + if (!cMinReqs) + cMinReqs = 1; + + /* + * Loop until we're woken up, hit an error (incl timeout), or + * have collected the desired number of requests. + */ + int rc = VINF_SUCCESS; + int cRequestsCompleted = 0; + while ( !pCtxInt->fWokenUp + && (cMinReqs > 0)) + { + uint64_t StartNanoTS = 0; + DWORD dwTimeout = cMillisTimeout == RT_INDEFINITE_WAIT ? INFINITE : cMillisTimeout; + DWORD cbTransfered; + LPOVERLAPPED pOverlapped; + ULONG_PTR lCompletionKey; + BOOL fSucceeded; + + if (cMillisTimeout != RT_INDEFINITE_WAIT) + StartNanoTS = RTTimeNanoTS(); + + ASMAtomicXchgBool(&pCtxInt->fWaiting, true); + fSucceeded = GetQueuedCompletionStatus(pCtxInt->hIoCompletionPort, + &cbTransfered, + &lCompletionKey, + &pOverlapped, + dwTimeout); + ASMAtomicXchgBool(&pCtxInt->fWaiting, false); + if (!fSucceeded) + { + /* Includes VERR_TIMEOUT */ + rc = RTErrConvertFromWin32(GetLastError()); + break; + } + + /* Check if we got woken up. */ + if (lCompletionKey == AIO_CONTEXT_WAKEUP_EVENT) + break; + else + { + /* A request completed. */ + PRTFILEAIOREQINTERNAL pReqInt = OVERLAPPED_2_RTFILEAIOREQINTERNAL(pOverlapped); + AssertPtr(pReqInt); + Assert(pReqInt->u32Magic == RTFILEAIOREQ_MAGIC); + + /* Mark the request as finished. */ + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + + /* completion status. */ + DWORD cbTransfered; + fSucceeded = GetOverlappedResult(pReqInt->hFile, + &pReqInt->Overlapped, + &cbTransfered, + FALSE); + pReqInt->cbTransfered = cbTransfered; + pReqInt->Rc = VINF_SUCCESS; + + pahReqs[cRequestsCompleted++] = (RTFILEAIOREQ)pReqInt; + + /* Update counter. */ + cMinReqs --; + + if (cMillisTimeout != RT_INDEFINITE_WAIT) + { + /* Recalculate timeout. */ + uint64_t NanoTS = RTTimeNanoTS(); + uint64_t cMilliesElapsed = (NanoTS - StartNanoTS) / 1000000; + cMillisTimeout -= cMilliesElapsed; + } + } + } + + /* + * Update the context state and set the return value. + */ + *pcReqs = cRequestsCompleted; + ASMAtomicSubS32(&pCtxInt->cRequests, cRequestsCompleted); + + /* + * Clear the wakeup flag and set rc. + */ + if ( pCtxInt->fWokenUp + && RT_SUCCESS(rc)) + { + ASMAtomicXchgBool(&pCtxInt->fWokenUp, false); + rc = VERR_INTERRUPTED; + } + + return rc; +} + +RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx) +{ + int rc = VINF_SUCCESS; + PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; + RTFILEAIOCTX_VALID_RETURN(pCtxInt); + + bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true); + bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting); + + if ( !fWokenUp + && fWaiting) + { + BOOL fSucceeded = PostQueuedCompletionStatus(pCtxInt->hIoCompletionPort, + 0, AIO_CONTEXT_WAKEUP_EVENT, + NULL); + + if (!fSucceeded) + rc = RTErrConvertFromWin32(GetLastError()); + } + + return rc; +} + diff --git a/src/VBox/Runtime/r3/win/fileio-win.cpp b/src/VBox/Runtime/r3/win/fileio-win.cpp index 9f8e71948..d0d3ae209 100644 --- a/src/VBox/Runtime/r3/win/fileio-win.cpp +++ b/src/VBox/Runtime/r3/win/fileio-win.cpp @@ -1,4 +1,4 @@ -/* $Id: fileio-win.cpp $ */ +/* $Id: fileio-win.cpp 19186 2009-04-26 09:05:32Z vboxsync $ */ /** @file * IPRT - File I/O, native implementation for the Windows host platform. */ @@ -260,6 +260,8 @@ RTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, unsigned fOpen dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; if (fOpen & RTFILE_O_WRITE_THROUGH) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH; + if (fOpen & RTFILE_O_ASYNC_IO) + dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED; /* * Open/Create the file. diff --git a/src/VBox/Runtime/r3/win/fs-win.cpp b/src/VBox/Runtime/r3/win/fs-win.cpp index 174a66ef3..7c267d07e 100644 --- a/src/VBox/Runtime/r3/win/fs-win.cpp +++ b/src/VBox/Runtime/r3/win/fs-win.cpp @@ -1,4 +1,4 @@ -/* $Id: fs-win.cpp $ */ +/* $Id: fs-win.cpp 13837 2008-11-05 02:54:02Z vboxsync $ */ /** @file * IPRT - File System, Win32. */ diff --git a/src/VBox/Runtime/r3/win/ldrNative-win.cpp b/src/VBox/Runtime/r3/win/ldrNative-win.cpp index b596c6792..4722b0348 100644 --- a/src/VBox/Runtime/r3/win/ldrNative-win.cpp +++ b/src/VBox/Runtime/r3/win/ldrNative-win.cpp @@ -1,4 +1,4 @@ -/* $Id: ldrNative-win.cpp $ */ +/* $Id: ldrNative-win.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - Binary Image Loader, Win32 native. */ diff --git a/src/VBox/Runtime/r3/win/localipc-win.cpp b/src/VBox/Runtime/r3/win/localipc-win.cpp index 27afa7c3c..e5270e116 100644 --- a/src/VBox/Runtime/r3/win/localipc-win.cpp +++ b/src/VBox/Runtime/r3/win/localipc-win.cpp @@ -1,4 +1,4 @@ -/* $Id: localipc-win.cpp $ */ +/* $Id: localipc-win.cpp 11725 2008-08-27 22:21:47Z vboxsync $ */ /** @file * IPRT - Local IPC, Windows Implementation Using Named Pipes. */ diff --git a/src/VBox/Runtime/r3/win/mp-win.cpp b/src/VBox/Runtime/r3/win/mp-win.cpp index 48e05a19f..ffb3884ec 100644 --- a/src/VBox/Runtime/r3/win/mp-win.cpp +++ b/src/VBox/Runtime/r3/win/mp-win.cpp @@ -1,4 +1,4 @@ -/* $Id: mp-win.cpp $ */ +/* $Id: mp-win.cpp 9429 2008-06-05 15:22:37Z vboxsync $ */ /** @file * IPRT - Multiprocessor, Windows. */ diff --git a/src/VBox/Runtime/r3/win/path-win.cpp b/src/VBox/Runtime/r3/win/path-win.cpp index 6413cc961..a84082543 100644 --- a/src/VBox/Runtime/r3/win/path-win.cpp +++ b/src/VBox/Runtime/r3/win/path-win.cpp @@ -1,4 +1,4 @@ -/* $Id: path-win.cpp $ */ +/* $Id: path-win.cpp 15813 2009-01-05 16:06:55Z vboxsync $ */ /** @file * IPRT - Path manipulation. */ diff --git a/src/VBox/Runtime/r3/win/process-win.cpp b/src/VBox/Runtime/r3/win/process-win.cpp index 39e47a12d..862c63b72 100644 --- a/src/VBox/Runtime/r3/win/process-win.cpp +++ b/src/VBox/Runtime/r3/win/process-win.cpp @@ -1,4 +1,4 @@ -/* $Id: process-win.cpp $ */ +/* $Id: process-win.cpp 20497 2009-06-12 11:01:30Z vboxsync $ */ /** @file * IPRT - Process, Win32. */ @@ -93,6 +93,8 @@ RTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, AssertReturn(Env != NIL_RTENV, VERR_INVALID_PARAMETER); const char * const *papszEnv = RTEnvGetExecEnvP(Env); AssertPtrReturn(papszEnv, VERR_INVALID_HANDLE); + AssertPtrReturn(papszArgs, VERR_INVALID_PARAMETER); + AssertPtrReturn(*papszArgs, VERR_INVALID_PARAMETER); /* later: path searching. */ /* diff --git a/src/VBox/Runtime/r3/win/rtFileNativeSetAttributes-win.cpp b/src/VBox/Runtime/r3/win/rtFileNativeSetAttributes-win.cpp index 1bc78292c..08f323fa5 100644 --- a/src/VBox/Runtime/r3/win/rtFileNativeSetAttributes-win.cpp +++ b/src/VBox/Runtime/r3/win/rtFileNativeSetAttributes-win.cpp @@ -1,4 +1,4 @@ -/* $Id: rtFileNativeSetAttributes-win.cpp $ */ +/* $Id: rtFileNativeSetAttributes-win.cpp 17357 2009-03-04 17:41:31Z vboxsync $ */ /** @file * IPRT - NtSetInformationFile wrapper. */ diff --git a/src/VBox/Runtime/r3/win/rtProcInitExePath-win.cpp b/src/VBox/Runtime/r3/win/rtProcInitExePath-win.cpp index fa2f6d485..3d0f2c21a 100644 --- a/src/VBox/Runtime/r3/win/rtProcInitExePath-win.cpp +++ b/src/VBox/Runtime/r3/win/rtProcInitExePath-win.cpp @@ -1,4 +1,4 @@ -/* $Id: rtProcInitExePath-win.cpp $ */ +/* $Id: rtProcInitExePath-win.cpp 11838 2008-08-29 17:14:02Z vboxsync $ */ /** @file * IPRT - rtProcInitName, Windows. */ diff --git a/src/VBox/Runtime/r3/win/sched-win.cpp b/src/VBox/Runtime/r3/win/sched-win.cpp index 7a2f7878b..1697f7736 100644 --- a/src/VBox/Runtime/r3/win/sched-win.cpp +++ b/src/VBox/Runtime/r3/win/sched-win.cpp @@ -1,4 +1,4 @@ -/* $Id: sched-win.cpp $ */ +/* $Id: sched-win.cpp 13837 2008-11-05 02:54:02Z vboxsync $ */ /** @file * IPRT - Scheduling, Win32. */ diff --git a/src/VBox/Runtime/r3/win/sems-win.cpp b/src/VBox/Runtime/r3/win/sems-win.cpp index 46c871749..5560d1596 100644 --- a/src/VBox/Runtime/r3/win/sems-win.cpp +++ b/src/VBox/Runtime/r3/win/sems-win.cpp @@ -1,4 +1,4 @@ -/* $Id: sems-win.cpp $ */ +/* $Id: sems-win.cpp 10839 2008-07-23 19:48:51Z vboxsync $ */ /** @file * IPRT - Semaphores, implementation for Windows host platform. */ diff --git a/src/VBox/Runtime/r3/win/thread-win.cpp b/src/VBox/Runtime/r3/win/thread-win.cpp index 6ad8f8146..eb24437f7 100644 --- a/src/VBox/Runtime/r3/win/thread-win.cpp +++ b/src/VBox/Runtime/r3/win/thread-win.cpp @@ -1,4 +1,4 @@ -/* $Id: thread-win.cpp $ */ +/* $Id: thread-win.cpp 13837 2008-11-05 02:54:02Z vboxsync $ */ /** @file * IPRT - Threads, Win32. */ diff --git a/src/VBox/Runtime/r3/win/time-win.cpp b/src/VBox/Runtime/r3/win/time-win.cpp index 52290fd45..df71c5cd1 100644 --- a/src/VBox/Runtime/r3/win/time-win.cpp +++ b/src/VBox/Runtime/r3/win/time-win.cpp @@ -1,4 +1,4 @@ -/* $Id: time-win.cpp $ */ +/* $Id: time-win.cpp 20736 2009-06-20 20:49:09Z vboxsync $ */ /** @file * IPRT - Time, win32. */ @@ -46,19 +46,19 @@ # define USE_INTERRUPT_TIME #else //# define USE_FILE_TIME -#endif +#endif #ifdef USE_INTERRUPT_TIME -typedef struct _MY_KSYSTEM_TIME +typedef struct _MY_KSYSTEM_TIME { ULONG LowPart; LONG High1Time; LONG High2Time; } MY_KSYSTEM_TIME; -typedef struct _MY_KUSER_SHARED_DATA +typedef struct _MY_KUSER_SHARED_DATA { ULONG TickCountLowDeprecated; ULONG TickCountMultiplier; @@ -72,14 +72,14 @@ typedef struct _MY_KUSER_SHARED_DATA DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void) { #if defined USE_TICK_COUNT - /* - * This would work if it didn't flip over every 49 (or so) days. + /* + * This would work if it didn't flip over every 49 (or so) days. */ return (uint64_t)GetTickCount() * (uint64_t)1000000; #elif defined USE_PERFORMANCE_COUNTER - /* - * Slow and no derived from InterruptTime. + /* + * Slow and not derived from InterruptTime. */ static LARGE_INTEGER llFreq; static unsigned uMult; @@ -98,23 +98,23 @@ DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void) return (uint64_t)GetTickCount() * (uint64_t)1000000; #elif defined USE_FILE_TIME - /* - * This is SystemTime not InterruptTime. + /* + * This is SystemTime not InterruptTime. */ uint64_t u64; /* manual say larger integer, should be safe to assume it's the same. */ GetSystemTimeAsFileTime((LPFILETIME)&u64); return u64 * 100; #elif defined USE_INTERRUPT_TIME - /* - * This is exactly what we want, but we have to obtain it by non-official + /* + * This is exactly what we want, but we have to obtain it by non-official * means. */ static MY_KUSER_SHARED_DATA *s_pUserSharedData = NULL; if (!s_pUserSharedData) { /** @todo find official way of getting this or some more clever - * detection algorithm if necessary. The com debugger class + * detection algorithm if necessary. The com debugger class * exports this too, windbg knows it too... */ s_pUserSharedData = (MY_ KUSER_SHARED_DATA *)(uintptr_t)0x7ffe0000; } diff --git a/src/VBox/Runtime/r3/win/timer-win.cpp b/src/VBox/Runtime/r3/win/timer-win.cpp index 709c67840..a73f88a7b 100644 --- a/src/VBox/Runtime/r3/win/timer-win.cpp +++ b/src/VBox/Runtime/r3/win/timer-win.cpp @@ -1,4 +1,4 @@ -/* $Id: timer-win.cpp $ */ +/* $Id: timer-win.cpp 20374 2009-06-08 00:43:21Z vboxsync $ */ /** @file * IPRT - Timer. */ @@ -74,11 +74,11 @@ #include <iprt/err.h> #include "internal/magics.h" -__BEGIN_DECLS +RT_C_DECLS_BEGIN /* from sysinternals. */ NTSYSAPI LONG NTAPI NtSetTimerResolution(IN ULONG DesiredResolution, IN BOOLEAN SetResolution, OUT PULONG CurrentResolution); NTSYSAPI LONG NTAPI NtQueryTimerResolution(OUT PULONG MaximumResolution, OUT PULONG MinimumResolution, OUT PULONG CurrentResolution); -__END_DECLS +RT_C_DECLS_END /******************************************************************************* diff --git a/src/VBox/Runtime/r3/win/tls-win.cpp b/src/VBox/Runtime/r3/win/tls-win.cpp index 801798704..df74e2fe5 100644 --- a/src/VBox/Runtime/r3/win/tls-win.cpp +++ b/src/VBox/Runtime/r3/win/tls-win.cpp @@ -1,4 +1,4 @@ -/* $Id: tls-win.cpp $ */ +/* $Id: tls-win.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - Thread Local Storage (TLS), Win32. */ diff --git a/src/VBox/Runtime/r3/win/utf16locale-win.cpp b/src/VBox/Runtime/r3/win/utf16locale-win.cpp index 01d630471..cb75099f8 100644 --- a/src/VBox/Runtime/r3/win/utf16locale-win.cpp +++ b/src/VBox/Runtime/r3/win/utf16locale-win.cpp @@ -1,4 +1,4 @@ -/* $Id: utf16locale-win.cpp $ */ +/* $Id: utf16locale-win.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - UTF-16 Locale Specific Manipulation, Win32. */ diff --git a/src/VBox/Runtime/r3/win/utf8-win.cpp b/src/VBox/Runtime/r3/win/utf8-win.cpp index eab3af0b0..90faed767 100644 --- a/src/VBox/Runtime/r3/win/utf8-win.cpp +++ b/src/VBox/Runtime/r3/win/utf8-win.cpp @@ -1,4 +1,4 @@ -/* $Id: utf8-win.cpp $ */ +/* $Id: utf8-win.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */ /** @file * IPRT - UTF8 helpers. */ diff --git a/src/VBox/Runtime/r3/win/uuid-win.cpp b/src/VBox/Runtime/r3/win/uuid-win.cpp index 266a11087..1e3eba31d 100644 --- a/src/VBox/Runtime/r3/win/uuid-win.cpp +++ b/src/VBox/Runtime/r3/win/uuid-win.cpp @@ -1,4 +1,4 @@ -/* $Id: uuid-win.cpp $ */ +/* $Id: uuid-win.cpp 9743 2008-06-16 22:53:02Z vboxsync $ */ /** @file * IPRT - UUID, Windows implementation. */ |
