// Copyright 2016 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 rr_Thread_hpp
#define rr_Thread_hpp

#if defined(_WIN32)
	#ifndef WIN32_LEAN_AND_MEAN
		#define WIN32_LEAN_AND_MEAN
	#endif
	#include <windows.h>
	#include <intrin.h>
#else
	#include <pthread.h>
	#include <sched.h>
	#include <unistd.h>
	#define TLS_OUT_OF_INDEXES (pthread_key_t)(~0)
#endif

#include <stdlib.h>

#if defined(__clang__)
#if __has_include(<atomic>) // clang has an explicit check for the availability of atomic
#define USE_STD_ATOMIC 1
#endif
// atomic is available in C++11 or newer, and in Visual Studio 2012 or newer
#elif (defined(_MSC_VER) && (_MSC_VER >= 1700)) || (__cplusplus >= 201103L)
#define USE_STD_ATOMIC 1
#endif

#if USE_STD_ATOMIC
#include <atomic>
#endif

namespace rr {

class Event;

class Thread
{
public:
	Thread(void (*threadFunction)(void *parameters), void *parameters);

	~Thread();

	void join();

	static void yield();
	static void sleep(int milliseconds);

	#if defined(_WIN32)
		typedef DWORD LocalStorageKey;
	#else
		typedef pthread_key_t LocalStorageKey;
	#endif

	static LocalStorageKey allocateLocalStorageKey(void (*destructor)(void *storage) = free);
	static void freeLocalStorageKey(LocalStorageKey key);
	static void *allocateLocalStorage(LocalStorageKey key, size_t size);
	static void *getLocalStorage(LocalStorageKey key);
	static void freeLocalStorage(LocalStorageKey key);

private:
	struct Entry
	{
		void (*const threadFunction)(void *parameters);
		void *threadParameters;
		Event *init;
	};

	#if defined(_WIN32)
		static unsigned long __stdcall startFunction(void *parameters);
		HANDLE handle;
	#else
		static void *startFunction(void *parameters);
		pthread_t handle;
	#endif

	bool hasJoined = false;
};

class Event
{
	friend class Thread;

public:
	Event();

	~Event();

	void signal();
	void wait();

private:
	#if defined(_WIN32)
		HANDLE handle;
	#else
		pthread_cond_t handle;
		pthread_mutex_t mutex;
		volatile bool signaled;
	#endif
};

#if PERF_PROFILE
int64_t atomicExchange(int64_t volatile *target, int64_t value);
int atomicExchange(int volatile *target, int value);
#endif

int atomicIncrement(int volatile *value);
int atomicDecrement(int volatile *value);
int atomicAdd(int volatile *target, int value);
void nop();

}  // namespace rr

/* Inline implementation */

