96 lines
2.9 KiB
C
96 lines
2.9 KiB
C
|
#pragma once
|
||
|
|
||
|
#include <3ds/types.h>
|
||
|
#include <3ds/synchronization.h>
|
||
|
#include "intrusive_list.h"
|
||
|
|
||
|
#define FOREACH_PROCESS(list, process) \
|
||
|
for (process = ProcessList_GetFirst(list); !ProcessList_TestEnd(list, process); process = ProcessList_GetNext(process))
|
||
|
|
||
|
enum {
|
||
|
PROCESSFLAG_NOTIFY_TERMINATION = BIT(0),
|
||
|
PROCESSFLAG_KIP = BIT(1),
|
||
|
PROCESSFLAG_DEPENDENCIES_LOADED = BIT(2),
|
||
|
PROCESSFLAG_AUTOLOADED = BIT(3),
|
||
|
PROCESSFLAG_NOTIFY_TERMINATION_TERMINATED = BIT(4),
|
||
|
PROCESSFLAG_NORMAL_APPLICATION = BIT(5), // Official PM doesn't have this
|
||
|
};
|
||
|
|
||
|
typedef enum TerminationStatus {
|
||
|
TERMSTATUS_RUNNING = 0,
|
||
|
TERMSTATUS_NOTIFICATION_SENT = 1,
|
||
|
TERMSTATUS_NOTIFICATION_FAILED = 2,
|
||
|
TERMSTATUS_TERMINATED = 3,
|
||
|
} TerminationStatus;
|
||
|
|
||
|
typedef struct ProcessData {
|
||
|
IntrusiveNode node;
|
||
|
Handle handle;
|
||
|
u32 pid;
|
||
|
u64 titleId;
|
||
|
u64 programHandle;
|
||
|
u8 flags;
|
||
|
u8 terminatedNotificationVariation;
|
||
|
TerminationStatus terminationStatus;
|
||
|
u8 refcount;
|
||
|
} ProcessData;
|
||
|
|
||
|
typedef struct ProcessList {
|
||
|
RecursiveLock lock;
|
||
|
IntrusiveList list;
|
||
|
IntrusiveList freeList;
|
||
|
} ProcessList;
|
||
|
|
||
|
static inline void ProcessList_Init(ProcessList *list, void *buf, size_t num)
|
||
|
{
|
||
|
IntrusiveList_Init(&list->list);
|
||
|
IntrusiveList_CreateFromBuffer(&list->freeList, buf, sizeof(ProcessData), sizeof(ProcessData) * num);
|
||
|
RecursiveLock_Init(&list->lock);
|
||
|
}
|
||
|
|
||
|
static inline void ProcessList_Lock(ProcessList *list)
|
||
|
{
|
||
|
RecursiveLock_Lock(&list->lock);
|
||
|
}
|
||
|
|
||
|
static inline void ProcessList_Unlock(ProcessList *list)
|
||
|
{
|
||
|
RecursiveLock_Unlock(&list->lock);
|
||
|
}
|
||
|
|
||
|
static inline ProcessData *ProcessList_GetNext(const ProcessData *process)
|
||
|
{
|
||
|
return (ProcessData *)process->node.next;
|
||
|
}
|
||
|
|
||
|
static inline ProcessData *ProcessList_GetPrev(const ProcessData *process)
|
||
|
{
|
||
|
return (ProcessData *)process->node.next;
|
||
|
}
|
||
|
|
||
|
static inline ProcessData *ProcessList_GetFirst(const ProcessList *list)
|
||
|
{
|
||
|
return (ProcessData *)list->list.first;
|
||
|
}
|
||
|
|
||
|
static inline ProcessData *ProcessList_GetLast(const ProcessList *list)
|
||
|
{
|
||
|
return (ProcessData *)list->list.last;
|
||
|
}
|
||
|
|
||
|
static inline bool ProcessList_TestEnd(const ProcessList *list, const ProcessData *process)
|
||
|
{
|
||
|
return IntrusiveList_TestEnd(&list->list, &process->node);
|
||
|
}
|
||
|
|
||
|
ProcessData *ProcessList_New(ProcessList *list);
|
||
|
void ProcessList_Delete(ProcessList *list, ProcessData *process);
|
||
|
|
||
|
ProcessData *ProcessList_FindProcessById(const ProcessList *list, u32 pid);
|
||
|
ProcessData *ProcessList_FindProcessByTitleId(const ProcessList *list, u64 titleId);
|
||
|
ProcessData *ProcessList_FindProcessByHandle(const ProcessList *list, Handle handle);
|
||
|
|
||
|
void ProcessData_Incref(ProcessData *process, u32 amount);
|
||
|
Result ProcessData_Notify(const ProcessData *process, u32 notificationId);
|
||
|
Result ProcessData_SendTerminationNotification(ProcessData *process);
|