Version française
Home     About     Download     Resources     Contact us    
Browse thread
[ANN] coThreads 0.10
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: skaller <skaller@u...>
Subject: Re: [Caml-list] [ANN] coThreads 0.10
On Tue, 2007-09-18 at 16:23 +1000, Erik de Castro Lopo wrote:
> skaller wrote:

> > It is not clear that a seek to an invalid position in the file
> > is going to succeed. It's also not clear to me that the seek
> > argument isn't 32 bits (depends on complex ugly GNU macro
> > hackery what type off_t is .. my Caml got built with
> > the LARGE_FILE macro thing so it should be 64 bits).
> 
> Shouldn't off_t always be 64 bits on a 64 bit CPU? 

I don't know. I traced through the code and did some debugging,
and the problem is that system wide mutex is emulated by using
locking on an lseek on a (deleted) lock file. The seek address
is a magic number which is rather large, and this appears to
cause the EINVAL errno on the lseek call.

let lock_fd = 
  print_endline "CREATING MUTEX";
  let lock_name = fresh_name "_mutex" in
  remove_exists lock_name; 
  let fd = openfile lock_name [O_WRONLY; O_CREAT] file_perm in
  remove_exists lock_name;
  fd

type t = int (* The offset *)

let create = fresh_number

let rec lock lk = 
  print_endline ("LOCK " ^ string_of_int lk);
  if lk <> lseek lock_fd lk SEEK_SET then assert false;
  lockf lock_fd F_LOCK 1

So basically a mutex is modelled by an offset,
which is created by fresh_number routine, and using
Unix discretionary locks with lockf function, which
is based on the current position in the file.

Well, I don't see how the lseek can fail unless there
is a filesize constraint somewhere detecting that

1695112678495748100

is an invalid offset for lseek. 

A possible patch is to take this in process.coordinator

(* fresh_number fresh_name ensure that there won't exist number/name
   confliction between running processes.
*)
let fresh_number =
  let usable_size = Sys.word_size -2 in
  let bits_of_id = 16 in (* Should be sufficient in most OS *)
  let bits_of_num = usable_size - bits_of_id in
  let counter = ref 0 in
  fun () ->
    let self_id = id (self ()) in
    let id_part = bit_chop_to_n bits_of_id self_id in
    let num_part = 
      counter := bit_chop_to_n bits_of_num (!counter + 1);
      !counter in
    (id_part lsl bits_of_num) + num_part


and use the line 2:

  let usable_size = 30 in

instead (though I didn't try it, some other places may need
to replace Sys.word_size the same way for it to work
properly).

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net