Exemplo n.º 1
0
static inline void HandleListInsertBefore(struct PVRSRV_HANDLE_BASE *psBase,
				    u32 ui32InsIndex, struct sHandleList *psIns,
				    size_t uiParentOffset, u32 ui32EntryIndex,
				    struct sHandleList *psEntry,
				    size_t uiEntryOffset, u32 ui32ParentIndex)
{
	struct sHandleList *psPrevIns =
	    LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev,
					   ui32ParentIndex, uiParentOffset,
					   uiEntryOffset);

	PVR_ASSERT(psEntry->hParent == NULL);
	PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
	PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET
		   (psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset,
		    uiParentOffset)->hParent == INDEX_TO_HANDLE(psBase,
							ui32ParentIndex));

	psEntry->ui32Prev = psIns->ui32Prev;
	psIns->ui32Prev = ui32EntryIndex;
	psEntry->ui32Next = ui32InsIndex;
	psPrevIns->ui32Next = ui32EntryIndex;

	psEntry->hParent = INDEX_TO_HANDLE(psBase, ui32ParentIndex);
}
Exemplo n.º 2
0
static INLINE
IMG_VOID InitParentList(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
{
	IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psBase, psHandle);

	HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(psBase, ui32Parent));
}
Exemplo n.º 3
0
static inline void InitParentList(struct PVRSRV_HANDLE_BASE *psBase,
			    struct sHandle *psHandle)
{
	u32 ui32Parent = HANDLE_PTR_TO_INDEX(psBase, psHandle);

	HandleListInit(ui32Parent, &psHandle->sChildren,
		       INDEX_TO_HANDLE(psBase, ui32Parent));
}
Exemplo n.º 4
0
static int nbd_co_send_request(BlockDriverState *bs,
                               struct nbd_request *request,
                               QEMUIOVector *qiov, int offset)
{
    NbdClientSession *s = nbd_get_client_session(bs);
    AioContext *aio_context;
    int rc, ret, i;

    qemu_co_mutex_lock(&s->send_mutex);

    for (i = 0; i < MAX_NBD_REQUESTS; i++) {
        if (s->recv_coroutine[i] == NULL) {
            s->recv_coroutine[i] = qemu_coroutine_self();
            break;
        }
    }

    g_assert(qemu_in_coroutine());
    assert(i < MAX_NBD_REQUESTS);
    request->handle = INDEX_TO_HANDLE(s, i);

    if (!s->ioc) {
        qemu_co_mutex_unlock(&s->send_mutex);
        return -EPIPE;
    }

    s->send_coroutine = qemu_coroutine_self();
    aio_context = bdrv_get_aio_context(bs);

    aio_set_fd_handler(aio_context, s->sioc->fd, false,
                       nbd_reply_ready, nbd_restart_write, bs);
    if (qiov) {
        qio_channel_set_cork(s->ioc, true);
        rc = nbd_send_request(s->ioc, request);
        if (rc >= 0) {
            ret = nbd_wr_syncv(s->ioc, qiov->iov, qiov->niov,
                               offset, request->len, 0);
            if (ret != request->len) {
                rc = -EIO;
            }
        }
        qio_channel_set_cork(s->ioc, false);
    } else {
        rc = nbd_send_request(s->ioc, request);
    }
    aio_set_fd_handler(aio_context, s->sioc->fd, false,
                       nbd_reply_ready, NULL, bs);
    s->send_coroutine = NULL;
    qemu_co_mutex_unlock(&s->send_mutex);
    return rc;
}
Exemplo n.º 5
0
static int nbd_co_send_request(BlockDriverState *bs,
                               struct nbd_request *request,
                               QEMUIOVector *qiov, int offset)
{
    NbdClientSession *s = nbd_get_client_session(bs);
    AioContext *aio_context;
    int rc, ret, i;

    qemu_co_mutex_lock(&s->send_mutex);

    for (i = 0; i < MAX_NBD_REQUESTS; i++) {
        if (s->recv_coroutine[i] == NULL) {
            s->recv_coroutine[i] = qemu_coroutine_self();
            break;
        }
    }

    assert(i < MAX_NBD_REQUESTS);
    request->handle = INDEX_TO_HANDLE(s, i);
    s->send_coroutine = qemu_coroutine_self();
    aio_context = bdrv_get_aio_context(bs);

    aio_set_fd_handler(aio_context, s->sock, AIO_CLIENT_PROTOCOL,
                       nbd_reply_ready, nbd_restart_write, bs);
    if (qiov) {
        if (!s->is_unix) {
            socket_set_cork(s->sock, 1);
        }
        rc = nbd_send_request(s->sock, request);
        if (rc >= 0) {
            ret = qemu_co_sendv(s->sock, qiov->iov, qiov->niov,
                                offset, request->len);
            if (ret != request->len) {
                rc = -EIO;
            }
        }
        if (!s->is_unix) {
            socket_set_cork(s->sock, 0);
        }
    } else {
        rc = nbd_send_request(s->sock, request);
    }
    aio_set_fd_handler(aio_context, s->sock, AIO_CLIENT_PROTOCOL,
                       nbd_reply_ready, NULL, bs);
    s->send_coroutine = NULL;
    qemu_co_mutex_unlock(&s->send_mutex);
    return rc;
}
Exemplo n.º 6
0
static INLINE
IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIndex, struct sHandleList *psIns, IMG_SIZE_T uiParentOffset, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_UINT32 ui32ParentIndex)
{
	 
	struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);

	PVR_ASSERT(psEntry->hParent == IMG_NULL);
	PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
	PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(psBase, ui32ParentIndex));

	psEntry->ui32Prev = psIns->ui32Prev;
	psIns->ui32Prev = ui32EntryIndex;
	psEntry->ui32Next = ui32InsIndex;
	psPrevIns->ui32Next = ui32EntryIndex;

	psEntry->hParent = INDEX_TO_HANDLE(psBase, ui32ParentIndex);
}
Exemplo n.º 7
0
static int nbd_co_send_request(BlockDriverState *bs,
                               NBDRequest *request,
                               QEMUIOVector *qiov)
{
    NBDClientSession *s = nbd_get_client_session(bs);
    int rc, ret, i;

    qemu_co_mutex_lock(&s->send_mutex);
    while (s->in_flight == MAX_NBD_REQUESTS) {
        qemu_co_queue_wait(&s->free_sema, &s->send_mutex);
    }
    s->in_flight++;

    for (i = 0; i < MAX_NBD_REQUESTS; i++) {
        if (s->recv_coroutine[i] == NULL) {
            s->recv_coroutine[i] = qemu_coroutine_self();
            break;
        }
    }

    g_assert(qemu_in_coroutine());
    assert(i < MAX_NBD_REQUESTS);
    request->handle = INDEX_TO_HANDLE(s, i);

    if (!s->ioc) {
        qemu_co_mutex_unlock(&s->send_mutex);
        return -EPIPE;
    }

    if (qiov) {
        qio_channel_set_cork(s->ioc, true);
        rc = nbd_send_request(s->ioc, request);
        if (rc >= 0) {
            ret = nbd_rwv(s->ioc, qiov->iov, qiov->niov, request->len, false,
                          NULL);
            if (ret != request->len) {
                rc = -EIO;
            }
        }
        qio_channel_set_cork(s->ioc, false);
    } else {
        rc = nbd_send_request(s->ioc, request);
    }
    qemu_co_mutex_unlock(&s->send_mutex);
    return rc;
}
Exemplo n.º 8
0
static void nbd_coroutine_start(BDRVNBDState *s, struct nbd_request *request)
{
    int i;

    /* Poor man semaphore.  The free_sema is locked when no other request
     * can be accepted, and unlocked after receiving one reply.  */
    if (s->in_flight >= MAX_NBD_REQUESTS - 1) {
        qemu_co_mutex_lock(&s->free_sema);
        assert(s->in_flight < MAX_NBD_REQUESTS);
    }
    s->in_flight++;

    for (i = 0; i < MAX_NBD_REQUESTS; i++) {
        if (s->recv_coroutine[i] == NULL) {
            s->recv_coroutine[i] = qemu_coroutine_self();
            break;
        }
    }

    assert(i < MAX_NBD_REQUESTS);
    request->handle = INDEX_TO_HANDLE(s, i);
}
Exemplo n.º 9
0
static int nbd_co_send_request(BlockDriverState *bs,
                               NBDRequest *request,
                               QEMUIOVector *qiov)
{
    NBDClientSession *s = nbd_get_client_session(bs);
    int rc, i;

    qemu_co_mutex_lock(&s->send_mutex);
    while (s->in_flight == MAX_NBD_REQUESTS) {
        qemu_co_queue_wait(&s->free_sema, &s->send_mutex);
    }
    s->in_flight++;

    for (i = 0; i < MAX_NBD_REQUESTS; i++) {
        if (s->requests[i].coroutine == NULL) {
            break;
        }
    }

    g_assert(qemu_in_coroutine());
    assert(i < MAX_NBD_REQUESTS);

    s->requests[i].coroutine = qemu_coroutine_self();
    s->requests[i].receiving = false;

    request->handle = INDEX_TO_HANDLE(s, i);

    if (s->quit) {
        rc = -EIO;
        goto err;
    }
    if (!s->ioc) {
        rc = -EPIPE;
        goto err;
    }

    if (qiov) {
        qio_channel_set_cork(s->ioc, true);
        rc = nbd_send_request(s->ioc, request);
        if (rc >= 0 && !s->quit) {
            assert(request->len == iov_size(qiov->iov, qiov->niov));
            if (qio_channel_writev_all(s->ioc, qiov->iov, qiov->niov,
                                       NULL) < 0) {
                rc = -EIO;
            }
        }
        qio_channel_set_cork(s->ioc, false);
    } else {
        rc = nbd_send_request(s->ioc, request);
    }

err:
    if (rc < 0) {
        s->quit = true;
        s->requests[i].coroutine = NULL;
        s->in_flight--;
        qemu_co_queue_next(&s->free_sema);
    }
    qemu_co_mutex_unlock(&s->send_mutex);
    return rc;
}
Exemplo n.º 10
0
/*!
******************************************************************************

 @Function	AcquireHandle

 @Description	Acquire a new handle

 @Input		psBase - Pointer to handle base structure
		phHandle - Points to a handle pointer
		pvData - Pointer to resource to be associated with the handle

 @Output	phHandle - Points to a handle pointer

 @Return	Error code or PVRSRV_OK

******************************************************************************/
static PVRSRV_ERROR AcquireHandle(HANDLE_IMPL_BASE *psBase, 
				  IMG_HANDLE *phHandle, 
				  IMG_VOID *pvData)
{
	IMG_UINT32 ui32NewIndex = BASE_TO_TOTAL_INDICES(psBase);
	HANDLE_IMPL_DATA *psNewHandleData = IMG_NULL;
	PVRSRV_ERROR eError;

	PVR_ASSERT(psBase != IMG_NULL);
	PVR_ASSERT(phHandle != IMG_NULL);
	PVR_ASSERT(pvData != IMG_NULL);

	/* Ensure there is a free handle */
	eError = EnsureFreeHandles(psBase, 1);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR, "%s: EnsureFreeHandles failed (%s)",
			 __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
		return eError;
	}
	PVR_ASSERT(psBase->ui32TotalFreeHandCount != 0);

	if (!psBase->bPurgingEnabled)
	{
		/* Array index of first free handle */
		ui32NewIndex = psBase->ui32FirstFreeIndex;

		/* Get handle array entry */
		psNewHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32NewIndex);
	}
	else
	{
		IMG_UINT32 ui32BlockedIndex;

		/*
		 * If purging is enabled, we always try to allocate handles
		 * at the front of the array, to increase the chances that
		 * the size of the handle array can be reduced by a purge.
		 * No linked list of free handles is kept; we search for
		 * free handles as required.
		 */

		/*
		 * ui32FirstFreeIndex should only be set when a new batch of
		 * handle structures is allocated, and should always be a
		 * multiple of the block size.
		 */
		PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0);

		for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
		{
			HANDLE_BLOCK *psHandleBlock = BASE_AND_INDEX_TO_HANDLE_BLOCK(psBase, ui32BlockedIndex);

			if (psHandleBlock->ui32FreeHandCount == 0)
			{
				continue;
			}

			for (ui32NewIndex = ui32BlockedIndex; ui32NewIndex < ui32BlockedIndex + HANDLE_BLOCK_SIZE; ui32NewIndex++)
			{
				psNewHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32NewIndex);
				if (psNewHandleData->pvData == IMG_NULL)
				{
					break;
				}
			}
		}
		psBase->ui32FirstFreeIndex = 0;
		PVR_ASSERT(INDEX_IS_VALID(psBase, ui32NewIndex));
	}
	PVR_ASSERT(psNewHandleData != IMG_NULL);

	psBase->ui32TotalFreeHandCount--;

	PVR_ASSERT(INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE);
	PVR_ASSERT(INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex) > 0);

	INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex)--;

	/* No free list management if purging is enabled */
	if (!psBase->bPurgingEnabled)
	{
		/* Check whether the last free handle has been allocated */
		if (psBase->ui32TotalFreeHandCount == 0)
		{
			PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));

			psBase->ui32LastFreeIndexPlusOne = 0;
			psBase->ui32FirstFreeIndex = 0;
		}
		else
		{
			/*
			 * Update the first free handle index.
			 * If the "next free index plus one" field in the new
			 * handle structure is zero, the next free index is
			 * the index of the new handle plus one.  This
			 * convention has been adopted to simplify the
			 * initialisation of freshly allocated handle
			 * space.
			 */
			if (psNewHandleData->ui32NextIndexPlusOne == 0)
			{
				psBase->ui32FirstFreeIndex = ui32NewIndex + 1;
			}
			else
			{
				psBase->ui32FirstFreeIndex = psNewHandleData->ui32NextIndexPlusOne - 1;
			}
		}
	}

	PVR_ASSERT(HANDLE_DATA_TO_HANDLE(psNewHandleData) == INDEX_TO_HANDLE(ui32NewIndex));

	psNewHandleData->pvData = pvData;
	psNewHandleData->ui32NextIndexPlusOne = 0;

	/* Return the new handle to the client */
	*phHandle = INDEX_TO_HANDLE(ui32NewIndex);

