Created
July 14, 2011 20:47
-
-
Save iriina/1083407 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static int | |
ckpt_thaw_proc(struct lwp *lp, struct file *fp) | |
{ | |
struct proc *p = lp->lwp_proc; | |
Elf_Phdr *phdr = NULL; | |
Elf_Ehdr *ehdr = NULL; | |
int error; | |
void *base; | |
vm_offset_t start, end; | |
vm_offset_t tmpaddr; | |
void *res; | |
size_t nbyte; | |
int i; | |
int nthreads; | |
char *note; | |
size_t notesz; | |
prpsinfo_t *psinfo; | |
prstatus_t *status, *p_status; | |
prfpregset_t *fpregset, *p_fpregset; | |
prsavetls_t *tls, *p_tls; | |
TRACE_ENTER; | |
ehdr = kmalloc(sizeof(Elf_Ehdr), M_TEMP, M_ZERO | M_WAITOK); | |
if ((error = elf_gethdr(fp, ehdr)) != 0) | |
goto done; | |
nbyte = sizeof(Elf_Phdr) * ehdr->e_phnum; | |
phdr = kmalloc(nbyte, M_TEMP, M_WAITOK); | |
/* fetch description of program writable mappings */ | |
if ((error = elf_getphdrs(fp, phdr, nbyte)) != 0) | |
goto done; | |
/* fetch notes section containing register state */ | |
notesz = phdr->p_filesz; | |
//FIXME: find a valid way to retrieve numthreads on restore | |
nthreads = (notesz - sizeof(prpsinfo_t) - 20)/(sizeof(prstatus_t) + | |
sizeof(prfpregset_t) + sizeof(prsavetls_t) + 60); | |
PRINTF(("reading notes header nthreads=%d\n", nthreads)); | |
if (nthreads <= 0 || nthreads > CKPT_MAXTHREADS) | |
return EINVAL; | |
psinfo = kmalloc(sizeof(prpsinfo_t), M_TEMP, M_ZERO | M_WAITOK); | |
status = kmalloc(nthreads*sizeof(prstatus_t), M_TEMP, M_WAITOK); | |
fpregset = kmalloc(nthreads*sizeof(prfpregset_t), M_TEMP, M_WAITOK); | |
tls = kmalloc(nthreads*sizeof(prsavetls_t), M_TEMP, M_WAITOK); | |
note = kmalloc(notesz, M_TEMP, M_WAITOK); | |
PRINTF(("reading notes section\n")); | |
if ((error = read_check(fp, note, notesz)) != 0) | |
goto done; | |
error = elf_demarshalnotes(note, psinfo, status, fpregset, tls, nthreads); | |
if (error) | |
goto done; | |
/* fetch psinfo */ | |
error = elf_getpsinfo(lp, psinfo); | |
if (error) | |
goto done; | |
/* fetch register state from notes for the first thread */ | |
error = elf_loadnotes(lp, status, fpregset, tls, MAIN); | |
if (error) | |
goto done; | |
/* fetch program text vnodes */ | |
if ((error = elf_gettextvp(p, fp)) != 0) | |
goto done; | |
/* fetch signal disposition */ | |
if ((error = elf_getsigs(lp, fp)) != 0) | |
goto done; | |
/* fetch open files */ | |
if ((error = elf_getfiles(lp, fp)) != 0) | |
goto done; | |
/* handle mappings last in case we are reading from a socket */ | |
error = elf_loadphdrs(fp, phdr, ehdr->e_phnum); | |
/* Recreate vmspace0 */ | |
kprintf("XXX Test kva/vmspace0\n"); | |
/* XXX currently hardcoded values for file desc and base address */ | |
base = (void *)0x40000000; | |
int MemImageFd = 3; | |
error = kern_mmap(p->p_vmspace, base, 0x40000000, | |
PROT_READ|PROT_WRITE, | |
MAP_FILE|MAP_SHARED|MAP_VPAGETABLE, | |
MemImageFd, 0, &res); | |
kprintf("XXX Map %i\n", error); | |
if (!error) { | |
//madvise | |
tmpaddr = (vm_offset_t)base + 0x40000000; | |
start = trunc_page((vm_offset_t)base); | |
end = round_page(tmpaddr); | |
error = vm_map_madvise(&p->p_vmspace->vm_map, start, end, | |
MADV_NOSYNC, 0); | |
kprintf("XXX Madvise %i\n", error); | |
if (!error) { | |
//mcontrol | |
tmpaddr = (vm_offset_t)base + 0x40000000; | |
start = trunc_page((vm_offset_t)base); | |
end = round_page(tmpaddr); | |
error = vm_map_madvise(&p->p_vmspace->vm_map, start, end, | |
MADV_SETMAP, 0 | VPTE_R | VPTE_W | VPTE_V); | |
kprintf("XXX Mcontrol %i\n", error); | |
} | |
} | |
/* | |
* Set the textvp to the checkpoint file and mark the vnode so | |
* a future checkpointing of this checkpoint-restored program | |
* will copy out the contents of the mappings rather then trying | |
* to record the vnode info related to the checkpoint file, which | |
* is likely going to be destroyed when the program is re-checkpointed. | |
*/ | |
if (error == 0 && fp->f_data && fp->f_type == DTYPE_VNODE) { | |
if (p->p_textvp) | |
vrele(p->p_textvp); | |
p->p_textvp = (struct vnode *)fp->f_data; | |
vsetflags(p->p_textvp, VCKPT); | |
vref(p->p_textvp); | |
} | |
/* recreate the threads */ | |
kprintf("core tid %i\n", status->pr_pid); | |
p_status = status; | |
p_fpregset = fpregset; | |
p_tls = tls; | |
for (i = 0; i < nthreads-1; i++) { | |
p_status++; p_fpregset++; p_tls++; | |
kprintf("tid %i\n", p_status->pr_pid); | |
error = elf_loadnotes(lp, p_status, p_fpregset, p_tls, SECOND); | |
if (error) | |
goto done; | |
} | |
done: | |
if (psinfo) | |
kfree(psinfo, M_TEMP); | |
if (status) | |
kfree(status, M_TEMP); | |
if (fpregset) | |
kfree(fpregset, M_TEMP); | |
if (tls) | |
kfree(tls, M_TEMP); | |
if (note) | |
kfree(note, M_TEMP); | |
if (ehdr) | |
kfree(ehdr, M_TEMP); | |
if (phdr) | |
kfree(phdr, M_TEMP); | |
/* signal THAW */ | |
lwpsignal(p, lp, SIGTHAW); | |
TRACE_EXIT; | |
return error; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment