Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
in_memory.ml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160(* * Copyright (C) Citrix Systems Inc. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *) module Config = struct open Lwt type t = { ring_ref: string; event_channel: string; } let tbl: (Port.t, t) Hashtbl.t = Hashtbl.create 16 let c = Lwt_condition.create () let write ~client_domid:_ ~port t = Hashtbl.replace tbl port t; return () let read ~server_domid:_ ~port = let rec loop () = if Hashtbl.mem tbl port then return (Hashtbl.find tbl port) else Lwt_condition.wait c >>= fun () -> loop () in loop () let delete ~client_domid:_ ~port = Hashtbl.remove tbl port; return () let assert_cleaned_up () = if Hashtbl.length tbl <> 0 then begin Printf.fprintf stderr "Stale config entries in xenstore\n%!"; failwith "stale config entries in xenstore"; end end module Memory = struct type grant = int32 let grant_of_int32 x = x let int32_of_grant x = x type page = Io_page.t let x = x.grants let x = x.mapping let get = let g = ref Int32.zero in fun () -> g := Int32.succ !g; Int32.pred !g let rec get_n n = if n = 0 then [] else get () :: (get_n (n-1)) let individual_pages = Hashtbl.create 16 let big_mapping = Hashtbl.create 16 let ~domid:_ ~npages ~rw:_ = let mapping = Io_page.get npages in let grants = get_n npages in let = { grants; mapping } in let pages = Io_page.to_pages mapping in List.iter (fun (grant, page) -> Hashtbl.replace individual_pages grant page) (List.combine grants pages); Hashtbl.replace big_mapping (List.hd grants) mapping; share let remove tbl key = if Hashtbl.mem tbl key then Hashtbl.remove tbl key else begin Printf.fprintf stderr "Attempt to remove non-existing mapping\n%!"; failwith "Attempt to remove non-existing mapping" end let = List.iter (fun grant -> remove individual_pages grant) share.grants; remove big_mapping (List.hd share.grants); Lwt.return_unit type mapping = { mapping: page; grants: (int * int32) list; } let buf_of_mapping x = x.mapping let currently_mapped = Hashtbl.create 16 let map ~domid ~grant ~rw:_ = let mapping = Hashtbl.find individual_pages grant in if Hashtbl.mem currently_mapped grant then begin Printf.fprintf stderr "map: grant %ld is already mapped\n%!" grant; failwith (Printf.sprintf "map: grant %ld is already mapped" grant); end; Hashtbl.replace currently_mapped grant (); { mapping; grants = [ domid, grant ] } let mapv ~grants ~rw:_ = if grants = [] then begin Printf.fprintf stderr "mapv called with empty grant list\n%!"; failwith "mapv: empty list" end; let first = snd (List.hd grants) in let mapping = Hashtbl.find big_mapping first in if Hashtbl.mem currently_mapped first then begin Printf.fprintf stderr "mapv: grant %ld is already mapped\n%!" first; failwith (Printf.sprintf "mapv: grant %ld is already mapped" first); end; Hashtbl.replace currently_mapped first (); { mapping; grants } let unmap { mapping = _; grants } = let first = snd (List.hd grants) in if Hashtbl.mem currently_mapped first then Hashtbl.remove currently_mapped first else begin Printf.fprintf stderr "unmap called with already-unmapped grant\n%!"; failwith "unmap: already unmapped" end let assert_cleaned_up () = if Hashtbl.length currently_mapped <> 0 then begin Printf.fprintf stderr "Some grants are still mapped in\n%!"; failwith "some grants are still mapped in" end; if Hashtbl.length big_mapping <> 0 then begin Printf.fprintf stderr "Some grants are still active\n%!"; failwith "some grants are still active" end end let assert_cleaned_up () = Memory.assert_cleaned_up (); Config.assert_cleaned_up (); In_memory_events.assert_cleaned_up () include Endpoint.Make(In_memory_events)(Memory)(Config)