namespace rr {

inline void Thread::yield()
{
	#if defined(_WIN32)
		Sleep(0);
	#elif defined(__APPLE__)
		pthread_yield_np();
	#else
		sched_yield();
	#endif
}

inline void Thread::sleep(int milliseconds)
{
	#if defined(_WIN32)
		Sleep(milliseconds);
	#else
		usleep(1000 * milliseconds);
	#endif
}

inline Thread::LocalStorageKey Thread::allocateLocalStorageKey(void (*destructor)(void *storage))
{
	#if defined(_WIN32)
		return TlsAlloc();
	#else
		LocalStorageKey key;
		pthread_key_create(&key, destructor);
		return key;
	#endif
}

inline void Thread::freeLocalStorageKey(LocalStorageKey key)
{
	#if defined(_WIN32)
		TlsFree(key);
	#else
		pthread_key_delete(key);   // Using an invalid key is an error but not undefined behavior.
	#endif
}

inline void *Thread::allocateLocalStorage(LocalStorageKey key, size_t size)
{
	if(key == TLS_OUT_OF_INDEXES)
	{
		return nullptr;
	}

	freeLocalStorage(key);

	void *storage = malloc(size);

	#if defined(_WIN32)
		TlsSetValue(key, storage);
	#else
		pthread_setspecific(key, storage);
	#endif

	return storage;
}

inline void *Thread::getLocalStorage(LocalStorageKey key)
{
	#if defined(_WIN32)
		return TlsGetValue(key);
	#else
		if(key == TLS_OUT_OF_INDEXES)   // Avoid undefined behavior.
		{
			return nullptr;
		}

		return pthread_getspecific(key);
	#endif
}

inline void Thread::freeLocalStorage(LocalStorageKey key)
{
	free(getLocalStorage(key));

	#if defined(_WIN32)
		TlsSetValue(key, nullptr);
	#else
		pthread_setspecific(key, nullptr);
	#endif
}

inline void Event::signal()
{
	#if defined(_WIN32)
		SetEvent(handle);
	#else
		pthread_mutex_lock(&mutex);
		signaled = true;
		pthread_cond_signal(&handle);
		pthread_mutex_unlock(&mutex);
	#endif
}

inline void Event::wait()
{
	#if defined(_WIN32)
		WaitForSingleObject(handle, INFINITE);
	#else
		pthread_mutex_lock(&mutex);
		while(!signaled) pthread_cond_wait(&handle, &mutex);
		signaled = false;
		pthread_mutex_unlock(&mutex);
	#endif
}

#if PERF_PROFILE
inline int64_t atomicExchange(volatile int64_t *target, int64_t value)
{
	#if defined(_WIN32)
		return InterlockedExchange64(target, value);
	#else
		int ret;
		__asm__ __volatile__("lock; xchg8 %x0,(%x1)" : "=r" (ret) :"r" (target), "0" (value) : "memory" );
		return ret;
	#endif
}

inline int atomicExchange(volatile int *target, int value)
{
	#if defined(_WIN32)
		return InterlockedExchange((volatile long*)target, (long)value);
	#else
		int ret;
		__asm__ __volatile__("lock; xchgl %x0,(%x1)" : "=r" (ret) :"r" (target), "0" (value) : "memory" );
		return ret;
	#endif
}
#endif

inline int atomicIncrement(volatile int *value)
{
	#if defined(_WIN32)
		return InterlockedIncrement((volatile long*)value);
	#else
		return __sync_add_and_fetch(value, 1);
	#endif
}

inline int atomicDecrement(volatile int *value)
{
	#if defined(_WIN32)
		return InterlockedDecrement((volatile long*)value);
	#else
		return __sync_sub_and_fetch(value, 1);
	#endif
}

inline int atomicAdd(volatile int* target, int value)
{
	#if defined(_WIN32)
		return InterlockedExchangeAdd((volatile long*)target, value) + value;
	#else
		return __sync_add_and_fetch(target, value);
	#endif
}

inline void nop()
{
	#if defined(_WIN32)
		__nop();
	#else
		__asm__ __volatile__ ("nop");
	#endif
}

#if USE_STD_ATOMIC
	class AtomicInt
	{
	public:
		AtomicInt() : ai() {}
		AtomicInt(int i) : ai(i) {}

		inline operator int() const { return ai.load(std::memory_order_acquire); }
		inline void operator=(const AtomicInt& i) { ai.store(i.ai.load(std::memory_order_acquire), std::memory_order_release); }
		inline void operator=(int i) { ai.store(i, std::memory_order_release); }
		inline void operator--() { ai.fetch_sub(1, std::memory_order_acq_rel); }
		inline void operator++() { ai.fetch_add(1, std::memory_order_acq_rel); }
		inline int operator--(int) { return ai.fetch_sub(1, std::memory_order_acq_rel) - 1; }
		inline int operator++(int) { return ai.fetch_add(1, std::memory_order_acq_rel) + 1; }
		inline void operator-=(int i) { ai.fetch_sub(i, std::memory_order_acq_rel); }
		inline void operator+=(int i) { ai.fetch_add(i, std::memory_order_acq_rel); }
	private:
		std::atomic<int> ai;
	};
#else
	class AtomicInt
	{
	public:
		AtomicInt() {}
		AtomicInt(int i) : vi(i) {}

		inline operator int() const { return vi; } // Note: this isn't a guaranteed atomic operation
		inline void operator=(const AtomicInt& i) { atomicExchange(&vi, i.vi); }
		inline void operator=(int i) { atomicExchange(&vi, i); }
		inline void operator--() { atomicDecrement(&vi); }
		inline void operator++() { atomicIncrement(&vi); }
		inline int operator--(int) { return atomicDecrement(&vi); }
		inline int operator++(int) { return atomicIncrement(&vi); }
		inline void operator-=(int i) { atomicAdd(&vi, -i); }
		inline void operator+=(int i) { atomicAdd(&vi, i); }
	private:
		volatile int vi;
	};
#endif

}  // namespace rr

#endif   // rr_Thread_hpp