#if defined(DEBUG_HANDLEALLOC_KM)
	PVR_DPF((PVR_DBG_MESSAGE, "Handle acquire base %p hdl %p", psBase, *phHandle));
#endif

	return PVRSRV_OK;
}
Exemplo n.º 11
0
/*!
******************************************************************************

 @Function	ReallocHandleBlockArray

 @Description	Reallocate the handle block array

 @Input		psBase - Pointer to handle base structure
		ui32NewCount - The new total number of handles

 @Return	Error code or PVRSRV_OK

******************************************************************************/
static PVRSRV_ERROR ReallocHandleBlockArray(HANDLE_IMPL_BASE *psBase, 
					    IMG_UINT32 ui32NewCount)
{
	HANDLE_BLOCK *psOldArray = psBase->psHandleBlockArray;
	IMG_UINT32 ui32OldCount = psBase->ui32TotalHandCount;
	HANDLE_BLOCK *psNewArray = IMG_NULL;
	PVRSRV_ERROR eError = PVRSRV_OK;
	IMG_UINT32 ui32Index;

	if (ui32NewCount == ui32OldCount)
	{
		return PVRSRV_OK;
	}

	if (ui32NewCount != 0 && 
	    !psBase->bPurgingEnabled &&
	    ui32NewCount < ui32OldCount)
	{
		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) ||
	    ((ui32NewCount % HANDLE_BLOCK_SIZE) != 0))
	{
		PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0);
		PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0);

		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	if (ui32NewCount != 0)
	{
		/* Allocate new handle array */
		psNewArray = OSAllocMem(HANDLE_BLOCK_ARRAY_SIZE(ui32NewCount) * sizeof(HANDLE_BLOCK));
		if (psNewArray == IMG_NULL)
		{
			PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't allocate new handle array", __FUNCTION__));
			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
			goto error;
		}

		if (ui32OldCount != 0)
		{
			OSMemCopy(psNewArray, psOldArray, HANDLE_BLOCK_ARRAY_SIZE(MIN(ui32NewCount, ui32OldCount)) * sizeof(HANDLE_BLOCK));
		}
	}

	/*
	 * If the new handle array is smaller than the old one, free
	 * unused handle data structure arrays
	 */
	for (ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE)
	{
		HANDLE_BLOCK *psHandleBlock = BLOCK_ARRAY_AND_INDEX_TO_HANDLE_BLOCK(psOldArray, ui32Index);

		OSFreeMem(psHandleBlock->psHandleDataArray);
	}

	/*
	 * If the new handle array is bigger than the old one, allocate
	 * new handle data structure arrays
	 */
	for (ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
	{
		/* PRQA S 0505 1 */ /* psNewArray is never NULL, see assert earlier */
		HANDLE_BLOCK *psHandleBlock = BLOCK_ARRAY_AND_INDEX_TO_HANDLE_BLOCK(psNewArray, ui32Index);

		psHandleBlock->psHandleDataArray = OSAllocMem(sizeof(HANDLE_IMPL_DATA) * HANDLE_BLOCK_SIZE);
		if (psHandleBlock->psHandleDataArray != IMG_NULL)
		{
			IMG_UINT32 ui32SubIndex;

			psHandleBlock->ui32FreeHandCount = HANDLE_BLOCK_SIZE;

			for (ui32SubIndex = 0; ui32SubIndex < HANDLE_BLOCK_SIZE; ui32SubIndex++)
			{
				HANDLE_IMPL_DATA *psHandleData = psHandleBlock->psHandleDataArray + ui32SubIndex;

				psHandleData->hHandle = INDEX_TO_HANDLE(ui32SubIndex + ui32Index);
				psHandleData->pvData = IMG_NULL;
				psHandleData->ui32NextIndexPlusOne = 0;
			}
		}
		else
		{
			PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't allocate handle structures", __FUNCTION__));
			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
		}
	}

	if (eError != PVRSRV_OK)
	{
		goto error;
	}

#if defined(DEBUG_MAX_HANDLE_COUNT)
	/* Force handle failure to test error exit code */
	if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT)
	{
		PVR_DPF((PVR_DBG_ERROR, "%s: Max handle count (%u) reached", __FUNCTION__, DEBUG_MAX_HANDLE_COUNT));
		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
		goto error;
	}
