// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// 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.

#ifndef VK_SEMAPHORE_EXTERNAL_LINUX_H_
#define VK_SEMAPHORE_EXTERNAL_LINUX_H_

#include "System/Linux/MemFd.hpp"
#include "System/Memory.hpp"

#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <sys/mman.h>

// An external semaphore implementation for Linux, that uses memfd-backed
// shared memory regions as the underlying implementation. The region contains
// a single SharedSemaphore instance, which is a reference-counted semaphore
// implementation based on a pthread process-shared mutex + condition variable
// pair.
//
// This implementation works on any Linux system with at least kernel 3.17
// (which should be sufficient for any not-so-recent Android system) and doesn't
// require special libraries installed on the system.
//
// NOTE: This is not interoperable with other Linux ICDs that use Linux kernel
// sync file objects (which correspond to
// VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) instead.
//

// A process-shared semaphore implementation that can be stored in
// a process-shared memory region. It also includes a reference count to
// ensure it is only destroyed when the last reference to it is dropped.
class SharedSemaphore
{
public:
	SharedSemaphore()
	{
		pthread_mutexattr_t mattr;
		pthread_mutexattr_init(&mattr);
		pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
		pthread_mutex_init(&mutex, &mattr);
		pthread_mutexattr_destroy(&mattr);

		pthread_condattr_t cattr;
		pthread_condattr_init(&cattr);
		pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
		pthread_cond_init(&cond, &cattr);
		pthread_condattr_destroy(&cattr);
	}

	~SharedSemaphore()
	{
		pthread_cond_destroy(&cond);
		pthread_mutex_destroy(&mutex);
	}

	// Increment reference count.
	void addRef()
	{
		pthread_mutex_lock(&mutex);
		ref_count++;
		pthread_mutex_unlock(&mutex);
	}

	// Decrement reference count and returns true iff it reaches 0.
	bool deref()
	{
		pthread_mutex_lock(&mutex);
		bool result = (--ref_count == 0);
		pthread_mutex_unlock(&mutex);
		return result;
	}

	void wait()
	{
		pthread_mutex_lock(&mutex);
		while(!signaled)
		{
			pthread_cond_wait(&cond, &mutex);
		}
		// From Vulkan 1.1.119 spec, section 6.4.2:
		// Unlike fences or events, the act of waiting for a semaphore also
		// unsignals that semaphore.
		signaled = false;
		pthread_mutex_unlock(&mutex);
	}

	// Just like wait() but never blocks. Returns true if the semaphore
	// was signaled (and reset by the function), or false otherwise.
	// Used to avoid using a background thread for waiting in the case
	// where the semaphore is already signaled.
	bool tryWait()
	{
		pthread_mutex_lock(&mutex);
		bool result = signaled;
		if(result)
		{
			signaled = false;
		}
		pthread_mutex_unlock(&mutex);
		return result;
	}

	void signal()
	{
		pthread_mutex_lock(&mutex);
		signaled = true;
		pthread_cond_broadcast(&cond);
		pthread_mutex_unlock(&mutex);
	}

private:
	pthread_mutex_t mutex;
	pthread_cond_t cond;
	int ref_count = 1;
	bool signaled = false;
};

namespace vk {

class Semaphore::External
{
public:
	// The type of external semaphore handle types supported by this implementation.
	static const VkExternalSemaphoreHandleTypeFlags kExternalSemaphoreHandleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;

	// Default constructor. Note that one should call either init() or
	// importFd() before any call to wait() or signal().
	External() = default;

	~External() { close(); }

	// Initialize instance by creating a new shared memory region.
	void init()
	{
		// Allocate or import the region's file descriptor.
		const size_t size = sw::memoryPageSize();
		// To be exportable, the PosixSemaphore must be stored in a shared
		// memory region.
		static int counter = 0;
		char name[40];
		snprintf(name, sizeof(name), "SwiftShader.Semaphore.%d", ++counter);
		if(!memfd.allocate(name, size))
		{
			ABORT("memfd.allocate() returned %s", strerror(errno));
		}
		mapRegion(size, true);
	}

	// Import an existing semaphore through its file descriptor.
	VkResult importFd(int fd)
	{
		close();
		memfd.importFd(fd);
		mapRegion(sw::memoryPageSize(), false);
		return VK_SUCCESS;
	}

	// Export the current semaphore as a duplicated file descriptor to the same
	// region. This can be consumed by importFd() running in a different
	// process.
	VkResult exportFd(int *pFd) const
	{
		int fd = memfd.exportFd();
		if(fd < 0)
		{
			return VK_ERROR_INVALID_EXTERNAL_HANDLE;
		}
		*pFd = fd;
		return VK_SUCCESS;
	}

	void wait()
	{
		semaphore->wait();
	}

	bool tryWait()
	{
		return semaphore->tryWait();
	}

	void signal()
	{
		semaphore->signal();
	}

private:
	// Unmap the semaphore if needed and close its file descriptor.
	void close()
	{
		if(semaphore)
		{
			if(semaphore->deref())
			{
				semaphore->~SharedSemaphore();
			}
			memfd.unmap(semaphore, sw::memoryPageSize());
			memfd.close();
			semaphore = nullptr;
		}
	}

	// Remap the shared region and setup the semaphore or increment its reference count.
	void mapRegion(size_t size, bool needInitialization)
	{
		// Map the region into memory and point the semaphore to it.
		void *addr = memfd.mapReadWrite(0, size);
		if(!addr)
		{
			ABORT("mmap() failed: %s", strerror(errno));
		}
		semaphore = reinterpret_cast<SharedSemaphore *>(addr);
		if(needInitialization)
		{
			new(semaphore) SharedSemaphore();
		}
		else
		{
			semaphore->addRef();
		}
	}

	LinuxMemFd memfd;
	SharedSemaphore *semaphore = nullptr;
};

}  // namespace vk

#endif  // VK_SEMAPHORE_EXTERNAL_LINUX_H_
