Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://bitbucket.org/adelard/simple-concurrency
16 July 2020, 04:59:35 UTC
  • Code
  • Branches (2)
  • Releases (0)
  • Visits
    • Branches
    • Releases
    • HEAD
    • branch-tip/byako/test
    • branch-tip/default
    No releases to show
  • e4d595e
  • /
  • concur_gui.ml
Raw File Download Save again
Take a new snapshot of a software origin

If the archived software origin currently browsed is not synchronized with its upstream version (for instance when new commits have been issued), you can explicitly request Software Heritage to take a new snapshot of it.

Use the form below to proceed. Once a request has been submitted and accepted, it will be processed as soon as possible. You can then check its processing state by visiting this dedicated page.
swh spinner

Processing "take a new snapshot" request ...

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
  • revision
  • snapshot
origin badgecontent badge
swh:1:cnt:82e0d494faf06747d4f0d84d61ccb5f429352e4b
origin badgedirectory badge
swh:1:dir:e4d595ee90553d4d4eb96aa716bc6b01210af2c9
origin badgerevision badge
swh:1:rev:cd7dfa9b13e79137daa54446067371af0a68515d
origin badgesnapshot badge
swh:1:snp:c4b5596e0a959f5423a65cdaf9ad7aba9e9b4ce1

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
  • revision
  • snapshot
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
Tip revision: cd7dfa9b13e79137daa54446067371af0a68515d authored by Dan Sheridan on 27 February 2015, 15:32:58 UTC
Change -accesses-for to report accesses from the "main" entry point even if it is not explicitly listed in -threads; this better matches the behaviour of -var-overlap.
Tip revision: cd7dfa9
concur_gui.ml
(**************************************************************************)
(*                                                                        *)
(*  This file is part of the Concurrency Plugin for Frama-C               *)
(*                                                                        *)
(*  Copyright (C) 2013                                                    *)
(*    Adelard LLP                                                         *)
(*    CINIF (Control and Instrumentation Nuclear Industry Forum)          *)
(*                                                                        *)
(*  You can redistribute it and/or modify it under the terms of the GNU   *)
(*  Lesser General Public License as published by the Free Software       *)
(*  Foundation, version 3.                                                *)
(*                                                                        *)
(*  It is distributed in the hope that it will be useful,                 *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
(*  GNU Lesser General Public License for more details.                   *)
(*                                                                        *)
(*  See the GNU Lesser General Public License version v3                  *)
(*  for more details (enclosed in the file ./LGPLv3).                     *)
(*                                                                        *)
(**************************************************************************)

(**
* This is the main entry for the Concurrency plugin gui.
*)

(*GUIs*)
open Gtk_helper
open Pretty_source 

(*Plugin modules*)
open Concurrency_main
open Cil_datatype 
open Cil_types
open Visitor

(*open Option - was not been able to link this library ExtLib*)
open Concurguiglobs
open Vappgui
open Accessesgui 
open Epsgui


let show_column = ref (fun _ -> ());;	(*the 'Concurrency' column in filetree*)

(** Computes an intersection of the variable sets used by the main thread
 *  and the selected thread*)
let update_var_overlap () =
  if (List.length (SelectedThreads.get ())) > 0  && ((SelectedMain.get) () != init_fundec)
  then
    (
      let main_vars = variables_used (get_option !cg) (SelectedMain.get ()) in
 
      let intersect_vars st f2 =
	if f2 != (SelectedMain.get ()) then
	  Varinfo.Set.inter st (variables_used (get_option !cg) f2)
	else
	  st
      in
 
      let out_set = List.fold_left intersect_vars main_vars (SelectedThreads.get ()) in
	
      VarOverlapSet_ref.set out_set;
    )
  else
    () ;;
 
(** Updates the R/W access locations for a particular variable and thread 
 * and converts this data to the local data holder type*)
let update_acc() =
  if (List.length (SelectedThreads.get ())) > 0  
    && (SelectedMain.get ()) != init_fundec 
      && (LockedVar.get ()) != init_varinfo
  then
    begin
      (*obtains the locs for the current entry point*)
      let get_locs_for_v_from_ep v ep = 
	let vis = new varAccess v in
	let visfun _ f = 
	  let _ = visitFramacFunction (vis:>frama_c_visitor) f in ()
	in
	cg_dfs_fundecs (get_option !cg) visfun ep;
	vis#locs
      in
      
      (*converts locs to the AccessForList type*)
      let to_access_for ep (a, b, c) =
	(ep, a, b, c) 
      in
      
      let main_locs = get_locs_for_v_from_ep (LockedVar.get ()) (SelectedMain.get ()) in
      
      AccessForList.set [];
      AccessForList.set (List.append (AccessForList.get ()) (List.map (to_access_for (SelectedMain.get ())) main_locs));
      
      
      let apply_to_all_eps ep =
	let ep_locs = get_locs_for_v_from_ep (LockedVar.get ()) ep in
	AccessForList.set (List.append (AccessForList.get ()) (List.map (to_access_for ep) ep_locs))
      in
      List.iter apply_to_all_eps (SelectedThreads.get ())
    end ;;

(** Updates the pretty source viewer part of the Frama-C GUI
* to highlight the critical regions in the code.
*)
let concur_highlighter buffer loc ~start ~stop =
  if (List.length (AccessForList.get ())) > 0 then
    begin
      let highlight clr =
	(*make_tag apply_tag are frama-c functions*)
	let tag = make_tag buffer "concurrency" [`BACKGROUND clr ] in
        apply_tag buffer tag start stop
      in 
      
      match loc with
        | PLval (_, ki, (lh,_)) ->     
	  let same_lval ki lh (_,k,_,_) = 
	    (Kinstr.equal ki k) && 
	      match lh with 
		| Var(vi) -> (Varinfo.equal vi (LockedVar.get ()))  
		| _ ->  false 
	  in
	  if List.exists (same_lval ki lh) (AccessForList.get ()) then
 	    highlight "yellow";
	| PTermLval (_,ki,(lh,_)) ->	  
	  let same_tlval ki lh (_,k,_,_) = 
	    (Kinstr.equal ki k) && 
	      match lh with 
		| TVar(tv) ->
		  begin
		    match tv.lv_origin with
		      | Some(vi) -> (Varinfo.equal vi (LockedVar.get ()))  
		      | None ->  false
		  end
		| _ -> false
	  in 
	  if List.exists (same_tlval ki lh) (AccessForList.get ()) then 
	    highlight "yellow"
		
	| PVDecl(_, vi') when Varinfo.equal (LockedVar.get ()) vi' ->
	  highlight "yellow"
	    
        | PVDecl _ | PStmt _ | PGlobal _ | PIP _ -> ()
    end;;

(** Configures the concurrency plugin side panel and loads the additional forms. 
*)
let concurrency_panel main_ui =  
  let eps_display = new vEpsWindow in 			(*entry points form*)
  let var_overlap_display = new vAppWindow in		(*intersected variables form*)
  let access_display = new vAccWindow main_ui in	(*access form*) 

  (*setup the side panel*)
  let v_box = GPack.vbox () in 
  let h0_box = GPack.hbox ~packing: v_box#pack () in
  let _ = GMisc.label 
    ~xalign:0.0 
    ~text:"Filter:" 
    ~width:100
    ~packing:(h0_box#pack ~expand:false) () 
  in
  let open_ep_filter = GButton.button ~label:"Entry Points" ~packing:h0_box#pack () in
 
  ignore (open_ep_filter#connect#pressed (fun () -> eps_display#show_eps ()));

  (*Create Main combo and label*)
  let h2_box = GPack.hbox ~packing: v_box#pack () in

  let _ = GMisc.label 
    ~xalign:0.0 
    ~text:"Current main: "
    ~width:100
    ~packing:(h2_box#pack ~expand:false) () 
  in

  let main_combo = GEdit.combo_box_text ~strings:[] 
    ~has_frame:true ~packing:h2_box#pack () 
  in
  
  (*Populates the main entry point combo box with 
    selection of available entry points*)
  let populate_main () =
    let add_eps_to_combo ep = 
      let ep_name = (Kernel_function.get_name ep) in
      GEdit.text_combo_add main_combo ep_name
    in
    let (_,(a,_)) = main_combo in
    a#clear ();
    List.iter add_eps_to_combo (FilteredEntryPoints.get ()) 
  in

  let (a,_) = main_combo in
  ignore(a#connect#changed (fun () -> 
    let mn = match GEdit.text_combo_get_active main_combo with
      | Some(a) -> Globals.Functions.find_by_name a
      | None ->   init_fundec
    in
    if mn != init_fundec then
      begin
	SelectedMain.set mn; 
	LockedVar.set  init_varinfo; 
	AccessForList.set []; 
	SelectedThreads.set [];
	VarOverlapSet_ref.set Varinfo.Set.empty;
	refresh := (false,true,true,true,false)	(*update gui*)
      end));
 
  (*Create E.P. combo and label*)
  let h3_box = GPack.hbox ~packing: v_box#pack () in

  let _ = GMisc.label 
    ~xalign:0.0 
    ~text:"Current E.P.: " 
    ~width:100
    ~packing:(h3_box#pack ~expand:false) () 
  in

  let eps_combo = GEdit.combo_box_text ~strings:[] ~has_frame:true ~packing:h3_box#pack () in

  (* Populates the Entry Points combo with the 
  available entry points except what was selected as a main entry point*)
  let populate_eps () =
    let current_main = match GEdit.text_combo_get_active main_combo with
      | Some(a) -> a
      | None -> ""
    in
    let add_eps_to_combo ep = 
      let ep_name = (Kernel_function.get_name ep) in
      if not (ep_name = current_main) then
	GEdit.text_combo_add eps_combo ep_name
    in
    let (_,(a,_)) = eps_combo in
    a#clear ();
    List.iter add_eps_to_combo (FilteredEntryPoints.get ()) 
  in
  let (a,_) = eps_combo in
  ignore(a#connect#changed (
    fun () -> 
      let ep = match GEdit.text_combo_get_active eps_combo with
	| Some(a) -> Globals.Functions.find_by_name a
	| None ->  init_fundec
      in
      if ep != init_fundec then
	begin
	  SelectedThreads.set [ep];
	  LockedVar.set  init_varinfo; 
	  VarOverlapSet_ref.set Varinfo.Set.empty;
	  AccessForList.set [];
	  refresh := (false,false,true,true,false) (*update gui*)
	end));

  (*Create the currently selected variable combo box*)
  let h1_box = GPack.hbox ~packing: v_box#pack () in
  
  let _ = GMisc.label 
    ~xalign:0.0 
    ~text:"Current variable:" 
    ~width:100
    ~packing:(h1_box#pack ~expand:false) () 
  in
 
  let var_combo = GEdit.combo_box_text ~strings:[] ~has_frame:true ~packing:h1_box#pack () in

  (*Populates the combo box with the current 
  variables shared between main and EP thread.*)
  let populate_var () = 
    let (a,(b,_)) = var_combo in
    let add_vars_to_combo vi c =
      if not (Cil.isFunctionType vi.vtype) then begin
        GEdit.text_combo_add var_combo vi.vname;
      
        (*the purpose of this is to activate the currently selected variable*)
        if vi.vname == (LockedVar.get ()).vname then
	  a#set_active c; (*how to get the number of elements added*)
        c+1
      end
      else c
    in
    b#clear (); 
    ignore(Varinfo.Set.fold  add_vars_to_combo (VarOverlapSet_ref.get ()) 0);
  in

  let (a,_) = var_combo in
  ignore(a#connect#changed (fun () ->  
    let vi = match GEdit.text_combo_get_active var_combo with
      | Some(a) ->
        (try Globals.Vars.find_from_astinfo a VGlobal
         with Not_found -> init_varinfo)
      | None ->  init_varinfo
    in
    if vi != init_varinfo then
      LockedVar.set vi;
    AccessForList.set [];
    refresh := (false, false, false, true, false) (*update gui*)
  ));

  (*create buttons*)
  let show_vapp = GButton.button ~label:"Details" ~packing:h1_box#pack () in
 
  ignore (show_vapp#connect#pressed (fun () -> var_overlap_display#show_vapp ()));
  
  let h4_box = GPack.hbox ~packing: v_box#pack () in 
  let _ = GMisc.label 
    ~xalign:0.0 
    ~text:"Compute:" 
    ~width:100
    ~packing:(h4_box#pack ~expand:false) () 
  in

  let button_access_details = GButton.button ~label:"Show Details" ~packing:h4_box#pack () in
  ignore (button_access_details#connect#pressed(fun () -> update_acc (); access_display#show_acc ()));

  (* Drives the GUI statemachine updating the Concurrency section of the GUI*)
  let refresh = fun () -> 
    begin 
      (*We could replace this by some sort of signal*)
      let (m,e,v,g,_) = !refresh in
      if m then
	populate_main ();

      (*main has changed*)
      if e then
	populate_eps ();
      
      (*main or eps have changed*)
      if v then 
	begin
	  update_var_overlap (); 
	  populate_var ();
	  !show_column `Visibility
	end;

      (*main or eps or var have changed*)
      if g then
	begin
	  populate_var (); 
	  update_acc ();
	  !show_column `Visibility
	end;

     if m || e || v || g then
       (
	 var_overlap_display#refresh ();
	 access_display#refresh (); 
	 main_ui#rehighlight ();
       );

     
      refresh := (false,false, false, false, false)
    end	
  in
  "Concurrency", v_box#coerce, Some refresh 
;;     

(** Decorates the file tree Concurrency colum to show the 
 * functions where a particular variable is used.
*)
let file_tree_decorate (file_tree:Filetree.t) =
  show_column := 
    file_tree#append_pixbuf_column 
    ~title:"Concurrency"
    (fun globs ->
      if  List.length (AccessForList.get ()) > 0 then
	begin
          let in_globals (_,ki,_,_) =
            match ki with
              | Kglobal -> false
              | Kstmt stmt ->
		let kf = Kernel_function.find_englobing_kf stmt in
		let {vid=v0} = Kernel_function.get_vi kf in
		List.exists
                  (fun glob -> match glob with
                    | GFun ({svar ={vid=v1}},_ ) -> v1=v0
                    |  _ -> false)
                  globs
          in
          if (List.exists in_globals (AccessForList.get ())) then [`STOCK_ID "gtk-apply"]
          else [`STOCK_ID ""]
	end
      else
        [`STOCK_ID ""])
    (fun () -> not (Varinfo.equal (LockedVar.get ()) init_varinfo));
  !show_column `Visibility ;;


let concur_gui_f main_ui= 
  (*init*)
  start_concurrency ();
  Self.result "Starting concur plugin";
  (*menu accessible from right clicking on the source viewer*)
  (*main_ui#register_source_selector concur_menu_item;*)
  (*highlights in main code display when necessary parameters of the plugin 
  are set*)
  main_ui#register_source_highlighter concur_highlighter;
  main_ui#register_panel concurrency_panel;
  file_tree_decorate main_ui#file_tree;
;;

(*Register the main_gui function as enty point for Concur GUI*)
let () = Design.register_extension concur_gui_f ;;

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API