#endif /* defined(DEBUG_MAX_HANDLE_COUNT) */

	if (psOldArray != IMG_NULL)
	{
		/* Free old handle array */
		OSFreeMem(psOldArray);
	}

	psBase->psHandleBlockArray = psNewArray;
	psBase->ui32TotalHandCount = ui32NewCount;

	if (ui32NewCount > ui32OldCount)
	{
		/* Check for wraparound */
		PVR_ASSERT(psBase->ui32TotalFreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32TotalFreeHandCount);

		/* PRQA S 3382 1 */ /* ui32NewCount always > ui32OldCount */
		psBase->ui32TotalFreeHandCount += (ui32NewCount - ui32OldCount);

		/*
		 * If purging is enabled, there is no free handle list
		 * management, but as an optimization, when allocating
		 * new handles, we use ui32FirstFreeIndex to point to
		 * the first handle in a newly allocated block.
		 */
		if (psBase->ui32FirstFreeIndex == 0)
		{
			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);

			psBase->ui32FirstFreeIndex = ui32OldCount;
		}
		else
		{
			if (!psBase->bPurgingEnabled)
			{
				PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
				PVR_ASSERT(INDEX_TO_HANDLE_DATA(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);

				INDEX_TO_HANDLE_DATA(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1;
			}
		}

		if (!psBase->bPurgingEnabled)
		{
			psBase->ui32LastFreeIndexPlusOne = ui32NewCount;
		}
	}
	else
	{
		if (ui32NewCount == 0)
		{
			psBase->ui32TotalFreeHandCount = 0;
			psBase->ui32FirstFreeIndex = 0;
			psBase->ui32LastFreeIndexPlusOne = 0;
		}
		else
		{
			PVR_ASSERT(psBase->bPurgingEnabled);
			PVR_ASSERT(psBase->ui32FirstFreeIndex <= ui32NewCount);
			PVR_ASSERT(psBase->ui32TotalFreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32TotalFreeHandCount);

			/* PRQA S 3382 1 */ /* ui32OldCount always >= ui32NewCount */
			psBase->ui32TotalFreeHandCount -= (ui32OldCount - ui32NewCount);
		}
	}

	PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount);

	return PVRSRV_OK;

