diff options
author | Alexis211 <alexis211@gmail.com> | 2010-04-05 16:56:17 +0200 |
---|---|---|
committer | Alexis211 <alexis211@gmail.com> | 2010-04-05 16:56:17 +0200 |
commit | 8d94ae49601e0e4023bcdc35191669b2c24f6c96 (patch) | |
tree | 64d625ee6aa5a897666be2768d009b2353ba97d9 /src/library/gc/server.c | |
parent | b945eafa126d6a17aa8826a405df7d5d4d999008 (diff) | |
download | TCE-8d94ae49601e0e4023bcdc35191669b2c24f6c96.tar.gz TCE-8d94ae49601e0e4023bcdc35191669b2c24f6c96.zip |
More work on IPC.
Diffstat (limited to 'src/library/gc/server.c')
-rw-r--r-- | src/library/gc/server.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/library/gc/server.c b/src/library/gc/server.c new file mode 100644 index 0000000..9fd1616 --- /dev/null +++ b/src/library/gc/server.c @@ -0,0 +1,206 @@ +#include <gc/server.h> +#include <gm/method.h> +#include <gc/mem.h> +#include <gc/shm.h> + +Server procServer; +static Server* servers = 0; + +static method_handler getHandler(Server *o, uint32_t m); +static struct method_ret checkIfHandles(struct method_data *d); +static struct method_ret checkIfHandlesMany(struct method_data *d); + +void objsrv_init() { + procServer.id = 0; + procServer.methods = 0; + procServer.next = 0; + procServer.data = 0; + servers = &procServer; + srv_addHandler(&procServer, M_HANDLECHECK_BIVV, checkIfHandles); + srv_addHandler(&procServer, M_HANDLECHECK_BMIV, checkIfHandlesMany); +} + +void srv_handleAll() { + Server *i = servers; + while (i) { + srv_handle(i, HA_ONCE); + i = i->next; + } +} + +void srv_handle(Server *o, int act) { + int i; + + if (act == HA_LOOP) { + while (1) srv_handle(o, HA_WAIT); + } else { + struct user_request rq; + int v = request_get(o->id, &rq, (act == HA_WAIT)); + if (v == 0) { + method_handler m = getHandler(o, rq.func); + if (m == 0) { + if (rq.isBlocking) { + request_answer(o->id, 0, 0, ME_UNHANDLED); + } + } else { + struct method_data md; + md.func = rq.func; + md.blocking = rq.isBlocking; + md.obj = o; + //get parameters + for (i = 0; i < 3; i++) { + md.parameters[i].type = (rq.func >> (28 - (2 * i))) & 3; + switch (md.parameters[i].type) { + case PT_LONG: + case PT_OBJDESC: + md.parameters[i].val.i = rq.params[i]; + break; + case PT_SHM: //all the fuss about keepShm only applies to messages. + md.parameters[i].keepShm = 1; //if local memory or if nothing, do not unmap it + if (rq.params[i] == 0) { //TODO : map shm (shm manager) !!! + void* p = shm_alloc(rq.shmsize[i]); + md.parameters[i].val.p = p; + if (p != 0) { + request_mapShm(o->id, (size_t)p, i); + md.parameters[i].keepShm = 0; //we had to map it, so mark it to be unmapped + } + } else { + md.parameters[i].val.p = (void*)rq.params[i]; + } + break; + } + } + + struct method_ret ret = m(&md); //Call method + if (rq.isBlocking) { + uint32_t a = 0, b = 0; + if (ret.type == PT_OBJDESC || ret.type == PT_LONG) a = ret.i; + if (ret.type == PT_LONGLONG) a = (uint32_t)ret.l, b = (uint32_t)((uint64_t)ret.l >> 32); + request_answer(o->id, a, b, ret.status); + } else { + for (i = 0; i < 3; i++) { + if (md.parameters[i].type == PT_SHM && md.parameters[i].keepShm == 0) { + shm_freeDel(md.parameters[i].val.p); + } + } + } + } + } + } +} + +void srv_addHandler(Server* o, uint32_t method, method_handler h) { + struct method_srv *s = malloc(sizeof(struct method_srv)); + s->id = method; + s->h = h; + s->next = o->methods; + o->methods = s; +} + +Server *srv_create() { + Server *s = malloc(sizeof(Server)); + s->id = object_create(); + s->methods = 0; + s->data = 0; + s->next = servers; + srv_addHandler(s, M_HANDLECHECK_BIVV, checkIfHandles); + srv_addHandler(s, M_HANDLECHECK_BMIV, checkIfHandlesMany); + servers = s; + return s; +} + +Server *srv_get(int descriptor) { + Server *s = servers; + while (s) { + if (s->id == descriptor) return s; + s = s->next; + } + return 0; +} + +void srv_delete(Server* s) { + //remove s from servers + if (servers == s) { + servers = s->next; + } else { + Server *i = servers; + while (i->next != 0) { + if (i->next == s) { + i->next = s->next; + break; + } + i = i->next; + } + } + //close s + object_close(s->id); + //free methods for s + while (s->methods != 0) { + struct method_srv *m = s->methods->next; + free(s->methods); + s->methods = m; + } + //free s + free(s); +} + +// internal use + +method_handler getHandler(Server *o, uint32_t m) { + struct method_srv *i = o->methods; + while (i) { + if (i->id == m) return i->h; + i = i->next; + } + return 0; +} + +struct method_ret checkIfHandles(struct method_data *d) { + if (getHandler(d->obj, d->parameters[0].val.i) == 0) { + return mr_long(0); + } + return mr_long(1); +} + +struct method_ret checkIfHandlesMany(struct method_data *d) { + if (d->parameters[0].type != PT_SHM) return mr_err(-1); + if (d->parameters[1].type != PT_LONG) return mr_err(-1); + uint32_t *data = d->parameters[0].val.p, i; + if (data == 0) return mr_long(0); + for (i = 0; i < d->parameters[1].val.i; i++) { + if (getHandler(d->obj, data[i]) == 0) return mr_long(0); + } + return mr_long(1); +} + +// ***************************** HELPER FUNCTIONS FOR RETRUN VALUES + +struct method_ret mr_long(int val) { + struct method_ret r; r.status = 0; r.type = PT_LONG; r.i = val; + return r; +} + +struct method_ret mr_llong(int64_t val) { + struct method_ret r; r.status = 0; r.type = PT_LONGLONG; r.l = val; + return r; +} + +struct method_ret mr_obj(Object* obj) { + struct method_ret r; r.status = 0; r.type = PT_OBJDESC; r.i = obj->id; + return r; +} + +struct method_ret mr_srv(Server* obj) { + struct method_ret r; r.status = 0; r.type = PT_OBJDESC; r.i = obj->id; + return r; +} + +struct method_ret mr_void() { + struct method_ret r; r.status = 0; r.type = PT_VOID; + return r; +} + +struct method_ret mr_err(int error) { + struct method_ret r; r.status = error; r.type = PT_VOID; r.l = 0; + return r; +} |