FreeRDP/winpr/libwinpr/synch/semaphore.c
Bernhard Miklautz 68e8569110 winpr/synch: remove the dependency on winsock.h
winsock.h pulls in a lot of defines and dependencies that are not
required and partially unwanted in winpr's core (for parts that are not
related to network). In order to get rid of this dependency and have an
independent defines for extended winpr functions the WINPR_FD_* defines
are used internally (and for exposed functions). Where required, like in
WSAEventSelect, the FD_* is mapped to WINPR_FD_*.
2015-07-14 11:39:41 +02:00

244 lines
5.1 KiB
C

/**
* WinPR: Windows Portable Runtime
* Synchronization Functions
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/synch.h>
#include "synch.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef _WIN32
#include <errno.h>
#include "../handle/handle.h"
#include "../log.h"
#define TAG WINPR_TAG("synch.semaphore")
static BOOL SemaphoreCloseHandle(HANDLE handle);
static BOOL SemaphoreIsHandled(HANDLE handle)
{
WINPR_TIMER* pSemaphore = (WINPR_TIMER*) handle;
if (!pSemaphore || (pSemaphore->Type != HANDLE_TYPE_SEMAPHORE))
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
return TRUE;
}
static int SemaphoreGetFd(HANDLE handle)
{
WINPR_SEMAPHORE *sem = (WINPR_SEMAPHORE *)handle;
if (!SemaphoreIsHandled(handle))
return -1;
return sem->pipe_fd[0];
}
static DWORD SemaphoreCleanupHandle(HANDLE handle)
{
int length;
WINPR_SEMAPHORE *sem = (WINPR_SEMAPHORE *)handle;
if (!SemaphoreIsHandled(handle))
return WAIT_FAILED;
length = read(sem->pipe_fd[0], &length, 1);
if (length != 1)
{
WLog_ERR(TAG, "semaphore read() failure [%d] %s", errno, strerror(errno));
return WAIT_FAILED;
}
return WAIT_OBJECT_0;
}
BOOL SemaphoreCloseHandle(HANDLE handle) {
WINPR_SEMAPHORE *semaphore = (WINPR_SEMAPHORE *) handle;
if (!SemaphoreIsHandled(handle))
return FALSE;
#ifdef WINPR_PIPE_SEMAPHORE
if (semaphore->pipe_fd[0] != -1)
{
close(semaphore->pipe_fd[0]);
semaphore->pipe_fd[0] = -1;
if (semaphore->pipe_fd[1] != -1)
{
close(semaphore->pipe_fd[1]);
semaphore->pipe_fd[1] = -1;
}
}
#else
#if defined __APPLE__
semaphore_destroy(mach_task_self(), *((winpr_sem_t*) semaphore->sem));
#else
sem_destroy((winpr_sem_t*) semaphore->sem);
#endif
#endif
free(semaphore);
return TRUE;
}
static HANDLE_OPS ops = {
SemaphoreIsHandled,
SemaphoreCloseHandle,
SemaphoreGetFd,
SemaphoreCleanupHandle
};
HANDLE CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName)
{
HANDLE handle;
WINPR_SEMAPHORE* semaphore;
semaphore = (WINPR_SEMAPHORE*) calloc(1, sizeof(WINPR_SEMAPHORE));
if (!semaphore)
return NULL;
semaphore->pipe_fd[0] = -1;
semaphore->pipe_fd[0] = -1;
semaphore->sem = (winpr_sem_t*) NULL;
semaphore->ops = &ops;
if (semaphore)
{
#ifdef WINPR_PIPE_SEMAPHORE
if (pipe(semaphore->pipe_fd) < 0)
{
WLog_ERR(TAG, "failed to create semaphore");
free(semaphore);
return NULL;
}
while (lInitialCount > 0)
{
if (write(semaphore->pipe_fd[1], "-", 1) != 1)
{
close(semaphore->pipe_fd[0]);
close(semaphore->pipe_fd[1]);
free(semaphore);
return NULL;
}
lInitialCount--;
}
#else
semaphore->sem = (winpr_sem_t*) malloc(sizeof(winpr_sem_t));
if (!semaphore->sem)
{
WLog_ERR(TAG, "failed to allocate semaphore memory");
free(semaphore);
return NULL;
}
#if defined __APPLE__
if (semaphore_create(mach_task_self(), semaphore->sem, SYNC_POLICY_FIFO, lMaximumCount) != KERN_SUCCESS)
#else
if (sem_init(semaphore->sem, 0, lMaximumCount) == -1)
#endif
{
WLog_ERR(TAG, "failed to create semaphore");
free(semaphore->sem);
free(semaphore);
return NULL;
}
#endif
}
WINPR_HANDLE_SET_TYPE_AND_MODE(semaphore, HANDLE_TYPE_SEMAPHORE, WINPR_FD_READ);
handle = (HANDLE) semaphore;
return handle;
}
HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCSTR lpName)
{
return CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, NULL);
}
HANDLE OpenSemaphoreW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName)
{
WLog_ERR(TAG, "not implemented");
return NULL;
}
HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName)
{
WLog_ERR(TAG, "not implemented");
return NULL;
}
BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount)
{
ULONG Type;
WINPR_HANDLE* Object;
WINPR_SEMAPHORE* semaphore;
if (!winpr_Handle_GetInfo(hSemaphore, &Type, &Object))
return FALSE;
if (Type == HANDLE_TYPE_SEMAPHORE)
{
semaphore = (WINPR_SEMAPHORE*) Object;
#ifdef WINPR_PIPE_SEMAPHORE
if (semaphore->pipe_fd[0] != -1)
{
while (lReleaseCount > 0)
{
if (write(semaphore->pipe_fd[1], "-", 1) != 1)
return FALSE;
lReleaseCount--;
}
}
#else
#if defined __APPLE__
semaphore_signal(*((winpr_sem_t*) semaphore->sem));
#else
sem_post((winpr_sem_t*) semaphore->sem);
#endif
#endif
return TRUE;
}
WLog_ERR(TAG, "calling %s on a handle that is not a semaphore");
return FALSE;
}
#endif