mirror of
https://github.com/InoriRus/Kyty.git
synced 2026-08-28 05:06:40 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTFLAG_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTFLAG_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Kernel/Pthread.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::LibKernel::EventFlag {
|
||||
|
||||
class KernelEventFlagPrivate;
|
||||
|
||||
using KernelEventFlag = KernelEventFlagPrivate*;
|
||||
|
||||
int KYTY_SYSV_ABI KernelCreateEventFlag(KernelEventFlag* ef, const char* name, uint32_t attr, uint64_t init_pattern, const void* param);
|
||||
int KYTY_SYSV_ABI KernelDeleteEventFlag(KernelEventFlag ef);
|
||||
int KYTY_SYSV_ABI KernelWaitEventFlag(KernelEventFlag ef, uint64_t bit_pattern, uint32_t wait_mode, uint64_t* result_pat,
|
||||
KernelUseconds* timeout);
|
||||
int KYTY_SYSV_ABI KernelPollEventFlag(KernelEventFlag ef, uint64_t bit_pattern, uint32_t wait_mode, uint64_t* result_pat);
|
||||
int KYTY_SYSV_ABI KernelSetEventFlag(KernelEventFlag ef, uint64_t bit_pattern);
|
||||
int KYTY_SYSV_ABI KernelClearEventFlag(KernelEventFlag ef, uint64_t bit_pattern);
|
||||
int KYTY_SYSV_ABI KernelCancelEventFlag(KernelEventFlag ef, uint64_t set_pattern, int* num_wait_threads);
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel::EventFlag
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTFLAG_H_ */
|
||||
@@ -0,0 +1,75 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTQUEUE_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTQUEUE_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Kernel/Pthread.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::LibKernel::EventQueue {
|
||||
|
||||
constexpr int16_t KERNEL_EVFILT_TIMER = -7;
|
||||
constexpr int16_t KERNEL_EVFILT_READ = -1;
|
||||
constexpr int16_t KERNEL_EVFILT_WRITE = -2;
|
||||
constexpr int16_t KERNEL_EVFILT_USER = -11;
|
||||
constexpr int16_t KERNEL_EVFILT_FILE = -4;
|
||||
constexpr int16_t KERNEL_EVFILT_GRAPHICS = -14;
|
||||
constexpr int16_t KERNEL_EVFILT_VIDEO_OUT = -13;
|
||||
constexpr int16_t KERNEL_EVFILT_HRTIMER = -15;
|
||||
|
||||
class KernelEqueuePrivate;
|
||||
struct KernelEqueueEvent;
|
||||
|
||||
using trigger_func_t = void (*)(KernelEqueueEvent* event, void* trigger_data);
|
||||
using reset_func_t = void (*)(KernelEqueueEvent* event);
|
||||
using delete_func_t = void (*)(KernelEqueueEvent* event);
|
||||
|
||||
struct KernelEvent
|
||||
{
|
||||
uintptr_t ident = 0;
|
||||
int16_t filter = 0;
|
||||
uint16_t flags = 0;
|
||||
uint32_t fflags = 0;
|
||||
intptr_t data = 0;
|
||||
void* udata = nullptr;
|
||||
};
|
||||
|
||||
struct KernelFilter
|
||||
{
|
||||
void* data = nullptr;
|
||||
trigger_func_t trigger_func = nullptr;
|
||||
reset_func_t reset_func = nullptr;
|
||||
delete_func_t delete_func = nullptr;
|
||||
};
|
||||
|
||||
struct KernelEqueueEvent
|
||||
{
|
||||
bool triggered = false;
|
||||
KernelEvent event;
|
||||
KernelFilter filter;
|
||||
};
|
||||
|
||||
using KernelEqueue = KernelEqueuePrivate*;
|
||||
|
||||
int KYTY_SYSV_ABI KernelAddEvent(KernelEqueue eq, const KernelEqueueEvent& event);
|
||||
int KYTY_SYSV_ABI KernelTriggerEvent(KernelEqueue eq, uintptr_t ident, int16_t filter, void* trigger_data);
|
||||
int KYTY_SYSV_ABI KernelDeleteEvent(KernelEqueue eq, uintptr_t ident, int16_t filter);
|
||||
|
||||
int KYTY_SYSV_ABI KernelCreateEqueue(KernelEqueue* eq, const char* name);
|
||||
int KYTY_SYSV_ABI KernelDeleteEqueue(KernelEqueue eq);
|
||||
int KYTY_SYSV_ABI KernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo);
|
||||
|
||||
intptr_t KYTY_SYSV_ABI KernelGetEventData(const KernelEvent* ev);
|
||||
intptr_t KYTY_SYSV_ABI KernelGetEventFflags(const KernelEvent* ev);
|
||||
int KYTY_SYSV_ABI KernelGetEventFilter(const KernelEvent* ev);
|
||||
uintptr_t KYTY_SYSV_ABI KernelGetEventId(const KernelEvent* ev);
|
||||
void* KYTY_SYSV_ABI KernelGetEventUserData(const KernelEvent* ev);
|
||||
int KYTY_SYSV_ABI KernelGetEventError(const KernelEvent* ev);
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel::EventQueue
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTQUEUE_H_ */
|
||||
@@ -0,0 +1,60 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_FILESYSTEM_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_FILESYSTEM_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Kernel/Pthread.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::LibKernel::FileSystem {
|
||||
|
||||
struct FileStat
|
||||
{
|
||||
uint32_t st_dev;
|
||||
uint32_t st_ino;
|
||||
uint16_t st_mode;
|
||||
uint16_t st_nlink;
|
||||
uint32_t st_uid;
|
||||
uint32_t st_gid;
|
||||
uint32_t st_rdev;
|
||||
KernelTimespec st_atim;
|
||||
KernelTimespec st_mtim;
|
||||
KernelTimespec st_ctim;
|
||||
int64_t st_size;
|
||||
int64_t st_blocks;
|
||||
uint32_t st_blksize;
|
||||
uint32_t st_flags;
|
||||
uint32_t st_gen;
|
||||
int32_t st_lspare;
|
||||
KernelTimespec st_birthtim;
|
||||
unsigned int: (8 / 2) * (16 - static_cast<int>(sizeof(KernelTimespec)));
|
||||
unsigned int: (8 / 2) * (16 - static_cast<int>(sizeof(KernelTimespec)));
|
||||
};
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(FileSystem);
|
||||
|
||||
void Mount(const String& folder, const String& point);
|
||||
void Umount(const String& folder_or_point);
|
||||
String GetRealFilename(const String& mounted_file_name);
|
||||
|
||||
int KYTY_SYSV_ABI KernelOpen(const char* path, int flags, uint16_t mode);
|
||||
int KYTY_SYSV_ABI KernelClose(int d);
|
||||
int64_t KYTY_SYSV_ABI KernelRead(int d, void* buf, size_t nbytes);
|
||||
int64_t KYTY_SYSV_ABI KernelPread(int d, void* buf, size_t nbytes, int64_t offset);
|
||||
int64_t KYTY_SYSV_ABI KernelWrite(int d, const void* buf, size_t nbytes);
|
||||
int64_t KYTY_SYSV_ABI KernelPwrite(int d, const void* buf, size_t nbytes, int64_t offset);
|
||||
int64_t KYTY_SYSV_ABI KernelLseek(int d, int64_t offset, int whence);
|
||||
int KYTY_SYSV_ABI KernelStat(const char* path, FileStat* sb);
|
||||
int KYTY_SYSV_ABI KernelFstat(int d, FileStat* sb);
|
||||
int KYTY_SYSV_ABI KernelUnlink(const char* path);
|
||||
int KYTY_SYSV_ABI KernelGetdirentries(int fd, char* buf, int nbytes, int64_t* basep);
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel::FileSystem
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_FILESYSTEM_H_ */
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_MEMORY_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_MEMORY_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::LibKernel::Memory {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Memory);
|
||||
|
||||
int KYTY_SYSV_ABI KernelMapNamedFlexibleMemory(void** addr_in_out, size_t len, int prot, int flags, const char* name);
|
||||
int KYTY_SYSV_ABI KernelMunmap(uint64_t vaddr, size_t len);
|
||||
size_t KYTY_SYSV_ABI KernelGetDirectMemorySize();
|
||||
int KYTY_SYSV_ABI KernelAllocateDirectMemory(int64_t search_start, int64_t search_end, size_t len, size_t alignment, int memory_type,
|
||||
int64_t* phys_addr_out);
|
||||
int KYTY_SYSV_ABI KernelReleaseDirectMemory(int64_t start, size_t len);
|
||||
int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int flags, int64_t direct_memory_start, size_t alignment);
|
||||
int KYTY_SYSV_ABI KernelQueryMemoryProtection(void* addr, void** start, void** end, int* prot);
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel::Memory
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_MEMORY_H_ */
|
||||
@@ -0,0 +1,159 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_PTHREAD_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_PTHREAD_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
// IWYU pragma: no_include <pthread.h>
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
extern "C" {
|
||||
struct sched_param;
|
||||
}
|
||||
|
||||
namespace Kyty::Loader {
|
||||
struct Program;
|
||||
} // namespace Kyty::Loader
|
||||
|
||||
namespace Kyty::Libs::LibKernel {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Pthread);
|
||||
|
||||
struct PthreadAttrPrivate;
|
||||
struct PthreadPrivate;
|
||||
struct PthreadMutexPrivate;
|
||||
struct PthreadMutexattrPrivate;
|
||||
struct PthreadRwlockPrivate;
|
||||
struct PthreadRwlockattrPrivate;
|
||||
struct PthreadCondattrPrivate;
|
||||
struct PthreadCondPrivate;
|
||||
|
||||
struct KernelTimespec
|
||||
{
|
||||
int64_t tv_sec;
|
||||
int64_t tv_nsec;
|
||||
};
|
||||
|
||||
struct KernelTimeval
|
||||
{
|
||||
int64_t tv_sec;
|
||||
int64_t tv_usec;
|
||||
};
|
||||
|
||||
using PthreadAttr = PthreadAttrPrivate*;
|
||||
using Pthread = PthreadPrivate*;
|
||||
using KernelCpumask = uint64_t;
|
||||
using PthreadMutex = PthreadMutexPrivate*;
|
||||
using PthreadMutexattr = PthreadMutexattrPrivate*;
|
||||
using KernelSchedParam = struct sched_param;
|
||||
using PthreadRwlock = PthreadRwlockPrivate*;
|
||||
using PthreadRwlockattr = PthreadRwlockattrPrivate*;
|
||||
using KernelUseconds = unsigned int;
|
||||
using PthreadCondattr = PthreadCondattrPrivate*;
|
||||
using PthreadCond = PthreadCondPrivate*;
|
||||
using KernelClockid = int32_t;
|
||||
|
||||
using pthread_entry_func_t = KYTY_SYSV_ABI void* (*)(void*);
|
||||
using thread_dtors_func_t = KYTY_SYSV_ABI void (*)();
|
||||
|
||||
void PthreadInitSelfForMainThread();
|
||||
void PthreadDeleteStaticObjects(Loader::Program* program);
|
||||
|
||||
int KYTY_SYSV_ABI PthreadMutexattrInit(PthreadMutexattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadMutexattrDestroy(PthreadMutexattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadMutexattrSettype(PthreadMutexattr* attr, int type);
|
||||
int KYTY_SYSV_ABI PthreadMutexattrSetprotocol(PthreadMutexattr* attr, int protocol);
|
||||
int KYTY_SYSV_ABI PthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name);
|
||||
int KYTY_SYSV_ABI PthreadMutexDestroy(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI PthreadMutexLock(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI PthreadMutexTrylock(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI PthreadMutexUnlock(PthreadMutex* mutex);
|
||||
|
||||
Pthread KYTY_SYSV_ABI PthreadSelf();
|
||||
int KYTY_SYSV_ABI PthreadCreate(Pthread* thread, const PthreadAttr* attr, pthread_entry_func_t entry, void* arg, const char* name);
|
||||
int KYTY_SYSV_ABI PthreadDetach(Pthread thread);
|
||||
int KYTY_SYSV_ABI PthreadJoin(Pthread thread, void** value);
|
||||
int KYTY_SYSV_ABI PthreadCancel(Pthread thread);
|
||||
int KYTY_SYSV_ABI PthreadSetcancelstate(int state, int* old_state);
|
||||
int KYTY_SYSV_ABI PthreadSetcanceltype(int type, int* old_type);
|
||||
void KYTY_SYSV_ABI PthreadTestcancel();
|
||||
void KYTY_SYSV_ABI PthreadExit(void* value);
|
||||
int KYTY_SYSV_ABI PthreadEqual(Pthread thread1, Pthread thread2);
|
||||
int KYTY_SYSV_ABI PthreadGetname(Pthread thread, char* name);
|
||||
int KYTY_SYSV_ABI KernelUsleep(KernelUseconds microseconds);
|
||||
unsigned int KYTY_SYSV_ABI KernelSleep(unsigned int seconds);
|
||||
int KYTY_SYSV_ABI KernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp);
|
||||
|
||||
void KYTY_SYSV_ABI KernelSetThreadDtors(thread_dtors_func_t dtors);
|
||||
|
||||
int KYTY_SYSV_ABI PthreadAttrInit(PthreadAttr* attr);
|
||||
int KYTY_SYSV_ABI PthreadAttrDestroy(PthreadAttr* attr);
|
||||
int KYTY_SYSV_ABI PthreadAttrGet(Pthread thread, PthreadAttr* attr);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetaffinity(const PthreadAttr* attr, KernelCpumask* mask);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetdetachstate(const PthreadAttr* attr, int* state);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetguardsize(const PthreadAttr* attr, size_t* guard_size);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetinheritsched(const PthreadAttr* attr, int* inherit_sched);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetschedparam(const PthreadAttr* attr, KernelSchedParam* param);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetschedpolicy(const PthreadAttr* attr, int* policy);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetstack(const PthreadAttr* __restrict attr, void** __restrict stack_addr, size_t* __restrict stack_size);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetstackaddr(const PthreadAttr* attr, void** stack_addr);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetstacksize(const PthreadAttr* attr, size_t* stack_size);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetaffinity(PthreadAttr* attr, KernelCpumask mask);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetdetachstate(PthreadAttr* attr, int state);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetguardsize(PthreadAttr* attr, size_t guard_size);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetinheritsched(PthreadAttr* attr, int inherit_sched);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetschedpolicy(PthreadAttr* attr, int policy);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetstack(PthreadAttr* attr, void* addr, size_t size);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetstackaddr(PthreadAttr* attr, void* addr);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetstacksize(PthreadAttr* attr, size_t stack_size);
|
||||
|
||||
int KYTY_SYSV_ABI PthreadRwlockDestroy(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockInit(PthreadRwlock* rwlock, const PthreadRwlockattr* attr, const char* name);
|
||||
int KYTY_SYSV_ABI PthreadRwlockRdlock(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockTimedrdlock(PthreadRwlock* rwlock, KernelUseconds usec);
|
||||
int KYTY_SYSV_ABI PthreadRwlockTimedwrlock(PthreadRwlock* rwlock, KernelUseconds usec);
|
||||
int KYTY_SYSV_ABI PthreadRwlockTryrdlock(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockTrywrlock(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockUnlock(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockWrlock(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockattrDestroy(PthreadRwlockattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadRwlockattrInit(PthreadRwlockattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadRwlockattrGettype(PthreadRwlockattr* attr, int* type);
|
||||
int KYTY_SYSV_ABI PthreadRwlockattrSettype(PthreadRwlockattr* attr, int type);
|
||||
|
||||
int KYTY_SYSV_ABI PthreadCondattrDestroy(PthreadCondattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadCondattrInit(PthreadCondattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadCondBroadcast(PthreadCond* cond);
|
||||
int KYTY_SYSV_ABI PthreadCondDestroy(PthreadCond* cond);
|
||||
int KYTY_SYSV_ABI PthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name);
|
||||
int KYTY_SYSV_ABI PthreadCondSignal(PthreadCond* cond);
|
||||
int KYTY_SYSV_ABI PthreadCondSignalto(PthreadCond* cond, Pthread thread);
|
||||
int KYTY_SYSV_ABI PthreadCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, KernelUseconds usec);
|
||||
int KYTY_SYSV_ABI PthreadCondWait(PthreadCond* cond, PthreadMutex* mutex);
|
||||
|
||||
int KYTY_SYSV_ABI KernelClockGetres(KernelClockid clock_id, KernelTimespec* tp);
|
||||
int KYTY_SYSV_ABI KernelClockGettime(KernelClockid clock_id, KernelTimespec* tp);
|
||||
int KYTY_SYSV_ABI KernelGettimeofday(KernelTimeval* tp);
|
||||
uint64_t KYTY_SYSV_ABI KernelGetTscFrequency();
|
||||
uint64_t KYTY_SYSV_ABI KernelReadTsc();
|
||||
uint64_t KYTY_SYSV_ABI KernelGetProcessTime();
|
||||
uint64_t KYTY_SYSV_ABI KernelGetProcessTimeCounter();
|
||||
uint64_t KYTY_SYSV_ABI KernelGetProcessTimeCounterFrequency();
|
||||
|
||||
int KYTY_SYSV_ABI pthread_cond_broadcast_s(PthreadCond* cond);
|
||||
int KYTY_SYSV_ABI pthread_cond_wait_s(PthreadCond* cond, PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI pthread_mutex_lock_s(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI pthread_mutex_unlock_s(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI pthread_rwlock_rdlock_s(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI pthread_rwlock_unlock_s(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI pthread_rwlock_wrlock_s(PthreadRwlock* rwlock);
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_PTHREAD_H_ */
|
||||
Reference in New Issue
Block a user