[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: deadlock on ptrace
斉藤@densanと言います。
> 今後使われない(?) pmapを追いかけても仕方なさそうですし、
> 次の正式リリースを待つのも手でしょうか。
gdbを使っているとあまりによくhung-upするので、pmap を直してみました。
変更内容をpatch形式で示します。しかし、
patchを当てて下さいと言う意味では決してありません。
以前のsys/uvm/uvm_fault.cに加えた変更よりは、マトモだと思います。
変更の主旨ですが、kernel_mapを二重にlockする場合があり、
LK_SHAREDとLK_EXCLUSIVEの両方の場合があります。
pmap_alloc_pv()からuvm_km_zalloc(kernel_map, NBPG)が呼ばれ、
pmap_free_pv()からuvm_km_free(kernel_map, (vaddr_t)pvp, NBPG)呼ばれます。
trap.cの変更では、pmap_alloc_pv()の呼出元が、kernel_mapをlockする前に、
pmap_alloc_pv_before()の新しい関数を呼び出して、予め必要なページをallocします。
pmap_free_pv()では、kernel_mapのlock状態を見て、
uvm_km_free()を呼ばないようにしてます。
ここで飛ばしても問題は発生しないと読んだんですが。
--- pmap.c2 Tue Feb 19 17:11:08 2002
+++ pmap.c Wed Feb 20 18:33:51 2002
@@ -98,6 +98,7 @@
LIST_HEAD(pv_page_list, pv_page) pv_page_freelist;
int pv_nfree;
int pv_pcnt;
+void pmap_alloc_pv_before __P((void));
static struct pv_entry *pmap_alloc_pv __P((void));
static void pmap_free_pv __P((struct pv_entry *));
void pmap_pinit __P((pmap_t));
@@ -738,8 +739,8 @@
bcopy((caddr_t)src, (caddr_t)dst, NBPG);
}
-static struct pv_entry *
-pmap_alloc_pv()
+void
+pmap_alloc_pv_before()
{
struct pv_page *pvp;
struct pv_entry *pv;
@@ -749,14 +750,23 @@
if (!(pvp = (struct pv_page *)uvm_km_zalloc(kernel_map, NBPG)))
panic("pmap_alloc_pv: uvm_km_zalloc() failed");
pv_pcnt++;
- pvp->pvp_pgi.pgi_freelist = pv = &pvp->pvp_pv[1];
- for (i = NPVPPG - 2; --i >= 0; pv++)
+ pvp->pvp_pgi.pgi_freelist = pv = &pvp->pvp_pv[0];
+ for (i = NPVPPG - 1; --i >= 0; pv++)
pv->pv_next = pv + 1;
pv->pv_next = 0;
- pv_nfree += pvp->pvp_pgi.pgi_nfree = NPVPPG - 1;
+ pv_nfree += pvp->pvp_pgi.pgi_nfree = NPVPPG;
LIST_INSERT_HEAD(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
- pv = pvp->pvp_pv;
- } else {
+ }
+}
+
+static struct pv_entry *
+pmap_alloc_pv()
+{
+ struct pv_page *pvp;
+ struct pv_entry *pv;
+
+ pmap_alloc_pv_before();
+ {
pv_nfree--;
pvp = pv_page_freelist.lh_first;
if (--pvp->pvp_pgi.pgi_nfree <= 0)
@@ -778,11 +788,14 @@
case 1:
LIST_INSERT_HEAD(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
default:
+ free:
pv->pv_next = pvp->pvp_pgi.pgi_freelist;
pvp->pvp_pgi.pgi_freelist = pv;
pv_nfree++;
break;
case NPVPPG:
+ if (kernel_map->lock.lk_sharecount || kernel_map->lock.lk_exclusivecount)
+ goto free;
pv_nfree -= NPVPPG - 1;
pv_pcnt--;
LIST_REMOVE(pvp, pvp_pgi.pgi_list);
--- trap.c2 Wed Feb 20 16:13:16 2002
+++ trap.c Wed Feb 20 16:23:34 2002
@@ -63,6 +63,7 @@
volatile int want_resched;
static int fix_unaligned __P((struct proc *p, struct trapframe *frame));
+void pmap_alloc_pv_before __P((void));
void
trap(frame)
@@ -104,6 +105,8 @@
ftype = VM_PROT_READ | VM_PROT_WRITE;
else
ftype = VM_PROT_READ;
+ if (map == kernel_map)
+ pmap_alloc_pv_before();
if (uvm_fault(map, trunc_page(va), 0, ftype)
== KERN_SUCCESS) {
/*