Blame winpr/libwinpr/synch/semaphore.c

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