1
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
type thread_ic = in_channel
let prepare_in_channel_for_thread_friendly_io ic = ic
let thread_friendly_read_fd fd s ~off ~len =
let rec loop () =
try Unix.read fd s off len
with Unix.Unix_error(Unix.EINTR,_,_) -> loop ()
in
loop ()
let thread_friendly_read ic s ~off ~len =
try
let fd = Unix.descr_of_in_channel ic in
thread_friendly_read_fd fd s ~off ~len
with Unix.Unix_error _ -> 0
let really_read_fd fd s off len =
let i = ref 0 in
while !i < len do
let off = off + !i in
let len = len - !i in
let r = thread_friendly_read_fd fd s ~off ~len in
if r = 0 then raise End_of_file;
i := !i + r
done
let really_read_fd_2_oc fd oc len =
let i = ref 0 in
let size = 4096 in
let s = Bytes.create size in
while !i < len do
let len = len - !i in
let r = thread_friendly_read_fd fd s ~off:0 ~len:(min len size) in
if r = 0 then raise End_of_file;
i := !i + r;
output oc s 0 r;
done
let thread_friendly_really_read ic s ~off ~len =
try
let fd = Unix.descr_of_in_channel ic in
really_read_fd fd s off len
with Unix.Unix_error _ -> raise End_of_file
let thread_friendly_really_read_line ic =
try
let fd = Unix.descr_of_in_channel ic in
let b = Buffer.create 1024 in
let s = Bytes.make 1 '\000' in
let endl = Bytes.of_string "\n" in
while Bytes.compare s endl <> 0 do
let n = thread_friendly_read_fd fd s ~off:0 ~len:1 in
if n = 0 then raise End_of_file;
if Bytes.compare s endl <> 0 then Buffer.add_bytes b s;
done;
Buffer.contents b
with Unix.Unix_error _ -> raise End_of_file
let thread_friendly_input_value ic =
try
let fd = Unix.descr_of_in_channel ic in
let = Bytes.create Marshal.header_size in
really_read_fd fd header 0 Marshal.header_size;
let body_size = Marshal.data_size header 0 in
let desired_size = body_size + Marshal.header_size in
if desired_size <= Sys.max_string_length then begin
let msg = Bytes.create desired_size in
Bytes.blit header 0 msg 0 Marshal.header_size;
really_read_fd fd msg Marshal.header_size body_size;
Marshal.from_bytes msg 0
end else begin
let name, oc =
Filename.open_temp_file ~mode:[Open_binary] "coq" "marshal" in
try
output oc header 0 Marshal.header_size;
really_read_fd_2_oc fd oc body_size;
close_out oc;
let ic = open_in_bin name in
let data = Marshal.from_channel ic in
close_in ic;
Sys.remove name;
data
with e -> Sys.remove name; raise e
end
with Unix.Unix_error _ | Sys_error _ -> raise End_of_file
let mask_sigalrm f x =
begin try ignore(Thread.sigmask Unix.SIG_BLOCK [Sys.sigalrm])
with Invalid_argument _ -> () end;
f x
let create f x =
Thread.create (mask_sigalrm f) x
external unlock: Mutex.t -> unit = "caml_mutex_unlock"
let[@inline never] with_lock m ~scope =
let () = Mutex.lock m in
match scope () with
| x -> unlock m ; x
| exception e -> unlock m ; raise e