diff options
author | eutarass | 2009-12-31 00:30:41 +0000 |
---|---|---|
committer | eutarass | 2009-12-31 00:30:41 +0000 |
commit | e4d12adfd4e4aa10a6c9c83e5d0654c5c5dff60a (patch) | |
tree | 9912c34cc78a466a0cf64deafcfc8a0ccb070551 /server/services/context-proxy.c | |
parent | cda6e73f09ab43ccfed996362ffaf43852b2da20 (diff) | |
download | org.eclipse.tcf.agent-e4d12adfd4e4aa10a6c9c83e5d0654c5c5dff60a.tar.gz org.eclipse.tcf.agent-e4d12adfd4e4aa10a6c9c83e5d0654c5c5dff60a.tar.xz org.eclipse.tcf.agent-e4d12adfd4e4aa10a6c9c83e5d0654c5c5dff60a.zip |
TCF Agent: more value-add support: run control and memory map caches are now working
Diffstat (limited to 'server/services/context-proxy.c')
-rw-r--r-- | server/services/context-proxy.c | 472 |
1 files changed, 341 insertions, 131 deletions
diff --git a/server/services/context-proxy.c b/server/services/context-proxy.c index b494e9e5..8cc4750f 100644 --- a/server/services/context-proxy.c +++ b/server/services/context-proxy.c @@ -25,6 +25,7 @@ #include "stdio.h" #include "context.h" #include "myalloc.h" +#include "trace.h" #include "exceptions.h" #include "protocol.h" #include "json.h" @@ -32,24 +33,29 @@ #include "memorymap.h" #include "context-proxy.h" +#define ENABLE_CACHE_PRELOAD 1 + typedef struct ContextCache ContextCache; typedef struct MemoryCache MemoryCache; typedef struct PeerCache PeerCache; struct ContextCache { + LINK link_peer; + char id[256]; char parent_id[256]; Context * ctx; PeerCache * peer; - AbstractCache cache; /* Memory Map */ - ErrorReport * mem_regions_error; - unsigned mem_regions_cnt; - MemoryRegion * mem_regions; - ReplyHandlerInfo * pending_get_map; + AbstractCache mmap_cache; + ErrorReport * mmap_error; + unsigned mmap_size; + MemoryRegion * mmap_regions; + ReplyHandlerInfo * pending_get_mmap; /* Register definitions */ + AbstractCache regs_cache; ErrorReport * reg_error; unsigned reg_cnt; char ** reg_ids; @@ -65,10 +71,8 @@ struct ContextCache { long can_resume; long can_count; int can_terminate; - + /* Run Control State */ - int state_valid; - int is_suspended; int pc_valid; int64_t suspend_pc; char suspend_reason[256]; @@ -78,7 +82,7 @@ struct ContextCache { }; struct MemoryCache { - LINK link; + LINK link_ctx; AbstractCache cache; int canceled; ErrorReport * error; @@ -90,6 +94,7 @@ struct MemoryCache { struct PeerCache { LINK link_all; + LINK ctx_cache; Channel * host; Channel * target; ForwardingInputStream fwd; @@ -97,7 +102,8 @@ struct PeerCache { }; #define peers2peer(A) ((PeerCache *)((char *)(A) - offsetof(PeerCache, link_all))) -#define mems2mem(A) ((MemoryCache *)((char *)(A) - offsetof(MemoryCache, link))) +#define peer2ctx(A) ((ContextCache *)((char *)(A) - offsetof(ContextCache, link_peer))) +#define ctx2mem(A) ((MemoryCache *)((char *)(A) - offsetof(MemoryCache, link_ctx))) static LINK peers; @@ -175,69 +181,13 @@ static void read_ids_item(InputStream * inp, void * args) { str_buf_pos += n; } -static int validate_context_cache(Channel * c, void * args, int error) { - ContextCache * cache = (ContextCache *)args; - - assert(cache->peer->target == c); - if (cache->ctx->parent == NULL) { - /* Get memory map */ - if (cache->pending_get_map != NULL) { - assert(cache->mem_regions == NULL); - cache->mem_regions_error = get_error_report(error); - if (!error) { - cache->mem_regions_error = get_error_report(read_errno(&c->inp)); - if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); - mem_buf_pos = 0; - json_read_array(&c->inp, read_memory_map_item, NULL); - cache->mem_regions_cnt = mem_buf_pos; - cache->mem_regions = loc_alloc(sizeof(MemoryRegion) * mem_buf_pos); - memcpy(cache->mem_regions, mem_buf, sizeof(MemoryRegion) * mem_buf_pos); - if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); - if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); - } - } - else if (cache->mem_regions == NULL && cache->mem_regions_error == 0) { - cache->pending_get_map = protocol_send_command(c, "MemoryMap", "get", validate_context_cache, args); - write_stringz(&c->out, container_id(cache->ctx)); - write_stream(&c->out, MARKER_EOM); - flush_stream(&c->out); - return 0; - } - } - else { - /* Get register descriptions */ - if (cache->pending_get_regs != NULL) { - assert(cache->reg_ids == NULL); - assert(cache->reg_ids_str == NULL); - cache->reg_error = get_error_report(error); - if (!error) { - unsigned i; - cache->reg_error = get_error_report(read_errno(&c->inp)); - if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); - ids_buf_pos = 0; - str_buf_pos = 0; - json_read_array(&c->inp, read_ids_item, NULL); - cache->reg_cnt = ids_buf_pos; - cache->reg_ids = loc_alloc(sizeof(char *) * ids_buf_pos); - cache->reg_ids_str = loc_alloc(str_buf_pos); - memcpy(cache->reg_ids_str, str_buf, str_buf_pos); - for (i = 0; i < cache->reg_cnt; i++) { - cache->reg_ids[i] = cache->reg_ids_str + ids_buf[i]; - } - if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); - if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); - } - } - else if (cache->reg_ids == NULL && cache->reg_error == 0) { - cache->pending_get_regs = protocol_send_command(c, "Registers", "getChildren", validate_context_cache, args); - write_stringz(&c->out, thread_id(cache->ctx)); - write_stream(&c->out, MARKER_EOM); - flush_stream(&c->out); - return 0; - } +static ContextCache * find_context_cache(PeerCache * p, char * id) { + LINK * l; + for (l = p->ctx_cache.next; l != &p->ctx_cache; l = l->next) { + ContextCache * c = peer2ctx(l); + if (strcmp(c->id, id) == 0) return c; } - - return 1; + return NULL; } static void read_run_control_context_property(InputStream * inp, char * name, void * args) { @@ -259,37 +209,124 @@ static void read_context_suspended_data(InputStream * inp, char * name, void * a } static void read_context_added_item(InputStream * inp, void * args) { - ContextCache ctx; - memset(&ctx, 0, sizeof(ctx)); - json_read_struct(inp, read_run_control_context_property, &ctx); - printf("added %s\n", ctx.id); + PeerCache * p = (PeerCache *)args; + ContextCache * c = loc_alloc_zero(sizeof(ContextCache)); + + list_init(&c->mem_cache); + list_add_first(&c->link_peer, &p->ctx_cache); + c->peer = p; + json_read_struct(inp, read_run_control_context_property, c); + + c->ctx = (Context *)loc_alloc_zero(sizeof(Context)); + list_init(&c->ctx->children); + list_init(&c->ctx->cldl); + c->ctx->pid = id2pid(c->id, NULL); + c->ctx->mem = c->ctx->pid; + c->ctx->proxy = c; + c->ctx->ref_count = 1; + if (c->parent_id[0]) { + ContextCache * h = find_context_cache(p, c->parent_id); + if (h == NULL) { + trace(LOG_ALWAYS, "Invalid parent ID in 'context added' event: %s", c->parent_id); + } + else { + c->ctx->parent = h->ctx; + c->ctx->mem = h->ctx->mem; + h->ctx->ref_count++; + list_add_last(&c->ctx->cldl, &h->ctx->children); + } + } + send_context_created_event(c->ctx); } static void read_context_changed_item(InputStream * inp, void * args) { - ContextCache ctx; - memset(&ctx, 0, sizeof(ctx)); - json_read_struct(inp, read_run_control_context_property, &ctx); - printf("changed %s\n", ctx.id); + PeerCache * p = (PeerCache *)args; + ContextCache * c = NULL; + ContextCache buf; + memset(&buf, 0, sizeof(buf)); + json_read_struct(inp, read_run_control_context_property, &buf); + c = find_context_cache(p, buf.id); + if (c == NULL) { + trace(LOG_ALWAYS, "Invalid ID in 'context changed' event: %s", buf.id); + } + else { + strcpy(c->parent_id, buf.parent_id); + c->has_state = buf.has_state; + c->is_container = buf.is_container; + c->can_suspend = buf.can_suspend; + c->can_resume = buf.can_resume; + c->can_count = buf.can_count; + c->can_terminate = buf.can_terminate; + if (c->mmap_regions != NULL || c->mmap_error != NULL) { + release_error_report(c->mmap_error); + loc_free(c->mmap_regions); + c->mmap_error = NULL; + c->mmap_regions = NULL; + c->mmap_size = 0; + } + send_context_changed_event(c->ctx); + } } static void read_context_removed_item(InputStream * inp, void * args) { + PeerCache * p = (PeerCache *)args; + ContextCache * c = NULL; char id[256]; json_read_string(inp, id, sizeof(id)); - printf("removed %s\n", id); + c = find_context_cache(p, id); + if (c == NULL) { + trace(LOG_ALWAYS, "Invalid ID in 'context removed' event: %s", id); + } + else { + assert(c->ctx->proxy == c); + c->ctx->exited = 1; + send_context_exited_event(c->ctx); + if (c->ctx->parent != NULL) { + list_remove(&c->ctx->cldl); + context_unlock(c->ctx->parent); + c->ctx->parent = NULL; + } + context_unlock(c->ctx); + } } static void read_container_suspended_item(InputStream * inp, void * args) { PeerCache * p = (PeerCache *)args; + ContextCache * c = NULL; char id[256]; json_read_string(inp, id, sizeof(id)); - printf("suspended %s\n", id); + c = find_context_cache(p, id); + if (c == NULL) { + trace(LOG_ALWAYS, "Invalid ID in 'container suspended' event: %s", id); + } + else { + assert(c->ctx->proxy == c); + if (!c->ctx->stopped) { + c->ctx->stopped = 1; + c->ctx->intercepted = 1; + send_context_stopped_event(c->ctx); + } + } } static void read_container_resumed_item(InputStream * inp, void * args) { PeerCache * p = (PeerCache *)args; + ContextCache * c = NULL; char id[256]; json_read_string(inp, id, sizeof(id)); - printf("resumed %s\n", id); + c = find_context_cache(p, id); + if (c == NULL) { + trace(LOG_ALWAYS, "Invalid ID in 'container resumed' event: %s", id); + } + else { + assert(c->ctx->proxy == c); + if (c->ctx->stopped) { + c->ctx->stopped = 0; + c->ctx->intercepted = 0; + c->pc_valid = 0; + send_context_started_event(c->ctx); + } + } } static void event_context_added(Channel * c, void * args) { @@ -297,7 +334,7 @@ static void event_context_added(Channel * c, void * args) { write_stringz(&p->host->out, "E"); write_stringz(&p->host->out, RUN_CONTROL); write_stringz(&p->host->out, "contextAdded"); - json_read_array(p->fwd_inp, read_context_added_item, NULL); + json_read_array(p->fwd_inp, read_context_added_item, p); if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(p->fwd_inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); } @@ -307,7 +344,7 @@ static void event_context_changed(Channel * c, void * args) { write_stringz(&p->host->out, "E"); write_stringz(&p->host->out, RUN_CONTROL); write_stringz(&p->host->out, "contextChanged"); - json_read_array(p->fwd_inp, read_context_changed_item, NULL); + json_read_array(p->fwd_inp, read_context_changed_item, p); if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(p->fwd_inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); } @@ -317,17 +354,20 @@ static void event_context_removed(Channel * c, void * args) { write_stringz(&p->host->out, "E"); write_stringz(&p->host->out, RUN_CONTROL); write_stringz(&p->host->out, "contextRemoved"); - json_read_array(p->fwd_inp, read_context_removed_item, NULL); + json_read_array(p->fwd_inp, read_context_removed_item, p); if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(p->fwd_inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); } -static void event_context_suspended(Channel * c, void * args) { +static void event_context_suspended(Channel * ch, void * args) { PeerCache * p = (PeerCache *)args; + ContextCache * c = NULL; char id[256]; - char reason[256]; + char reason[sizeof(c->suspend_reason)]; int64_t pc; - ContextCache ctx; + ContextCache buf; + + assert(p->target == ch); write_stringz(&p->host->out, "E"); write_stringz(&p->host->out, RUN_CONTROL); write_stringz(&p->host->out, "contextSuspended"); @@ -337,20 +377,53 @@ static void event_context_suspended(Channel * c, void * args) { if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX); json_read_string(p->fwd_inp, reason, sizeof(reason)); if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX); - json_read_struct(p->fwd_inp, read_context_suspended_data, &ctx); + json_read_struct(p->fwd_inp, read_context_suspended_data, &buf); if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(p->fwd_inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); + + c = find_context_cache(p, id); + if (c == NULL) { + trace(LOG_ALWAYS, "Invalid ID in 'context suspended' event: %s", id); + } + else { + assert(c->ctx->proxy == c); + c->pc_valid = 1; + c->suspend_pc = pc; + strcpy(c->suspend_reason, reason); + if (!c->ctx->stopped) { + c->ctx->stopped = 1; + c->ctx->intercepted = 1; + send_context_stopped_event(c->ctx); + } + } } -static void event_context_resumed(Channel * c, void * args) { +static void event_context_resumed(Channel * ch, void * args) { PeerCache * p = (PeerCache *)args; + ContextCache * c = NULL; char id[256]; + + assert(p->target == ch); write_stringz(&p->host->out, "E"); write_stringz(&p->host->out, RUN_CONTROL); write_stringz(&p->host->out, "contextResumed"); json_read_string(p->fwd_inp, id, sizeof(id)); if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(p->fwd_inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); + + c = find_context_cache(p, id); + if (c == NULL) { + trace(LOG_ALWAYS, "Invalid ID in 'context resumed' event: %s", id); + } + else { + assert(c->ctx->proxy == c); + if (c->ctx->stopped) { + c->ctx->stopped = 0; + c->ctx->intercepted = 0; + c->pc_valid = 0; + send_context_started_event(c->ctx); + } + } } static void event_container_suspended(Channel * c, void * args) { @@ -385,11 +458,6 @@ static void event_container_resumed(Channel * c, void * args) { if (read_stream(p->fwd_inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); } -static ContextCache * alloc_context_cache(void) { - ContextCache * c = loc_alloc_zero(sizeof(ContextCache)); - list_init(&c->mem_cache); -} - void create_context_proxy(Channel * host, Channel * target) { LINK * l; PeerCache * p; @@ -401,6 +469,7 @@ void create_context_proxy(Channel * host, Channel * target) { p->host = host; p->target = target; p->fwd_inp = create_forwarding_input_stream(&p->fwd, &target->inp, &host->out); + list_init(&p->ctx_cache); list_add_first(&p->link_all, &peers); channel_lock(host); channel_lock(target); @@ -414,40 +483,45 @@ void create_context_proxy(Channel * host, Channel * target) { } void context_lock(Context * ctx) { - assert(ctx->ref_count > 0); ctx->ref_count++; } +static void free_context_cache(ContextCache * c) { + assert(c->pending_get_mmap == NULL); + assert(c->pending_get_regs == NULL); + assert(!c->mmap_cache.posted); + assert(!c->regs_cache.posted); + if (c->peer != NULL) list_remove(&c->link_peer); + release_error_report(c->mmap_error); + release_error_report(c->reg_error); + loc_free(c->mmap_regions); + loc_free(c->reg_ids); + loc_free(c->reg_ids_str); + loc_free(c->reg_defs); + while (!list_is_empty(&c->mem_cache)) { + MemoryCache * m = ctx2mem(c->mem_cache.next); + list_remove(&m->link_ctx); + if (!m->pending_command || protocol_cancel_command(m->pending_command)) { + release_error_report(m->error); + loc_free(m->buf); + loc_free(m); + } + else { + m->canceled = 1; + } + } + loc_free(c); +} + void context_unlock(Context * ctx) { assert(ctx->ref_count > 0); if (--ctx->ref_count == 0) { ContextCache * c = ctx->proxy; assert(list_is_empty(&ctx->children)); assert(ctx->parent == NULL); - assert(c->pending_get_map == NULL); - assert(c->pending_get_regs == NULL); - list_remove(&ctx->ctxl); - list_remove(&ctx->pidl); - release_error_report(ctx->regs_error); - loc_free(ctx->bp_ids); - loc_free(ctx->regs); loc_free(ctx); - loc_free(c->mem_regions); - loc_free(c->reg_ids); - loc_free(c->reg_ids_str); - loc_free(c->reg_defs); - while (!list_is_empty(&c->mem_cache)) { - MemoryCache * m = mems2mem(c->mem_cache.next); - list_remove(&m->link); - if (m->pending_command != NULL) { - m->canceled = 1; - } - else { - loc_free(m->buf); - loc_free(m); - } - } - loc_free(c); + c->ctx = NULL; + free_context_cache(c); } } @@ -457,12 +531,13 @@ Context * id2ctx(char * id) { int context_has_state(Context * ctx) { ContextCache * cache = (ContextCache *)ctx->proxy; - if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->cache); return cache->has_state; } static void validate_memory_cache(Channel * c, void * args, int error) { MemoryCache * m = (MemoryCache *)args; + assert(m->pending_command != NULL); + m->pending_command = NULL; m->error = get_error_report(error); if (!error) { size_t pos = 0; @@ -476,10 +551,15 @@ static void validate_memory_cache(Channel * c, void * args, int error) { json_read_binary_end(&state); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); m->error = get_error_report(read_errno(&c->inp)); - - + while (read_stream(&c->inp) != 0) {} if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); } + cache_notify(&m->cache); + if (m->canceled) { + release_error_report(m->error); + loc_free(m->buf); + loc_free(m); + } } int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t size) { @@ -494,7 +574,7 @@ int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t s LINK * l = NULL; for (l = cache->mem_cache.next; l != &cache->mem_cache; l = l->next) { - m = mems2mem(l); + m = ctx2mem(l); if (address >= m->addr && address + size <= m->addr + m->size) { if (m->pending_command != NULL) cache_wait(&m->cache); memcpy(buf, (int8_t *)m->buf + (address - m->addr), size); @@ -523,29 +603,101 @@ int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t s return -1; } +static void validate_memory_map_cache(Channel * c, void * args, int error) { + ContextCache * cache = (ContextCache *)args; + + assert(cache->peer->target == c); + assert(cache->ctx->parent == NULL); + assert(cache->mmap_regions == NULL); + assert(cache->pending_get_mmap != NULL); + cache->pending_get_mmap = NULL; + cache->mmap_error = get_error_report(error); + if (!error) { + cache->mmap_error = get_error_report(read_errno(&c->inp)); + mem_buf_pos = 0; + json_read_array(&c->inp, read_memory_map_item, NULL); + cache->mmap_size = mem_buf_pos; + cache->mmap_regions = loc_alloc(sizeof(MemoryRegion) * mem_buf_pos); + memcpy(cache->mmap_regions, mem_buf, sizeof(MemoryRegion) * mem_buf_pos); + if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); + if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); + } + cache_notify(&cache->mmap_cache); +} + void memory_map_get_regions(Context * ctx, MemoryRegion ** regions, unsigned * cnt) { - ContextCache * cache = (ContextCache *)ctx->proxy; - if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->cache); - *regions = cache->mem_regions; - *cnt = cache->mem_regions_cnt; + ContextCache * cache = NULL; + while (ctx->parent != NULL) ctx = ctx->parent; + cache = (ContextCache *)ctx->proxy; + if (cache->pending_get_mmap != NULL) cache_wait(&cache->mmap_cache); + if (cache->mmap_regions == NULL && cache->mmap_error == NULL && cache->peer != NULL) { + Channel * c = cache->peer->target; + cache->pending_get_mmap = protocol_send_command(c, "MemoryMap", "get", validate_memory_map_cache, cache); + json_write_string(&c->out, cache->id); + write_stream(&c->out, 0); + write_stream(&c->out, MARKER_EOM); + flush_stream(&c->out); + cache_wait(&cache->mmap_cache); + } + *regions = cache->mmap_regions; + *cnt = cache->mmap_size; +} + +static int validate_context_cache(Channel * c, void * args, int error) { + ContextCache * cache = (ContextCache *)args; + + assert(cache->peer->target == c); + if (cache->ctx->parent != NULL) { + /* Get register descriptions */ + if (cache->pending_get_regs != NULL) { + assert(cache->reg_ids == NULL); + assert(cache->reg_ids_str == NULL); + cache->reg_error = get_error_report(error); + if (!error) { + unsigned i; + cache->reg_error = get_error_report(read_errno(&c->inp)); + ids_buf_pos = 0; + str_buf_pos = 0; + json_read_array(&c->inp, read_ids_item, NULL); + cache->reg_cnt = ids_buf_pos; + cache->reg_ids = loc_alloc(sizeof(char *) * ids_buf_pos); + cache->reg_ids_str = loc_alloc(str_buf_pos); + memcpy(cache->reg_ids_str, str_buf, str_buf_pos); + for (i = 0; i < cache->reg_cnt; i++) { + cache->reg_ids[i] = cache->reg_ids_str + ids_buf[i]; + } + if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); + if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); + } + } + else if (cache->reg_ids == NULL && cache->reg_error == 0) { + cache->pending_get_regs = protocol_send_command(c, "Registers", "getChildren", validate_context_cache, args); + write_stringz(&c->out, thread_id(cache->ctx)); + write_stream(&c->out, MARKER_EOM); + flush_stream(&c->out); + return 0; + } + } + + return 1; } RegisterDefinition * get_reg_definitions(Context * ctx) { ContextCache * cache = (ContextCache *)ctx->proxy; - if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->cache); + if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->regs_cache); return cache->reg_defs; } RegisterDefinition * get_PC_definition(Context * ctx) { ContextCache * cache = (ContextCache *)ctx->proxy; - if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->cache); + if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->regs_cache); return cache->pc_def; } RegisterDefinition * get_reg_by_id(Context * ctx, unsigned id, unsigned munbering_convention) { RegisterDefinition * defs; ContextCache * cache = (ContextCache *)ctx->proxy; - if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->cache); + if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->regs_cache); defs = cache->reg_defs; while (defs != NULL && defs->name != NULL) { switch (munbering_convention) { @@ -570,15 +722,73 @@ static void channel_close_listener(Channel * c) { channel_unlock(p->host); channel_unlock(p->target); list_remove(&p->link_all); + while (!list_is_empty(&p->ctx_cache)) { + ContextCache * c = peer2ctx(p->ctx_cache.next); + c->peer = NULL; + list_remove(&c->link_peer); + if (c->ctx != NULL) { + if (c->ctx->parent != NULL) { + list_remove(&c->ctx->cldl); + context_unlock(c->ctx->parent); + c->ctx->parent = NULL; + } + context_unlock(c->ctx); + } + else { + free_context_cache(c); + } + } loc_free(p); return; } } } +#if ENABLE_CACHE_PRELOAD + +static void mmap_cache_client(void * x) { + Context * ctx = (Context *)x; + MemoryRegion * regions = NULL; + unsigned cnt = 0; + memory_map_get_regions(ctx, ®ions, &cnt); + cache_exit(); + context_unlock(ctx); +} + +static void evt_context_created(Context * ctx, void * args) { + context_lock(ctx); + cache_enter(mmap_cache_client, ctx); +} + +static void evt_context_exited(Context * ctx, void * args) { +} + +static void evt_context_stopped(Context * ctx, void * args) { +} + +static void evt_context_started(Context * ctx, void * args) { +} + +static void evt_context_changed(Context * ctx, void * args) { + context_lock(ctx); + cache_enter(mmap_cache_client, ctx); +} + +static ContextEventListener context_listener = { + evt_context_created, + evt_context_exited, + evt_context_stopped, + evt_context_started, + evt_context_changed +}; +#endif + void init_contexts_sys_dep(void) { list_init(&peers); add_channel_close_listener(channel_close_listener); +#if ENABLE_CACHE_PRELOAD + add_context_event_listener(&context_listener, NULL); +#endif } #endif /* ENABLE_DebugContext && ENABLE_ContextProxy */ |