[Eric_Jacobs@fc.mcps.k12.md.us (Eric Jacobs) writes:]
>I just finished unconvering a nasty race for virtual memory that
>sometimes occurs in multi-threaded processes. The most likely to
>be affected are processes that call static-linked functions for the
>first time in two or more threads at the same time.
>...
Attached below is a proposed patch to fix this problem. It seems to fix the
kernel crach for me... care to look it over and also give it a spin? If it
all looks OK, I'll put it in for 1.6.3.
Thanks,
Andy
*** 1.8 1997/09/28 12:15:24
--- include/sys/pview.h 1999/11/09 15:51:44
***************
*** 18,25 ****
--- 18,27 ----
struct pview /* For listing under vas */
*p_next;
uchar p_prot; /* Protections on view */
struct hatpview p_hat; /* HAT contribution */
+ uchar *p_valid; /* If attached to a VAS, flags which */
+ /* virtual slots have mappings */
};
/*
* Bits for protection
*** 1.8 1997/12/22 17:32:31
--- include/sys/malloc.h 1999/11/09 16:01:32
***************
*** 43,52 ****
#define MT_PGRP (21) /* Process grouping */
#define MT_ATL (22) /* Attach lists */
#define MT_FPU (23) /* FPU save state */
#define MT_OPENPORT (24) /* FOD pset data structure */
! #define MALLOCTYPES (25) /* UPDATE when you add values above */
/* ALSO check n_allocname[] */
/*
* Our per-storage-size information
--- 43,53 ----
#define MT_PGRP (21) /* Process grouping */
#define MT_ATL (22) /* Attach lists */
#define MT_FPU (23) /* FPU save state */
#define MT_OPENPORT (24) /* FOD pset data structure */
+ #define MT_PVIEW_VALID (25) /* pview valid page map */
! #define MALLOCTYPES (26) /* UPDATE when you add values above */
/* ALSO check n_allocname[] */
/*
* Our per-storage-size information
*** 1.15 1997/09/28 12:18:26
--- src/os/dbg/dump.c 1999/11/19 14:48:40
***************
*** 296,305 ****
do_dump_pview(struct pview *pv)
{
printf(" pview @ 0x%x vaddr 0x%x len 0x%x off 0x%x hat 0x%x\n",
pv, pv->p_vaddr, pv->p_len, pv->p_off, &pv->p_hat);
! printf(" vas 0x%x next 0x%x prot 0x%x pset 0x%x\n",
! pv->p_vas, pv->p_next, pv->p_prot, pv->p_set);
}
/*
* dump_pview()
--- 296,305 ----
do_dump_pview(struct pview *pv)
{
printf(" pview @ 0x%x vaddr 0x%x len 0x%x off 0x%x hat 0x%x\n",
pv, pv->p_vaddr, pv->p_len, pv->p_off, &pv->p_hat);
! printf(" vas 0x%x next 0x%x prot 0x%x pset 0x%x valid 0x%x\n",
! pv->p_vas, pv->p_next, pv->p_prot, pv->p_set, pv->p_valid);
}
/*
* dump_pview()
*** 1.15 1995/10/27 05:43:05
--- src/os/kern/malloc.c 1999/11/09 16:02:46
***************
*** 28,60 ****
* Value to name mapping, to help the kernel debugger print
* things out nicely
*/
char *n_allocname[MALLOCTYPES] = {
! "MT_RMAP",
! "MT_EVENT",
! "MT_EXITGRP",
! "MT_EXITST",
! "MT_MSG",
! "MT_SYSMSG",
! "MT_PORT",
! "MT_PORTREF",
! "MT_PVIEW",
! "MT_PSET",
! "MT_PROC",
! "MT_THREAD",
! "MT_KSTACK",
! "MT_VAS",
! "MT_PERPAGE",
! "MT_QIO",
! "MT_SCHED",
! "MT_SEG",
! "MT_EVENTQ",
! "MT_L1PT",
! "MT_L2PT",
! "MT_PGRP",
! "MT_ATL",
! "MT_FPU",
! "MT_OPENPORT",
};
#endif /* DEBUG */
/*
--- 28,41 ----
* Value to name mapping, to help the kernel debugger print
* things out nicely
*/
char *n_allocname[MALLOCTYPES] = {
! "MT_RMAP", "MT_EVENT", "MT_EXITGRP", "MT_EXITST", "MT_MSG",
! "MT_SYSMSG", "MT_PORT", "MT_PORTREF", "MT_PVIEW", "MT_PSET",
! "MT_PROC", "MT_THREAD", "MT_KSTACK", "MT_VAS", "MT_PERPAGE",
! "MT_QIO", "MT_SCHED", "MT_SEG", "MT_EVENTQ", "MT_L1PT",
! "MT_L2PT", "MT_PGRP", "MT_ATL", "MT_FPU", "MT_OPENPORT",
! "MT_PVIEW_VALID",
};
#endif /* DEBUG */
/*
*** 1.8 1996/04/18 08:13:40
--- src/os/kern/pview.c 1999/11/09 16:10:30
***************
*** 35,42 ****
--- 35,43 ----
void
free_pview(struct pview *pv)
{
deref_pset(pv->p_set);
+ ASSERT_DEBUG(pv->p_valid == 0, "free_pview: p_valid not cleared");
FREE(pv, MT_PVIEW);
}
/*
***************
*** 52,59 ****
--- 53,61 ----
bcopy(opv, pv, sizeof(*pv));
ref_pset(pv->p_set);
pv->p_next = 0;
pv->p_vas = 0;
+ pv->p_valid = 0;
return(pv);
}
/*
***************
*** 86,95 ****
struct pview *pv;
extern struct pview *detach_pview();
pv = detach_pview(vas, vaddr);
! deref_pset(pv->p_set);
! FREE(pv, MT_PVIEW);
}
/*
* attach_valid_slots()
--- 88,96 ----
struct pview *pv;
extern struct pview *detach_pview();
pv = detach_pview(vas, vaddr);
! free_pview(pv);
}
/*
* attach_valid_slots()
***************
*** 111,117 ****
--- 112,119 ----
hat_addtrans(pv, (char *)pv->p_vaddr + ptob(x),
pp->pp_pfn, pv->p_prot |
((pp->pp_flags & PP_COW) ? PROT_RO : 0));
ref_slot(ps, pp, idx);
+ pv->p_valid[x] = 1;
}
}
}
*** 1.57 1997/12/07 23:10:29
--- src/os/kern/proc.c 1999/11/18 16:19:30
***************
*** 44,54 ****
ps = physmem_pset(pfn, pages);
pv = alloc_pview(ps);
pv->p_vaddr = vaddr;
! pv->p_vas = vas;
! pv->p_next = vas->v_views;
! vas->v_views = pv;
return(pv);
}
/*
--- 44,52 ----
ps = physmem_pset(pfn, pages);
pv = alloc_pview(ps);
pv->p_vaddr = vaddr;
! ASSERT(attach_pview(vas, pv), "mkview: attach failed");
return(pv);
}
/*
*** 1.19 1998/12/13 22:19:14
--- src/os/kern/vm_steal.c 1999/11/09 16:14:58
***************
*** 139,146 ****
--- 139,151 ----
hat_deletetrans(pv, (char *)pv->p_vaddr +
ptob(a->a_idx), pp->pp_pfn);
flags |= hat_getbits(pv,
(char *)pv->p_vaddr + ptob(a->a_idx));
+
+ /*
+ * Virtual map under this pview not valid any more
+ */
+ pv->p_valid[a->a_idx] = 0;
}
/*
* Free attach list element, update ref count
*** 1.8 1996/04/18 08:13:40
--- src/os/kern/vm_fault.c 1999/11/30 16:37:12
***************
*** 66,74 ****
{
struct pview *pv;
struct pset *ps;
struct perpage *pp;
! uint idx;
int error = 0;
int wasvalid;
/*
--- 66,74 ----
{
struct pview *pv;
struct pset *ps;
struct perpage *pp;
! uint idx, pvidx;
int error = 0;
int wasvalid;
/*
***************
*** 76,83 ****
--- 76,84 ----
*/
if ((pv = find_pview(vas, vaddr)) == 0) {
return(1);
}
+ ASSERT_DEBUG(pv->p_valid, "vas_fault: pview !p_valid");
ps = pv->p_set;
/*
* Next easiest--trying to write to read-only view
***************
*** 89,97 ****
/*
* Transfer from pset lock to page slot lock
*/
! idx = btop(((char *)vaddr - (char *)pv->p_vaddr)) + pv->p_off;
pp = find_pp(ps, idx);
lock_slot(ps, pp);
/*
--- 90,99 ----
/*
* Transfer from pset lock to page slot lock
*/
! pvidx = btop((char *)vaddr - (char *)pv->p_vaddr);
! idx = pvidx + pv->p_off;
pp = find_pp(ps, idx);
lock_slot(ps, pp);
/*
***************
*** 121,151 ****
/*
* Break COW association when we write it
*/
if ((pp->pp_flags & PP_COW) && write) {
if (wasvalid) {
! uint pvidx;
!
! /*
! * May or may not be there. If it is, remove
! * its reference from the per-page struct.
! */
! pvidx = btop((ulong)vaddr - (ulong)pv->p_vaddr);
! if (delete_atl(pp, pv, pvidx) == 0) {
! deref_slot(ps, pp, idx);
}
}
cow_write(ps, pp, idx);
ASSERT(pp->pp_flags & PP_V, "vm_fault: lost the page 2");
}
/*
* With a valid slot, add a hat translation and tabulate
* the entry with an atl.
*/
! add_atl(pp, pv, btop((ulong)vaddr - (ulong)(pv->p_vaddr)), 0);
hat_addtrans(pv, vaddr, pp->pp_pfn, pv->p_prot |
((pp->pp_flags & PP_COW) ? PROT_RO : 0));
/*
* Free the various things we hold and return
*/
--- 123,164 ----
/*
* Break COW association when we write it
*/
if ((pp->pp_flags & PP_COW) && write) {
+ /*
+ * May or may not be there. If it is, remove
+ * its reference from the per-page struct.
+ */
if (wasvalid) {
! if (pv->p_valid[pvidx]) {
! ASSERT(delete_atl(pp, pv, pvidx) == 0,
! "vas_fault: p_valid no atl");
! pv->p_valid[pvidx] = 0;
}
+ deref_slot(ps, pp, idx);
}
cow_write(ps, pp, idx);
ASSERT(pp->pp_flags & PP_V, "vm_fault: lost the page 2");
+
+ /*
+ * If not writing to a COW association, then inhibit adding
+ * the translation if it's already present (another thread
+ * ran and brought it in for us, probably)
+ */
+ } else if (pv->p_valid[pvidx]) {
+ deref_slot(ps, pp, idx);
+ goto out;
}
/*
* With a valid slot, add a hat translation and tabulate
* the entry with an atl.
*/
! add_atl(pp, pv, pvidx, 0);
hat_addtrans(pv, vaddr, pp->pp_pfn, pv->p_prot |
((pp->pp_flags & PP_COW) ? PROT_RO : 0));
+ ASSERT_DEBUG(pv->p_valid[pvidx] == 0, "vas_fault: p_valid went on");
+ pv->p_valid[pvidx] = 1;
/*
* Free the various things we hold and return
*/
*** 1.13 1996/01/04 22:48:17
--- src/os/kern/vas.c 1999/11/18 16:23:00
***************
*** 59,66 ****
--- 59,67 ----
struct pset *ps;
struct perpage *pp;
int x;
struct pview *pv, **pvp;
+ char *va;
/*
* Remove our pview from the vas. It's singly linked, so we
* have to search from the front.
***************
*** 76,83 ****
--- 77,85 ----
pvp = &pv->p_next;
}
ASSERT(pv, "detach_pview: lost a pview");
v_lock(&vas->v_lock, SPL0_SAME);
+ ASSERT_DEBUG(pv->p_valid, "detach_pview: !p_valid");
ps = pv->p_set;
/*
* Walk each valid slot, and tear down any HAT translation.
***************
*** 85,125 ****
p_lock_void(&ps->p_lock, SPL0_SAME);
for (x = 0; x < pv->p_len; ++x) {
uint pfn, idx;
- idx = pv->p_off + x;
- pp = find_pp(ps, idx);
-
/*
! * Can't be a translation if not a valid page
*/
! if (!(pp->pp_flags & PP_V)) {
continue;
}
pfn = pp->pp_pfn;
/*
* Lock the slot. Lock the underlying page. Delete
* translation, and deref our use of the slot.
*/
lock_slot(ps, pp);
! if (delete_atl(pp, pv, x) == 0) {
! char *va;
! /*
! * Valid in our view; delete HAT translation. Record
! * ref/mod bits for final time.
! */
! va = pv->p_vaddr;
! va += ptob(x);
! hat_deletetrans(pv, va, pfn);
! pp->pp_flags |= hat_getbits(pv, va);
!
! /*
! * Release our reference to the slot
! */
! deref_slot(ps, pp, idx);
! }
unlock_slot(ps, pp);
/*
* Reacquire pset lock
--- 87,131 ----
p_lock_void(&ps->p_lock, SPL0_SAME);
for (x = 0; x < pv->p_len; ++x) {
uint pfn, idx;
/*
! * Skip all but those with active mappings
*/
! if (!pv->p_valid[x]) {
continue;
}
+
+ /*
+ * Point to the mapping
+ */
+ idx = pv->p_off + x;
+ pp = find_pp(ps, idx);
+ ASSERT_DEBUG(pp->pp_flags & PP_V,
+ "detach_pview: p_valid !PP_V");
pfn = pp->pp_pfn;
/*
* Lock the slot. Lock the underlying page. Delete
* translation, and deref our use of the slot.
*/
lock_slot(ps, pp);
! ASSERT(delete_atl(pp, pv, x) == 0,
! "detach_pview: p_valid but not ATL");
! /*
! * Valid in our view; delete HAT translation. Record
! * ref/mod bits for final time.
! */
! va = pv->p_vaddr;
! va += ptob(x);
! hat_deletetrans(pv, va, pfn);
! pp->pp_flags |= hat_getbits(pv, va);
!
! /*
! * Release our reference to the slot
! */
! deref_slot(ps, pp, idx);
unlock_slot(ps, pp);
/*
* Reacquire pset lock
***************
*** 136,143 ****
--- 142,155 ----
* Let hat hear about detach
*/
hat_detach(pv);
+ /*
+ * Free valid map memory
+ */
+ FREE(pv->p_valid, MT_PVIEW_VALID);
+ pv->p_valid = 0;
+
return(pv);
}
/*
***************
*** 174,181 ****
--- 186,199 ----
pv->p_vas = 0;
return(0);
}
vaddr = pv->p_vaddr;
+
+ /*
+ * Get the memory for the valid map
+ */
+ pv->p_valid = MALLOC(pv->p_len, MT_PVIEW_VALID);
+ bzero(pv->p_valid, pv->p_len);
/*
* Now that we're committed, link it onto the vas
*/
Received on Tue Nov 30 17:27:59 1999
This archive was generated by hypermail 2.1.8 : Thu Sep 22 2005 - 15:12:56 PDT