spin_unlock_irqrestore(&vmm_lock, irqf);
}
+uintptr_t vmm_virt_to_phys(uint64_t virt) {
+ uint32_t pi = pae_pdpt_index(virt);
+ uint32_t di = pae_pd_index(virt);
+ uint32_t ti = pae_pt_index(virt);
+
+ uintptr_t irqf = spin_lock_irqsave(&vmm_lock);
+ volatile uint64_t* pd = pae_pd_recursive(pi);
+ if ((pd[di] & X86_PTE_PRESENT) == 0) {
+ spin_unlock_irqrestore(&vmm_lock, irqf);
+ return 0;
+ }
+ volatile uint64_t* pt = pae_pt_recursive(pi, di);
+ uint64_t pte = pt[ti];
+ spin_unlock_irqrestore(&vmm_lock, irqf);
+
+ if (!(pte & X86_PTE_PRESENT)) return 0;
+ return (uintptr_t)(pte & ~0xFFFULL);
+}
+
void vmm_set_page_flags(uint64_t virt, uint32_t flags) {
uintptr_t irqf = spin_lock_irqsave(&vmm_lock);
vmm_set_page_flags_nolock(virt, flags);
return -EINVAL;
}
+ /* Track mapped pages for rollback on allocation failure */
+ uint32_t mapped_va[1024];
+ uint32_t mapped_count = 0;
+
for (uint16_t i = 0; i < e_phnum; i++) {
uint8_t* ph = fbuf + e_phoff + (uint32_t)i * e_phentsize;
uint32_t p_type = *(uint32_t*)(ph + 0);
for (uint32_t va = start_page; va <= end_page; va += 0x1000) {
extern void* pmm_alloc_page(void);
void* frame = pmm_alloc_page();
- if (!frame) { kfree(fbuf); return -ENOMEM; }
+ if (!frame) {
+ /* Rollback: unmap and free all pages mapped so far */
+ for (uint32_t j = 0; j < mapped_count; j++) {
+ uintptr_t phys = vmm_virt_to_phys((uint64_t)mapped_va[j]);
+ vmm_unmap_page((uint64_t)mapped_va[j]);
+ if (phys) pmm_free_page((void*)phys);
+ }
+ kfree(fbuf);
+ return -ENOMEM;
+ }
vmm_map_page((uint64_t)(uintptr_t)frame, (uint64_t)va,
VMM_FLAG_PRESENT | VMM_FLAG_RW | VMM_FLAG_USER);
+ if (mapped_count < 1024)
+ mapped_va[mapped_count++] = va;
}
if (p_filesz && p_offset + p_filesz <= flen)
CLONE_CHILD_CLEARTID)
if (clone_flags & ~CLONE_SUPPORTED_MASK) return -EINVAL;
+ /* CLONE_THREAD requires CLONE_VM — threads must share address space */
+ if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_VM))
+ return -EINVAL;
+
struct process* child = process_clone_create(clone_flags, child_stack, regs, tls_base);
if (!child) return -ENOMEM;
}
struct pipe_state {
+ spinlock_t lock;
uint8_t* buf;
uint32_t cap;
uint32_t rpos;
return;
}
- if (pn->is_read_end) {
- if (pn->ps->readers) pn->ps->readers--;
- } else {
- if (pn->ps->writers) pn->ps->writers--;
- }
-
struct pipe_state* ps = pn->ps;
+ uint32_t is_read_end = pn->is_read_end;
kfree(pn);
+ uintptr_t irqf = spin_lock_irqsave(&ps->lock);
if (ps->readers == 0 && ps->writers == 0) {
+ /* Already freed by the other end's close */
+ spin_unlock_irqrestore(&ps->lock, irqf);
+ return;
+ }
+
+ if (is_read_end) {
+ if (ps->readers) ps->readers--;
+ } else {
+ if (ps->writers) ps->writers--;
+ }
+
+ if (ps->readers == 0 && ps->writers == 0) {
+ spin_unlock_irqrestore(&ps->lock, irqf);
if (ps->buf) kfree(ps->buf);
kfree(ps);
+ } else {
+ spin_unlock_irqrestore(&ps->lock, irqf);
}
}
struct pipe_state* ps = (struct pipe_state*)kmalloc(sizeof(*ps));
if (!ps) return -ENOMEM;
memset(ps, 0, sizeof(*ps));
+ spinlock_init(&ps->lock);
ps->cap = 512;
ps->buf = (uint8_t*)kmalloc(ps->cap);
if (!ps->buf) {