5 #include <minix/callnr.h>
6 #include <minix/type.h>
7 #include <minix/config.h>
8 #include <minix/const.h>
9 #include <minix/sysutil.h>
10 #include <minix/syslib.h>
11 #include <minix/debug.h>
12 #include <minix/bitmap.h>
13 #include <minix/hash.h>
23 #include <sys/param.h>
30 #include "sanitycheck.h"
34 struct phys_block
*pb_new(phys_bytes phys
)
36 struct phys_block
*newpb
;
38 if(!SLABALLOC(newpb
)) {
39 printf("vm: pb_new: couldn't allocate phys block\n");
43 assert(!(phys
% VM_PAGE_SIZE
));
44 assert(phys
!= MAP_NONE
);
49 newpb
->firstregion
= NULL
;
55 struct phys_region
*pb_reference(struct phys_block
*newpb
, vir_bytes offset
, struct vir_region
*region
)
57 struct phys_region
*newphysr
;
59 if(!SLABALLOC(newphysr
)) {
60 printf("vm: pb_reference: couldn't allocate phys region\n");
64 /* New physical region. */
66 newphysr
->offset
= offset
;
68 newphysr
->parent
= region
;
69 newphysr
->next_ph_list
= newpb
->firstregion
;
70 newpb
->firstregion
= newphysr
;);
73 physr_insert(region
->phys
, newphysr
);
78 /*===========================================================================*
80 *===========================================================================*/
81 void pb_unreferenced(struct vir_region
*region
, struct phys_region
*pr
, int rm
)
83 struct phys_block
*pb
;
86 assert(pb
->refcount
> 0);
87 USE(pb
, pb
->refcount
--;);
88 assert(pb
->refcount
>= 0);
90 if(pb
->firstregion
== pr
) {
91 USE(pb
, pb
->firstregion
= pr
->next_ph_list
;);
93 struct phys_region
*others
;
95 for(others
= pb
->firstregion
; others
;
96 others
= others
->next_ph_list
) {
97 assert(others
->ph
== pb
);
98 if(others
->next_ph_list
== pr
) {
99 USE(others
, others
->next_ph_list
= pr
->next_ph_list
;);
104 assert(others
); /* Otherwise, wasn't on the list. */
107 if(pb
->refcount
== 0) {
108 assert(!pb
->firstregion
);
109 if(region
->flags
& VR_ANON
) {
110 free_mem(ABS2CLICK(pb
->phys
), 1);
111 } else if(region
->flags
& VR_DIRECT
) {
112 ; /* No action required. */
114 panic("strange phys flags");
119 if(rm
) physr_remove(region
->phys
, pr
->offset
);