Blame winpr/libwinpr/synch/semaphore.c

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