Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file netsys_mem.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550(* $Id$ *)openNetsys_typesopenPrintftypememory=(char,Bigarray.int8_unsigned_elt,Bigarray.c_layout)Bigarray.Array1.texternalblit_memory_to_string_unsafe :memory->int->Bytes.t->int->int ->unit="netsys_blit_memory_to_string" NOALLOCexternalblit_memory_to_bytes_unsafe:memory->int->Bytes.t->int->int->unit="netsys_blit_memory_to_string" NOALLOCexternalblit_string_to_memory_unsafe:string->int->memory->int->int->unit="netsys_blit_string_to_memory"NOALLOCexternalblit_bytes_to_memory_unsafe:Bytes.t->int->memory->int->int->unit="netsys_blit_string_to_memory"NOALLOCletblit_memory_to_bytesmemmemoffssoff len=letmemlen=Bigarray.Array1.dimmeminletslen=Bytes.lengthsiniflen<0||memoff<0||memoff>memlen-len ||soff<0||soff>slen-lentheninvalid_arg"Netsys_mem.blit_memory_to_bytes";blit_memory_to_bytes_unsafememmemoffssofflenletblit_memory_to_string=blit_memory_to_bytesletblit_string_to_memoryssoffmemmemofflen =letmemlen=Bigarray.Array1.dimmeminletslen=String.lengthsiniflen<0||memoff <0||memoff>memlen-len||soff<0||soff>slen-lentheninvalid_arg"Netsys_mem.blit_string_to_memory";blit_string_to_memory_unsafessoffmemmemofflenletblit_bytes_to_memoryssoffmemmemofflen=blit_string_to_memory(Bytes.unsafe_to_strings)soff memmemofflenletmemory_of_strings=letn=String.lengthsinletm=Bigarray.Array1.createBigarray.charBigarray.c_layoutninblit_string_to_memorys0m0n;mletmemory_of_bytess=memory_of_string(Bytes.unsafe_to_strings)letbytes_of_memory m=letn=Bigarray.Array1.dimminlets=Bytes.createninblit_memory_to_bytes m0s0n;sletstring_of_memorym=Bytes.unsafe_to_string(bytes_of_memorym)externalmemory_address:memory->nativeint="netsys_memory_address"externalreshape:'a->memory="netsys_reshape"(* 'a = any bigarray *)letmemory_of_bigarrayb=reshapebletmemory_of_bigarray_1b=reshapebletmemory_of_bigarray_2b=reshapebletmemory_of_bigarray_3b=reshapebexternal getpagesize:unit->int="netsys_getpagesize"letpagesize=trygetpagesize()withInvalid_argument_->4096externalnetsys_alloc_memory_pages:nativeint->int->bool->memory="netsys_alloc_memory_pages"letalloc_memory_pages?(addr=0n)?(exec=false)len=netsys_alloc_memory_pagesaddrlenexecexternalalloc_aligned_memory:int->int->memory="netsys_alloc_aligned_memory"externalnetsys_map_file :Unix.file_descr->int64 ->nativeint->bool->int-> memory="netsys_map_file"letmemory_map_filefd?(pos=0L)?(addr=0n)sharedsize=netsys_map_filefdposaddrsharedsizeexternalmemory_unmap_file:memory->unit="netsys_memory_unmap_file"externalnetsys_zero_pages:memory->int->int->unit="netsys_zero_pages"letzero_pagesmem poslen=letmemlen=Bigarray.Array1.dimmeminiflen<0||pos<0||pos>memlen-lentheninvalid_arg"Netsys_mem.zero_pages (index out of range)";netsys_zero_pages memposlenexternalgrab:nativeint ->int->memory="netsys_grab"external as_value:memory->int->'a="netsys_as_value"letas_objmemoffs=Obj.repr(as_valuememoffs)(*
external netsys_value_area_add : memory -> unit
= "netsys_value_area_add"
external netsys_value_area_remove : memory -> unit
= "netsys_value_area_remove"let value_area m =
netsys_value_area_add m;
Gc.finalise netsys_value_area_remove m;
()
*)externalobj_address:Obj.t->nativeint="netsys_obj_address"externalhdr_address:Obj.t->nativeint="netsys_hdr_address"externalinit_header :memory->int->int->int->unit="netsys_init_header"externalcmp_bytes:Bytes.t->Bytes.t->int="netsys_cmp_string"externalcmp_string:string->string->int="netsys_cmp_string"externalnetsys_init_string:memory->int->int->unit="netsys_init_string"letinit_string_bytelenlen=let ws=Sys.word_size /8in(* word size in bytes *)((len+ws)/ws+1)*wsexceptionOut_of_spacelet_=Callback.register_exception"Netsys_mem.Out_of_space"Out_of_spaceletinit_stringmemoffsetlen=letws =Sys.word_size/8in(* word size in bytes *)letmemlen=Bigarray.Array1.dimmeminifoffset<0||len<0theninvalid_arg"Netsys_mem.init_string";letblen=init_string_bytelen leninifblen>memlen-offsetthenraiseOut_of_space;netsys_init_stringmemoffsetlen;(offset+ws,blen)letinit_array_bytelensize=letws=Sys.word_size /8in(* word size in bytes *)(size+1)*wslet init_array memoffsetsize=letws=Sys.word_size/8in(* word size in bytes *)letmemlen=Bigarray.Array1.dimmeminifoffset<0||size<0theninvalid_arg"Netsys_mem.init_array";letblen=init_array_bytelensizeinifblen>memlen-offset thenraiseOut_of_space;init_headermemoffset0size;Bigarray.Array1.fill(Bigarray.Array1.submem(offset+ws)(size*ws))'\001';(offset+ws,blen)letinit_float_array_bytelensize=letws=Sys.word_size/8in(* word size in bytes *)ifws=4then(2*size +1)*wselse(size+1)*wsletinit_float_arraymemoffsetsize=letws=Sys.word_size/8in(* word size in bytes *)let memlen=Bigarray.Array1.dimmeminifoffset <0||size<0theninvalid_arg "Netsys_mem.init_array";letblen=init_float_array_bytelensizeinif blen>memlen-offsetthenraiseOut_of_space;init_headermemoffsetObj.double_array_tagsize;Bigarray.Array1.fill(Bigarray.Array1.submem(offset+ws)(size*ws))'\001';(offset+ws,blen)typeinit_value_flag =|Copy_bigarray|Copy_custom_int|Copy_atom|Copy_simulate|Copy_conditionally|Keep_atomtypecustom_ops=nativeint(*
external netsys_init_value :
memory -> int -> 'a -> init_value_flag list -> nativeint -> (string* custom_ops) list -> ((int*int) list) -> (int * int) = "netsys_init_value_bc" "netsys_init_value"
let init_value ?targetaddr ?(target_custom_ops=[]) ?(cc=[])
mem offset v flags =
let taddr =
match targetaddr with
| None ->
memory_address mem
| Some a ->
a in
let cc =
List.map
(fun (s,e) ->
( Nativeint.to_int (Nativeint.shift_right s 1),
Nativeint.to_int (Nativeint.shift_right e 1)
)
)
cc in
netsys_init_value mem offset v flags taddr target_custom_ops cc
external get_custom_ops : 'a -> string * custom_ops
= "netsys_get_custom_ops"
external copy_value : init_value_flag list -> 'a -> 'a
= "netsys_copy_value"
*)typecolor=White|Gray|Blue|Black(*
external color : Obj.t -> color
= "netsys_color"
external set_color : Obj.t -> color -> unit
= "netsys_set_color"
external is_bigarray : Obj.t -> bool
= "netsys_is_bigarray"
*)externalnetsys_mem_read:Unix.file_descr->memory->int->int->int="netsys_mem_read"externalnetsys_mem_write:Unix.file_descr->memory->int->int->int="netsys_mem_write"letmem_readfdmemofflen=iflen<0||off<0||len >Bigarray.Array1.dimmem-offtheninvalid_arg"Netsys_mem.mem_read";netsys_mem_readfdmemofflenletmem_writefdmemofflen=iflen<0||off<0||len>Bigarray.Array1.dimmem-offtheninvalid_arg"Netsys_mem.mem_write";netsys_mem_writefdmemofflenexternalnetsys_mem_recv:Unix.file_descr->memory->int-> int->Unix.msg_flaglist->int="netsys_mem_recv"(*
externalnetsys_mem_recvfrom : Unix.file_descr -> memory -> int -> int-> Unix.msg_flag list ->
int * Unix.sockaddr
= "netsys_mem_recvfrom"
*)externalnetsys_mem_send:Unix.file_descr->memory->int->int->Unix.msg_flaglist ->int="netsys_mem_send"(*
external netsys_mem_sendto :
Unix.file_descr ->memory -> int -> int -> Unix.msg_flag list ->
Unix.sockaddr -> int
= "netsys_mem_sendto" "netsys_mem_sendto_native"
*)letmem_recvfdmemofflenflags=iflen<0||off<0||len>Bigarray.Array1.dimmem-offtheninvalid_arg"Netsys_mem.mem_recv";netsys_mem_recvfdmemofflenflags(*
let mem_recvfrom fd mem off len flags =
if len < 0 || off < 0 || len > Bigarray.Array1.dim mem - off then
invalid_arg "Netsys_mem.mem_recvfrom";
netsys_mem_recvfrom fd mem off len flags
*)letmem_sendfdmemofflenflags=iflen<0||off<0||len>Bigarray.Array1.dimmem-offtheninvalid_arg"Netsys_mem.mem_send";netsys_mem_send fdmemofflenflags(*
let mem_sendto fd mem off len flags addr =
iflen< 0|| off < 0 || len > Bigarray.Array1.dim mem - off then
invalid_arg "Netsys_mem.mem_sendto";
netsys_mem_sendto fd mem off len flags addr
*)letmin_pool_factor=4letmax_pool_factor=8typebigblock={bb_id:<>;mutable bb_use_counter:int;mutablebb_mem:memory;mutablebb_age:int;}typememory_pool={pool_block_size:int;mutablepool_blocks:(int*bigblock*boolref)list;(* The bool is set to [false] if the block is unused *)mutablepool_free_blocks:(memory*int*bigblock)list;(* The int is the GC age *)pool_mutex:Netsys_oothr.mutex;mutablepool_factor:int;mutablepool_free_age:int;}let create_poolbsize=ifbsize<=0||bsizemodpagesize<>0theninvalid_arg"Netsys_mem.create_pool";letm=!Netsys_oothr.provider#create_mutex()in{pool_block_size =bsize;pool_blocks=[];pool_free_blocks=[];pool_mutex=m;pool_factor=min_pool_factor;pool_free_age =0;}letpool_move_to_free_listp=letage=(Gc.quick_stat()).Gc.major_collectionsinletub,fb=List.partition(fun(_,_,is_used)->!is_used)p.pool_blocksinp.pool_blocks<-ub;(* prerr_endline ("Found new free blocks: " ^ string_of_int (List.length fb));*)p.pool_free_blocks<-(List.map(fun(k,bb,_)->letm=Bigarray.Array1.subbb.bb_mem(k*p.pool_block_size)p.pool_block_sizein(m,k,bb))fb)@p.pool_free_blocks;List.iter(fun(_,bb,_)->bb.bb_use_counter<-bb.bb_use_counter-1;bb.bb_age <-age)fb(*
let bb_finalise _ =
prerr_endline "bb_finalise"
*)letpool_alloc_blocksp=pool_move_to_free_listp;ifp.pool_free_blocks=[]then (letage=(Gc.quick_stat()).Gc.major_collectionsin(* Nothing free, sowe have to allocate new blocks: *)letbigblock_size=p.pool_factor*p.pool_block_sizeinletbigblock_mem=tryalloc_memory_pagesbigblock_sizewithInvalid_argument_->(* OS does not support it... *)Bigarray.Array1.createBigarray.charBigarray.c_layoutbigblock_sizeinletbigblock={bb_id=(objectend);bb_use_counter=0;bb_mem=bigblock_mem;bb_age=age;}in(* Gc.finalise bb_finalise bigblock_mem; *)fork=0top.pool_factor-1doletm=Bigarray.Array1.subbigblock_mem (k*p.pool_block_size)p.pool_block_sizeinp.pool_free_blocks<-(m,k,bigblock)::p.pool_free_blocksdone;(* prerr_endline ("alloc blocks: " ^ string_of_int p.pool_factor); *)p.pool_factor<-minmax_pool_factor(p.pool_factor*2);)elsep.pool_factor<-min_pool_factorletpool_free_blocks?(force=false)p=letage=(Gc.quick_stat()).Gc.major_collectionsinifforce||age>p.pool_free_agethen(pool_move_to_free_list p;letdb,fb=List.partition(fun(_,_,bb)->bb.bb_use_counter =0&&(force||age-bb.bb_age>=2))p.pool_free_blocksin(* Sort the free blocks, to achieve that big, filled blocks are preferred
whennew blocks are takenfrom the free list. So small and quite empty
blocks are more likely to be given back to the OS.
- Hopefully this is not tooexpensive.
*)letfb_sorted=List.sort(fun(_,_,bb1)(_,_,bb2)->(* highest use counter first, then oldest *)matchbb2.bb_use_counter-bb1.bb_use_counterwith|0->Oo.idbb1.bb_id-Oo.idbb2.bb_id|d->d)fbinp.pool_free_blocks<-fb_sorted;p.pool_free_age<-age;(* prerr_endline ("pool_free_blocks db=" ^ string_of_int (List.length db))*)(* unmap_file is not supported for the "bigblock" approach CHECK *))letpool_reclaim p=pool_free_blocks~force:truepletset_falsev_=(* prerr_endline "finaliser"; *)v:=falseletpool_alloc_memory2p=Netsys_oothr.serializep.pool_mutex(fun()->letdo_free_check=reftrueinifp.pool_free_blocks =[]then(pool_alloc_blocksp;do_free_check:=false);matchp.pool_free_blockswith|(m,k,bb)::l->p.pool_free_blocks<-l;bb.bb_use_counter<-bb.bb_use_counter +1;letis_used=reftrueinletfree=set_falseis_usedin(* avoid referencing m ! *)letfree2=set_falseis_usedinif!do_free_check&&l<>[]thenpool_free_blocksp;p.pool_blocks<-(k,bb,is_used)::p.pool_blocks;Gc.finalisefreem;(m,free2)|[]->assertfalse)()letpool_alloc_memoryp=fst(pool_alloc_memory2p)letpool_block_sizep=p.pool_block_sizeletdefault_block_size=pagesize*16letdefault_pool=create_pooldefault_block_sizeletsmall_block_size=pagesizeletsmall_pool=create_poolsmall_block_sizeletpool_reportp=letb=Buffer.create500inbprintfb"POOL GENERALPARAMETERS:\n\n";bprintfb"pool_block_size=%d\n" p.pool_block_size;bprintfb"pool_factor=%d\n"p.pool_factor;bprintfb"length pool_blocks=%d (used+prop)\n"(List.lengthp.pool_blocks);bprintfb"length pool_free_blocks=%d\n\n"(List.lengthp.pool_free_blocks);letbb_tab=Hashtbl.create10inletadd_bbbb=ifnot (Hashtbl.membb_tabbb.bb_id)then(letcnt_used=ref0inlet cnt_prop=ref0inHashtbl.addbb_tabbb.bb_id(bb,cnt_used,cnt_prop))inList.iter(fun(_,bb,_)->add_bbbb)p.pool_blocks;List.iter(fun(_,_,bb)->add_bbbb)p.pool_free_blocks;List.iter(fun(k,bb,is_used)->let(_,cnt_used,cnt_prop)=Hashtbl.findbb_tabbb.bb_idinif!is_usedthenincrcnt_usedelseincrcnt_prop)p.pool_blocks;bprintfb"POOL BY BIGBLOCK:\n\n";Hashtbl.iter(funbb_id(bb,cnt_used,cnt_prop)->letsize=Bigarray.Array1.dimbb.bb_mem/p.pool_block_sizeinbprintf b"block %d: age=%d size=%d used=%d propagate=%d free=%d\n"(Oo.idbb_id)bb.bb_agesize!cnt_used!cnt_prop(size-!cnt_used -!cnt_prop))bb_tab;Buffer.contentsb