error:
	PVR_ASSERT(eError != PVRSRV_OK);

	if (psNewArray != IMG_NULL)
	{
		/* Free any new handle structures that were allocated */
		for (ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
		{
			HANDLE_BLOCK *psHandleBlock = BLOCK_ARRAY_AND_INDEX_TO_HANDLE_BLOCK(psNewArray, ui32Index);
			if (psHandleBlock->psHandleDataArray != IMG_NULL)
			{
				OSFreeMem(psHandleBlock->psHandleDataArray);
			}
		}

		/* Free new handle array */
		OSFreeMem(psNewArray);
	}

	return eError;
}
Exemplo n.º 12
0
NTSTATUS
InitializeIoHandleTable(
    IN OUT PCONSOLE_INFORMATION Console,
    OUT PCONSOLE_PER_PROCESS_DATA ProcessData,
    OUT PHANDLE StdIn,
    OUT PHANDLE StdOut,
    OUT PHANDLE StdErr
)

/*++

Routine Description:

    This routine initializes a process's handle table for the first
    time (there is no parent process).  It also sets up stdin, stdout,
    and stderr.

Arguments:

    Console - Pointer to console information structure.

    ProcessData - Pointer to per process data structure.

    Stdin - Pointer in which to return StdIn handle.

    StdOut - Pointer in which to return StdOut handle.

    StdErr - Pointer in which to return StdErr handle.

Return Value:

--*/

