From a26bec34abbb05abeeb6049cefd30b4347e6e604 Mon Sep 17 00:00:00 2001 From: deadwood Date: Sat, 3 May 2014 18:18:27 +0000 Subject: [PATCH] debug.library: improve performance of un-registering segments Decrease the number of linear searches through the list of module by assuming most segments will follow DOS segment order. git-svn-id: https://svn.aros.org/svn/aros/trunk/AROS@48980 fb15a70f-31f2-0310-bbcc-cdcc74a49acc --- rom/debug/unregistermodule.c | 155 +++++++++++++++++++++++++++---------------- 1 file changed, 96 insertions(+), 59 deletions(-) diff --git a/rom/debug/unregistermodule.c b/rom/debug/unregistermodule.c index 62675e3c28..e210968a5d 100644 --- a/rom/debug/unregistermodule.c +++ b/rom/debug/unregistermodule.c @@ -15,7 +15,9 @@ #include "debug_intern.h" -static BOOL ScanAndRemoveSegment(module_t *mod, BPTR segList); +static module_t * FindModule(BPTR segList, struct Library * DebugBase); +static LONG FindIndex(module_t * mod, BPTR segList); +static VOID RemoveSegmentRange(module_t * mod, LONG firstidx, LONG count); /***************************************************************************** @@ -56,95 +58,130 @@ static BOOL ScanAndRemoveSegment(module_t *mod, BPTR segList); { AROS_LIBFUNC_INIT - module_t *mod; - module_t *modlast = NULL; /* In most (all?) cases, all segments will be within one module */ + module_t *mod = NULL; + LONG i, rangestart = -1; D(bug("[Debug] UnregisterModule(0x%p)\n", segList)); ObtainSemaphore(&DBGBASE(DebugBase)->db_ModSem); while (segList) { - if (modlast && ScanAndRemoveSegment(modlast, segList)) - { - /* Nothing */ - } - else + if (mod == NULL) /* Search for new module */ + mod = FindModule(segList, DebugBase); + + if (mod) { - struct Node * tmpnode; + if (rangestart == -1) /* Search for new index */ + i = rangestart = FindIndex(mod, segList); - ForeachNodeSafe(&DBGBASE(DebugBase)->db_Modules, mod, tmpnode) + /* Optimization assumes order of segments is similar to order of DOS segments */ + if ((i >= mod->m_segcnt) || (mod->m_segments[i]->s_seg != segList)) { - if (ScanAndRemoveSegment(mod, segList)) - { - modlast = mod; - break; - } + /* Order broken, clear ordered segments */ + RemoveSegmentRange(mod, rangestart, (i - rangestart)); + + /* Restart */ + i = rangestart = FindIndex(mod, segList); } + + i++; } /* Advance to next DOS segment */ segList = *(BPTR *)BADDR(segList); } + if (mod != NULL && rangestart > -1) + RemoveSegmentRange(mod, rangestart, (i - rangestart)); + ReleaseSemaphore(&DBGBASE(DebugBase)->db_ModSem); AROS_LIBFUNC_EXIT } -static BOOL ScanAndRemoveSegment(module_t *mod, BPTR segList) +static module_t * FindModule(BPTR segList, struct Library * DebugBase) +{ + module_t *mod; + LONG i; + + ForeachNode(&DBGBASE(DebugBase)->db_Modules, mod) + { + for (i = 0; i < mod->m_segcnt; i++) + { + if (mod->m_segments[i]->s_seg == segList) + { + return mod; + } + } + } + + return NULL; +} + +static LONG FindIndex(module_t * mod, BPTR segList) { - struct segment * seg = NULL; - LONG i, j; + LONG i; for (i = 0; i < mod->m_segcnt; i++) { - seg = mod->m_segments[i]; + if (mod->m_segments[i]->s_seg == segList) + { + return i; + } + } - if (seg->s_seg == segList) + return -1; +} + +static VOID RemoveSegmentRange(module_t * mod, LONG firstidx, LONG count) +{ + struct segment * seg; + LONG i; + + for (i = 0 ; i < count ; i++) + { + seg = mod->m_segments[i + firstidx]; + + FreeMem(seg, sizeof(struct segment)); + + /* If module's segment count reached 0, remove the whole + module information */ + if (--mod->m_segcnt == 0) { - D(bug("[Debug] Removing segment 0x%p\n", segList)); - /* "Shrink" array of segments so that at any given time the array is valid for - * binary search - */ - for (j = i;j < mod->m_segcnt - 1; j++) - mod->m_segments[j] = mod->m_segments[j + 1]; - - /* If module's segment count reached 0, remove the whole - module information */ - if (--mod->m_segcnt == 0) - { - D(bug("[Debug] Removing module %s\n", mod->m_name)); - - /* Free associated symbols */ - if (mod->m_symbols) { - D(bug("[Debug] Removing symbol table 0x%p\n", mod->m_symbols)); - FreeVec(mod->m_symbols); - } - - /* Free associated string tables */ - if (mod->m_str) { - D(bug("[Debug] Removing symbol name table 0x%p\n", mod->m_str)); - FreeVec(mod->m_str); - } - if (mod->m_shstr) { - D(bug("[Debug] Removing section name table 0x%p\n", mod->m_str)); - FreeVec(mod->m_shstr); - } - - Remove((struct Node *)mod); - FreeVec(mod->m_segments); -#if AROS_MODULES_DEBUG - FreeVec(mod->m_seggdbhlp); -#endif - /* Free module descriptor at last */ - FreeVec(mod); + D(bug("[Debug] Removing module %s\n", mod->m_name)); + + /* Free associated symbols */ + if (mod->m_symbols) { + D(bug("[Debug] Removing symbol table 0x%p\n", mod->m_symbols)); + FreeVec(mod->m_symbols); + } + + /* Free associated string tables */ + if (mod->m_str) { + D(bug("[Debug] Removing symbol name table 0x%p\n", mod->m_str)); + FreeVec(mod->m_str); + } + if (mod->m_shstr) { + D(bug("[Debug] Removing section name table 0x%p\n", mod->m_str)); + FreeVec(mod->m_shstr); } - FreeMem(seg, sizeof(struct segment)); + Remove((struct Node *)mod); + FreeVec(mod->m_segments); +#if AROS_MODULES_DEBUG + FreeVec(mod->m_seggdbhlp); +#endif + /* Free module descriptor at last */ + FreeVec(mod); - return TRUE; + return; } } - return FALSE; + /* "Shrink" array of segments so that at any given time the array is valid for + * binary search + */ + for (i = firstidx;i < mod->m_segcnt; i++) + mod->m_segments[i] = mod->m_segments[i + count]; + } -- 2.11.4.GIT