Corrige
Transcription
Corrige
TP7-8: Allocateur de mémoire. (Basé sur Centrale 1999)– Correction MP2/MP*- Khôles Caml 7-8 TP7-8: Allocateur de mémoire. (Basé sur Centrale 1999)– Correction Damien Martin-Guillerez Lycée Chateaubriand Février 2007 Si vous avez des questions, n’hésitez pas à m’interroger lors d’une séance de TP, ou par courrier électronique : [email protected] 1 Un corrigé I Question 1 l e t a l l o c a t o r l i s t = r e f [ ( 0 , memsize ) ] ; ; let f i r s t f i t size = l e t rec aux = fun | [] −> r a i s e NotEnoughMemory | ( ( a , s ) : : q) −> i f s > s i z e then a , ( a+s i z e , s−s i z e ) : : q e l s e i f s = s i z e then a , q else l e t a ’ , l = aux q in a’,(a, s ):: l in l e t x , l = aux ! a l l o c a t o r l i s t in a l l o c a t o r l i s t := l ; x ;; I Question 2 let best fit size = l e t rec aux r = fun | [] −> i f ( f s t r ) < 0 then r a i s e NotEnoughMemory e l s e r , [ ] | ( ( a , s ) : : q) −> i f s = s i z e then ( a , s ) , q e l s e i f ( s > s i z e ) && (( snd r ) > s ) then l e t r ’ , l = aux ( a , s ) q in i f ( f s t r ’) <> a then r ’ , ( ( a , s ) : : l ) e l s e ( a , s ) , ( ( a+s i z e , s−s i z e ) : : l ) else l e t a ’ , l = aux r q in a’,(a, s ):: l in l e t x , l = aux (−1, max int ) ! a l l o c a t o r l i s t in a l l o c a t o r l i s t := l ; fst x ;; 1 TP7-8: Allocateur de mémoire. (Basé sur Centrale 1999)– Correction MP2/MP*- Khôles Caml 7-8 I Question 3 let | | | merge chunks = fun [] −> [] [t] −> [t ] ( ( a1 , s1 ) : : ( a2 , s2 ) : : q) −> i f a1+s1 = a2 then ( a1 , s1+s2 ) : : q else ( a1 , s1 ) : : ( a2 , s2 ) : : q ;; let free a t = l e t rec aux = fun | [] −> [(a , t ) ] | [( x, s )] −> i f x < a then merge chunks [ ( x , s ) ; ( a , t ) ] e l s e merge chunks [ ( a , t ) ; ( x , s ) ] | ( ( x1 , s1 ) : : ( x2 , s2 ) : : q) −> i f ( a > x1) && (a < x2 ) then merge chunks ( ( x1 , s1 ) : : ( merge chunks ( ( a , t ) : : ( x2 , s2 ) : : q ) ) ) e l s e i f a < x1 then merge chunks ( ( a , t ) : : ( x1 , s1 ) : : ( x2 , s2 ) : : q) else ( x1 , s1 ) : : ( aux ( ( x2 , s2 ) : : q ) ) in a l l o c a t o r l i s t : = aux ! a l l o c a t o r l i s t ;; Le test demandé rendait la dernière allocation impossible selon la stratégie first-fit alors qu’il n’y avait aucun problème sur la stratégie best-fit. On obtenait l’inverse en mettant la demande d’allocation de 500 mots à la fin. I Question 4 On conservait le haut de la liste des blocs libre dans une référence vers un entier ( let head chunks = ref 0;;). Tout d’abord, il était utile de faire des fonctions de manipulation des blocs. l e t chunk size a = abs mem. ( a ) ; ; le t set chunk size a s = mem. ( a+(abs s)−1) <− abs s ; mem. ( a ) <− s ; ;; l e t create chunk a s = mem. ( a ) <− s ; mem. ( a+(abs s)−1) <− abs s ; mem. ( a+1) <− −1; mem. ( a+2) <− −1 ;; l e t chunk inuse a = mem. ( a ) < 0 ; ; l e t c h u n k n e x t l i s t a = mem. ( a +1);; l e t c h u n k p r e v l i s t a = mem. ( a +2);; l e t insert chunk w a = mem. ( a+2) <− w; mem. ( a+1) <− mem. (w+1); mem. (w+1) <− a ; i f mem. ( a+1) >= 0 then mem. (mem. ( a+1)+2) <− a ;; l e t insert chunk top w a = mem. ( a+2) <− −1; mem. (w+2) <− a ; mem. ( a+1) <− w ;; l e t unlink chunk a = i f mem. ( a+1) >= 0 then mem. (mem. ( a+1)+2) <− mem. ( a+2); i f mem. ( a+2) >= 0 then mem. (mem. ( a+2)+1) <− mem. ( a+1); 2 TP7-8: Allocateur de mémoire. (Basé sur Centrale 1999)– Correction MP2/MP*- Khôles Caml 7-8 mem. ( a+1) <− −1; mem. ( a+2) <− −1 ;; l e t chunk next a = i f a+mem. ( a) >= memsize then −1 e l s e a + ( abs mem. ( a ) ) ; ; l e t chunk prev a = i f a > 0 then a − mem. ( a−1) e l s e − 1 ; ; Une fonction donnant la taille nécessaire en fonction de la taille demandée était utile également : let convert size s = let t = s + 2 in i f t < min size then min size e l s e i f ( t mod alignement ) <> 0 then t − ( t mod alignement ) + alignement else t ;; Ensuite, on pouvait faire la fonction d’initialisation : l e t init mem () = create chunk 0 memsize ; head chunks := 0 ;; Après quelques fonctions de manipulation des listes de blocs : l e t rec i n s e r t c h u n k l i s t b a c k w a r d top prev next cur = i f prev < 0 then begin i f next >= 0 then insert chunk top next cur e l s e (mem. ( cur+1) <− −1; mem. ( cur+2) <− −1); cur end e l s e i f ( chunk size prev ) > ( chunk size cur ) then i n s e r t c h u n k l i s t b a c k w a r d top ( c h u n k p r e v l i s t prev ) prev cur e l s e ( insert chunk prev cur ; top ) ;; l e t rec i n s e r t c h u n k l i s t f o r w a r d top prev next cur = i f next < 0 then begin i f prev >= 0 then ( insert chunk prev cur ; top ) e l s e (mem. ( cur+1) <− −1; mem. ( cur+2) <− −1; cur ) end e l s e i f ( chunk size next ) < ( chunk size cur ) then i n s e r t c h u n k l i s t f o r w a r d top next ( c h u n k n e x t l i s t next ) cur e l s e i f prev < 0 then ( insert chunk top next cur ; cur ) e l s e ( insert chunk prev cur ; top ) ;; l e t chunk allocate top a t = l e t x = chunk size a in i f x <= t+min size then begin l e t n = c h u n k n e x t l i s t a in unlink chunk a ; s e t c h u n k s i z e a (−x ) ; i f top = a then n e l s e top end else begin l e t prev = c h u n k p r e v l i s t a and next = c h u n k n e x t l i s t a in unlink chunk a ; 3 TP7-8: Allocateur de mémoire. (Basé sur Centrale 1999)– Correction MP2/MP*- Khôles Caml 7-8 set chunk size a (−t ) ; create chunk ( a+t ) ( x−t ) ; i n s e r t c h u n k l i s t b a c k w a r d top prev next ( a+t ) end ;; l e t chunk merge top a = l e t next = chunk next a and prev = chunk prev a and t = r e f top and adr = r e f a in i f next >= 0 then i f not ( chunk inuse next ) then begin i f next = top then t : = ( c h u n k n e x t l i s t next ) ; unlink chunk next ; s e t c h u n k s i z e a ( ( chunk size a)+( chunk size next ) ) end ; i f prev >= 0 then i f not ( chunk inuse prev ) then begin i f prev = ! t then t : = ( c h u n k n e x t l i s t prev ) ; unlink chunk prev ; s e t c h u n k s i z e prev ( ( chunk size prev)+( chunk size a ) ) ; adr : = prev end ; ! t , ! adr ;; l e t chunk free top a = create chunk a ( chunk size a ) ; l e t x , adr = chunk merge top a in i n s e r t c h u n k l i s t f o r w a r d x (−1) x adr ;; l e t rec c h u n k f i r s t f i t top t = i f top < 0 then r a i s e NotEnoughMemory e l s e i f ( chunk size top) >= t then top e l s e c h u n k f i r s t f i t ( c h u n k n e x t l i s t top ) t ;; Enfin, on pouvait faire les fonctions d’allocation et de libération : let bin alloc size = let t = convert size size in l e t a = c h u n k f i r s t f i t ! head chunks t in head chunks : = chunk allocate ! head chunks a t ; a+1 ;; l e t b i n f r e e adr = l e t a = adr − 1 in i f not ( chunk inuse a ) then r a i s e DoubleFree ; head chunks : = chunk free ! head chunks a ;; I Question 5 Ici, quelques adaptations simples était nécessaire, notamment pour remettre les blocs dans les bonnes listes. l e t bins = make vect 8 8 ( − 1 ) ; ; l e t log2 n = let r = ref 0 4 TP7-8: Allocateur de mémoire. (Basé sur Centrale 1999)– Correction MP2/MP*- Khôles Caml 7-8 and m = r e f n in while !m <> 0 do incr r ; m : = !m / 2 done ; ! r−1 ;; l e t index from size s i z e = i f s i z e <= 128 then ( ( s i z e +1) / 2) − 1 e l s e ( log2 s i z e ) + 57 ;; l e t d l i n i t () = create chunk 0 memsize ; f o r i = 0 to ( v e c t l e n g t h bins )−1 do bins . ( i ) <− −1 done ; bins . ( i n d e x f r o m s i z e memsize) <− 0 ;; l e t choose bin t = l e t i = r e f ( index from size t ) in while ( ! i < ( v e c t l e n g t h bins )) && ( bins . ( ! i ) = −1) do i n c r i done ; i f ! i = ( v e c t l e n g t h bins ) then r a i s e NotEnoughMemory else ! i ;; l e t next bin b = l e t i = r e f ( b+1) in while ( ! i < ( v e c t l e n g t h bins )) && ( bins . ( ! i ) = −1) do i n c r i done ; i f ! i = ( v e c t l e n g t h bins ) then r a i s e NotEnoughMemory else ! i ;; l e t dl movebin bin = l e t x = bins . ( bin ) in i f x >= 0 then l e t i = i n d e x f r o m s i z e ( chunk size x) in i f i <> bin then begin bins . ( bin) <− c h u n k n e x t l i s t x ; unlink chunk x ; bins . ( i ) <− i n s e r t c h u n k l i s t f o r w a r d bins . ( i ) (−1) bins . ( i ) x end ;; let dl alloc size = let t = convert size size in l e t bin = r e f ( choose bin t ) in l e t a = ( try c h u n k f i r s t f i t bins . ( ! bin ) t with NotEnoughMemory −> bin : = next bin ! bin ; c h u n k f i r s t f i t bins . ( ! bin ) t ) in bins . ( ! bin) <− chunk allocate bins . ( ! bin ) a t ; dl movebin ! bin ; a+1 ;; l e t dl chunk merge a = l e t next = chunk next a and prev = chunk prev a and adr = r e f a in i f next >= 0 then i f not ( chunk inuse next ) then begin l e t i = ( i n d e x f r o m s i z e ( chunk size next ) ) in i f next = bins . ( i ) then bins . ( i ) <− ( c h u n k n e x t l i s t next ) ; unlink chunk next ; s e t c h u n k s i z e a ( ( chunk size a)+( chunk size next ) ) end ; 5 TP7-8: Allocateur de mémoire. (Basé sur Centrale 1999)– Correction MP2/MP*- Khôles Caml 7-8 i f prev >= 0 then i f not ( chunk inuse prev ) then begin l e t i = ( i n d e x f r o m s i z e ( chunk size prev ) ) in i f prev = bins . ( i ) then bins . ( i ) <− ( c h u n k n e x t l i s t prev ) ; unlink chunk prev ; s e t c h u n k s i z e prev ( ( chunk size prev)+( chunk size a ) ) ; adr : = prev end ; ! adr ;; l e t d l f r e e adr = l e t a = adr − 1 in i f not ( chunk inuse a ) then r a i s e DoubleFree ; create chunk a ( chunk size a ) ; l e t x = dl chunk merge a in l e t i = i n d e x f r o m s i z e ( chunk size x) in bins . ( i ) <− i n s e r t c h u n k l i s t f o r w a r d bins . ( i ) (−1) bins . ( i ) x ;; 6