{
    ULONG i;
    HANDLE Handle;
    NTSTATUS Status;
    PHANDLE_DATA HandleData;

    // HandleTablePtr gets set up by ConsoleAddProcessRoutine.
    // it will be != to HandleTable if the new process was created
    // using "start xxx" at the command line and cmd.exe has >
    // CONSOLE_INITIAL_IO_HANDLES.

    if (ProcessData->HandleTablePtr != ProcessData->HandleTable) {
        ASSERT(ProcessData->HandleTableSize != CONSOLE_INITIAL_IO_HANDLES);
        HeapFree(pConHeap,0,ProcessData->HandleTablePtr);
        ProcessData->HandleTablePtr = ProcessData->HandleTable;
    }

    for (i=0; i<CONSOLE_INITIAL_IO_HANDLES; i++) {
        ProcessData->HandleTable[i].HandleType = CONSOLE_FREE_HANDLE;
    }

    ProcessData->HandleTableSize = CONSOLE_INITIAL_IO_HANDLES;
    ProcessData->Foo = 0xF00;

    //
    // set up stdin, stdout, stderr.  we don't do any cleanup in case
    // of errors because we're going to fail the console creation.
    //
    // stdin
    //

    Status = AllocateIoHandle(ProcessData,
                              CONSOLE_INPUT_HANDLE,
                              &Handle
                             );
    if (!NT_SUCCESS(Status)) {
        return((ULONG) Status);
    }
    Status = DereferenceIoHandleNoCheck(ProcessData,
                                        Handle,
                                        &HandleData
                                       );
    ASSERT (NT_SUCCESS(Status));
    if (!NT_SUCCESS(Status)) {
        return((ULONG) Status);
    }
    if (!InitializeInputHandle(HandleData,
                               &Console->InputBuffer)) {
        return STATUS_NO_MEMORY;
    }
    HandleData->HandleType |= CONSOLE_INHERITABLE;
    Status = ConsoleAddShare(GENERIC_READ | GENERIC_WRITE,
                             FILE_SHARE_READ | FILE_SHARE_WRITE,
                             &Console->InputBuffer.ShareAccess,
                             HandleData
                            );
    ASSERT(NT_SUCCESS(Status));
    if (!NT_SUCCESS(Status)) {
        return((ULONG) Status);
    }
    *StdIn = INDEX_TO_HANDLE(Handle);

    //
    // stdout
    //

    Status = AllocateIoHandle(ProcessData,
                              CONSOLE_OUTPUT_HANDLE,
                              &Handle
                             );
    if (!NT_SUCCESS(Status)) {
        return((ULONG) Status);
    }
    Status = DereferenceIoHandleNoCheck(ProcessData,
                                        Handle,
                                        &HandleData
                                       );
    ASSERT (NT_SUCCESS(Status));
    if (!NT_SUCCESS(Status)) {
        return((ULONG) Status);
    }
    InitializeOutputHandle(HandleData,Console->CurrentScreenBuffer);
    HandleData->HandleType |= CONSOLE_INHERITABLE;
    Status = ConsoleAddShare(GENERIC_READ | GENERIC_WRITE,
                             FILE_SHARE_READ | FILE_SHARE_WRITE,
                             &Console->ScreenBuffers->ShareAccess,
                             HandleData
                            );
    ASSERT(NT_SUCCESS(Status));
    if (!NT_SUCCESS(Status)) {
        return((ULONG) Status);
    }
    *StdOut = INDEX_TO_HANDLE(Handle);

    //
    // stderr
    //

    Status = AllocateIoHandle(ProcessData,
                              CONSOLE_OUTPUT_HANDLE,
                              &Handle
                             );
    if (!NT_SUCCESS(Status)) {
        return((ULONG) Status);
    }
    Status = DereferenceIoHandleNoCheck(ProcessData,
                                        Handle,
                                        &HandleData
                                       );
    ASSERT (NT_SUCCESS(Status));
    if (!NT_SUCCESS(Status)) {
        return((ULONG) Status);
    }
    InitializeOutputHandle(HandleData,Console->CurrentScreenBuffer);
    HandleData->HandleType |= CONSOLE_INHERITABLE;
    Status = ConsoleAddShare(GENERIC_READ | GENERIC_WRITE,
                             FILE_SHARE_READ | FILE_SHARE_WRITE,
                             &Console->ScreenBuffers->ShareAccess,
                             HandleData
                            );
    ASSERT(NT_SUCCESS(Status));
    if (!NT_SUCCESS(Status)) {
        return((ULONG) Status);
    }
    *StdErr = INDEX_TO_HANDLE(Handle);
    return STATUS_SUCCESS;
}