package erjang.m.erts_internal;
import erjang.*;
import erjang.m.erlang.ErlProc;
import kilim.Pausable;
public class Native extends ENative {
static final EAtom am_check_process_code = EAtom.intern("check_process_code");
static final EAtom am_garbage_collect = EAtom.intern("garbage_collect");
@BIF
public static EAtom is_system_process(EObject pid) {
return ERT.FALSE;
}
private static boolean check_process_code(EModule mod)
{
Class mc = mod.getClass();
String className = mc.getName();
for (Class c : sm.getClassContext()) {
if (className.equals(c.getName()) && mc != c) {
return true;
}
}
return false;
}
/*
-spec request_system_task(Pid, Prio, Request) -> 'ok' when
Prio :: 'max' | 'high' | 'normal' | 'low',
Request :: {'garbage_collect', term()}
| {'check_process_code', term(), module(), boolean()},
Pid :: pid().
*/
@BIF
public static EAtom request_system_task(final EProc self, EObject pid0, EObject prio0, EObject request0)
throws Pausable
{
EInternalPID pid = pid0.testInternalPID();
EAtom prio = prio0.testAtom();
ETuple4 cpc = ETuple4.cast(request0);
ETuple2 gc = ETuple2.cast(request0);
if (pid == null || prio == null || (cpc==null && gc==null))
throw ERT.badarg(pid0, prio0, request0);
EObject ref;
EAtom module, allow_gc;
if (cpc != null
&& cpc.elem1 == am_check_process_code
&& (ref = cpc.elem2) != null
&& (module = cpc.elem3.testAtom()) != null
&& (allow_gc = cpc.elem4.testBoolean()) != null) {
final EModule mod = EModuleManager.get_loaded_module(module);
final EObject final_ref = ref;
if (mod == null || !pid.is_alive_dirtyread()) {
self.mbox_send(ETuple3.make_tuple(am_check_process_code, ref, ERT.FALSE));
} else if (pid0 == self.self_handle()) {
self.mbox_send(ETuple3.make_tuple(
am_check_process_code,
ref,
ERT.box(check_process_code(mod))));
} else {
Runnable runner =
new Runnable() {
@Override
public void run() {
self.mbox()
.putb(ETuple3.make_tuple(
am_check_process_code,
final_ref,
ERT.box(check_process_code(mod))));
}
};
pid.task().runOnStack(runner);
}
} else if (gc != null
&& gc.elem1 == am_garbage_collect
&& (ref = gc.elem2) != null) {
// We cannot force GC of a single process...
self.mbox_send(ETuple3.make_tuple(am_garbage_collect, ref, ERT.TRUE));
} else {
throw ERT.badarg(pid0, prio0, request0);
}
return ERT.am_ok;
}
static SM sm = new SM();
static class SM extends SecurityManager {
@Override
public Class[] getClassContext() {
return super.getClassContext();
}
}
}