/* This file is part of jpcsp. Jpcsp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Jpcsp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.HLE.kernel.types; import jpcsp.Emulator; import jpcsp.HLE.Modules; import jpcsp.HLE.kernel.managers.SceUidManager; public class SceKernelThreadEventHandlerInfo extends pspAbstractMemoryMappedStructureVariableLength { public final String name; public final int thid; public int mask; public int handler; public final int common; private boolean active; // Internal info. public final int uid; private static final String uidPurpose = "ThreadMan-ThreadEventHandler"; // Thread Event IDs. public final static int THREAD_EVENT_ID_ALL = 0xFFFFFFFF; public final static int THREAD_EVENT_ID_KERN = 0xFFFFFFF8; public final static int THREAD_EVENT_ID_USER = 0xFFFFFFF0; public final static int THREAD_EVENT_ID_CURRENT = 0x0; // Thread Events. public final static int THREAD_EVENT_CREATE = 0x1; public final static int THREAD_EVENT_START = 0x2; public final static int THREAD_EVENT_EXIT = 0x4; public final static int THREAD_EVENT_DELETE = 0x8; public final static int THREAD_EVENT_ALL = 0xF; public SceKernelThreadEventHandlerInfo(String name, int thid, int mask, int handler, int common) { this.name = name; this.thid = thid; this.mask = mask; this.handler = handler; this.common = common; setActive(true); uid = SceUidManager.getNewUid(uidPurpose); } public void release() { SceUidManager.releaseUid(uid, uidPurpose); mask = 0; handler = 0; setActive(false); } public boolean hasEventMask(int event) { return (mask & event) == event; } public void triggerThreadEventHandler(SceKernelThreadInfo contextThread, int event) { // Execute the handler and preserve the complete CpuState (i.e. restore all the CPU register after the execution of the handler) Modules.ThreadManForUserModule.executeCallback(contextThread, handler, new AfterEventHandler(), false, true, event, thid, common); } public boolean appliesFor(SceKernelThreadInfo currentThread, SceKernelThreadInfo thread, int event) { if ((mask & event) == 0) { return false; } if (!isActive()) { return false; } if (!currentThread.isUserMode() && thread.isUserMode()) { return false; } if (thid == THREAD_EVENT_ID_ALL || thid == THREAD_EVENT_ID_KERN || thid == thread.uid) { return true; } if (thid == THREAD_EVENT_ID_USER && thread.isUserMode() && currentThread.isUserMode()) { return true; } return false; } public boolean isActive() { return active; } public void setActive(boolean active) { this.active = active; } @Override protected void write() { super.write(); writeStringNZ(32, name); write32(thid); write32(mask); write32(handler); write32(common); } private class AfterEventHandler implements IAction { @Override public void execute() { int result = Emulator.getProcessor().cpu._v0; // The event handler is deleted when it returns a value != 0 if (result != 0) { setActive(false); } if (Modules.log.isInfoEnabled()) { Modules.log.info(String.format("Thread Event Handler exit detected (thid=0x%X, result=0x%08X)", thid, result)); } } } }