Skip to content

Instantly share code, notes, and snippets.

@iriina
Created July 14, 2011 20:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iriina/1083407 to your computer and use it in GitHub Desktop.
Save iriina/1083407 to your computer and use it in GitHub Desktop.
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