diff options
Diffstat (limited to 'lib/tools/src')
| -rw-r--r-- | lib/tools/src/Makefile | 7 | ||||
| -rw-r--r-- | lib/tools/src/cover.erl | 129 | ||||
| -rw-r--r-- | lib/tools/src/eprof.erl | 52 | ||||
| -rw-r--r-- | lib/tools/src/fprof.erl | 5 | ||||
| -rw-r--r-- | lib/tools/src/instrument.erl | 538 | ||||
| -rw-r--r-- | lib/tools/src/lcnt.erl | 7 | ||||
| -rw-r--r-- | lib/tools/src/xref.erl | 6 | ||||
| -rw-r--r-- | lib/tools/src/xref_utils.erl | 9 | 
8 files changed, 278 insertions, 475 deletions
| diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile index 032bd612db..cc5bee9a8f 100644 --- a/lib/tools/src/Makefile +++ b/lib/tools/src/Makefile @@ -1,7 +1,7 @@  #  # %CopyrightBegin%  # -# Copyright Ericsson AB 1996-2016. All Rights Reserved. +# Copyright Ericsson AB 1996-2018. All Rights Reserved.  #  # Licensed under the Apache License, Version 2.0 (the "License");  # you may not use this file except in compliance with the License. @@ -72,6 +72,9 @@ APP_TARGET = $(EBIN)/$(APP_FILE)  APPUP_SRC = $(APPUP_FILE).src  APPUP_TARGET = $(EBIN)/$(APPUP_FILE) +PRIVDIR = ../priv +CSS = $(PRIVDIR)/styles.css +  # ----------------------------------------------------  # FLAGS  # ---------------------------------------------------- @@ -110,5 +113,7 @@ release_spec: opt  	$(INSTALL_DIR) "$(RELSYSDIR)/ebin"  	$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \  		"$(RELSYSDIR)/ebin" +	$(INSTALL_DIR) "$(RELSYSDIR)/priv" +	$(INSTALL_DATA) $(CSS) "$(RELSYSDIR)/priv"  release_docs_spec: diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 4e64d7aa4e..8d4561ca9e 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %% -%% Copyright Ericsson AB 2001-2017. All Rights Reserved. +%% Copyright Ericsson AB 2001-2018. All Rights Reserved.  %%  %% Licensed under the Apache License, Version 2.0 (the "License");  %% you may not use this file except in compliance with the License. @@ -144,6 +144,8 @@          end).  -define(SPAWN_DBG(Tag,Value),put(Tag,Value)). +-define(STYLESHEET, "styles.css"). +-define(TOOLS_APP, tools).  -include_lib("stdlib/include/ms_transform.hrl"). @@ -2415,20 +2417,8 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->  	    case file:open(OutFile, [write,raw,delayed_write]) of  		{ok, OutFd} ->                      Enc = encoding(ErlFile), -		    if HTML ->  -                           Header = -                               ["<!DOCTYPE HTML PUBLIC " -                                "\"-//W3C//DTD HTML 3.2 Final//EN\">\n" -                                "<html>\n" -                                "<head>\n" -                                "<meta http-equiv=\"Content-Type\"" -                                " content=\"text/html; charset=", -                                html_encoding(Enc),"\"/>\n" -                                "<title>",OutFile,"</title>\n" -                                "</head>" -                                "<body style='background-color: white;" -                                " color: black'>\n" -                                "<pre>\n"], +		    if HTML -> +                            Header = create_header(OutFile, Enc),                              H1Bin = unicode:characters_to_binary(Header,Enc,Enc),                              ok = file:write(OutFd,H1Bin);  		       true -> ok @@ -2439,20 +2429,25 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->                     Timestamp =                         io_lib:format("~p-~s-~s at ~s:~s:~s",                                       [Y, -                                      string:right(integer_to_list(Mo), 2, $0), -                                      string:right(integer_to_list(D),  2, $0), -                                      string:right(integer_to_list(H),  2, $0), -                                      string:right(integer_to_list(Mi), 2, $0), -                                      string:right(integer_to_list(S),  2, $0)]), - -                    H2Bin = unicode:characters_to_binary( -                              ["File generated from ",ErlFile," by COVER ", -                                Timestamp,"\n\n" -                                "**************************************" -                                "**************************************" -                                "\n\n"], -                              Enc, Enc), -                    ok = file:write(OutFd, H2Bin), +                                      string:pad(integer_to_list(Mo), 2, leading, $0), +                                      string:pad(integer_to_list(D),  2, leading, $0), +                                      string:pad(integer_to_list(H),  2, leading, $0), +                                      string:pad(integer_to_list(Mi), 2, leading, $0), +                                      string:pad(integer_to_list(S),  2, leading, $0)]), + +                   OutFileInfo = +                       if HTML -> +                            create_footer(ErlFile, Timestamp); +                          true -> +                            ["File generated from ",ErlFile," by COVER ", +                             Timestamp, "\n\n", +                             "**************************************" +                             "**************************************" +                             "\n\n"] +                          end, + +                   H2Bin = unicode:characters_to_binary(OutFileInfo,Enc,Enc), +                   ok = file:write(OutFd, H2Bin),  		    Pattern = {#bump{module=Module,line='$1',_='_'},'$2'},  		    MS = [{Pattern,[{is_integer,'$1'},{'>','$1',0}],[{{'$1','$2'}}]}], @@ -2462,7 +2457,7 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->  		    print_lines(Module, CovLines, InFd, OutFd, 1, HTML),  		    if HTML -> -                           ok = file:write(OutFd, "</pre>\n</body>\n</html>\n"); +                           ok = file:write(OutFd, close_html());  		       true -> ok  		    end, @@ -2497,14 +2492,13 @@ print_lines(Module, CovLines, InFd, OutFd, L, HTML) ->  	    case CovLines of  	       [{L,N}|CovLines1] ->                      if N=:=0, HTML=:=true -> -                           LineNoNL = Line -- "\n", -                           Str = "     0", -                           %%Str = string:right("0", 6, 32), -                           RedLine = ["<font color=red>",Str,fill1(), -                                      LineNoNL,"</font>\n"], -                           ok = file:write(OutFd, RedLine); +                           MissedLine = table_row("miss", Line, L, N), +                           ok = file:write(OutFd, MissedLine); +                       HTML=:=true -> +                           HitLine = table_row("hit", Line, L, N), +                           ok = file:write(OutFd, HitLine);                         N < 1000000 -> -                           Str = string:right(integer_to_list(N), 6, 32), +                           Str = string:pad(integer_to_list(N), 6, leading, $\s),                             ok = file:write(OutFd, [Str,fill1(),Line]);                         N < 10000000 ->                             Str = integer_to_list(N), @@ -2515,7 +2509,11 @@ print_lines(Module, CovLines, InFd, OutFd, L, HTML) ->                      end,  		    print_lines(Module, CovLines1, InFd, OutFd, L+1, HTML);  		_ ->                            %Including comment lines -		    ok = file:write(OutFd, [tab(),Line]), +        NonCoveredContent = +                    if HTML -> table_row(Line, L); +                    true -> [tab(),Line] +                    end, +		    ok = file:write(OutFd, NonCoveredContent),  		    print_lines(Module, CovLines, InFd, OutFd, L+1, HTML)  	    end      end. @@ -2525,6 +2523,61 @@ fill1() ->      "..|  ".  fill2() ->       ".|  ".  fill3() ->        "|  ". +%% HTML sections +create_header(OutFile, Enc) -> +    ["<!doctype html>\n" +    "<html>\n" +    "<head>\n" +    "<meta charset=\"",html_encoding(Enc),"\">\n" +    "<title>",OutFile,"</title>\n" +    "<style>"] ++ +    read_stylesheet() ++ +    ["</style>\n", +    "</head>\n" +    "<body>\n" +    "<h1><code>",OutFile,"</code></h1>\n"]. + +create_footer(ErlFile, Timestamp) -> +    ["<footer><p>File generated from <code>",ErlFile, +    "</code> by <a href=\"http://erlang.org/doc/man/cover.html\">cover</a> at ", +    Timestamp,"</p></footer>\n<table>\n<tbody>\n"]. + +close_html() -> +    ["</tbody>\n", +     "<thead>\n", +     "<tr>\n", +     "<th>Line</th>\n", +     "<th>Hits</th>\n", +     "<th>Source</th>\n", +     "</tr>\n", +     "</thead>\n", +     "</table>\n", +     "</body>\n" +     "</html>\n"]. + +table_row(CssClass, Line, L, N) -> +    ["<tr class=\"",CssClass,"\">\n", table_data(Line, L, N)]. +table_row(Line, L) -> +    ["<tr>\n", table_data(Line, L, "")]. + +table_data(Line, L, N) -> +   LineNoNL = Line -- "\n", +   ["<td class=\"line\" id=\"L",integer_to_list(L),"\">", +    "<a href=\"#L",integer_to_list(L),"\">", +    integer_to_list(L), +    "</a></td>\n", +   "<td class=\"hits\">",maybe_integer_to_list(N),"</td>\n", +   "<td class=\"source\"><code>",LineNoNL,"</code></td>\n</tr>\n"]. + +maybe_integer_to_list(0) -> "<pre style=\"display: inline;\">:-(</pre>"; +maybe_integer_to_list(N) when is_integer(N) -> integer_to_list(N); +maybe_integer_to_list(_) -> "". + +read_stylesheet() -> +    PrivDir = code:priv_dir(?TOOLS_APP), +    {ok, Css} = file:read_file(filename:join(PrivDir, ?STYLESHEET)), +    [Css]. +  %%%--Export--------------------------------------------------------------  do_export(Module, OutFile, From, State) ->      case file:open(OutFile,[write,binary,raw,delayed_write]) of diff --git a/lib/tools/src/eprof.erl b/lib/tools/src/eprof.erl index 535ddbcd04..86e3d3a8b8 100644 --- a/lib/tools/src/eprof.erl +++ b/lib/tools/src/eprof.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %% -%% Copyright Ericsson AB 1996-2017. All Rights Reserved. +%% Copyright Ericsson AB 1996-2018. All Rights Reserved.  %%  %% Licensed under the Apache License, Version 2.0 (the "License");  %% you may not use this file except in compliance with the License. @@ -26,11 +26,11 @@  -export([start/0,  	 stop/0, -	 dump/0, +	 dump/0, dump_data/0,  	 start_profiling/1, start_profiling/2, start_profiling/3,  	 profile/1, profile/2, profile/3, profile/4, profile/5,  	 stop_profiling/0, -	 analyze/0, analyze/1, analyze/2, +	 analyze/0, analyze/1, analyze/2, analyze/4,  	 log/1]).  %% Internal exports  @@ -117,6 +117,9 @@ profile(Rootset, M, F, A, Pattern, Options) ->  dump() ->       gen_server:call(?MODULE, dump, infinity). +dump_data() -> +    gen_server:call(?MODULE, dump_data, infinity). +  log(File) ->      gen_server:call(?MODULE, {logfile, File}, infinity). @@ -151,22 +154,18 @@ init([]) ->  %% analyze -handle_call({analyze, _, _}, _, #state{ bpd = #bpd{ p = {0,nil}, us = 0, n = 0} = Bpd } = S) when is_record(Bpd, bpd) -> +handle_call( +  {analyze, _, _}, _, +  #state{ bpd = #bpd{ p = {0,nil}, us = 0, n = 0 } } = S) ->      {reply, nothing_to_analyze, S}; -handle_call({analyze, procs, Opts}, _, #state{ bpd = #bpd{ p = Ps, us = Tus} = Bpd, fd = Fd} = S) when is_record(Bpd, bpd) -> -    lists:foreach(fun -	    ({Pid, Mfas}) -> -		{Pn, Pus} =  sum_bp_total_n_us(Mfas), -		format(Fd, "~n****** Process ~w    -- ~s % of profiled time *** ~n", [Pid, s("~.2f", [100.0*divide(Pus,Tus)])]), -		print_bp_mfa(Mfas, {Pn,Pus}, Fd, Opts), -		ok -	end, gb_trees:to_list(Ps)), -    {reply, ok, S}; +handle_call({analyze, procs, Opts}, _, #state{ bpd = Bpd, fd = Fd } = S) +  when is_record(Bpd, bpd) -> +    {reply, analyze(Fd, procs, Opts, Bpd), S}; -handle_call({analyze, total, Opts}, _, #state{ bpd = #bpd{ mfa = Mfas, n = Tn, us = Tus} = Bpd, fd = Fd} = S) when is_record(Bpd, bpd) -> -    print_bp_mfa(Mfas, {Tn, Tus}, Fd, Opts), -    {reply, ok, S}; +handle_call({analyze, total, Opts}, _, #state{ bpd = Bpd, fd = Fd } = S) +  when is_record(Bpd, bpd) -> +    {reply, analyze(Fd, total, Opts, Bpd), S};  handle_call({analyze, Type, _Opts}, _, S) ->      {reply, {error, {undefined, Type}}, S}; @@ -260,6 +259,10 @@ handle_call({logfile, File}, _From, #state{ fd = OldFd } = S) ->  handle_call(dump, _From, #state{ bpd = Bpd } = S) when is_record(Bpd, bpd) ->      {reply, gb_trees:to_list(Bpd#bpd.p), S}; +handle_call(dump_data, _, #state{ bpd = #bpd{} = Bpd } = S) +  when is_record(Bpd, bpd) -> +    {reply, Bpd, S}; +  handle_call(stop, _FromTag, S) ->      {stop, normal, stopped, S}. @@ -438,6 +441,23 @@ collect_bpdfp(Mfa, Tree, Data) ->  	    {PTno + Ni, PTuso + Time, Ti1}      end, {0,0, Tree}, Data). + + +analyze(Fd, procs, Opts, #bpd{ p = Ps, us = Tus }) -> +    lists:foreach( +      fun +          ({Pid, Mfas}) -> +              {Pn, Pus} =  sum_bp_total_n_us(Mfas), +              format( +                Fd, +                "~n****** Process ~w    -- ~s % of profiled time *** ~n", +                [Pid, s("~.2f", [100.0*divide(Pus, Tus)])]), +              print_bp_mfa(Mfas, {Pn,Pus}, Fd, Opts), +              ok +      end, gb_trees:to_list(Ps)); +analyze(Fd, total, Opts, #bpd{ mfa = Mfas, n = Tn, us = Tus } ) -> +    print_bp_mfa(Mfas, {Tn, Tus}, Fd, Opts). +  %% manipulators  sort_mfa(Bpfs, mfa) when is_list(Bpfs) ->      lists:sort(fun diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl index fb657c2928..36d4828861 100644 --- a/lib/tools/src/fprof.erl +++ b/lib/tools/src/fprof.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %%  -%% Copyright Ericsson AB 2001-2017. All Rights Reserved. +%% Copyright Ericsson AB 2001-2018. All Rights Reserved.  %%   %% Licensed under the Apache License, Version 2.0 (the "License");  %% you may not use this file except in compliance with the License. @@ -1242,8 +1242,7 @@ spawn_3step(Spawn, FunPrelude, FunAck, FunBody)  		    catch Child ! {Parent, Ref, Go},  		    Result  	    catch -		Class:Reason -> -		    Stacktrace = erlang:get_stacktrace(), +		Class:Reason:Stacktrace ->  		    catch exit(Child, kill),  		    erlang:raise(Class, Reason, Stacktrace)  	    end; diff --git a/lib/tools/src/instrument.erl b/lib/tools/src/instrument.erl index 055f4a7afb..0203fefe13 100644 --- a/lib/tools/src/instrument.erl +++ b/lib/tools/src/instrument.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %%  -%% Copyright Ericsson AB 1998-2016. All Rights Reserved. +%% Copyright Ericsson AB 1998-2018. All Rights Reserved.  %%   %% Licensed under the Apache License, Version 2.0 (the "License");  %% you may not use this file except in compliance with the License. @@ -19,410 +19,140 @@  %%  -module(instrument). --export([holes/1, mem_limits/1, memory_data/0, read_memory_data/1, -	 sort/1, store_memory_data/1, sum_blocks/1, -	 descr/1, type_descr/2, allocator_descr/2, class_descr/2, -	 type_no_range/1, block_header_size/1, store_memory_status/1, -	 read_memory_status/1, memory_status/1]). - - --define(OLD_INFO_SIZE, 32). %% (sizeof(mem_link) in pre R9C utils.c) - --define(IHMARKER(H),  element(1, H)). --define(VSN(H),       element(2, H)). --define(INFO_SIZE(H), element(3, H)). --define(TYPEMAP(H),   element(4, H)). - --define(IHDR(H), is_tuple(H), ?IHMARKER(H) =:= instr_hdr). --define(IHDRVSN(H, V), ?IHDR(H), ?VSN(H) =:= V). - -memory_data() -> -    case catch erlang:system_info(allocated) of -	{'EXIT',{Error,_}} -> -	    erlang:error(Error, []); -	{'EXIT',Error} -> -	    erlang:error(Error, []); -	Res -> -	    Res +-export([allocations/0, allocations/1, +         carriers/0, carriers/1]). + +-type block_histogram() :: tuple(). + +-type allocation_summary() :: +    {HistogramStart :: non_neg_integer(), +     UnscannedSize :: non_neg_integer(), +     Allocations :: #{ Origin :: atom() => +                       #{ Type :: atom() => block_histogram() }}}. + +-spec allocations() -> {ok, Result} | {error, Reason} when +    Result :: allocation_summary(), +    Reason :: not_enabled. +allocations() -> +    allocations(#{}). + +-spec allocations(Options) -> {ok, Result} | {error, Reason} when +    Result :: allocation_summary(), +    Reason :: not_enabled, +    Options :: #{ scheduler_ids => list(non_neg_integer()), +                  allocator_types => list(atom()), +                  histogram_start => pos_integer(), +                  histogram_width => pos_integer() }. +allocations(Options) -> +    Ref = make_ref(), + +    Defaults = #{ scheduler_ids => lists:seq(0, erlang:system_info(schedulers)), +                  allocator_types => erlang:system_info(alloc_util_allocators), +                  histogram_start => 128, +                  histogram_width => 18 }, + +    {HistStart, MsgCount} = +        dispatch_gather(maps:merge(Defaults, Options), Ref, +                        fun erts_internal:gather_alloc_histograms/1), + +    alloc_hist_receive(HistStart, MsgCount, Ref). + +alloc_hist_receive(_HistStart, 0, _Ref) -> +    {error, not_enabled}; +alloc_hist_receive(HistStart, MsgCount, Ref) when MsgCount > 0 -> +    {Unscanned, Histograms} = alloc_hist_receive_1(MsgCount, Ref, 0, #{}), +    {ok, {HistStart, Unscanned, Histograms}}. + +alloc_hist_receive_1(0, _Ref, Unscanned, Result) -> +    {Unscanned, Result}; +alloc_hist_receive_1(MsgCount, Ref, Unscanned0, Result0) -> +    receive +        {Ref, Unscanned, Tags} -> +            Result = lists:foldl(fun alloc_hist_fold_result/2, Result0, Tags), +            alloc_hist_receive_1(MsgCount - 1, Ref, Unscanned0 + Unscanned, Result)      end. -store_memory_data(File) -> -    case catch erlang:system_info({allocated, File}) of -	{'EXIT',{Error,_}} -> -	    erlang:error(Error, [File]); -	{'EXIT',Error} -> -	    erlang:error(Error, [File]); -	Res -> -	    Res +alloc_hist_fold_result({Id, Type, BlockHist}, Result0) -> +    IdAllocs0 = maps:get(Id, Result0, #{}), +    MergedHists = case maps:find(Type, IdAllocs0) of +                      {ok, PrevHist} -> +                          alloc_hist_merge_hist(tuple_size(BlockHist), +                                                BlockHist, +                                                PrevHist); +                      error -> +                          BlockHist +                  end, +    IdAllocs = IdAllocs0#{ Type => MergedHists }, +    Result0#{ Id => IdAllocs }. + +alloc_hist_merge_hist(0, A, _B) -> +    A; +alloc_hist_merge_hist(Index, A, B) -> +    Merged = setelement(Index, A, element(Index, A) + element(Index, B)), +    alloc_hist_merge_hist(Index - 1, Merged, B). + +-type carrier_info_list() :: +    {HistogramStart :: non_neg_integer(), +     Carriers :: [{AllocatorType :: atom(), +                   TotalSize :: non_neg_integer(), +                   UnscannedSize :: non_neg_integer(), +                   AllocatedSize :: non_neg_integer(), +                   AllocatedCount :: non_neg_integer(), +                   InPool :: boolean(), +                   FreeBlocks :: block_histogram()}]}. + +-spec carriers() -> {ok, Result} | {error, Reason} when +    Result :: carrier_info_list(), +    Reason :: not_enabled. +carriers() -> +    carriers(#{}). + +-spec carriers(Options) -> {ok, Result} | {error, Reason} when +    Result :: carrier_info_list(), +    Reason :: not_enabled, +    Options :: #{ scheduler_ids => list(non_neg_integer()), +                  allocator_types => list(atom()), +                  histogram_start => pos_integer(), +                  histogram_width => pos_integer() }. +carriers(Options) -> +    Ref = make_ref(), + +    Defaults = #{ scheduler_ids => lists:seq(0, erlang:system_info(schedulers)), +                  allocator_types => erlang:system_info(alloc_util_allocators), +                  histogram_start => 512, +                  histogram_width => 14 }, + +    {HistStart, MsgCount} = +        dispatch_gather(maps:merge(Defaults, Options), Ref, +                        fun erts_internal:gather_carrier_info/1), + +    carrier_info_receive(HistStart, MsgCount, Ref). + +carrier_info_receive(_HistStart, 0, _Ref) -> +    {error, not_enabled}; +carrier_info_receive(HistStart, MsgCount, Ref) -> +    {ok, {HistStart, carrier_info_receive_1(MsgCount, Ref, [])}}. + +carrier_info_receive_1(0, _Ref, Result) -> +    lists:flatten(Result); +carrier_info_receive_1(MsgCount, Ref, Result0) -> +    receive +        {Ref, Carriers} -> +            carrier_info_receive_1(MsgCount - 1, Ref, [Carriers, Result0])      end. -memory_status(Type) when is_atom(Type) -> -    case catch erlang:system_info({allocated, status, Type}) of -	{'EXIT',{Error,_}} -> -	    erlang:error(Error, [Type]); -	{'EXIT',Error} -> -	    erlang:error(Error, [Type]); -	Res -> -	    Res -    end; -memory_status(Type) -> -    erlang:error(badarg, [Type]). - -store_memory_status(File) when is_list(File) -> -    case catch erlang:system_info({allocated, status, File}) of -	{'EXIT',{Error,_}} -> -	    erlang:error(Error, [File]); -	{'EXIT',Error} -> -	    erlang:error(Error, [File]); -	Res -> -	    Res -    end; -store_memory_status(File) -> -    erlang:error(badarg, [File]). - -read_memory_data(File) when is_list(File) -> -    case file:consult(File) of -	{ok, [Hdr|MD]} when ?IHDR(Hdr) -> -	    {Hdr, MD}; -	{ok, [{T,A,S,undefined}|_] = MD} when is_integer(T), -					      is_integer(A), -					      is_integer(S) -> -	    {{instr_hdr, 1, ?OLD_INFO_SIZE}, MD}; -	{ok, [{T,A,S,{X,Y,Z}}|_] = MD} when is_integer(T), -					    is_integer(A), -					    is_integer(S), -					    is_integer(X), -					    is_integer(Y), -					    is_integer(Z) -> -	    {{instr_hdr, 1, ?OLD_INFO_SIZE}, MD}; -	{ok, _} -> -	    {error, eio}; -	Error -> -	    Error -    end; -read_memory_data(File) -> -    erlang:error(badarg, [File]). - -read_memory_status(File) when is_list(File) -> -    case file:consult(File) of -	{ok, [{instr_vsn, _}|Stat]} -> -	    Stat; -	{ok, _} -> -	    {error, eio}; -	Error -> -	    Error -    end; -read_memory_status(File) -> -    erlang:error(badarg, [File]). - -holes({Hdr, MD}) when ?IHDR(Hdr) -> -    check_holes(?INFO_SIZE(Hdr), MD). - -check_holes(_ISz, []) -> -    ok; -check_holes(ISz, [E | L]) -> -    check_holes(ISz, E, L). - -check_holes(_ISz, _E1, []) -> -    io:format("~n"); -check_holes(ISz, E1, [E2 | Rest]) -> -    check_hole(ISz, E1, E2), -    check_holes(ISz, E2, Rest). - -check_hole(ISz, {_,P1,S1,_}, {_,P2,_,_}) -> -    End = P1+S1, -    Hole = P2 - (End + ISz), -    if -	Hole =< 7 -> -	    ok; -	true -> -	    io:format(" ~p", [Hole]) -    end. - -sum_blocks({Hdr, L}) when ?IHDR(Hdr) -> -    lists:foldl(fun({_,_,S,_}, Sum) -> S+Sum end, -		0, -		L). - -mem_limits({Hdr, L}) when ?IHDR(Hdr) -> -    {_, P1, _, _} = hd(L), -    {_, P2, S2, _} = lists:last(L), -    {P1, P2+S2}. - -sort({Hdr, MD}) when ?IHDR(Hdr) -> -    {Hdr, lists:keysort(2, MD)}. - -descr({Hdr, MD} = ID) when ?IHDR(Hdr) -> -    {Hdr, lists:map(fun ({TN, Addr, Sz, {0, N, S}}) -> -			    {type_descr(ID, TN), -			     Addr, -			     Sz, -			     list_to_pid("<0." -					 ++ integer_to_list(N) -					 ++ "." -					 ++ integer_to_list(S) -					 ++ ">")}; -			({TN, Addr, Sz, undefined}) -> -			    {type_descr(ID, TN), -			     Addr, -			     Sz, -			     undefined} -		    end, -		    MD)}. - -block_header_size({Hdr, _}) when ?IHDR(Hdr) -> -    ?INFO_SIZE(Hdr). - -type_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 2), -				  is_integer(TypeNo) -> -    case catch element(1, element(TypeNo, ?TYPEMAP(Hdr))) of -	{'EXIT', _} -> invalid_type; -	Type -> Type -    end; -type_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 1), -				  is_integer(TypeNo) -> -    type_string(TypeNo). - - -allocator_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 2), is_integer(TypeNo) -> -    case catch element(2, element(TypeNo, ?TYPEMAP(Hdr))) of -	{'EXIT', _} -> invalid_type; -	Type -> Type -    end; -allocator_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 1), is_integer(TypeNo) -> -    "unknown". - -class_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 2), is_integer(TypeNo) -> -    case catch element(3, element(TypeNo, ?TYPEMAP(Hdr))) of -	{'EXIT', _} -> invalid_type; -	Type -> Type -    end; -class_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 1), is_integer(TypeNo) -> -    "unknown". - -type_no_range({Hdr, _}) when ?IHDRVSN(Hdr, 2) -> -    {1, tuple_size(?TYPEMAP(Hdr))}; -type_no_range({Hdr, _}) when ?IHDRVSN(Hdr, 1) -> -    {-1, 1000}. - -type_string(-1) -> -    "unknown"; -type_string(1) -> -    "atom text"; -type_string(11) -> -    "atom desc"; -type_string(2) -> -    "bignum (big_to_list)"; -type_string(31) -> -    "fixalloc"; -type_string(32) -> -    "unknown fixalloc block"; -type_string(33) -> -    "message buffer"; -type_string(34) -> -    "message link"; -type_string(4) -> -    "estack"; -type_string(40) -> -    "db table vec"; -type_string(41) -> -    "db tree select buffer"; -type_string(43) -> -    "db hash select buffer"; -type_string(44) -> -    "db hash select list"; -type_string(45) -> -    "db match prog stack"; -type_string(46) -> -    "db match prog heap data"; -type_string(47) -> -    "db temp buffer"; -type_string(48) -> -    "db error"; -type_string(49) -> -    "db error info"; -type_string(50) -> -    "db trans tab"; -type_string(51) -> -    "db segment"; -type_string(52) -> -    "db term"; -type_string(53) -> -    "db add_counter"; -type_string(54) -> -    "db segment table"; -type_string(55) -> -    "db table (fix)"; -type_string(56) -> -    "db bindings"; -type_string(57) -> -    "db counter"; -type_string(58) -> -    "db trace vec"; -type_string(59) -> -    "db fixed deletion"; -type_string(60) -> -    "binary (external.c)"; -type_string(61) -> -    "binary"; -type_string(62) -> -    "procbin (fix)"; -type_string(70) -> -    "driver alloc (io.c)"; -type_string(71) -> -    "binary (io.c)"; -type_string(72) -> -    "binary vec (io.c)"; -type_string(73) -> -    "binary vec 2 (io.c)"; -type_string(74) -> -    "io vec (io.c)"; -type_string(75) -> -    "io vec 2 (io.c)"; -type_string(76) -> -    "temp io buffer (io.c)"; -type_string(77) -> -    "temp io buffer 2 (io.c)"; -type_string(78) -> -    "line buffer (io.c)"; -type_string(8) -> -    "heap"; -type_string(801) -> -    "heap (1)"; -type_string(802) -> -    "heap (2)"; -type_string(803) -> -    "heap (3)"; -type_string(804) -> -    "heap (4)"; -type_string(805) -> -    "heap (5)"; -type_string(821) -> -    "heap fragment (1)"; -type_string(822) -> -    "heap fragment (2)"; -type_string(830) -> -    "sequential store buffer (for vectors)"; -type_string(91) -> -    "process table"; -type_string(92) -> -    "process desc"; -type_string(110) -> -    "hash buckets"; -type_string(111) -> -    "hash table"; -type_string(120) -> -    "index init"; -type_string(121) -> -    "index table"; -type_string(130) -> -    "temp buffer"; -type_string(140) -> -    "timer wheel"; -type_string(150) -> -    "distribution cache"; -type_string(151) -> -    "dmem"; -type_string(152) -> -    "distribution table"; -type_string(153) -> -    "distribution table buckets"; -type_string(154) -> -    "distribution table entry"; -type_string(155) -> -    "node table"; -type_string(156) -> -    "node table buckets"; -type_string(157) -> -    "node table entry"; -type_string(160) -> -    "port table"; -type_string(161) -> -    "driver entry"; -type_string(162) -> -    "port setup"; -type_string(163) -> -    "port wait"; -type_string(170) -> -    "module"; -type_string(171) -> -    "fundef"; -type_string(180) -> -    "file table"; -type_string(181) -> -    "driver table"; -type_string(182) -> -    "poll struct"; -type_string(190) -> -    "inet driver"; -type_string(200) -> -    "efile driver"; -type_string(210) -> -    "gc root set"; -type_string(220) -> -    "breakpoint data"; -type_string(230) -> -    "async queue"; -type_string(231) -> -    "async (exit)"; -type_string(232) -> -    "async (driver)"; -type_string(240) -> -    "bits buffer"; -type_string(241) -> -    "bits temp buffer"; -type_string(250) -> -    "modules (loader)"; -type_string(251) -> -    "code (loader)"; -type_string(252) -> -    "atom tab (loader)"; -type_string(253) -> -    "import tab (loader)"; -type_string(254) -> -    "export tab (loader)"; -type_string(255) -> -    "lable tab (loader)"; -type_string(256) -> -    "gen op (loader)"; -type_string(257) -> -    "gen op args (loader)"; -type_string(258) -> -    "gen op args 2 (loader)"; -type_string(259) -> -    "gen op args 3 (loader)"; -type_string(260) -> -    "lambdas (loader)"; -type_string(261) -> -    "temp int buffer (loader)"; -type_string(262) -> -    "temp heap (loader)"; -type_string(280) -> -    "dist ctrl msg buffer"; -type_string(281) -> -    "dist_buf"; -type_string(290) -> -    "call trace buffer"; -type_string(300) -> -    "bif timer rec"; -type_string(310) -> -    "argument registers"; -type_string(320) -> -    "compressed binary temp buffer"; -type_string(330) -> -    "term_to_binary temp buffer"; -type_string(340) -> -    "proc dict"; -type_string(350) -> -    "trace to port temp buffer"; -type_string(360) -> -    "lists subtract temp buffer"; -type_string(370) -> -    "link (lh)"; -type_string(380) -> -    "port call buffer"; -type_string(400) -> -    "definite_alloc block"; -type_string(_) -> -    invalid_type. - +dispatch_gather(#{ allocator_types := AllocatorTypes, +                   scheduler_ids := SchedulerIds, +                   histogram_start := HistStart, +                   histogram_width := HistWidth }, Ref, Gather) +        when is_list(AllocatorTypes), +             is_list(SchedulerIds), +             HistStart >= 1, HistStart =< (1 bsl 28), +             HistWidth >= 1, HistWidth =< 32 -> +    MsgCount = lists:sum( +        [Gather({AllocatorType, SchedId, HistWidth, HistStart, Ref}) || +         SchedId <- SchedulerIds, +         AllocatorType <- AllocatorTypes]), +    {HistStart, MsgCount}; +dispatch_gather(_, _, _) -> +    error(badarg). diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl index d0152a4915..ee6057e4f5 100644 --- a/lib/tools/src/lcnt.erl +++ b/lib/tools/src/lcnt.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %% -%% Copyright Ericsson AB 2010-2017. All Rights Reserved. +%% Copyright Ericsson AB 2010-2018. All Rights Reserved.  %%  %% Licensed under the Apache License, Version 2.0 (the "License");  %% you may not use this file except in compliance with the License. @@ -125,7 +125,7 @@  %% -------------------------------------------------------------------- %%  start()  -> gen_server:start({local, ?MODULE}, ?MODULE, [], []). -stop()   -> gen_server:call(?MODULE, stop, infinity). +stop()   -> gen_server:stop(?MODULE, normal, infinity).  init([]) -> {ok, #state{ locks = [], duration = 0 } }.  start_internal() -> @@ -442,9 +442,6 @@ handle_call({save, Filename}, _From, State) ->  	    {reply, {error, Error}, State}      end; -handle_call(stop, _From, State) -> -    {stop, normal, ok, State}; -  handle_call(Command, _From, State) ->      {reply, {error, {undefined, Command}}, State}. diff --git a/lib/tools/src/xref.erl b/lib/tools/src/xref.erl index 32efa36fa2..466ec7d331 100644 --- a/lib/tools/src/xref.erl +++ b/lib/tools/src/xref.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %%  -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2018. All Rights Reserved.  %%   %% Licensed under the Apache License, Version 2.0 (the "License");  %% you may not use this file except in compliance with the License. @@ -182,7 +182,9 @@ split_args(Opts) ->      end.  stop(Name) -> -    gen_server:call(Name, stop, infinity). +    try gen_server:call(Name, stop, infinity) +    after catch unregister(Name) % ensure the name is gone +    end.  add_release(Name, Dir) ->      gen_server:call(Name, {add_release, Dir}, infinity). diff --git a/lib/tools/src/xref_utils.erl b/lib/tools/src/xref_utils.erl index 02e207d40c..eca751337b 100644 --- a/lib/tools/src/xref_utils.erl +++ b/lib/tools/src/xref_utils.erl @@ -557,12 +557,9 @@ subdir(Dir, SubDir, true) ->  %% Avoid "App-01.01" - the zeroes will be lost.  filename2appl(File) -> -    Pos = string:rstr(File, "-"), -    true = Pos > 1, -    V = string:sub_string(File, Pos+1), -    true = string:len(V) > 0, -    VsnT = string:tokens(V, "."), -    ApplName = string:sub_string(File, 1, Pos-1), +    [ApplName, V] = string:split(File, "-", trailing), +    true = string:length(V) > 0, +    VsnT = string:lexemes(V, "."),      Vsn = [list_to_integer(Vsn) || Vsn <- VsnT],      {list_to_atom(ApplName),Vsn}. | 
