Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreutarass2011-05-24 17:25:48 +0000
committereutarass2011-05-24 17:25:48 +0000
commitfe66758ad6c6cc1f723aac032be4fc86dc0ccbfa (patch)
treebb1525572ed9a918238ed99114963f1d3149f780
parent3783e0d21934ec75f7c77b231c8ac0f82329ba23 (diff)
downloadorg.eclipse.tcf.agent-fe66758ad6c6cc1f723aac032be4fc86dc0ccbfa.tar.gz
org.eclipse.tcf.agent-fe66758ad6c6cc1f723aac032be4fc86dc0ccbfa.tar.xz
org.eclipse.tcf.agent-fe66758ad6c6cc1f723aac032be4fc86dc0ccbfa.zip
TCF Agent: Breakpoints service performance improvements.
-rw-r--r--services/breakpoints.c116
-rw-r--r--services/breakpoints.h4
-rw-r--r--services/runctrl.c2
-rw-r--r--system/GNU/Linux/context-linux.c4
-rw-r--r--system/Windows/context-win32.c2
5 files changed, 82 insertions, 46 deletions
diff --git a/services/breakpoints.c b/services/breakpoints.c
index 914af011..1c18216f 100644
--- a/services/breakpoints.c
+++ b/services/breakpoints.c
@@ -67,6 +67,7 @@ struct BreakpointAttribute {
};
struct BreakpointInfo {
+ Context * ctx; /* NULL means all contexts */
LINK link_all;
LINK link_id;
LINK link_clients;
@@ -133,6 +134,7 @@ struct ConditionEvaluationRequest {
struct EvaluationRequest {
Context * ctx;
+ BreakpointInfo * bp; /* NULL means all breakpoints */
LINK link_posted;
LINK link_active;
int location;
@@ -323,17 +325,18 @@ static BreakInstruction * add_instruction(Context * ctx, ContextAddress address)
return bi;
}
-static void clear_instruction_refs(Context * ctx) {
+static void clear_instruction_refs(Context * ctx, BreakpointInfo * bp) {
LINK * l = instructions.next;
while (l != &instructions) {
int i;
BreakInstruction * bi = link_all2bi(l);
for (i = 0; i < bi->ref_cnt; i++) {
- if (bi->refs[i].ctx == ctx) {
- bi->refs[i].size = 0;
- bi->refs[i].cnt = 0;
- bi->valid = 0;
- }
+ InstructionRef * ref = bi->refs + i;
+ if (ref->ctx != ctx) continue;
+ if (bp != NULL && ref->bp != bp) continue;
+ ref->size = 0;
+ ref->cnt = 0;
+ bi->valid = 0;
}
l = l->next;
}
@@ -691,16 +694,15 @@ static EvaluationRequest * create_evaluation_request(Context * ctx, int bp_cnt)
return req;
}
-static EvaluationRequest * post_evaluation_request(EvaluationRequest * req) {
+static void post_evaluation_request(EvaluationRequest * req) {
if (list_is_empty(&req->link_posted)) {
context_lock(req->ctx);
list_add_last(&req->link_posted, &evaluations_posted);
post_safe_event(req->ctx, event_replant_breakpoints, (void *)++generation_posted);
}
- return req;
}
-static void post_location_evaluation_request(Context * ctx) {
+static void post_location_evaluation_request(Context * ctx, BreakpointInfo * bp) {
ContextExtensionBP * ext = EXT(ctx);
Context * grp = context_get_group(ctx, CONTEXT_GROUP_BREAKPOINT);
if (ext->bp_grp != NULL && ext->bp_grp != grp && !ext->bp_grp->exited) {
@@ -716,14 +718,26 @@ static void post_location_evaluation_request(Context * ctx) {
if (context_get_group(c, CONTEXT_GROUP_BREAKPOINT) == ext->bp_grp) cnt++;
}
if (cnt == 0) {
+ EvaluationRequest * req = create_evaluation_request(ext->bp_grp, 0);
+ req->bp = NULL;
+ req->location = 1;
+ post_evaluation_request(req);
EXT(ext->bp_grp)->empty_bp_grp = 1;
- post_evaluation_request(create_evaluation_request(ext->bp_grp, 0))->location = 1;
}
}
ext->bp_grp = grp;
if (grp != NULL) {
+ EvaluationRequest * req = create_evaluation_request(grp, 0);
+ if (!req->location) {
+ req->bp = bp;
+ req->location = 1;
+ post_evaluation_request(req);
+ }
+ else if (req->bp != bp) {
+ req->bp = NULL;
+ }
+ post_evaluation_request(req);
EXT(grp)->empty_bp_grp = 0;
- post_evaluation_request(create_evaluation_request(grp, 0))->location = 1;
}
}
@@ -757,6 +771,7 @@ static void free_bp(BreakpointInfo * bp) {
assert(bp->client_cnt == 0);
list_remove(&bp->link_all);
if (*bp->id) list_remove(&bp->link_id);
+ if (bp->ctx) context_unlock(bp->ctx);
release_error_report(bp->error);
loc_free(bp->address);
loc_free(bp->type);
@@ -1013,6 +1028,9 @@ static void evaluate_text_location(void * x) {
static int check_context_ids_location(BreakpointInfo * bp, Context * ctx) {
/* Check context IDs attribute and return 1 if the breakpoint should be planted in 'ctx' */
assert(ctx == context_get_group(ctx, CONTEXT_GROUP_BREAKPOINT));
+ if (bp->ctx != NULL) {
+ return context_get_group(bp->ctx, CONTEXT_GROUP_BREAKPOINT) == ctx;
+ }
if (bp->context_ids != NULL) {
int ok = 0;
char ** ids = bp->context_ids;
@@ -1029,6 +1047,9 @@ static int check_context_ids_location(BreakpointInfo * bp, Context * ctx) {
static int check_context_ids_condition(BreakpointInfo * bp, Context * ctx) {
/* Check context IDs attribute and return 1 if the breakpoint should be triggered by 'ctx' */
assert(context_has_state(ctx));
+ if (bp->ctx != NULL) {
+ return bp->ctx == ctx;
+ }
if (bp->context_ids != NULL) {
int ok = 0;
char ** ids = bp->context_ids;
@@ -1082,6 +1103,25 @@ static void evaluate_condition(void * x) {
expr_cache_exit(args);
}
+static void evaluate_bp_location(BreakpointInfo * bp, Context * ctx) {
+ if (is_disabled(bp)) return;
+ if (!check_context_ids_location(bp, ctx)) return;
+ if (bp->file != NULL) {
+#if ENABLE_LineNumbers
+ expr_cache_enter(evaluate_text_location, bp, ctx);
+#else
+ set_errno(ERR_UNSUPPORTED, "LineNumbers service not available");
+ address_expression_error(NULL, bp, errno);
+#endif
+ }
+ else if (bp->address != NULL) {
+ expr_cache_enter(evaluate_address_expression, bp, ctx);
+ }
+ else {
+ address_expression_error(NULL, bp, ERR_INV_EXPRESSION);
+ }
+}
+
static void event_replant_breakpoints(void * arg) {
LINK * q;
@@ -1100,29 +1140,20 @@ static void event_replant_breakpoints(void * arg) {
list_remove(&req->link_posted);
list_add_first(&req->link_active, &evaluations_active);
if (req->location) {
- LINK * l = breakpoints.next;
+ BreakpointInfo * bp = req->bp;
req->location = 0;
- clear_instruction_refs(ctx);
+ req->bp = NULL;
+ clear_instruction_refs(ctx, bp);
if (!ctx->exiting && !ctx->exited && !EXT(ctx)->empty_bp_grp) {
context_lock(ctx);
- while (l != &breakpoints) {
- BreakpointInfo * bp = link_all2bp(l);
- l = l->next;
- if (is_disabled(bp)) continue;
- if (!check_context_ids_location(bp, ctx)) continue;
- if (bp->file != NULL) {
-#if ENABLE_LineNumbers
- expr_cache_enter(evaluate_text_location, bp, ctx);
-#else
- set_errno(ERR_UNSUPPORTED, "LineNumbers service not available");
- address_expression_error(NULL, bp, errno);
-#endif
- }
- else if (bp->address != NULL) {
- expr_cache_enter(evaluate_address_expression, bp, ctx);
- }
- else {
- address_expression_error(NULL, bp, ERR_INV_EXPRESSION);
+ if (bp != NULL) {
+ evaluate_bp_location(bp, ctx);
+ }
+ else {
+ LINK * l = breakpoints.next;
+ while (l != &breakpoints) {
+ evaluate_bp_location(link_all2bp(l), ctx);
+ l = l->next;
}
}
context_unlock(ctx);
@@ -1174,13 +1205,16 @@ static int str_arr_equ(char ** x, char ** y) {
static void replant_breakpoint(BreakpointInfo * bp) {
if (list_is_empty(&context_root)) return;
- if (bp->context_ids == NULL || bp->context_ids_prev == NULL) {
+ if (bp->ctx != NULL) {
+ if (!bp->ctx->exited) post_location_evaluation_request(bp->ctx, bp);
+ }
+ else if (bp->context_ids == NULL || bp->context_ids_prev == NULL) {
LINK * l = context_root.next;
while (l != &context_root) {
Context * ctx = ctxl2ctxp(l);
l = l->next;
if (ctx->exited) continue;
- post_location_evaluation_request(ctx);
+ post_location_evaluation_request(ctx, bp);
}
bp->context_ids_prev = str_arr_dup(bp->context_ids);
}
@@ -1190,7 +1224,7 @@ static void replant_breakpoint(BreakpointInfo * bp) {
Context * ctx = id2ctx(*ids++);
if (ctx == NULL) continue;
if (ctx->exited) continue;
- post_location_evaluation_request(ctx);
+ post_location_evaluation_request(ctx, bp);
}
if (!str_arr_equ(bp->context_ids, bp->context_ids_prev)) {
ids = bp->context_ids_prev;
@@ -1198,7 +1232,7 @@ static void replant_breakpoint(BreakpointInfo * bp) {
Context * ctx = id2ctx(*ids++);
if (ctx == NULL) continue;
if (ctx->exited) continue;
- post_location_evaluation_request(ctx);
+ post_location_evaluation_request(ctx, bp);
}
bp->context_ids_prev = str_arr_dup(bp->context_ids);
}
@@ -2024,11 +2058,12 @@ void evaluate_breakpoint(Context * ctx) {
req->bp_cnt = bp_cnt;
}
}
- for (i = 0; i < bp_cnt; i++) {
+ for (i = 0; i < bi->ref_cnt; i++) {
BreakpointInfo * bp = bi->refs[i].bp;
assert(bp->instruction_cnt);
assert(bp->unsupported == NULL);
assert(bp->error == NULL);
+ assert(bi->refs[i].cnt > 0);
req->bp_arr[k + i].bp = bp;
@@ -2155,13 +2190,14 @@ int skip_breakpoint(Context * ctx, int single_step) {
return 1;
}
-BreakpointInfo * create_eventpoint(const char * location, EventPointCallBack * callback, void * callback_args) {
+BreakpointInfo * create_eventpoint(const char * location, Context * ctx, EventPointCallBack * callback, void * callback_args) {
BreakpointInfo * bp = (BreakpointInfo *)loc_alloc_zero(sizeof(BreakpointInfo));
bp->client_cnt = 1;
bp->enabled = 1;
bp->address = loc_strdup(location);
bp->event_callback = callback;
bp->event_callback_args = callback_args;
+ if (ctx != NULL) context_lock(bp->ctx = ctx);
list_init(&bp->link_clients);
assert(breakpoints.next != NULL);
list_add_last(&bp->link_all, &breakpoints);
@@ -2177,7 +2213,7 @@ void destroy_eventpoint(BreakpointInfo * bp) {
}
static void event_context_created_or_exited(Context * ctx, void * args) {
- post_location_evaluation_request(ctx);
+ post_location_evaluation_request(ctx, NULL);
}
static void event_context_changed(Context * ctx, void * args) {
@@ -2190,11 +2226,11 @@ static void event_context_changed(Context * ctx, void * args) {
l = l->next;
if (x->exited) continue;
if (context_get_group(x, CONTEXT_GROUP_PROCESS) != ctx) continue;
- post_location_evaluation_request(x);
+ post_location_evaluation_request(x, NULL);
}
}
else {
- post_location_evaluation_request(ctx);
+ post_location_evaluation_request(ctx, NULL);
}
}
diff --git a/services/breakpoints.h b/services/breakpoints.h
index e9c57335..54a90933 100644
--- a/services/breakpoints.h
+++ b/services/breakpoints.h
@@ -74,7 +74,7 @@ typedef void EventPointCallBack(Context *, void *);
/* Create, plant and return eventpoint. Eventpoints are breakpoints that are created by agent to control execution of debugee.
* Eventpoint are not exposed through "Breakpoints" TCF service, they are handled by agent itself. */
-extern BreakpointInfo * create_eventpoint(const char * location, EventPointCallBack * callback, void * callback_args);
+extern BreakpointInfo * create_eventpoint(const char * location, Context * ctx, EventPointCallBack * callback, void * callback_args);
/* Unplant and destroy eventpoint */
extern void destroy_eventpoint(BreakpointInfo * eventpoint);
@@ -87,7 +87,7 @@ extern void destroy_eventpoint(BreakpointInfo * eventpoint);
#define clone_breakpoints_on_process_fork(parent, child) 0
#define check_breakpoints_on_memory_read(ctx, address, buf, size) 0
#define check_breakpoints_on_memory_write(ctx, address, buf, size) 0
-#define create_eventpoint(location, callback, callback_args) 0
+#define create_eventpoint(location, ctx, callback, callback_args) 0
#endif /* SERVICE_Breakpoints */
diff --git a/services/runctrl.c b/services/runctrl.c
index afa3b090..2c2dc0b7 100644
--- a/services/runctrl.c
+++ b/services/runctrl.c
@@ -1147,7 +1147,7 @@ static int update_step_machine_state(Context * ctx) {
char bf[64];
snprintf(bf, sizeof(bf), "0x%" PRIX64, (uint64_t)step_bp_addr);
if (ext->step_bp_info != NULL) destroy_eventpoint(ext->step_bp_info);
- ext->step_bp_info = create_eventpoint(bf, step_machine_breakpoint, NULL);
+ ext->step_bp_info = create_eventpoint(bf, ctx, step_machine_breakpoint, NULL);
ext->step_bp_addr = step_bp_addr;
}
return 0;
diff --git a/system/GNU/Linux/context-linux.c b/system/GNU/Linux/context-linux.c
index 7777f07f..a0ead4ff 100644
--- a/system/GNU/Linux/context-linux.c
+++ b/system/GNU/Linux/context-linux.c
@@ -1020,9 +1020,9 @@ void init_contexts_sys_dep(void) {
ini_context_pid_hash();
#if SERVICE_Expressions && ENABLE_ELF
add_identifier_callback(expression_identifier_callback);
- create_eventpoint("$loader_brk", eventpoint_at_loader, NULL);
+ create_eventpoint("$loader_brk", NULL, eventpoint_at_loader, NULL);
#endif /* SERVICE_Expressions && ENABLE_ELF */
- create_eventpoint("main", eventpoint_at_main, NULL);
+ create_eventpoint("main", NULL, eventpoint_at_main, NULL);
}
#endif /* if ENABLE_DebugContext */
diff --git a/system/Windows/context-win32.c b/system/Windows/context-win32.c
index face33c1..a1f65c4a 100644
--- a/system/Windows/context-win32.c
+++ b/system/Windows/context-win32.c
@@ -1358,7 +1358,7 @@ void init_contexts_sys_dep(void) {
memset(&os_version, 0, sizeof(os_version));
os_version.dwOSVersionInfoSize = sizeof(os_version);
GetVersionEx((OSVERSIONINFO *)&os_version);
- create_eventpoint("main", eventpoint_at_main, NULL);
+ create_eventpoint("main", NULL, eventpoint_at_main, NULL);
}
#endif /* if ENABLE_DebugContext */

Back to the top