2 * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
11 #include "app_model.h"
14 #include <l4/cxx/auto_ptr>
15 #include <l4/cxx/ref_ptr>
16 #include <l4/libloader/elf>
17 #include <l4/util/bitops.h>
23 #include <pthread-l4.h>
30 inline void *operator new (size_t, void *p) throw() { return p; }
31 namespace Lua { namespace {
33 class Observer : public Ned::Server_object
36 int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
39 static Observer *observer;
42 Observer::dispatch(l4_umword_t, L4::Ipc_iostream &ios)
44 l4_cap_idx_t thread = L4::Ipc::read<l4_cap_idx_t>(ios);
45 App_task *t = (App_task*)L4::Ipc::read<l4_addr_t>(ios);
47 if (t->state() == App_task::Zombie)
54 class Am : public Rmt_app_model
63 L4::Cap<L4::Factory> _rm_fab;
65 l4_umword_t _cfg_integer(char const *f, l4_umword_t def = 0)
68 lua_getfield(_lua, _cfg_idx, f);
69 if (lua_isnumber(_lua, -1))
70 r = lua_tointeger(_lua, -1);
76 void _cfg_cap(char const *f, l4_fpage_t *r)
78 lua_getfield(_lua, _cfg_idx, f);
79 while (lua_isfunction(_lua, -1))
81 lua_pushvalue(_lua, _cfg_idx);
85 if (!lua_isnil(_lua, -1))
87 Cap *c = Lua::check_cap(_lua, -1);
88 *r = c->cap<void>().fpage(c->rights());
95 explicit Am(lua_State *l)
96 : Rmt_app_model(), _lua(l), _argc(lua_gettop(l)), _env_idx(0), _cfg_idx(1),
99 if (_argc > 2 && lua_type(_lua, _argc) == LUA_TTABLE)
106 l4_cap_idx_t push_initial_caps(l4_cap_idx_t start)
108 lua_getfield(_lua, _cfg_idx, "caps");
109 int tab = lua_gettop(_lua);
111 if (lua_isnil(_lua, tab))
118 while (lua_next(_lua, tab))
120 char const *r = luaL_checkstring(_lua, -2);
121 while (lua_isfunction(_lua, -1))
123 lua_pushvalue(_lua, tab);
124 lua_call(_lua, 1, 1);
127 if (!lua_isnil(_lua, -1) && lua_touserdata(_lua, -1))
129 Lua::check_cap(_lua, -1);
130 _stack.push(l4re_env_cap_entry_t(r, start));
131 start += L4_CAP_OFFSET;
139 void map_initial_caps(L4::Cap<L4::Task> task, l4_cap_idx_t start)
141 lua_getfield(_lua, _cfg_idx, "caps");
142 int tab = lua_gettop(_lua);
144 if (lua_isnil(_lua, tab))
151 while (lua_next(_lua, tab))
153 luaL_checkstring(_lua, -2);
154 while (lua_isfunction(_lua, -1))
156 lua_pushvalue(_lua, tab);
157 lua_call(_lua, 1, 1);
160 if (!lua_isnil(_lua, -1) && lua_touserdata(_lua, -1))
162 Cap *c = Lua::check_cap(_lua, -1);
163 chksys(task->map(L4Re::This_task, c->cap<void>().fpage(c->rights()), L4::Cap<void>(start).snd_base() | c->ext_rights()));
164 start += L4_CAP_OFFSET;
173 prog_info()->mem_alloc = L4Re::Env::env()->mem_alloc().fpage();
174 prog_info()->log = L4Re::Env::env()->log().fpage();
175 prog_info()->factory = L4Re::Env::env()->factory().fpage();
176 prog_info()->scheduler = L4Re::Env::env()->scheduler().fpage();
177 // parser.scheduler_cap.set_fpage(&am.prog_info()->scheduler);
179 prog_info()->ldr_flags = 0;
180 prog_info()->l4re_dbg = 0;
185 prog_info()->ldr_flags = _cfg_integer("ldr_flags", prog_info()->ldr_flags);
186 prog_info()->l4re_dbg = _cfg_integer("l4re_dbg", prog_info()->l4re_dbg);
188 _cfg_cap("log", &prog_info()->log);
189 _cfg_cap("mem", &prog_info()->mem_alloc);
190 _cfg_cap("factory", &prog_info()->factory);
191 _cfg_cap("scheduler", &prog_info()->scheduler);
193 l4_fpage_t fab = prog_info()->mem_alloc;
194 _cfg_cap("rm_fab", &fab);
195 _rm_fab = L4::Cap<L4::Factory>(fab.raw);
198 void set_task(App_task *t) { _task = t; }
200 void push_argv_strings()
203 for (int i = _arg_idx; i <= _argc; ++i)
205 if (lua_isnil(_lua, i))
209 char const *r = luaL_checklstring(_lua, i, &l);
210 argv.al = _stack.push_str(r, l);
216 void push_env_strings()
223 while (lua_next(_lua, _env_idx))
226 char const *k = luaL_checklstring(_lua, -2, &kl);
228 char const *v = luaL_checklstring(_lua, -1, &vl);
230 _stack.push_str(v, vl);
232 envp.al = _stack.push_object(k, kl);
244 static char const *const APP_TASK_TYPE = "L4_NED_APP_TASK";
245 typedef cxx::Ref_ptr<App_task> App_ptr;
248 App_ptr &check_at(lua_State *l, int i)
250 App_ptr *t = (App_ptr*)luaL_checkudata(l, i, APP_TASK_TYPE);
254 static int __task_state(lua_State *l)
256 App_ptr t = check_at(l, 1);
266 case App_task::Initializing:
267 lua_pushstring(l, "initializing");
270 case App_task::Running:
271 lua_pushstring(l, "running");
274 case App_task::Zombie:
275 lua_pushstring(l, "zombie");
279 lua_pushstring(l, "nan");
286 static int __task_exit_code(lua_State *l)
288 App_ptr t = check_at(l, 1);
292 lua_pushinteger(l, t->exit_code());
297 static int __task_wait(lua_State *l)
299 App_ptr &t = check_at(l, 1);
307 if (Ned::server->registry()->reap_list()->remove(t.get()))
309 lua_pushinteger(l, t->exit_code());
314 L4::Ipc::Iostream s(l4_utcb());
315 s << pthread_getl4cap(pthread_self()) << l4_addr_t(t.get());
316 s.call(observer->obj_cap().cap());
318 if (Ned::server->registry()->reap_list()->remove(t.get()))
319 lua_pushinteger(l, t->exit_code());
327 static int __task_gc(lua_State *l)
329 App_ptr &t = check_at(l, 1);
330 t = 0; // drop reference to task
334 static int __task_eq(lua_State *l)
336 App_ptr const &t1 = check_at(l, 1);
337 App_ptr const &t2 = check_at(l, 2);
338 lua_pushboolean(l, t1 == t2);
342 static int __task_lt(lua_State *l)
344 App_ptr const &t1 = check_at(l, 1);
345 App_ptr const &t2 = check_at(l, 2);
346 lua_pushboolean(l, t1 < t2);
350 static int __task_le(lua_State *l)
352 App_ptr const &t1 = check_at(l, 1);
353 App_ptr const &t2 = check_at(l, 2);
354 lua_pushboolean(l, t1 <= t2);
358 static const luaL_Reg _task_ops[] = {
359 { "state", __task_state },
360 { "exit_code", __task_exit_code },
361 { "wait", __task_wait },
366 static int wait_any(lua_State *l)
368 using Ned::Server_object;
369 while (Server_object *t = Ned::server->registry()->reap_list()->remove(0))
371 App_ptr ap(dynamic_cast<App_task*>(t));
375 App_ptr *at = new (lua_newuserdata(l, sizeof(App_ptr))) App_ptr();
378 // remove the reap_list reference
381 luaL_newmetatable(l, APP_TASK_TYPE);
382 lua_setmetatable(l, -2);
390 //void do_some_exc_tests();
392 static int exec(lua_State *l)
398 L4::Cap<L4Re::Mem_alloc> mem_alloc(am.prog_info()->mem_alloc.raw);
400 typedef cxx::Ref_ptr<App_task> App_ptr;
402 App_ptr app_task(new App_task(Ned::server->registry(), L4::cap_dynamic_cast<L4::Factory>(mem_alloc)));
406 Err().printf("could not allocate task control block\n");
411 am.set_task(app_task.get());
413 typedef Ldr::Elf_loader<Am, Dbg> Loader;
415 Dbg ldr(Dbg::Loader, "ldr");
417 _l.launch(&am, "rom/l4re", ldr);
421 App_ptr *at = new (lua_newuserdata(l, sizeof(App_ptr))) App_ptr();
424 luaL_newmetatable(l, APP_TASK_TYPE);
425 lua_setmetatable(l, -2);
429 printf("LUA ============================== EXEC FAILED\n");
430 luaL_error(l, "could not create process");
436 void do_some_exc_tests()
439 char const *const cont = "Das ist ein lustiger test";
441 for (unsigned i = 0; i < strlen(cont); ++i)
444 volatile int *x = (int*)0x500;
445 //printf("Test Exc\n");
451 static const luaL_Reg _task_meta_ops[] = {
452 { "__gc", __task_gc },
453 { "__eq", __task_eq },
454 { "__lt", __task_lt },
455 { "__le", __task_le },
459 class Lib_exec : public Lib
462 Lib_exec() : Lib(P_env) {}
463 void init(lua_State *l)
465 static const luaL_Reg _ops[] =
468 { "wait_any", wait_any },
471 luaL_register(l, "L4", _ops);
473 if (luaL_newmetatable(l, APP_TASK_TYPE))
476 luaL_register(l, NULL, _task_ops);
477 lua_setfield(l, -2, "__index");
478 luaL_register(l, NULL, _task_meta_ops);
482 observer = new Observer();
483 Ned::server->registry()->register_obj(observer);
487 static Lib_exec __lib;