[add] first
This commit is contained in:
30
Libraries/libil2cpp/include/os/Posix/ConditionVariableImpl.h
Normal file
30
Libraries/libil2cpp/include/os/Posix/ConditionVariableImpl.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#if IL2CPP_THREADS_PTHREAD && !RUNTIME_TINY
|
||||
|
||||
#include <pthread.h>
|
||||
#include "utils/NonCopyable.h"
|
||||
|
||||
class FastMutexImpl;
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
class ConditionVariableImpl : public il2cpp::utils::NonCopyable
|
||||
{
|
||||
public:
|
||||
ConditionVariableImpl();
|
||||
~ConditionVariableImpl();
|
||||
|
||||
int Wait(FastMutexImpl* lock);
|
||||
int TimedWait(FastMutexImpl* lock, uint32_t timeout_ms);
|
||||
void Broadcast();
|
||||
void Signal();
|
||||
|
||||
private:
|
||||
pthread_cond_t m_ConditionVariable;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
15
Libraries/libil2cpp/include/os/Posix/Error.h
Normal file
15
Libraries/libil2cpp/include/os/Posix/Error.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "os/ErrorCodes.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
ErrorCode SocketErrnoToErrorCode(int32_t code);
|
||||
ErrorCode FileErrnoToErrorCode(int32_t code);
|
||||
ErrorCode PathErrnoToErrorCode(const std::string& path, int32_t code);
|
||||
}
|
||||
}
|
||||
26
Libraries/libil2cpp/include/os/Posix/EventImpl.h
Normal file
26
Libraries/libil2cpp/include/os/Posix/EventImpl.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#if IL2CPP_THREADS_PTHREAD && !RUNTIME_TINY
|
||||
|
||||
#include "os/ErrorCodes.h"
|
||||
#include "os/WaitStatus.h"
|
||||
#include "PosixWaitObject.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
class EventImpl : public posix::PosixWaitObject
|
||||
{
|
||||
public:
|
||||
EventImpl(bool manualReset = false, bool signaled = false);
|
||||
|
||||
ErrorCode Set();
|
||||
ErrorCode Reset();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
|
||||
#if IL2CPP_THREADS_PTHREAD && IL2CPP_SUPPORT_THREADS
|
||||
|
||||
#include <pthread.h>
|
||||
#include "MutexImpl.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
// The pthread reader writer lock takes a lock to update its state on lock and unlock
|
||||
// So if you're read case time is on the order of taking a lock, then it's faster
|
||||
// to just use a non-recursive mutex
|
||||
class FastReaderReaderWriterLockImpl
|
||||
{
|
||||
public:
|
||||
|
||||
FastReaderReaderWriterLockImpl()
|
||||
{
|
||||
pthread_mutex_init(&m_Mutex, NULL);
|
||||
}
|
||||
|
||||
~FastReaderReaderWriterLockImpl()
|
||||
{
|
||||
pthread_mutex_destroy(&m_Mutex);
|
||||
}
|
||||
|
||||
void LockExclusive()
|
||||
{
|
||||
pthread_mutex_lock(&m_Mutex);
|
||||
}
|
||||
|
||||
void LockShared()
|
||||
{
|
||||
pthread_mutex_lock(&m_Mutex);
|
||||
}
|
||||
|
||||
void ReleaseExclusive()
|
||||
{
|
||||
pthread_mutex_unlock(&m_Mutex);
|
||||
}
|
||||
|
||||
void ReleaseShared()
|
||||
{
|
||||
pthread_mutex_unlock(&m_Mutex);
|
||||
}
|
||||
|
||||
pthread_mutex_t* GetOSHandle()
|
||||
{
|
||||
return &m_Mutex;
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_Mutex;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
49
Libraries/libil2cpp/include/os/Posix/FileHandle.h
Normal file
49
Libraries/libil2cpp/include/os/Posix/FileHandle.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
|
||||
#if IL2CPP_TARGET_POSIX
|
||||
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include "os/File.h"
|
||||
#include "os/c-api/OSGlobalEnums.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
struct FileHandle
|
||||
{
|
||||
int fd;
|
||||
FileType type;
|
||||
std::string path;
|
||||
int options;
|
||||
int shareMode;
|
||||
int accessMode;
|
||||
|
||||
// The default value of this field should be false,
|
||||
// meaning we _do_ own the file descriptor, and therefore
|
||||
// can close it. Zero-allocating this struct is something
|
||||
// we want to support, so make sure the default is 0.
|
||||
bool doesNotOwnFd;
|
||||
|
||||
// device and inode are used as key for finding file handles
|
||||
dev_t device;
|
||||
ino_t inode;
|
||||
|
||||
// Linked list of file handles
|
||||
FileHandle *prev;
|
||||
FileHandle *next;
|
||||
|
||||
FileHandle()
|
||||
: fd(-1), type(kFileTypeUnknown), options(0), shareMode(0), accessMode(0),
|
||||
doesNotOwnFd(false), device(0), inode(0), prev(NULL), next(NULL)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
73
Libraries/libil2cpp/include/os/Posix/MutexImpl.h
Normal file
73
Libraries/libil2cpp/include/os/Posix/MutexImpl.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#if IL2CPP_THREADS_PTHREAD && !RUNTIME_TINY
|
||||
|
||||
#include "os/ErrorCodes.h"
|
||||
#include "os/WaitStatus.h"
|
||||
#include "PosixWaitObject.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
class Thread;
|
||||
|
||||
class MutexImpl : public posix::PosixWaitObject
|
||||
{
|
||||
public:
|
||||
MutexImpl();
|
||||
|
||||
void Lock(bool interruptible);
|
||||
bool TryLock(uint32_t milliseconds, bool interruptible);
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
/// Thread that currently owns the object. Used for recursion checks.
|
||||
Thread* m_OwningThread;
|
||||
|
||||
/// Number of recursive locks on the owning thread.
|
||||
uint32_t m_RecursionCount;
|
||||
};
|
||||
|
||||
class FastMutexImpl
|
||||
{
|
||||
public:
|
||||
|
||||
FastMutexImpl()
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&m_Mutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
|
||||
~FastMutexImpl()
|
||||
{
|
||||
pthread_mutex_destroy(&m_Mutex);
|
||||
}
|
||||
|
||||
void Lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_Mutex);
|
||||
}
|
||||
|
||||
void Unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_Mutex);
|
||||
}
|
||||
|
||||
pthread_mutex_t* GetOSHandle()
|
||||
{
|
||||
return &m_Mutex;
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_Mutex;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#if !IL2CPP_USE_NETWORK_ACCESS_HANDLER
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
// Define a stub for platforms that don't require requesting access to network hardware
|
||||
class NetworkAccessHandler
|
||||
{
|
||||
public:
|
||||
typedef int SocketDescriptor;
|
||||
|
||||
void InheritNetworkAccessState(SocketDescriptor _fd) {}
|
||||
void CancelNetworkAccess() {}
|
||||
bool RequestNetwork(SocketDescriptor _fd, const struct sockaddr *sa = NULL, int32_t sa_size = 0) { return true; }
|
||||
bool PrepareForBind(SocketDescriptor _fd, const struct sockaddr *sa = NULL, int32_t sa_size = 0) { return true; }
|
||||
#if IL2CPP_SUPPORT_IPV6
|
||||
bool PrepareForBind(SocketDescriptor _fd, const struct sockaddr_in6* sa = NULL, int32_t sa_size = 0) { return true; }
|
||||
#endif
|
||||
bool PrepareForConnect(SocketDescriptor _fd, const struct sockaddr *sa = NULL, int32_t sa_size = 0) { return true; }
|
||||
bool WaitForNetworkStatus(SocketDescriptor _fd, bool isConnect = false) { return true; }
|
||||
|
||||
int32_t GetError() { return 0; }
|
||||
|
||||
class Auto
|
||||
{
|
||||
public:
|
||||
bool RequestAccessForAddressInfo(bool isLocalNetworkMode = false) { return true; }
|
||||
int32_t GetError() { return 0; }
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
65
Libraries/libil2cpp/include/os/Posix/PosixHelpers.h
Normal file
65
Libraries/libil2cpp/include/os/Posix/PosixHelpers.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#if (IL2CPP_TARGET_POSIX || IL2CPP_SUPPORT_SOCKETS_POSIX_API) && !RUNTIME_TINY
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include <sys/poll.h>
|
||||
#include "os/Thread.h"
|
||||
#include "os/Socket.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
namespace posix
|
||||
{
|
||||
inline timespec Ticks100NanosecondsToTimespec(int64_t ticks)
|
||||
{
|
||||
timespec result;
|
||||
result.tv_sec = ticks / 10000000;
|
||||
result.tv_nsec = (ticks % 10000000) * 100;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline timespec MillisecondsToTimespec(uint32_t ms)
|
||||
{
|
||||
timespec result;
|
||||
result.tv_sec = ms / 1000;
|
||||
result.tv_nsec = (ms % 1000) * 1000000;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Thread::ThreadId PosixThreadIdToThreadId(pthread_t thread)
|
||||
{
|
||||
Thread::ThreadId threadId = 0;
|
||||
memcpy(&threadId, &thread, std::min(sizeof(threadId), sizeof(thread)));
|
||||
return threadId;
|
||||
}
|
||||
|
||||
struct PosixAutoLock
|
||||
{
|
||||
pthread_mutex_t* mutex;
|
||||
PosixAutoLock(pthread_mutex_t* m)
|
||||
: mutex(m) { pthread_mutex_lock(mutex); }
|
||||
~PosixAutoLock()
|
||||
{ pthread_mutex_unlock(mutex); }
|
||||
};
|
||||
|
||||
|
||||
inline short PollFlagsToPollEvents(PollFlags flags)
|
||||
{
|
||||
return (short)flags;
|
||||
}
|
||||
|
||||
inline PollFlags PollEventsToPollFlags(short events)
|
||||
{
|
||||
return (PollFlags)events;
|
||||
}
|
||||
|
||||
int Poll(pollfd* handles, int numHandles, int timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // IL2CPP_TARGET_POSIX
|
||||
97
Libraries/libil2cpp/include/os/Posix/PosixWaitObject.h
Normal file
97
Libraries/libil2cpp/include/os/Posix/PosixWaitObject.h
Normal file
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#if IL2CPP_TARGET_POSIX && !RUNTIME_TINY
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include "utils/NonCopyable.h"
|
||||
#include "os/WaitStatus.h"
|
||||
|
||||
|
||||
#if (IL2CPP_USE_POSIX_COND_TIMEDWAIT_REL)
|
||||
int pthread_cond_timedwait_relative_np(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *spec);
|
||||
#endif
|
||||
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
class ThreadImpl;
|
||||
|
||||
namespace posix
|
||||
{
|
||||
const uint32_t kNoTimeout = UINT_MAX;
|
||||
|
||||
|
||||
////TODO: generalize this so that it can be used with c++11 condition variables
|
||||
|
||||
|
||||
/// Base class for all synchronization primitives when running on POSIX.
|
||||
///
|
||||
/// To support interruption and timeouts for all synchronization primitives (events, mutexes, and
|
||||
/// semaphores) we implement these primitives ourselves instead of using their standard POSIX/Mach
|
||||
/// system counterparts. See PosixWaitObject.cpp for an explanation why.
|
||||
class PosixWaitObject : public il2cpp::utils::NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
~PosixWaitObject();
|
||||
|
||||
WaitStatus Wait(bool interruptible = false);
|
||||
WaitStatus Wait(uint32_t ms, bool interruptible = false);
|
||||
|
||||
/// Cause an ongoing blocking wait on this object to exit and check for pending APCs.
|
||||
/// If the object is not currently being waited on, will cause the next wait to exit
|
||||
/// right away and check for APCs. After APCs have been handled, the object will go
|
||||
/// back to waiting except if the wait timeout has expired.
|
||||
void InterruptWait();
|
||||
|
||||
void* GetOSHandle();
|
||||
|
||||
static void LockWaitObjectDeletion();
|
||||
static void UnlockWaitObjectDeletion();
|
||||
|
||||
protected:
|
||||
|
||||
enum Type
|
||||
{
|
||||
kMutex, /// All mutexes are recursive.
|
||||
kManualResetEvent,
|
||||
kAutoResetEvent,
|
||||
kSemaphore
|
||||
};
|
||||
|
||||
PosixWaitObject(Type type);
|
||||
|
||||
Type m_Type;
|
||||
|
||||
/// Always have to acquire this mutex to touch m_Count.
|
||||
pthread_mutex_t m_Mutex;
|
||||
|
||||
/// Signal other threads of changes to m_Count.
|
||||
pthread_cond_t m_Condition;
|
||||
|
||||
/// "Release" count for the primitive. Means different things depending on the type of primitive
|
||||
/// but for all primitives, we wait until this is zero. Semaphores are the only primitive for which
|
||||
/// this can go past 1.
|
||||
uint32_t m_Count;
|
||||
|
||||
/// Number of threads waiting on this object. This is used to prevent unnecessary signals
|
||||
/// on m_Condition.
|
||||
uint32_t m_WaitingThreadCount;
|
||||
|
||||
bool HaveWaitingThreads() const { return (m_WaitingThreadCount != 0); }
|
||||
};
|
||||
|
||||
struct AutoLockWaitObjectDeletion
|
||||
{
|
||||
AutoLockWaitObjectDeletion() { PosixWaitObject::LockWaitObjectDeletion(); }
|
||||
~AutoLockWaitObjectDeletion() { PosixWaitObject::UnlockWaitObjectDeletion(); }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // IL2CPP_TARGET_POSIX
|
||||
70
Libraries/libil2cpp/include/os/Posix/ReaderWriterLockImpl.h
Normal file
70
Libraries/libil2cpp/include/os/Posix/ReaderWriterLockImpl.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
|
||||
#if IL2CPP_THREADS_PTHREAD && IL2CPP_SUPPORT_THREADS
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
class ReaderWriterLockImpl
|
||||
{
|
||||
public:
|
||||
|
||||
ReaderWriterLockImpl()
|
||||
{
|
||||
int result = pthread_rwlock_init(&m_Lock, NULL);
|
||||
NO_UNUSED_WARNING(result);
|
||||
IL2CPP_ASSERT(result == 0);
|
||||
}
|
||||
|
||||
~ReaderWriterLockImpl()
|
||||
{
|
||||
int result = pthread_rwlock_destroy(&m_Lock);
|
||||
NO_UNUSED_WARNING(result);
|
||||
IL2CPP_ASSERT(result == 0);
|
||||
}
|
||||
|
||||
void LockExclusive()
|
||||
{
|
||||
int result = pthread_rwlock_wrlock(&m_Lock);
|
||||
NO_UNUSED_WARNING(result);
|
||||
IL2CPP_ASSERT(result == 0);
|
||||
}
|
||||
|
||||
void LockShared()
|
||||
{
|
||||
int result = pthread_rwlock_rdlock(&m_Lock);
|
||||
NO_UNUSED_WARNING(result);
|
||||
IL2CPP_ASSERT(result == 0);
|
||||
}
|
||||
|
||||
void ReleaseExclusive()
|
||||
{
|
||||
int result = pthread_rwlock_unlock(&m_Lock);
|
||||
NO_UNUSED_WARNING(result);
|
||||
IL2CPP_ASSERT(result == 0);
|
||||
}
|
||||
|
||||
void ReleaseShared()
|
||||
{
|
||||
int result = pthread_rwlock_unlock(&m_Lock);
|
||||
NO_UNUSED_WARNING(result);
|
||||
IL2CPP_ASSERT(result == 0);
|
||||
}
|
||||
|
||||
pthread_rwlock_t* GetOSHandle()
|
||||
{
|
||||
return &m_Lock;
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_rwlock_t m_Lock;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
28
Libraries/libil2cpp/include/os/Posix/SemaphoreImpl.h
Normal file
28
Libraries/libil2cpp/include/os/Posix/SemaphoreImpl.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#if IL2CPP_THREADS_PTHREAD && !RUNTIME_TINY
|
||||
|
||||
#include "PosixWaitObject.h"
|
||||
#include "os/ErrorCodes.h"
|
||||
#include "os/WaitStatus.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
class SemaphoreImpl : public posix::PosixWaitObject
|
||||
{
|
||||
public:
|
||||
SemaphoreImpl(int32_t initialValue, int32_t maximumValue);
|
||||
|
||||
bool Post(int32_t releaseCount, int32_t* previousCount);
|
||||
|
||||
protected:
|
||||
uint32_t m_MaximumValue;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
146
Libraries/libil2cpp/include/os/Posix/SocketImpl.h
Normal file
146
Libraries/libil2cpp/include/os/Posix/SocketImpl.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#pragma once
|
||||
|
||||
#if (IL2CPP_TARGET_POSIX || IL2CPP_SUPPORT_SOCKETS_POSIX_API) && !RUNTIME_TINY
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "os/Socket.h"
|
||||
#include "os/ErrorCodes.h"
|
||||
#include "os/WaitStatus.h"
|
||||
#include "utils/Expected.h"
|
||||
#include "utils/NonCopyable.h"
|
||||
#if IL2CPP_USE_NETWORK_ACCESS_HANDLER
|
||||
#include "os/NetworkAccessHandler.h"
|
||||
#else
|
||||
#include "NetworkAccessHandlerStub.h"
|
||||
#endif
|
||||
|
||||
struct sockaddr;
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
class SocketImpl : public il2cpp::utils::NonCopyable
|
||||
{
|
||||
public:
|
||||
typedef int SocketDescriptor;
|
||||
|
||||
SocketImpl(ThreadStatusCallback thread_status_callback);
|
||||
~SocketImpl();
|
||||
|
||||
inline SocketDescriptor GetDescriptor()
|
||||
{
|
||||
return _fd;
|
||||
}
|
||||
|
||||
ErrorCode GetLastError() const;
|
||||
|
||||
WaitStatus Create(SocketDescriptor fd, int32_t family, int32_t type, int32_t protocol);
|
||||
WaitStatus Create(AddressFamily family, SocketType type, ProtocolType protocol);
|
||||
WaitStatus Close();
|
||||
|
||||
bool IsClosed()
|
||||
{
|
||||
return (_fd == -1);
|
||||
}
|
||||
|
||||
WaitStatus SetBlocking(bool blocking);
|
||||
|
||||
WaitStatus Listen(int32_t blacklog);
|
||||
|
||||
WaitStatus Bind(const char *path);
|
||||
WaitStatus Bind(const char *address, uint16_t port);
|
||||
WaitStatus Bind(uint32_t address, uint16_t port);
|
||||
utils::Expected<WaitStatus> Bind(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port);
|
||||
|
||||
WaitStatus Connect(const char *path);
|
||||
WaitStatus Connect(uint32_t address, uint16_t port);
|
||||
utils::Expected<WaitStatus> Connect(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port);
|
||||
|
||||
WaitStatus Disconnect(bool reuse);
|
||||
WaitStatus Shutdown(int32_t how);
|
||||
|
||||
WaitStatus GetLocalEndPointInfo(EndPointInfo &info);
|
||||
WaitStatus GetRemoteEndPointInfo(EndPointInfo &info);
|
||||
|
||||
WaitStatus Receive(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len);
|
||||
WaitStatus ReceiveFromInternal(const uint8_t *data, size_t count, int32_t flags, int32_t *len, struct sockaddr *from, int32_t *fromlen);
|
||||
|
||||
WaitStatus Send(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len);
|
||||
|
||||
WaitStatus SendArray(WSABuf *wsabufs, int32_t count, int32_t *sent, SocketFlags c_flags);
|
||||
WaitStatus ReceiveArray(WSABuf *wsabufs, int32_t count, int32_t *len, SocketFlags c_flags);
|
||||
|
||||
WaitStatus SendTo(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len);
|
||||
WaitStatus SendTo(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len);
|
||||
utils::Expected<WaitStatus> SendTo(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len);
|
||||
|
||||
WaitStatus RecvFrom(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep);
|
||||
WaitStatus RecvFrom(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep);
|
||||
utils::Expected<WaitStatus> RecvFrom(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep);
|
||||
|
||||
WaitStatus Available(int32_t *amount);
|
||||
|
||||
WaitStatus Accept(os::Socket **socket);
|
||||
|
||||
WaitStatus Ioctl(int32_t command, const uint8_t *in_data, int32_t in_len, uint8_t *out_data, int32_t out_len, int32_t *written);
|
||||
|
||||
WaitStatus GetSocketOption(SocketOptionLevel level, SocketOptionName name, uint8_t *buffer, int32_t *length);
|
||||
WaitStatus GetSocketOptionFull(SocketOptionLevel level, SocketOptionName name, int32_t *first, int32_t *second);
|
||||
|
||||
WaitStatus SetSocketOption(SocketOptionLevel level, SocketOptionName name, int32_t value);
|
||||
WaitStatus SetSocketOptionLinger(SocketOptionLevel level, SocketOptionName name, bool enabled, int32_t seconds);
|
||||
WaitStatus SetSocketOptionArray(SocketOptionLevel level, SocketOptionName name, const uint8_t *buffer, int32_t length);
|
||||
WaitStatus SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, uint32_t group_address, uint32_t local_address);
|
||||
#if IL2CPP_SUPPORT_IPV6
|
||||
WaitStatus SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, IPv6Address ipv6, uint64_t interfaceOffset);
|
||||
#endif
|
||||
|
||||
#if IL2CPP_SUPPORT_IPV6_SUPPORT_QUERY
|
||||
static bool IsIPv6Supported();
|
||||
#endif
|
||||
|
||||
WaitStatus SendFile(const char *filename, TransmitFileBuffers *buffers, TransmitFileOptions options);
|
||||
|
||||
static WaitStatus Poll(std::vector<PollRequest> &requests, int32_t count, int32_t timeout, int32_t *result, int32_t *error);
|
||||
static WaitStatus Poll(std::vector<PollRequest> &requests, int32_t timeout, int32_t *result, int32_t *error);
|
||||
static WaitStatus Poll(PollRequest& request, int32_t timeout, int32_t *result, int32_t *error);
|
||||
|
||||
static WaitStatus GetHostName(std::string &name);
|
||||
static WaitStatus GetHostByName(const std::string &host, std::string &name, std::vector<std::string> &aliases, std::vector<std::string> &addresses);
|
||||
static WaitStatus GetHostByName(const std::string &host, std::string &name, int32_t &family, std::vector<std::string> &aliases, std::vector<void*> &addr_list, int32_t &addr_size);
|
||||
static WaitStatus GetHostByAddr(const std::string &address, std::string &name, std::vector<std::string> &aliases, std::vector<std::string> &addr_list);
|
||||
|
||||
static void Startup();
|
||||
static void Cleanup();
|
||||
|
||||
static bool is_private(const struct sockaddr *sa, socklen_t sa_size);
|
||||
static bool is_private(const char* address);
|
||||
|
||||
private:
|
||||
|
||||
bool _is_valid;
|
||||
SocketDescriptor _fd;
|
||||
int32_t _domain;
|
||||
int32_t _type;
|
||||
int32_t _protocol;
|
||||
ErrorCode _saved_error;
|
||||
int32_t _still_readable;
|
||||
ThreadStatusCallback _thread_status_callback;
|
||||
NetworkAccessHandler _networkAccess;
|
||||
|
||||
void StoreLastError();
|
||||
void StoreLastError(int32_t error_no);
|
||||
|
||||
WaitStatus ConnectInternal(struct sockaddr *sa, int32_t sa_size);
|
||||
WaitStatus SendToInternal(struct sockaddr *sa, int32_t sa_size, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len);
|
||||
WaitStatus SetSocketOptionInternal(int32_t level, int32_t name, const void *value, int32_t len);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
112
Libraries/libil2cpp/include/os/Posix/ThreadImpl.h
Normal file
112
Libraries/libil2cpp/include/os/Posix/ThreadImpl.h
Normal file
@@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
|
||||
#if !IL2CPP_THREADS_STD && IL2CPP_THREADS_PTHREAD && !RUNTIME_TINY
|
||||
|
||||
#include <pthread.h>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
|
||||
#include "PosixWaitObject.h"
|
||||
#include "os/ErrorCodes.h"
|
||||
#include "os/Mutex.h"
|
||||
#include "os/Event.h"
|
||||
#include "os/Thread.h"
|
||||
#include "os/WaitStatus.h"
|
||||
#include "utils/NonCopyable.h"
|
||||
|
||||
#if defined(IL2CPP_ENABLE_PLATFORM_THREAD_AFFINTY)
|
||||
struct cpu_set_t;
|
||||
int pthread_attr_setaffinity_np(pthread_attr_t *attr, size_t cpusetsize, const cpu_set_t *cpuset);
|
||||
#endif
|
||||
|
||||
#if defined(IL2CPP_ENABLE_PLATFORM_THREAD_RENAME)
|
||||
int pthread_setname_np(pthread_t handle, const char *name);
|
||||
#endif
|
||||
|
||||
#if !defined(IL2CPP_DEFAULT_STACK_SIZE)
|
||||
#define IL2CPP_DEFAULT_STACK_SIZE ( 1 * 1024 * 1024) // default .NET stacksize is 1mb
|
||||
#endif
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
/// POSIX threads implementation. Supports APCs and interruptible waits.
|
||||
class ThreadImpl : public il2cpp::utils::NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
ThreadImpl();
|
||||
~ThreadImpl();
|
||||
|
||||
uint64_t Id();
|
||||
ErrorCode Run(Thread::StartFunc func, void* arg, int64_t affinityMask);
|
||||
void QueueUserAPC(Thread::APCFunc func, void* context);
|
||||
void SetName(const char* name);
|
||||
void SetPriority(ThreadPriority priority);
|
||||
ThreadPriority GetPriority();
|
||||
void SetStackSize(size_t newsize);
|
||||
static int GetMaxStackSize();
|
||||
|
||||
/// Handle any pending APCs.
|
||||
/// NOTE: Can only be called on current thread.
|
||||
void CheckForUserAPCAndHandle();
|
||||
|
||||
static void Sleep(uint32_t milliseconds, bool interruptible);
|
||||
static uint64_t CurrentThreadId();
|
||||
static ThreadImpl* GetCurrentThread();
|
||||
static ThreadImpl* CreateForCurrentThread();
|
||||
|
||||
static bool YieldInternal();
|
||||
|
||||
#if IL2CPP_HAS_NATIVE_THREAD_CLEANUP
|
||||
static void SetNativeThreadCleanup(Thread::ThreadCleanupFunc cleanupFunction);
|
||||
static void RegisterCurrentThreadForCleanup(void* arg);
|
||||
static void UnregisterCurrentThreadForCleanup();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
friend class posix::PosixWaitObject; // SetWaitObject(), CheckForAPCAndHandle()
|
||||
|
||||
std::atomic<pthread_t> m_Handle;
|
||||
|
||||
/// The synchronization primitive that this thread is currently blocked on.
|
||||
///
|
||||
/// NOTE: This field effectively turns these wait object into shared resources -- which makes deletion
|
||||
/// a tricky affair. To avoid one thread trying to interrupt a wait while the other thread already
|
||||
/// is in progress of deleting the wait object, we use a global mutex in PosixWaitObject.cpp that
|
||||
/// must be locked by any thread trying to trigger an interrupt.
|
||||
posix::PosixWaitObject* m_CurrentWaitObject;
|
||||
|
||||
/// Start data.
|
||||
Thread::StartFunc m_StartFunc;
|
||||
void* m_StartArg;
|
||||
|
||||
/// List of APC requests for this thread.
|
||||
struct APCRequest
|
||||
{
|
||||
Thread::APCFunc callback;
|
||||
void* context;
|
||||
|
||||
APCRequest(Thread::APCFunc callback, void* context) :
|
||||
callback(callback), context(context)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
pthread_mutex_t m_PendingAPCsMutex;
|
||||
std::vector<APCRequest> m_PendingAPCs;
|
||||
|
||||
size_t m_StackSize; // size of stack (can not be adjusted after thread creation)
|
||||
|
||||
/// Set the synchronization object the thread is about to wait on.
|
||||
/// NOTE: This can only be called on the current thread.
|
||||
void SetWaitObject(posix::PosixWaitObject* waitObject);
|
||||
|
||||
static void* ThreadStartWrapper(void* arg);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
118
Libraries/libil2cpp/include/os/Posix/ThreadLocalValueImpl.h
Normal file
118
Libraries/libil2cpp/include/os/Posix/ThreadLocalValueImpl.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#if IL2CPP_THREADS_PTHREAD
|
||||
|
||||
#include "os/ErrorCodes.h"
|
||||
#include "utils/NonCopyable.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
class ThreadLocalValueImpl : public il2cpp::utils::NonCopyable
|
||||
{
|
||||
public:
|
||||
inline ThreadLocalValueImpl()
|
||||
{
|
||||
pthread_key_t key;
|
||||
int result = pthread_key_create(&key, NULL);
|
||||
IL2CPP_ASSERT(result == 0);
|
||||
NO_UNUSED_WARNING(result);
|
||||
|
||||
m_Key = key;
|
||||
}
|
||||
|
||||
inline ~ThreadLocalValueImpl()
|
||||
{
|
||||
int result = pthread_key_delete(m_Key);
|
||||
IL2CPP_ASSERT(result == 0);
|
||||
NO_UNUSED_WARNING(result);
|
||||
}
|
||||
|
||||
inline ErrorCode SetValue(void* value)
|
||||
{
|
||||
#if IL2CPP_TARGET_DARWIN
|
||||
apple_pthread_setspecific_direct(m_Key, value);
|
||||
#else
|
||||
if (pthread_setspecific(m_Key, value))
|
||||
return kErrorCodeGenFailure;
|
||||
#endif
|
||||
|
||||
return kErrorCodeSuccess;
|
||||
}
|
||||
|
||||
inline ErrorCode GetValue(void** value)
|
||||
{
|
||||
#if IL2CPP_TARGET_DARWIN
|
||||
*value = apple_pthread_getspecific_direct(m_Key);
|
||||
#else
|
||||
*value = pthread_getspecific(m_Key);
|
||||
#endif
|
||||
|
||||
return kErrorCodeSuccess;
|
||||
}
|
||||
|
||||
private:
|
||||
#if IL2CPP_TARGET_DARWIN
|
||||
static inline void * apple_pthread_getspecific_direct(unsigned long slot)
|
||||
{
|
||||
void *ret;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
__asm__ ("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void**)(slot * sizeof(void *))));
|
||||
#elif (defined(__arm__) && (defined(_ARM_ARCH_6) || defined(_ARM_ARCH_5)))
|
||||
void **__pthread_tsd;
|
||||
#if defined(__arm__) && defined(_ARM_ARCH_6)
|
||||
uintptr_t __pthread_tpid;
|
||||
__asm__ ("mrc p15, 0, %0, c13, c0, 3" : "=r" (__pthread_tpid));
|
||||
__pthread_tsd = (void**)(__pthread_tpid & ~0x3ul);
|
||||
#elif defined(__arm__) && defined(_ARM_ARCH_5)
|
||||
register uintptr_t __pthread_tpid asm ("r9");
|
||||
__pthread_tsd = (void**)__pthread_tpid;
|
||||
#endif
|
||||
ret = __pthread_tsd[slot];
|
||||
#elif defined(__arm64__)
|
||||
ret = pthread_getspecific(slot);
|
||||
#else
|
||||
#error no _pthread_getspecific_direct implementation for this arch
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static void apple_pthread_setspecific_direct(unsigned long slot, void * val)
|
||||
{
|
||||
#if defined(__i386__)
|
||||
#if defined(__PIC__)
|
||||
__asm__ ("movl %1,%%gs:%0" : "=m" (*(void**)(slot * sizeof(void *))) : "rn" (val));
|
||||
#else
|
||||
__asm__ ("movl %1,%%gs:%0" : "=m" (*(void**)(slot * sizeof(void *))) : "ri" (val));
|
||||
#endif
|
||||
#elif defined(__x86_64__)
|
||||
/* PIC is free and cannot be disabled, even with: gcc -mdynamic-no-pic ... */
|
||||
__asm__ ("movq %1,%%gs:%0" : "=m" (*(void**)(slot * sizeof(void *))) : "rn" (val));
|
||||
#elif (defined(__arm__) && (defined(_ARM_ARCH_6) || defined(_ARM_ARCH_5)))
|
||||
void **__pthread_tsd;
|
||||
#if defined(__arm__) && defined(_ARM_ARCH_6)
|
||||
uintptr_t __pthread_tpid;
|
||||
__asm__ ("mrc p15, 0, %0, c13, c0, 3" : "=r" (__pthread_tpid));
|
||||
__pthread_tsd = (void**)(__pthread_tpid & ~0x3ul);
|
||||
#elif defined(__arm__) && defined(_ARM_ARCH_5)
|
||||
register uintptr_t __pthread_tpid asm ("r9");
|
||||
__pthread_tsd = (void**)__pthread_tpid;
|
||||
#endif
|
||||
__pthread_tsd[slot] = val;
|
||||
#elif defined(__arm64__)
|
||||
pthread_setspecific(slot, val);
|
||||
#else
|
||||
#error no _pthread_setspecific_direct implementation for this arch
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
pthread_key_t m_Key;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user